从零实现 Harness Agent:飞书事件服务接入
系列导航:系列目录 | 上一篇:从零实现 Harness Agent:可恢复 Plan Mode 设计 | 下一篇:从零实现 Harness Agent:上下文压缩器设计
本节目标
导读:本篇进入第四部分「外部集成与审批恢复」,先说明 Feishu 只是入口适配层,不能变成第二套 Agent runtime。
本节要实现的是统一 HTTP 事件服务中的 Feishu 回调入口:让 Feishu 消息可以进入同一套 Application.run() 和 MainLoop,而不是为外部平台复制一套 Agent runtime。
完成这一节后,系统会具备下面这些能力:
tiny-claw serve可以启动 HTTP 服务。- 服务提供
GET /health和POST /api/events/feishu。 - Feishu 文本消息会按
chat_id解析成独立 session。 - Feishu 运行过程通过
FeishuChannel发送开始、处理中、工具调用和最终回复。 - 外部平台默认使用 integration app,并在 OpenAI 配置缺失时给出明确提示。
这一节的关键目标是让 Feishu 成为“入口适配层”,而不是第二套 Agent 实现。
摘要
外部平台接入最容易犯的错,是把平台 adapter 写成另一套 Agent。tiny-claw serve 提供统一 HTTP 事件服务,当前支持健康检查和 Feishu 事件回调。本文介绍 Feishu webhook 如何被转换成 session-scoped Agent 请求,并通过 Channel 把运行进度和最终回复发送回外部平台。
背景与问题
一个 Agent CLI 一旦能在终端运行,下一步常见需求就是接入外部平台,例如 Feishu、Slack 或 Web UI。最容易走偏的实现是为每个平台写一套独立 Agent 逻辑。
这样会带来几个问题:
- CLI 和 Feishu 行为不一致。
- 外部平台绕过 session、memory、tools 和 provider 配置。
- 平台消息发送逻辑和 Agent 主循环耦合。
- 缺少 provider 配置时,服务启动和事件处理边界不清。
tiny-claw 的设计是:外部平台只做 adapter 和 channel,真正的运行仍然复用 Application.run()。
设计目标
- 统一入口:HTTP server 提供外部事件接入点。
- 复用运行时:Feishu 不实现自己的 Agent loop。
- 会话隔离:Feishu 按
chat_id映射 session。 - 进度可见:通过
Channel输出开始、思考、工具调用、完成等事件。 - 配置兜底:缺 OpenAI key 时 server 可启动,消息进来时回复明确错误。
- 可扩展:未来 Slack 等平台复用 integration app 思路。
整体方案
HTTP 服务由 server.py 创建,Feishu 相关逻辑由 FeishuEventAdapter 和 FeishuChannel 处理。
1 | sequenceDiagram |
核心实现
关键文件:
src/tiny_claw/_internal/server.pysrc/tiny_claw/_internal/integrations/feishu/events.pysrc/tiny_claw/_internal/integrations/feishu/bot.pysrc/tiny_claw/_internal/engine/channel.pytests/test_feishu_integration.py
HTTP 路由:
1 | web_app.router.add_get("/health", _health) |
Feishu 配置存在时创建 adapter:
1 | if _is_feishu_configured(app.settings): |
外部平台运行时默认使用 OpenAI:
1 | def build_integration_application(settings: Settings) -> Application: |
Feishu 消息进入后按 chat id 解析 session:
1 | session = self.app.session_manager.resolve_feishu_chat(message.chat_id) |
然后复用 Application.run():
1 | self.app.run( |
如果 integration app 未配置,adapter 不进入 MainLoop,而是直接回复配置错误。
使用方式
启动 HTTP 服务:
1 | uv run tiny-claw serve --host 0.0.0.0 --port 8000 |
健康检查:
1 | curl http://127.0.0.1:8000/health |
默认接口:
1 | GET /health |
Feishu 配置示例:
1 | FEISHU_APP_ID=cli_xxx \ |
如果 Feishu 后台没有配置 Encrypt Key 或 Verification Token,可以省略对应环境变量。
自定义回调路径:
1 | uv run tiny-claw serve --feishu-path /api/events/feishu-test |
本地调试时,Feishu 需要公网 HTTPS URL,可用隧道工具把本地端口暴露出去。
测试与验证
Feishu 集成测试:
1 | uv run pytest tests/test_feishu_integration.py |
CLI server help:
1 | uv run tiny-claw serve --help |
HTTP smoke test:
1 | uv run tiny-claw serve --host 127.0.0.1 --port 8000 |
完整验证:
1 | uv run ruff check . |
设计取舍与注意事项
Feishu adapter 不拼 prompt、不执行工具、不直接调用 provider。它只做平台协议转换:提取文本、解析 chat session、创建 channel,然后把请求交给 Application.run()。这样 CLI 和 Feishu 才能共享同一套 Agent runtime。
Feishu 使用 chat_id 隔离上下文,而不是 message_id。一条消息只是对话中的一个事件,chat 才是长期上下文边界。缺 OpenAI key 时,server 仍可启动,这是为了让 HTTP 服务和平台配置可以先验证;真正的运行时错误会在消息进入时回复给用户。
Channel 只发送简短进度,不把完整内部日志刷到聊天窗口。外部平台是用户交互面,不是调试控制台。当前只实现 Feishu,Slack 等平台属于后续扩展,不能把 integration app 的预留能力写成已完成平台。
总结
- 外部平台入口应该复用
Application和MainLoop,而不是复制 Agent 逻辑。 - Feishu adapter 负责协议转换,FeishuChannel 负责消息发送。
- Integration app 让外部平台默认使用真实 Provider。
- HTTP 服务提供了未来接入更多事件平台的统一位置。
按编号继续阅读:11:上下文压缩器 会回到上下文工程;按外部集成专题继续,可以跳到 19:审批 checkpoint 暂停恢复。
来源:本文整理自
tiny-claw/docs/tutorial/10-飞书事件服务.md。
项目地址:barry166/tiny-claw。









