拒绝“一问一答”!手把手教你在 OpenClaw 中开发多方法交互式 Skill
真实的业务场景中,我们往往需要更复杂的交互——比如让经理点击卡片上的按钮来审批报销单,或者让用户填写表单后提交数据。如何实现这种“有状态、可交互”的业务流?答案就是:在一个 Skill 中编写多个方法。今天,我们就通过一个极具代表性的真实场景—— “差旅报销智能审批” ,带你彻底掌握 OpenClaw 的多方法事件驱动开发模式。
在使用 OpenClaw(龙虾)进行 AI 自动化开发时,很多开发者最初接触到的都是“单次问答”模式:用户提问 -> AI 调用 execute 方法 -> 返回一段 Markdown 文本。但在真实的业务场景中,我们往往需要更复杂的交互——比如让经理点击卡片上的按钮来审批报销单,或者让用户填写表单后提交数据。
如何实现这种“有状态、可交互”的业务流?答案就是:在一个 Skill 中编写多个方法。今天,我们就通过一个极具代表性的真实场景—— “差旅报销智能审批” ,带你彻底掌握 OpenClaw 的多方法事件驱动开发模式。
📋 真实业务场景:从“AI分析”到“经理拍板”
假设员工张三提交了一笔 500 元的周末打车费报销。我们的目标是打造一个全自动的审批机器人:
- AI 自动初审:识别报销信息,生成一张带有“批准”和“驳回”按钮的交互式卡片,发送给部门经理。
- 经理交互决策:经理直接在聊天界面(如飞书、钉钉或 WebUI)点击按钮。
- 后台自动执行: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)” 。整个生命周期分为三个阶段:
- AI 编排与
**execute**触发
当你在对话框中输入“帮我审一下张三提交的 500 元打车费报销”时,OpenClaw 的主 Agent 会识别意图,提取参数,并实例化ExpenseApprovalSkill类,异步调用它的execute主方法。该方法运行完毕后,返回一段精心构造的 JSON(交互式卡片),你的聊天界面将其渲染成带按钮的漂亮卡片。 - 事件上报与精准路由
当经理在界面上点击“✅ 批准打款”按钮时,前端会立即向 OpenClaw 的后端网关发送一个 HTTP POST 请求,Payload 中包含了按钮上绑定的"action": "approve_expense"。OpenClaw 的网关收到请求后,会根据action的值去查找对应的 Skill。因为它发现了@Skill.on_action("approve_expense")这个装饰器,所以它会跳过**execute**,直接唤醒并执行**handle_approve**这个方法。 - 状态更新与闭环
handle_approve方法在后台静默执行了复杂的财务打款逻辑后,还可以通过ctx.update_card()反向控制前端,把原来的“待审批”卡片瞬间变成绿色的“已批准”状态。这不仅完成了业务闭环,还给了用户极佳的即时视觉反馈。
💡 总结与最佳实践
在一个 Skill 中编写多个方法,本质上就是把 AI 应用从简单的“单次问答”升级成了“有状态的交互应用”。
**execute**:是你的门面,负责接收 AI 的初始指令并展示界面。**@Skill.on_action(...)**** 或其他自定义方法**:是你的后台控制器,负责处理用户在界面上的具体点击、输入等交互行为。
掌握了这种模式,你就可以在 OpenClaw 中开发出像工单系统、电商下单、投票表决等极其复杂的自动化业务流,而不仅仅是做一个简单的聊天机器人。快去试试把你的第一个多方法 Skill 跑起来吧!
更多推荐



所有评论(0)