从零实现 Harness Agent:飞书审批 Adapter 设计
系列导航:系列目录 | 上一篇:从零实现 Harness Agent:审批 Checkpoint 暂停与恢复 | 下一篇:从零实现 Harness Agent:审批流程测试与验证
本节目标
导读:本篇属于第四部分「外部集成与审批恢复」,说明 Feishu 在审批体系中是平台 adapter,而不是模型可见工具。
本节要实现的是 Feishu 审批 adapter:把审批通知和 /approve / /reject 命令接入通用审批流程,同时保持工具系统不依赖平台 SDK。
完成这一节后,你会理解为什么飞书是外部 adapter,而不是模型可见工具。
摘要
本文要说明 tiny-claw 如何把 Feishu 接入人工审批流程,同时保持工具系统和外部平台解耦。这个模块适合外部集成维护者、Agent 平台开发者和需要在聊天工具中审批高危操作的读者。读完后,你会理解 FeishuChannel.request_approval(...)、/approve、/reject 的职责边界,以及为什么飞书不应该注册成模型可见工具。
背景与问题
当高危工具调用需要人工审批时,一个直觉方案是“做一个飞书审批工具”。这个方案看似直接,但会把边界搞乱:
- 模型会看到平台审批工具,可能主动调用它。
- 工具系统会依赖 Feishu SDK。
- 将来接 Slack、Web UI 或 CLI 审批时,需要改工具链。
- 审批回复属于外部事件,不属于模型发起的 tool call。
更清晰的设计是:审批逻辑属于通用 HumanApprovalMiddleware,Feishu 只做两件事:
- 收到审批请求时,把消息发到对应聊天。
- 收到
/approve或/reject命令时,调用应用恢复接口。
也就是说,Feishu 是 adapter,不是 tool。
设计目标
- 平台解耦:审批 middleware 不依赖 Feishu。
- 不暴露给模型:Feishu 审批不是模型可见工具。
- 复用会话隔离:按 Feishu
chat_id恢复对应 session。 - 命令简单:v1 使用文本命令,不依赖互动卡片。
- 异步友好:Feishu 事件处理不阻塞主事件循环。
- 可测试:用 fake sender / fake sdk channel 验证消息和路由。
整体方案
Feishu 审批由两条路径组成:
1 | flowchart TD |
发送审批消息时,MainLoop 将当前 channel 放入 tool context metadata:
1 | context_metadata={ |
如果当前 channel 是 FeishuChannel,它就满足 ApprovalRequester 协议,可以发送审批消息。
收到审批命令时,Feishu event adapter 不进入普通 Application.run(),而是直接走 Application.resume_approval(...)。
核心实现
关键文件:
src/tiny_claw/_internal/integrations/feishu/bot.pysrc/tiny_claw/_internal/integrations/feishu/events.pysrc/tiny_claw/_internal/app.pysrc/tiny_claw/_internal/approval.pytests/test_feishu_integration.py
FeishuChannel 既是运行进度 channel,也是审批 requester:
1 |
|
审批消息包含:
approval_id- session 显示名
- workdir
- tool 名称
- 风险原因
- 过期时间
/approve和/reject命令示例
命令解析由正则完成:
1 | APPROVAL_COMMAND_PATTERN = re.compile( |
FeishuEventAdapter._on_message(...) 会先判断是否是审批命令:
1 | approval_command = parse_approval_command(text) |
不是审批命令时,才进入普通 Agent 运行:
1 | self.app.run( |
恢复结果会回复到原消息:
1 | channel._send("\n".join(lines), reply=True) |
使用方式
启动 Feishu 事件服务并启用审批:
1 | TINY_CLAW_APPROVAL_PROVIDER=feishu \ |
默认回调路径:
1 | POST /api/events/feishu |
自定义路径:
1 | uv run tiny-claw serve --feishu-path /api/events/feishu-test |
高危工具调用被拦截后,Feishu 会收到类似命令提示:
1 | 批准:/approve <approval-id> |
审批通过:
1 | /approve abc123 |
审批拒绝:
1 | /reject abc123 这个文件不应该由 Agent 修改 |
测试与验证
Feishu 审批 adapter 测试:
1 | uv run pytest tests/test_feishu_integration.py |
重点覆盖:
FeishuChannel.request_approval(...)会发送审批消息。parse_approval_command(...)能解析 approve / reject。- 审批命令会路由到
Application.resume_approval(...)。 - 普通消息仍然进入
Application.run(...)。
Server help 和 HTTP 冒烟:
1 | uv run tiny-claw serve --help |
完整验证:
1 | uv run ruff check . |
设计取舍与注意事项
飞书审批 v1 使用文本命令,不使用互动卡片按钮。文本命令更容易测试,也不需要额外处理按钮回调协议。互动卡片可以作为后续 adapter 增强,但不应该改变 HumanApprovalMiddleware 的接口。
TINY_CLAW_APPROVAL_PROVIDER=feishu 的语义不是“把飞书注册为工具”,而是启用通用审批 middleware,并让 Feishu channel 在对应入口中承担审批通知能力。如果从 CLI 运行并设置了 feishu,但没有 Feishu channel,审批请求仍会持久化;通知投递能力取决于当前运行入口是否提供了 requester。
审批命令按当前 Feishu chat 解析 session。跨 chat 使用 approval id 会被 Application.resume_approval(...) 拒绝,因为 approval 记录绑定了 session key。
当前没有实现审批人白名单、管理员权限校验和互动卡片签名确认。真实生产环境如果需要更强的组织级审批控制,应在 Feishu adapter 或应用恢复入口增加身份校验。
总结
- Feishu 是审批 adapter,不是模型可见工具。
- 审批消息发送通过
FeishuChannel.request_approval(...)完成。 /approve和/reject命令走Application.resume_approval(...)。- 普通 Feishu 文本消息仍复用
Application.run(...)。 - 平台能力被隔离在 integration 层,审批核心保持通用。
按审批专题继续阅读:21:审批流程测试与验证 会把这条跨模块链路变成可证明的行为。
来源:本文整理自
tiny-claw/docs/tutorial/20-飞书审批-adapter.md。
项目地址:barry166/tiny-claw。









