Skip to content

构建外部 Agent 客户端 ​

外部客户端需要循环,而不是提示词技巧。它要取得有效会话、发现当前能力面、选择允许的操作、用新请求 id 调用,并解释协议结果与业务结果。模型可以提出决定,但客户端负责协议交换与人工审批边界。

最小状态机 ​

text
验证身份 → describe → 决定 → invoke → 检查结果
                    ↑                  │
                    └── 新页面 / 重试 ──┘

不要在导航、大范围筛选变化或会话范围变化后沿用旧描述。也不要把 HTTP 成功等同于业务成功。

客户端骨架 ​

ts
const surface = createSurfaceClient({ transport });

let description = await surface.describe({ limit: 8 });

const capability = chooseCapability(description, args);
if (!capability) throw new Error("没有匹配的已暴露能力");

const requestId = crypto.randomUUID();
const response = await surface.invoke(capability.id, inputFor(capability, args), { requestId });

if (!response.ok) {
  // 协议 / 会话 / 限流失败:不能宣称业务操作已执行。
  return reportProtocolFailure(response.error);
}

if (response.result && "error" in response.result) {
  // 业务失败:先看稳定错误码,再决定是否重新描述。
  return reportBusinessFailure(response.result.error);
}

// 有 response.after 时使用它;否则下一次决策前重新 describe。

具体客户端 API 由传输决定。关键是请求包络,以及把 ok: false 与 result.error 分开。

身份验证 ​

客户端不能接受模型参数中的身份。身份在协议循环之前完成:同页桥使用浏览器会话;网关使用委托 Agent token。Token 应限制能力、可过期、可撤销,不能出现在模型上下文、日志或页面投影中。

若需要真人审批,客户端可以收到 pending_approval 或页面宿主提供的 review URL;宿主提供状态工具时可以轮询结果。它不能获得批准函数。审批由页面呈现,并恢复同一请求。

工具说明 ​

MCP facade 把 describe 能力映射成工具,必须保留:

  • 稳定 id 与说明;
  • 输入 schema;
  • 风险与审批元数据;
  • 记录目标约定;
  • 有界记录窗口。

不要为了方便 facade 暴露通用 click 或 eval。不要从 UI 文案合成能力。页面没有声明的操作,不属于外部能力面。

处理失败 ​

失败客户端行为
ACTION_NOT_FOUND重新 describe;页面可能已变化
ACTION_UNAVAILABLE报告原因;前置条件改变前不要重试
INVALID_PARAMS按 schema 修正参数
EXPECTATION_FAILED重新观察页面再决定
PERMISSION_DENIED停止;请求真人处理,而不是 Agent 处理
SESSION_EXPIRED / SESSION_REVOKED重新登录或申请新委托
RATE_LIMITED遵守 retryAfterMs,不要空转
REPLAY_DETECTED只有逻辑上新请求才使用新 id;否则先检查前次结果

测试客户端 ​

先在确定性页面上测试:成功读取、带 schema 的写入、不可用动作、确认拒绝、会话过期和重复请求 id。再用真实浏览器会话与真人审批测试危险动作。

记录请求 id、协议版本、能力 id、结果和耗时,不记录完整页面投影或 token。一个无法解释自己调用了哪项能力、为什么调用的客户端,还不适合自主工作流。

参见 Surface 基础与 通过 MCP 接入外部 Agent。