gbrain 下游 Agent 接入指南:MCP over HTTP 与本地 shell-job 双表面的正确选型与实战
【免费下载链接】gbrainGarry's Opinionated OpenClaw/Hermes Agent Brain项目地址: https://gitcode.com/gh_mirrors/gb/gbrain
导读
本文面向所有需要从自身运行时调用 gbrain 能力的外部下游 Agent(你的 OpenClaw 实例、任何下游 fork、Claude Code / Codex / opencode 等 harness),完整讲解 gbrain 对外暴露的两套截然不同的接入面:MCP ops over HTTP(thin-client + OAuth)与本地 shell-jobinherit:。读完本文,你将掌握如何按"操作类型"而非"个人偏好"选择接入面、如何用一条命令完成带 OAuth 的 harness 接入、如何安全地把sync/embed/extract/dream等仅限本地的操作提交给 Minions worker 执行,以及如何从危险的env:传密迁移到只落名字不落值的inherit:模式。
先读本文可以替你省掉一轮排错:gbrain 有两个互不替代的表面,选错表面是下游 Agent 集成最常见的失败原因。
双表面总览:按操作选型,不按偏好选型
┌─────────────────────────────────────────────┐ │ gbrain process │ │ │ Agent (OpenClaw, │ ┌──────────────────┐ ┌────────────────┐ │ or any fork) ───────┼──▶ MCP ops surface │ │ local-only │ │ │ │ (HTTP + OAuth) │ │ commands │ │ │ │ │ │ │ │ │ │ search, query, │ │ sync, embed, │ │ │ │ put_page, │ │ extract, │ │ │ │ get_page, │ │ dream, │ │ │ │ find_experts, │ │ enrich, ... │ │ │ │ ... │ │ │ │ │ └──────────────────┘ └────────────────┘ │ │ ▲ ▲ │ │ │ │ │ │ │ │ │ │ thin-client OAuth shell-job `inherit:`│ │ (preferred for (only path for │ │ MCP-equivalent ops) local-only work) │ └─────────────────────────────┴───────────────┘两套表面不可互换:MCP ops surface 面向所有在src/core/operations.ts中有对应 MCP 操作、且localOnly标志未置位的操作;local-only 命令则被两层机制(操作层过滤 + CLI 层拒绝)从远程表面隔离出去,唯一合法路径是作为 shell job 提交到宿主机上的 Minions worker。决策的唯一依据是操作本身属于哪个表面。
表面一:MCP ops over HTTP(thin-client + OAuth)
适用操作
任何有 MCP 等价操作的能力都走 HTTP 表面:search、query、put_page、get_page、find_experts、find_orphans、find_anomalies、get_recent_salience、find_trajectory等等。权威清单是src/core/operations.ts中localOnly标志未置位(或为false)的那组操作——文档里抄的任何列表都不如直接读源码可靠,且该清单会随着版本演进自动变化。
让宿主以 HTTP 服务形态常驻
宿主把 gbrain 作为长驻 HTTP 服务运行:
gbrain serve --http --port 3131注意:serve本身位于src/cli.ts的THIN_CLIENT_REFUSED_COMMANDS集合中(见下文表面二),它必须运行在大脑宿主机器上,由可信的运维操作启动。
打包路径:gbrain agent register
对下游 Agent 而言,首选入口是gbrain agent register——它必须在大脑宿主上运行(这是一个受信任的本地操作,永远不是一种委派机制)。单条命令完成三件事:铸造一个带作用域的 OAuth client、签发一个 30 天有效的访问令牌、打印出目标 harness 的现成接线配置块:
gbrain agent register aurora-coder \ --harness claude-code \ --preset coding-agent \ --federated-read proj-widget \ --url https://brain.example.com/mcp从 agent-register.ts 可以看到完整参数面:--harness目前支持claude-code | codex | opencode | openclaw四种(REGISTER_HARNESSES硬校验);--preset支持daily-driver | coding-agent;此外还有--source(按 source 限定读写范围)、--scopes、--token-ttl SECONDS、--surface verbs|starter|full、--allow-old-serve(对未强制作用域令牌的旧 serve 放行并自担风险)、--show-token与--json输出控制。--reissue <client-id>用于令牌轮换。
gbrain agent register出于安全设计会打印接线块(默认脱敏,除非--show-token),不写入任何 harness 配置;且只允许read/write这类 agent 级作用域,operator 级作用域会被显式拒绝(见 agent-register.ts)。
底层原语:gbrain auth register-client
如果你需要完全自定义的流程——PKCE / authorization-code 客户端、绑定submit_agent的客户端、带 slug 前缀的写入围栏(write fence)、以及需要解析输出做自动化供给的脚本——则使用原始原语。它是一次性操作,只打印client_id+client_secret,不代办令牌交换与 harness 接线:
gbrain auth register-client aurora-coder \ --grant-types client_credentials \ --scopes "read write" # Prints client_id + client_secret one-time. Store securely.Thin-client 模式:gbrain init --mcp-only
thin-client 安装(gbrain init --mcp-only)把上述 client-credentials 接线一次性配好:gbrainCLI 本身会把所有 MCP 可路由的命令透过已配置的远程 MCP 转发,Agent 可以直接调用gbrain search/gbrain query,OAuth 握手由 CLI 自动完成。
认证与审计面
Agent 运行时以client_credentials授权类型换取 bearer token,调用/mcp端点。密钥始终留在gbrain serve进程内,Agent 永远看不到DATABASE_URL或任何 API key。在 http-transport.ts 中可以看到,token 以 SHA-256 哈希形式存储于access_tokens表(auth.ts负责创建/列出/吊销),每次请求都会写入一行mcp_request_log(含 token 名 + 操作 + 状态 + 延迟),构成统一审计面。
接入路径决策表(onboarding paths)
这是接入路径的权威决策表,其他文档都引用此表、无人复制:
| Path | When to use | Credential kind | Print vs write | Serve location |
|---|---|---|---|---|
gbrain agent register <name> --harness <h> | The packaged path: onboarding an agent harness (Claude Code, Codex, opencode, your OpenClaw) onto a shared brain. Presets (daily-driver,coding-agent), starter tool surface, 30-day token TTL,--reissuesecret rotation. | Scoped OAuth client + a minted access token (source-scoped, expiring) | PRINTS the harness block (redacted unless--show-token); writes nothing to harness configs | Runs ON the brain host against a remote-reachablegbrain serve --http;--urlor--portrequired (a live PGLite serve blocks it by design — stop the serve first; a serve too old to enforce scoped tokens is refused — upgrade it, or pass--allow-old-serveto accept the risk) |
gbrain connect <mcp-url> --token <t> | You already hold a bearer token and want ONE coding agent pointed at a running serve, from any machine. | Legacy bearer token (full-access unless minted with--scopes);--oauthvariant for OAuth-capable connectors./mcpverifies both kinds; a client status flag ofneedsAuthfrom an unauthenticated probe is not a bearer failure — see DEPLOY.md — Dual-mode auth | Prints the add command by default;--installruns it | Any machine; targets a remotegbrain serve --http |
gbrain bootstrap harness | Framework-spawned harnesses (claude -p/codex exec/opencode run) on the SAME box that hosts the brain; wires MCP registration + lifecycle hooks with receipts and mint-first token rotation. | Legacy bearer token, minted per run and rotated by receipt | WRITES managed config blocks (Claude Code user scope, codex TOML, opencode JSONC) + hooks | Local loopback serve on the same box (non-loopback URL requires an explicit supplied token) |
gbrain auth register-client <name> | The raw primitive: custom flows — PKCE/authorization-code clients, boundsubmit_agentclients, slug-prefix write fences, provisioning scripts that parse output. | Scoped OAuth client only (no token exchange, no TTL default beyond the server's) | Printsclient_id+client_secretone time; you do all wiring | Credential is server-side state; run on the brain host |
关于needsAuth的常见误判:/mcp是双模式认证(OAuth 2.1 access token 优先,随后回退到access_tokens表校验 legacy bearer),未携带Authorization头的心跳探测会返回 401 + RFC 9728resource_metadata挑战,客户端因此显示needsAuth,但这不代表你配置的 token 失效。判断认证是否成功应以whoami(transport: legacy|oauth)或gbrain auth test <url> --token <t>为准,详见 DEPLOY.md — Dual-mode auth。
为什么 MCP ops 首选此表面
- 密钥永不离开服务进程:Agent 只持有令牌,拿不到
DATABASE_URL或供应商 API key。 - OAuth 作用域天然隔离:
read、write、admin三层分离,Agent 只拿到它所需的最小权限。 - source-scoped 令牌:
register-client --source dept-x可把 Agent 限制在联邦大脑中的特定 source 内。 - 统一审计面:每一次操作调用都均匀地落在
mcp_request_log上,不存在旁路调用。
表面二:仅限本地的操作——shell-jobinherit:模式
两层机制把本地工作挡在远程表面之外
操作层(Op layer):src/core/operations.ts中标记localOnly: true的操作会直接从 HTTP MCP 表面被整体过滤掉——远程调用者根本看不到它们。实现见 serve-http.ts 的const mcpOperationsBase = operations.filter(op => !op.localOnly);。从源码看,connectors、entity_identity、embedding-migration、files、chronicle、sync-status、transcripts、pages(部分写操作)、extraction、code-intel等操作族中都存在 localOnly 成员。
CLI 层(CLI layer):在 thin-client 安装上(已配置远程 MCP、无本地引擎),需要本地引擎或本地文件系统的命令会在分发时被拒绝,并附带一条指名最近替代方案的精确提示。权威集合是 src/cli.ts 中的THIN_CLIENT_REFUSED_COMMANDS——请直接读源码,而不是信任任何抄进文档的列表。它覆盖sync、embed、extract、extract-conversation-facts、enrich、migrate、retrieval-upgrade、apply-migrations、repair-jsonb、orphans、integrity、serve、call、watch、dream、transcripts、storage、takes、sources、pages、files、eval、code-def、code-refs、code-callers、code-callees、config、sweep、compile-context等数十个命令。
每条拒绝都带具体提示(THIN_CLIENT_REFUSE_HINTS,见 src/cli.ts):例如sync会提示"在宿主机上运行gbrain sync或使用sync_brainMCP 操作",dream会提示"在宿主机运行gbrain dream"。refuseThinClient(src/cli.ts)在收到命中命令且当前是 thin-client 时,先尝试routeThinClientCommand做子命令级 MCP 路由,剩余不可路由部分才拒绝并以退出码 1 结束。
两个值得注意的非成员:doctor在 thin-client 上不被拒绝——它会改道到出站 HTTP 探针集合(src/core/doctor-remote.ts);bootstrap和hook无引擎依赖,任何安装形态都可运行(THIN_CLIENT_REFUSED_COMMANDS的注释明确要求这两个命令"永远不得出现")。
本地操作的唯一路径:作为 shell job 提交
被拒绝的命令无法经由 HTTP MCP 路由。正确路径是把gbrain作为 CLI 子进程执行,且推荐将子进程作为shell job 提交给 gbrain Minions worker,从而免费获得重试 / 退避 / DLQ / 审计轨迹:
gbrain jobs submit shell --params '{ "cmd": "gbrain sync --skip-failed && gbrain embed --stale", "cwd": "/data/gbrain", "inherit": ["database_url"] }'inherit:的底层原理
inherit: ["database_url"]告诉 worker 从它自己的loadConfig()(文件平面 + 环境变量合并)中查找database_url,把值以GBRAIN_DATABASE_URL注入子进程环境。minion_jobs.data的 DB 行里只存名字——inherit: ["database_url"]——永远不存值。完整校验规则与错误目录见 minions-shell-jobs.md#secrets。
实现细节在 shell-inherit.ts:
- 名字格式被正则钉死为
INHERIT_NAME_RE = /^[a-z][a-z0-9_]*$/,用于防原型污染形态(__proto__、constructor)和审计日志中的路径穿越形态; - 环境变量名派生规则
deriveEnvKey(name):默认name.toUpperCase()(anthropic_api_key→ANTHROPIC_API_KEY、voyage_api_key→VOYAGE_API_KEY),唯一例外是database_url→GBRAIN_DATABASE_URL(因为裸DATABASE_URL在 Postgres 应用语境中过于歧义); - 值解析
resolveInheritValue使用Object.hasOwn防御原型污染查询,仅接受非空字符串; - 快速失败:若 worker 上解析不到所请求的名字,校验器在入队前即拒绝,并给出可直接粘贴的
gbrain config set database_url <value>提示(该命令走文件平面,写入~/.gbrain/config.json,正是 worker 的loadConfig()读取的位置,即使 DB 不可达也能生效)。
inherit:是自由形态的:任何 snake_case 配置键都可以继承——database_url、anthropic_api_key、openai_api_key、openrouter_api_key、voyage_api_key、groq_api_key、zeroentropy_api_key,乃至你塞进~/.gbrain/config.json的任何自定义字段。Agent 按需挑选。
为什么胜过把密钥写进每任务的env:
// Rejected at submit: the URL would persist in minion_jobs.data plaintext. { "cmd": "gbrain sync --skip-failed", "cwd": "/data/gbrain", "env": { "GBRAIN_DATABASE_URL": "postgresql://..." } }每任务传env: { GBRAIN_DATABASE_URL: "postgresql://..." }会把 URL 以明文落入minion_jobs.data和 shell-audit JSONL——任何拥有大脑 DB 读权限的人(或一份大脑 dump,或通过 mounts 共享的大脑)都能看到。入队前校验会拒绝这种形态,错误消息直接指名inherit: ["database_url"]作为替代方案。
补充两条来自 minions-shell-jobs.md 的安全细节:
- shell 子进程环境是极简的:只有
PATH, HOME, USER, LANG, TZ, NODE_ENV。OPENAI_API_KEY这类密钥不会自动传给孩子,需要按任务显式env:(仅非密钥值)或inherit:放行——这能阻止用户脚本里意外的$OPENAI_API_KEY插值;但它不沙箱化文件系统读取(shell 脚本可以cat ~/.env),操作者选一个安全的cwd即是信任边界。 - 输出侧泄漏:
inherit:只保证值不进任务行输入字段,不保证脚本不把它打印出来(echo "$GBRAIN_DATABASE_URL")。如果脚本打印了密钥,明文会落入result.stdout_tail/result.stderr_tail。按任务设置"redact_secrets": true(或 CLI 加--redact-secrets)可启用输出侧脱敏,把inherit:解析出的每个值在持久化前以<REDACTED:name>替换;注意这是字面字符串替换,对 base64 编码、逐字符输出等对抗性形态无效——它防的是意外 echo,而非蓄意外泄。 - 审计是轨迹而非法证保障:每次提交写一行到
~/.gbrain/audit/shell-jobs-YYYY-Www.jsonl(ISO 周轮转,GBRAIN_AUDIT_DIR可覆盖),但写入失败只记 stderr、不阻塞提交。
Worker 一次性设置(每台宿主一次)
Agent 所在宿主需要一个能处理 shell job 的 worker:
# One-shot inline execution (PGLite or Postgres): gbrain jobs submit shell --params '{...}' --follow # Persistent worker (Postgres only — PGLite uses --follow inline): gbrain jobs work --allow-shell-jobs # or: GBRAIN_ALLOW_SHELL_JOBS=1 gbrain jobs work关键约束:
- PGLite 不跑常驻 worker(独占文件锁),每个 crontab 触发都必须用
--follow内联执行;Postgres 用户可跑常驻 worker,--max-attempts指定重试次数(指数退避),--timeout-ms指定超时。 --allow-shell-jobs(等价于在 worker 上导出GBRAIN_ALLOW_SHELL_JOBS=1;worker 目录里的.env不能设置它)是 worker 侧的一次性 opt-in。shell handler 总是注册但受守卫:未带旗标的 worker 一旦认领到 shell job 会立即死信(UnrecoverableError,不重试)——一个长期停留在waiting的 shell job 说明根本没有 worker 在跑。请把旗标放在 worker 的命令行(或部署单元 / launchd plist 的环境变量里),而不要放在每次提交里——提交方环境是 worker 环境的弱代理。- MCP 边界双保险:
submit_job携带name: 'shell'时,ctx.remote === true(MCP 调用者)会被拒绝,与 env 旗标相互独立——远程 Agent 永远无法提交 shell job;MinionQueue.add('shell', ...)自身也有守卫,进程内 handler 无法编程绕过。
操作决策表
| Operation | Surface | Why |
|---|---|---|
search/query | HTTP MCP via thin-client | Has MCP op; OAuth-scoped. |
get_page/list_pages | HTTP MCP | Same. |
put_page | HTTP MCP | Same; respects subagent allow-list when applicable. |
find_experts/find_orphans | HTTP MCP | Same. |
sync/embed/extract | Shell job +inherit: | Thin-client refused; needs local engine + FS. |
dream | Shell job +inherit: | Thin-client refused; synthesis runs on the host. |
doctor | Run directly (any install) | Not refused: thin clients get the remote probe set. |
autopilot | Run as a daemon directly on the host | Long-lived, not job-shaped. |
init/config | One-time host setup | Operator action, not agent action. |
推荐模式总结
- 想要不落进任务行的密钥,就用
inherit:。名字落进minion_jobs.data,值在子进程生成时从 worker 配置解析。若大脑 DB 未来穿越任何信任边界,密钥不随行。 env:仍然可用于非密钥值,或你希望值出现在行里的场景(例如审计流程稍后要读回的 opaque 关联令牌)。校验器不会替你做主。- 绝不尝试把被拒命令路由穿 thin-client。CLI 在分发时就会带提示拒绝。宿主机上用 shell-job +
inherit:(密钥)或env:(非密钥)代替。 - 推式上下文:除请求/响应式操作外,MCP 客户端还可以通过
volunteer_context操作接收大脑主动投递的上下文——详见 push-context.md。该通道共享一个零 LLM 核心(src/core/context/volunteer.ts),并带min_confidence(默认 0.7)置信度门控与 3 页默认上限(硬上限 5),确保推送噪声永远不会比拉取静默更糟。
迁移:从env:传密改为inherit:
如果你的 Agent 正在用env:向 shell job 传密钥,按下面两步迁移。
迁移前(提交时会被拒,URL 会以明文常驻minion_jobs.data):
// Rejected at submit: the URL would persist in minion_jobs.data plaintext. { "cmd": "gbrain sync --skip-failed", "cwd": "/data/gbrain", "env": { "GBRAIN_DATABASE_URL": "postgresql://..." } }迁移后(推荐形态,名字进行、值在子进程生成时从 worker 配置解析):
// Name in row, value resolved at child-spawn from worker config. { "cmd": "gbrain sync --skip-failed", "cwd": "/data/gbrain", "inherit": ["database_url"] }前置条件:worker 宿主必须已配置database_url——要么通过gbrain config set database_url <value>(文件平面路由,落入~/.gbrain/config.json,正是 worker 的loadConfig()读取的位置,DB 不可达时也可用),要么在 worker 进程上导出GBRAIN_DATABASE_URL/DATABASE_URL环境变量。若 worker 无法解析该键,校验器会在提交时拒绝任务,并给出可直接粘贴的修复提示。
进阶形态:如需输出侧脱敏,在参数中加入"redact_secrets": true(或 CLI 加--redact-secrets);对于程序化调用方,可用argv数组替代cmd字符串(不经 shell、无注入面),例如{"argv":["node","scripts/fetch.mjs","--date","2026-04-19"],"cwd":"/data"}。失败后务必用gbrain jobs get <id>检查实际持久化内容。
延伸阅读
- minions-shell-jobs.md:shell job 的完整校验规则、
--follow内联执行与 Postgres 常驻 worker 的 crontab 迁移示例、redact_secrets输出侧脱敏细节 - push-context.md:
volunteer_context推式上下文通道的触发时机与置信度门控 - DEPLOY.md:
/mcp双模式认证(OAuth 2.1 + legacy bearer)、.well-known资源元数据发现、Tailnet / LAN-only 暴露形态 - 源码级权威依据:操作清单与
localOnly标志见 src/core/operations.ts,thin-client 拒绝集合与提示见 src/cli.ts,HTTP 表面过滤见 src/commands/serve-http.ts,inherit:机制见 src/core/minions/handlers/shell-inherit.ts,审计写入见 src/core/minions/handlers/shell-audit.ts,agent register参数解析见 src/commands/agent-register.ts
【免费下载链接】gbrainGarry's Opinionated OpenClaw/Hermes Agent Brain项目地址: https://gitcode.com/gh_mirrors/gb/gbrain
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考