在使用 OpenClaw(龙虾)进行 AI 自动化开发时,很多开发者最初接触到的都是“单次问答”模式:用户提问 -> AI 调用 execute 方法 -> 返回一段 Markdown 文本。但在真实的业务场景中,我们往往需要更复杂的交互——比如让经理点击卡片上的按钮来审批报销单,或者让用户填写表单后提交数据。

如何实现这种“有状态、可交互”的业务流?答案就是:在一个 Skill 中编写多个方法。今天,我们就通过一个极具代表性的真实场景—— “差旅报销智能审批” ,带你彻底掌握 OpenClaw 的多方法事件驱动开发模式。
在这里插入图片描述

📋 真实业务场景:从“AI分析”到“经理拍板”

假设员工张三提交了一笔 500 元的周末打车费报销。我们的目标是打造一个全自动的审批机器人:

  1. AI 自动初审:识别报销信息,生成一张带有“批准”和“驳回”按钮的交互式卡片,发送给部门经理。
  2. 经理交互决策:经理直接在聊天界面(如飞书、钉钉或 WebUI)点击按钮。
  3. 后台自动执行:Skill 接收到点击事件,自动触发财务打款流程或退回申请,并实时更新卡片状态为“已处理”。
💻 核心编码实战:一个 Skill 搞定全流程

在 OpenClaw 中,一个 Skill 本质上就是一个功能完备的 Python 类。我们可以利用装饰器(如 @Skill.on_action)来定义不同的事件处理器,将“生成卡片”和“处理点击”完美封装在一起。

以下是一个完整的 Python Skill 代码示例:

import asyncio
from openclaw import Skill, SkillResult, Context

class ExpenseApprovalSkill(Skill):
    """差旅报销智能审批技能"""
    name = "expense_approval"
    description = "分析报销单合规性,并让经理通过交互式卡片进行审批决策"

    # 【方法一:主入口】由 AI 自动触发,负责生成审批卡片
    async def execute(self, employee_name: str, amount: float, details: str) -> SkillResult:
        # 1. AI 可以在这里先调用大模型分析 details,判断是否有风险(此处省略具体 LLM 调用代码)
        
        # 2. 构造交互式卡片 JSON (以通用的类飞书/钉钉格式为例)
        approval_card = {
            "header": {"title": f"🔔 待审批:{employee_name} 的报销申请", "template": "blue"},
            "elements": [
                {"tag": "div", "text": {"content": f"**金额:** ¥{amount}\n**事由:** {details}"}},
                # 定义两个按钮,分别携带不同的 action 值
                {"tag": "action", "actions": [
                    {"tag": "button", "text": {"content": "✅ 批准打款"}, "type": "primary", "value": {"action": "approve_expense", "amount": amount}},
                    {"tag": "button", "text": {"content": "❌ 驳回申请"}, "type": "danger", "value": {"action": "reject_expense"}}
                ]}
            ]
        }
        
        # 3. 将卡片数据返回给前端渲染
        return SkillResult(
            success=True,
            data={"interactive_card": approval_card},
            message=f"已为 {employee_name} 生成报销审批卡片,请经理决策。"
        )

    # 【方法二:回调接口】专门监听卡片上的“批准”动作
    @Skill.on_action("approve_expense") 
    async def handle_approve(self, ctx: Context, action_data: dict) -> SkillResult:
        amount = action_data.get("amount")
        # 在这里编写真实的业务逻辑,例如调用财务系统的打款 API
        print(f"【系统日志】正在执行打款操作,金额:{amount}元...")
        
        # 更新原卡片的状态,防止重复点击,给用户即时反馈
        await ctx.update_card({"header": {"title": "✅ 已批准", "template": "green"}, "elements": []})
        return SkillResult(success=True, message="审批通过,财务打款指令已下发!")

    # 【方法三:回调接口】专门监听卡片上的“驳回”动作
    @Skill.on_action("reject_expense")
    async def handle_reject(self, ctx: Context, action_data: dict) -> SkillResult:
        print("【系统日志】该笔报销已被经理驳回。")
        
        await ctx.update_card({"header": {"title": "❌ 已驳回", "template": "red"}, "elements": []})
        return SkillResult(success=True, message="已驳回该笔报销申请,并通知了申请人。")

skill_instance = ExpenseApprovalSkill()
⚙️ 深度揭秘:底层执行过程与原理

为什么写了多个方法,系统就能精准地找到对应的那一个去执行?这背后的核心原理是 “事件驱动路由(Event-Driven Routing)” 。整个生命周期分为三个阶段:

  1. AI 编排与 **execute** 触发
    当你在对话框中输入“帮我审一下张三提交的 500 元打车费报销”时,OpenClaw 的主 Agent 会识别意图,提取参数,并实例化 ExpenseApprovalSkill 类,异步调用它的 execute 主方法。该方法运行完毕后,返回一段精心构造的 JSON(交互式卡片),你的聊天界面将其渲染成带按钮的漂亮卡片。
  2. 事件上报与精准路由
    当经理在界面上点击“✅ 批准打款”按钮时,前端会立即向 OpenClaw 的后端网关发送一个 HTTP POST 请求,Payload 中包含了按钮上绑定的 "action": "approve_expense"。OpenClaw 的网关收到请求后,会根据 action 的值去查找对应的 Skill。因为它发现了 @Skill.on_action("approve_expense") 这个装饰器,所以它会跳过 **execute**,直接唤醒并执行 **handle_approve** 这个方法
  3. 状态更新与闭环
    handle_approve 方法在后台静默执行了复杂的财务打款逻辑后,还可以通过 ctx.update_card() 反向控制前端,把原来的“待审批”卡片瞬间变成绿色的“已批准”状态。这不仅完成了业务闭环,还给了用户极佳的即时视觉反馈。
💡 总结与最佳实践

在一个 Skill 中编写多个方法,本质上就是把 AI 应用从简单的“单次问答”升级成了“有状态的交互应用”。

  • **execute**:是你的门面,负责接收 AI 的初始指令并展示界面。
  • **@Skill.on_action(...)**** 或其他自定义方法**:是你的后台控制器,负责处理用户在界面上的具体点击、输入等交互行为。

掌握了这种模式,你就可以在 OpenClaw 中开发出像工单系统、电商下单、投票表决等极其复杂的自动化业务流,而不仅仅是做一个简单的聊天机器人。快去试试把你的第一个多方法 Skill 跑起来吧!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐