通过 JSON-RPC 代理的方式调试 ACP 集成问题,分享调试技巧和解决方案。
Agent Communication Protocol (ACP) 是 AI 编码 agent 与宿主系统通信的标准。但当 agent 声称支持某个功能却未正确实现时会发生什么?这是一个真实的调试故事。
问题
我们正在将一个编码 agent 集成到 ACP 兼容的运行时中。ACP 握手流程是:
- 启动 agent 进程
- 发送
initialize请求 - 发送
session/load携带现有会话 ID
agent 在 initialize 响应中报告 agentCapabilities.loadSession: true,所以我们期望 session/load 能工作。但它返回了:
{
"error": {
"code": -32601,
"message": "Session not found"
}
}
根本原因
agent 只接受它自己创建的会话 ID。当 ACP 发送外部生成的会话 ID(来自其自己的记录跟踪),agent 不知道如何处理。能力标志具有误导性——它意味着”我支持会话管理”而不是”我接受任意会话 ID”。
解决方案:JSON-RPC 代理
由于无法修改 agent 的代码,我们构建了一个轻量级代理来拦截和转换 JSON-RPC 消息。代理的核心逻辑:
// 拦截 stdin/stdout JSON-RPC
function transform(msg) {
if (msg.method === "session/load") {
const acpxId = msg.params ? msg.params.sessionId : null;
const mapFile = join(MAP_DIR, acpxId + ".json");
if (existsSync(mapFile)) {
// 已有映射,使用真实 session ID
const mapping = JSON.parse(readFileSync(mapFile, "utf8"));
msg.params.sessionId = mapping.realSessionId;
return msg;
}
// 首次加载 — 转换为 session/new
msg.method = "session/new";
msg._acpxSessionId = acpxId;
return msg;
}
return msg;
}
关键经验
- 能力标志不保证兼容性 — 始终测试实际行为,而不仅仅是 agent 声称支持的内容。
- 代理模式很强大 — 当无法修改源代码时,薄代理层可以桥接不兼容的接口。
- 状态映射至关重要 — 跟踪外部 ID 和内部 ID 之间的映射,以便后续请求正确路由。
- ACP 仍在成熟 — 不同的 agent 对规范的实现不同。防御性编码和回退策略是必要的。
关于 ACP
ACP (Agent Communication Protocol) 标准化了编码 agent 与宿主环境的通信方式。它使用 JSON-RPC 2.0 over stdio。关键方法包括 initialize、session/new、session/load 和 session/save。该协议很强大但实现各异——始终要有兼容层。
Full-Stack Developer with 10+ years of experience, specializing in QT C++ desktop application development and AI Agent systems.





