第3章 工具调用协议设计:HTTP / JSON-RPC / WebSocket、请求-响应模式、异常协议

协议是 Agent 与工具之间通信的语法契约。本章聚焦三种主流协议——HTTP REST、JSON-RPC、WebSocket——在设计工具调用时的核心差异、适用场景、请求-响应模式以及异常协议规范。

3.1 协议选型:性能、语义与适用场景

选择哪种协议取决于工具的使用模式:同步查询、异步任务、流式推送还是高频双向通信。下表从关键维度做了横向对比。

维度HTTP (REST)JSON-RPCWebSocket
通信模式请求-响应(同步)请求-响应(同步/异步)全双工(持久连接)
消息格式多样(JSON/XML/表单)JSON 严格结构文本/二进制帧
状态管理无状态(stateless)无状态 / 可携带上下文有状态(连接保持)
传输开销较高(头部冗余)中(可复用连接)低(长连接)
典型延迟几十~几百 ms几十 ms(keep-alive)毫秒级
适用场景CRUD / 知识查询远程过程调用 / 工具编排流式输出 / 实时监控
工具调用示例GET /tool/weather?city=北京{"method":"getWeather","params":["北京"]}订阅工具实时事件
选型建议: 80% 的工具调用场景用 HTTP REST 即可满足;当工具需要传递结构化参数并返回统一错误格式时,优先选择 JSON-RPC;需要流式推送或低延迟双向通信(如聊天 Agent 连续调用多个工具)时,使用 WebSocket。

3.2 HTTP 协议:端点设计与请求-响应模式

3.2.1 端点(Endpoint)设计原则

  • 使用名词复数表示资源:/tools、/tools/{id}/invoke
  • 动作通过 HTTP 方法表达:GET 查询、POST 调用、DELETE 撤销
  • 查询参数用于过滤,请求体用于传递调用输入
标准工具调用端点示例:
POST /api/v1/tools/weather/invoke
Content-Type: application/json

{
  "city": "北京",
  "date": "2025-06-10",
  "unit": "celsius"
}

响应:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "success": true,
  "data": {
    "temperature": 28,
    "condition": "晴",
    "humidity": 45
  },
  "request_id": "req-7a3f2c"
}

3.2.2 请求-响应生命周期

  1. Agent 构造请求体(含工具名、参数、元数据)
  2. 通过 HTTP POST 发送到工具端点
  3. 工具服务端校验参数 → 执行业务逻辑 → 构造响应
  4. Agent 接收响应并提取 data 或 error
  5. 若超时或状态码非 2xx,触发重试或降级策略

3.3 JSON-RPC 协议:结构化调用契约

JSON-RPC 是轻量级远程过程调用协议,天然适合 Agent 工具调用。每个请求包含固定的 jsonrpc、method、params、id 字段,响应严格对称。

3.3.1 请求与响应结构

// 请求
{
  "jsonrpc": "2.0",
  "method": "getWeather",
  "params": {
    "city": "北京",
    "date": "2025-06-10"
  },
  "id": 1
}

// 成功响应
{
  "jsonrpc": "2.0",
  "result": {
    "temperature": 28,
    "condition": "晴"
  },
  "id": 1
}

// 错误响应
{
  "jsonrpc": "2.0",
  "error": {
    "code": -32000,
    "message": "服务暂时不可用",
    "data": {
      "retry_after": 5
    }
  },
  "id": 1
}
关键约束: id 必须唯一且由请求方生成,用于匹配请求与响应;服务端不得修改 id。批量请求时可使用数组包裹多个请求对象。

3.3.2 方法命名规范

命名模式示例说明
动词+名词getWeather查询类工具
名词+动词orderCreate操作类工具
领域.动词+名词payment.refund带命名空间的工具

3.4 WebSocket 协议:流式与双向调用

当 Agent 需要连续调用多个工具或监听工具推送事件时,WebSocket 的长连接特性可以显著降低延迟。

3.4.1 连接建立与消息帧

// 客户端 → 服务端:调用请求
{
  "type": "invoke",
  "tool": "weather_stream",
  "params": { "city": "北京", "interval": 60 },
  "request_id": "ws-req-001"
}

// 服务端 → 客户端:流式数据块
{
  "type": "data",
  "request_id": "ws-req-001",
  "payload": { "temperature": 28, "timestamp": "2025-06-10T10:00:00Z" }
}

// 服务端 → 客户端:完成通知
{
  "type": "complete",
  "request_id": "ws-req-001",
  "status": "success"
}

// 服务端 → 客户端:错误通知
{
  "type": "error",
  "request_id": "ws-req-001",
  "code": -32001,
  "message": "数据源断开",
  "retryable": true
}

3.4.2 心跳保持与重连策略

  • 客户端每 30 秒发送 {"type":"ping"},服务端回复 {"type":"pong"}
  • 若连续 3 次未收到 pong,触发重连
  • 重连时使用指数退避:1s、2s、4s、8s …… 最大 60s

3.5 异常协议:统一错误码与异常传播

无论使用哪种传输协议,工具调用的异常信息必须结构化、可枚举、可处理。一套统一的异常协议能让 Agent 快速决策是重试、降级还是终止。

3.5.1 标准错误码体系

错误码范围类别示例是否可重试
-32700 ~ -32000JSON-RPC 标准错误-32600(无效请求)、-32601(方法不存在)否
-32000 ~ -31900工具通用错误-32000(服务内部错误)、-32001(超时)部分
1000 ~ 1999业务校验错误1001(参数缺失)、1002(参数类型错误)否
2000 ~ 2999资源状态错误2001(余额不足)、2002(频率限制)是(等待后重试)
3000 ~ 3999基础设施错误3001(下游超时)、3002(连接池耗尽)是
异常响应的最小字段集:
{
  "error": {
    "code": 2001,
    "message": "余额不足,当前可用额度 0.5 元",
    "data": {
      "required_amount": 10.0,
      "current_balance": 0.5,
      "suggestion": "请充值后重试"
    },
    "retryable": false,
    "retry_after": null
  }
}

3.5.2 异常传播链路

当工具调用链中某个环节失败时,异常信息应沿着调用链向上传播,并携带原始错误上下文,避免在中间层被吞没。

3.6 协议适配器架构

为支持多协议统一管理,建议在工具网关层引入 协议适配器,将不同协议的请求统一转换为内部标准 Invocation 对象。

工具调用协议栈与异常处理流程 HTTP REST 入口 POST /api/v1/tools/weather/invoke JSON-RPC 入口 { "method":"getWeather", "id":1 } WebSocket 入口 { "type":"invoke", "tool":"weather_stream" } 协议适配器 统一转为 Invocation 对象 工具执行引擎 调用目标工具 异常处理 错误码映射 / 重试决策 / 降级 结构化错误响应 code / message / retryable 说明: 1. 三种协议由适配器统一转换为内部标准调用对象 2. 执行引擎不关心外部协议,只处理 Invocation 3. 异常处理分支将错误映射为统一格式返回给客户端 异常传播原则: • 从不吞没原始异常(保留 cause) • 每层只补充当前上下文信息 • 最终向 Agent 返回可处理的错误码+建议

3.7 调试与部署检查清单

检查项HTTPJSON-RPCWebSocket
端点/路径是否正确校验路由和 method校验 method 是否存在校验连接 URL 和协议版本
参数格式JSON body 或 query严格 JSON 结构JSON 文本帧
超时设置客户端 10s~30s客户端 10s~30s心跳 30s,数据超时 60s
错误码映射HTTP 状态码 + bodyerror.code + messagetype=error + code
重试策略5xx 或超时重试-32000 ~ -31999 重试断线重连指数退避
日志记录记录 request_id + 耗时记录 id + method + 耗时记录 request_id + 连接 ID

3.8 常见错误与规避

  • 协议混用但适配器缺失:某工具同时暴露 HTTP 和 WebSocket 端点,但内部未统一调用模型,导致逻辑分支爆炸。解决方法是在网关层做协议适配。
  • JSON-RPC id 冲突:多个请求使用相同 id,导致响应匹配错乱。保证每次调用生成唯一 id(UUID 或递增整数)。
  • WebSocket 未处理心跳:连接被网络设备静默断开,Agent 仍认为连接可用。必须实现 ping/pong + 超时重连。
  • 异常被中间件吞没:工具链中某环节捕获异常后返回 null,上游误判为成功。始终传递 error 对象,不允许空响应代表成功。
规范红线: 所有工具调用响应(含异常)必须包含 request_id 或 id,否则 Agent 无法关联请求与结果。这条规则应作为 Code Review 的强制检查项。

3.9 性能与稳定性优化

优化方向措施预期效果
连接复用HTTP Keep-Alive / WebSocket 长连接减少握手开销 30%~50%
批量调用JSON-RPC 批量请求数组一次往返调用多个工具
响应压缩HTTP 启用 gzip / WebSocket 启用 permessage-deflate传输体积减少 60%~80%
熔断降级连续错误数 > N 时熔断 30s防止雪崩
请求去重基于 idempotency_key 去重避免重复扣费或重复操作

本章核心交付物:
① 协议选型决策矩阵(HTTP / JSON-RPC / WebSocket)
② 统一异常协议错误码表(5 段编码体系)
③ 协议适配器架构图(含异常传播链路)
④ 调试检查清单(15 项覆盖三种协议)