Skip to main content
Glama

AgentBus

一个用于 AI 智能体集群的持久化协调总线——在任何不可逆操作之前设有一道人工审批闸门。

智能体如今越来越多地被允许执行部署、发送、删除和支出等操作。到了这一步,有两件事会出问题,而它们都不是 LLM 的问题:

  1. 交接会丢失。 一个智能体完成工作,交给下一个,然后进程死亡。没有重试,也没有人注意到。

  2. 没有卡点。 审批只是提示词里的一句“先问我”——这是一个建议,而不是一种控制,并且不会记录是谁允许了什么。

AgentBus 就是底层那些朴实无华的基础设施:一个具有至少一次投递语义的持久化队列、一道阻塞式人工审批闸门,以及一个只追加的审计日志,记录每一条消息和每一项决定。

                    ┌──────────────────────────────┐
   agents  ────────▶│  topics · groups · leases    │────────▶  workers
   (MCP/HTTP/CLI)   │  retries · dead letters      │
                    ├──────────────────────────────┤
   agent  ─ ask ───▶│  approval gate  ── blocks ───│──▶ human (phone/dashboard)
                    ├──────────────────────────────┤
                    │  append-only audit log       │
                    └──────────────────────────────┘
                         one SQLite file

零运行时依赖。不需要 Redis、Postgres、消息代理,也不需要云账户。Node 24+ 加一个文件即可。


快速开始

npx agentbus serve                 # http://127.0.0.1:7801 — API + dashboard

将高风险操作置于人工审批之后

agentbus ask "Deploy api build 118 to production" \
  --action deploy.prod --risk high \
  --detail "3 commits, including a migration that drops a column." \
  --payload '{"service":"api","build":118}' \
  --wait && ./deploy.sh

ask --wait 会阻塞并打印一个链接。某人在手机上打开链接,批准或拒绝后,命令以 0 已批准 · 10 已拒绝 · 11 已过期 退出——因此 && 的行为完全正确,且该决定会记录在这位操作者的名下。

持久化工作交接

# Producer — survives a crash, deduplicated by key
agentbus pub job.render '{"file":"a.png"}' --key render-a

# Consumer — any shell command becomes a durable worker.
# Payload on stdin; exit 0 acks, non-zero retries with backoff, then dead-letters.
agentbus sub 'job.>' --group renderers --exec './render.sh'

未确认的工作会在租约到期时重新回到队列,因此一个在任务中途被终止的 worker 不会丢失任何东西。


Related MCP server: team-protocol

为智能体授予访问权限(MCP)

// .mcp.json  — or claude_desktop_config.json
{
  "mcpServers": {
    "agentbus": {
      "command": "npx",
      "args": ["-y", "agentbus", "mcp"],
      "env": { "AGENTBUS_URL": "http://127.0.0.1:7801", "AGENTBUS_AGENT": "deploy-agent" }
    }
  }
}

智能体将获得 request_approval、check_approval、publish、pull、ack、nack 和 stats 这几个工具。request_approval 会阻塞,直到人类做出决定,然后返回明确的指引:

{
  "state": "denied",
  "approved": false,
  "decidedBy": "sami",
  "reason": "not without a backup",
  "guidance": "Not approved (denied). Do NOT proceed. Tell the user and stop."
}

超时只会返回 pending,绝不会返回 approved——沉默永远不等于同意。


概念

主题使用点号分隔:deploy.prod.api。模式中,* 匹配一个片段,> 匹配其余部分——deploy.>、*.prod.api、>。

消费者组各自获得每条匹配消息的一份副本。在一个组内,一条消息在同一时间只会交给一个 worker。新组默认从 现在 开始;--earliest 会重放整个积压消息。

租约为 worker 提供一个可见性超时(默认 30 秒,可延长)。一旦错过,消息就会被重新投递。超过 max_attempts(5)次后,消息会进入死信队列,可在仪表盘上看到,并可一键重放。

审批包含标题、机器可读的操作、自由文本详情、结构化有效载荷、风险级别,以及可选的带标签选项(“canary 10%” 对比 “full rollout”)。它们会过期,而不是永远挂起。每个请求和决定——谁、何时、为什么——都会落入审计日志。

排序依据 SQLite 序列,而非时间戳:同一毫秒内发布的两条消息仍然具有明确顺序。


HTTP API

方法

路径

POST

/v1/publish

{topic, payload, idempotencyKey?, delayMs?}

POST

/v1/pull

{group, patterns?, max?, leaseMs?, waitMs?} — 长轮询

POST

/v1/ack · /v1/nack · /v1/extend

确认或延长一次投递

GET

/v1/stats · /v1/dead · /v1/audit

可观测性

POST

/v1/replay

将死信重新入队

POST

/v1/approvals

创建;返回带签名的可共享 URL

GET

/v1/approvals/:id/wait

长轮询直到作出决定

POST

/v1/approvals/:id/decide

{decision, by, reason?, choice?}

GET

/v1/stream

SSE 消息与审批流

GET

/ · /a/:id

仪表盘 · 单条审批页面

设置 AGENTBUS_TOKEN 后,将要求请求携带 Authorization: Bearer …。审批链接自带 HMAC 令牌,因此你可以将链接发送到手机,而无需交出 API 密钥。

环境变量: AGENTBUS_URL、AGENTBUS_TOKEN、AGENTBUS_DB、AGENTBUS_SECRET、AGENTBUS_AGENT、AGENTBUS_ALLOWED_ORIGINS。

浏览器来源策略

默认情况下,这是一个运行在回环地址上的未认证服务器,这意味着你碰巧打开的网页本来能够访问到它。三条规则阻止了这种情况,而且无论是否设置了令牌,这些规则都会生效:

  • 携带 Origin 头的请求会被拒绝,除非该来源是服务器自身、AGENTBUS_URL 中的主机,或已列入 AGENTBUS_ALLOWED_ORIGINS。被拒绝意味着 403——而不仅仅是缺少 CORS 头,后者只是隐藏响应,但仍然会执行写入。

  • POST 要求 content-type: application/json。表单和 text/plain 请求体属于 CORS 的“简单请求”,浏览器发送这类请求时根本不会预检,因此接受它们会重新打开这个漏洞。

  • 意外的 Host 头会被拒绝,从而阻止 DNS 重绑定。

非浏览器客户端——CLI、MCP 服务器、curl 和你自己的脚本——不会发送 Origin,因此不受影响。如果你在局域网地址上或代理后面提供仪表盘服务,以便审批能到达手机,请将 AGENTBUS_URL(或 --url)设置为该公共来源;反正审批链接就是根据它构建的。


开发

npm test          # 66 tests, no network, no fixtures
npm run typecheck # strict, noUncheckedIndexedAccess, erasableSyntaxOnly

TypeScript 通过原生类型剥离直接在 Node 24 上运行——没有构建步骤,运行时路径中也没有编译器。


许可证

MIT

Maintenance

ActivityStale
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers