close

Volume 2 · Chapter 32

SDK 与 API 服务:进程边界的另一边

到目前为止全部能力都在进程内。这一章看进程边界:JSON-RPC SDK(程序化驱动 harness)、ACP 服务(Agent Client Protocol 自动化协议)、api/remotes 与 apiproxy(Web 的 BFF 层)、MCP 客户端(把外部 MCP 服务器变成 dsh 工具)。

(卷一连接点) 05 页 ctx.agents(一切接口的根)· 06 页 session/event(推送流) 本域:sdk / acp / api-remotes / apiproxy / mcp-client / hooks (回心脏) 外部调用经 AgentRegistry 的 create/resume 进入 05 页循环

示例本次示例:一个程序驱动 dsh

示例轨迹 32-1 · Python SDK 的一次完整调用
# 仓库真实示例:examples/jsonrpc-agent(README 说「Python SDK 驱动的无人值守代理」)
# Python 侧(python/sdk/src/deepseek_harness/client.py):
#   client = Client("http://127.0.0.1:3080")   ← JSON-RPC over HTTP
#   session = client.new_session()
#   session.prompt("修复这个测试")
# dsh 侧:sdk server(inject=['agents'],sdk/server/src/index.ts:22)
#   → AgentRegistry.create(05 页)→ 跑 05-14 页循环
#   → 事件流回 Python 客户端(session/event → JSON-RPC 通知)
# 协议只做翻译,循环完全复用——这就是 32 页「入口极薄」的意思
来源:32 页 §3 + examples/jsonrpc-agent + python/sdk
示例轨迹 32-2 · MCP 服务器变成 dsh 工具
# 外部 MCP 服务器(如记忆服务)→ examples/mcp-memory overlay
# mcp-client(inject=['tools'])连接服务器 → 枚举其工具
# → 每个 MCP 工具注册进 14 页 registry
# → 12 页 assemble 时它们与原生工具并列进模型提示词
# 模型调用与原生工具无差别——工具通道的「本地化」
来源:32 页 §3 + examples/mcp-memory

§1挂载条目

  • typert* / api-gateway(03 页的 typert 家族)——类型图生成 + RPC 网关
  • 可选挂载:acp(inject = ['agents'],src/index.ts:45)、sdk server(inject = ['agents'],src/index.ts:22)、mcp-client(inject = ['tools'],src/index.ts:31)、apiproxy(ApiProxyService extends Service,src/index.ts:69)

§2包文件地图

规模角色
packages/sdk/JSON-RPC 协议 + server(inject = ['agents'])+ TypeScript client(6 文件 / 952 行)
packages/acp/acp/ACP 自动化协议服务器(inject = ['agents'])——Agent Client Protocol(Zed 等编辑器生态)
packages/host/apiproxy/5 文件 / 4463 行Web BFF:ApiProxyService extends Service implements ApiProxy(src/index.ts:69)——浏览器 UI 与宿主之间的 HTTP 代理层
packages/api/remotes/5 文件 / 327 行远程 BFF 组装(agent-lookup / remote-events)
packages/mcp/mcp-client/5 文件 / 1171 行MCP 客户端:把外部 MCP 服务器暴露为 dsh 工具(inject = ['tools']
packages/hooks/Claude Code/Codex hook 桥 + 线协议库(hook-protocol 9 文件 / 854 行)

§3机制:三条对外通道

  1. 机器通道(SDK / ACP):外部程序经 JSON-RPC(SDK)或 ACP 协议驱动 agents——inject = ['agents'] 说明它们站在 05 页的注册表上。SDK 是 dsh 自己的协议,ACP 是行业协议。
  2. 浏览器通道(apiproxy / remotes):Web UI(33 页)与宿主之间的 BFF——HTTP 请求 → 宿主内部调用 → 事件流回推。apiproxy 4463 行是宿主侧最大的服务之一。
  3. 工具通道(mcp-client):把外部 MCP 服务器的工具映射进 14 页 registry——模型看到它们与原生工具无差别。方向相反:dsh 是客户端,外部是服务器。

§4关键代码

packages/acp/acp/src/index.tsACP 服务器45
45export const inject = ['agents']
packages/mcp/mcp-client/src/index.tsMCP 客户端31
31export const inject = ['tools']
packages/host/apiproxy/src/index.tsWeb BFF69
69export class ApiProxyService extends Service implements ApiProxy {
45

ACP 与 SDK server 都只依赖 agents——外部协议的入口极薄:协议翻译 + 注册表调用(create/resume),循环完全复用。

31

mcp-client 只依赖 tools——它不碰 agents,只往 14 页的 registry 里加工具。MCP 服务器的能力经它「本地化」。

69

apiproxy 是 Web 的宿主侧根——它 implement ApiProxy 契约(浏览器侧的类型生成自同一契约,typert 的产物)。

§5易错点

进程边界的校验义务(AGENTS.md 的边界清单):wire 输入必须验证——ACP/SDK 的参数是外部 JSON,进 05 页之前要过 parser(不能假设类型)。这是 06 页「信任静态类型只在同进程边界」约定的另一半。

hooks 桥的意义:Claude Code/Codex 的 hook 协议让外部工具链在 dsh 的事件点上插桩——它是「互操作」域,不是核心循环的一部分。