为什么自托管?
不是每家公司都能把数据丢到别人的服务器上跑。有的是合规卡着,有的是安全评审不让过,有的就是 GC 不点头。理由不重要,重要的是你的 agent 之间还是得用开放的 A2A 标准互相通信。
所以我们做了一个单文件的 A2A provider,完完全全跑在你自己的机器上。不用注册平台账号,不走 WebSocket bridge,链路上没有任何外部服务。就一个 HTTP server,加你本地的 CLI agent。
60 秒跑起来
克隆示例,启动:
cd ah-cli/examples/self-hosted-a2a
npm install && npm start
完事。你现在有了一个标准 A2A 端点 http://127.0.0.1:8080/a2a,Agent Card 在 /.well-known/agent.json。
首次启动时,server 会生成一个随机 API token 打印到终端。之后所有发往 /a2a 的请求都要带上它作为 Bearer header。
盒子里有什么
server 实现了完整的 A2A 1.0 JSON-RPC 接口:
tasks/send:发消息,等完整响应。tasks/sendSubscribe:SSE 流式,agent 产一块就推一块。tasks/get:查任务状态,跑着还是跑完了。tasks/cancel:杀掉正在跑的任务。
每次请求都会 spawn 一个本地 CLI 进程。默认是 Claude Code,你想换成别的也行。agent 就在你指定的项目目录里跑,本地权限是完整的。
安全模型
这东西是给内网用的,不是给公网。但"内网"不代表可以不设防。
认证用 Bearer token,每个 /a2a 请求都得带,而且是常量时间比较,防时序攻击。server 默认只绑 127.0.0.1,你想开到内网再自己改 HOST=0.0.0.0。限流是滑动窗口,每分钟 30 个请求封顶。请求超过 5 分钟直接超时,失控的 agent 进程自动被 kill。超过 1 MB 的 body 在解析前就拒了。每条请求都以结构化 JSON 输出到 stderr,直接接你公司现有的日志系统就行。
换后端
默认后端是 Claude Code。任何能从参数读输入、往 stdout 写输出的东西都能用:
AGENT_CMD="codex" npm start
AGENT_CMD="node my-bot.js" npm start
AGENT_CMD="python agent.py" npm start
用户消息作为 CLI 参数传进去,stdout 流式返回。
开放给团队
要开放给内网的同事用:
HOST=0.0.0.0 API_TOKEN=team-secret npm start
长期跑就包一层 systemd 或者 Docker。server 是无状态的,不连数据库、不写磁盘,横向扩容不用想太多。
整体长这样
每一跳都在你自己的网络里:
内部调用方 → HTTP server → CLI 进程 → 响应
没有数据发给 Agents Hot,没有出站 WebSocket,没有遥测。Agent Card 端点是公开的(别的 A2A agent 做 discovery 要用),但上面只有 agent 的名字和能力描述,没有任何敏感信息。
全部源码:一个 TypeScript 文件,不到 400 行。读一遍,审一遍,随便改。这就是重点。
