同一个远程调用,既可以写成 Add(10, 20) 这样的方法调用,也可以写成 GET /tasks/1001 这样的资源请求。下面从 RPC 思想出发,依次看 JSON-RPC 1.0、2.0 和 RESTful 各自如何表达一次操作,最后看 A2A 如何在 JSON-RPC 之上定义 Agent 间的方法。
1. RPC 是什么?
RPC(Remote Procedure Call,远程过程调用)是一种通信思想:调用远程机器上的函数,就像调用本地函数一样。
例如,客户端想让服务端计算 10 + 20:
result := Add(10, 20)实际过程:
- 客户端将函数名
Add和参数10、20序列化。 - 通过网络发送给服务端。
- 服务端找到对应的
Add函数并执行。 - 服务端将结果返回。
- 客户端拿到结果。
RPC 本身不规定必须使用 HTTP,也不规定必须使用 JSON。
常见 RPC 技术:
- JSON-RPC
- gRPC
- XML-RPC
- Apache Thrift
核心:RPC 关注的是远程调用函数或方法。
2. JSON-RPC 1.0
JSON-RPC 是 RPC 的一种实现方式,使用 JSON 格式传递请求和响应。
2.1 怎么调用?
假设服务端提供了一个 add 方法,客户端想计算 10 + 20。
客户端发送:
{ "method": "add", "params": [10, 20], "id": 1}服务端返回:
{ "result": 30, "error": null, "id": 1}字段含义:
| 字段 | 作用 |
|---|---|
| method | 要调用的方法 |
| params | 方法参数 |
| id | 请求标识,用于匹配响应 |
| result | 调用成功后的结果 |
| error | 调用失败时的错误信息 |
2.2 再看一个实际例子
假设服务端提供了用户查询方法:
请求:
{ "method": "getUser", "params": [1001], "id": 2}响应:
{ "result": { "id": 1001, "name": "Tom" }, "error": null, "id": 2}这里相当于调用远程的:
user := getUser(1001)2.3 JSON-RPC 1.0 的特点
- 使用
method指定调用的方法。 - 使用
params传递参数,通常是数组。 - 使用
id关联请求和响应。 - 没有
jsonrpc版本字段。 - 通知请求使用
id: null,服务端不返回响应。
3. JSON-RPC 2.0
JSON-RPC 2.0 是 JSON-RPC 的后续版本,规范更加明确。
3.1 怎么调用?
还是计算 10 + 20。
请求:
{ "jsonrpc": "2.0", "method": "add", "params": [10, 20], "id": 1}响应:
{ "jsonrpc": "2.0", "result": 30, "id": 1}和 1.0 相比,最明显的变化是增加了:
"jsonrpc": "2.0"3.2 支持命名参数
JSON-RPC 2.0 的 params 不仅可以使用数组,还可以使用对象。
数组参数:
{ "jsonrpc": "2.0", "method": "add", "params": [10, 20], "id": 1}对象参数:
{ "jsonrpc": "2.0", "method": "add", "params": { "a": 10, "b": 20 }, "id": 1}对象参数的好处是可读性更好,也不容易搞错参数顺序。
3.3 错误响应
例如,客户端调用了一个不存在的方法:
{ "jsonrpc": "2.0", "method": "unknownMethod", "id": 1}服务端返回:
{ "jsonrpc": "2.0", "error": { "code": -32601, "message": "Method not found" }, "id": 1}常见错误码:
| 错误码 | 含义 |
|---|---|
| -32700 | JSON 解析错误 |
| -32600 | 无效请求 |
| -32601 | 方法不存在 |
| -32602 | 参数无效 |
| -32603 | 内部错误 |
3.4 通知 Notification
如果客户端只想通知服务端做一件事,不需要等待结果,可以发送通知。
{ "jsonrpc": "2.0", "method": "logEvent", "params": { "event": "user_login" }}NOTE这里没有
id。
服务端收到通知后执行操作,但不返回 JSON-RPC 响应。
3.5 批量请求 Batch
JSON-RPC 2.0 支持一次发送多个请求:
[ { "jsonrpc": "2.0", "method": "getUser", "params": [1001], "id": 1 }, { "jsonrpc": "2.0", "method": "getUser", "params": [1002], "id": 2 }]服务端可以返回多个响应:
[ { "jsonrpc": "2.0", "result": {"id": 1001, "name": "Tom"}, "id": 1 }, { "jsonrpc": "2.0", "result": {"id": 1002, "name": "Jack"}, "id": 2 }]响应顺序不一定与请求顺序一致,需要通过 id 匹配。
3.6 JSON-RPC 2.0 的特点
- 必须带有
jsonrpc: "2.0"。 method指定调用的方法。params支持数组和对象。id用于关联请求与响应。- 通知请求省略
id。 - 支持批量请求。
- 成功响应使用
result,失败响应使用error,两者不能同时出现。
4. RESTful API
RESTful 和 JSON-RPC 不一样。
JSON-RPC 是通过方法名来指定操作,而 RESTful 是围绕资源设计 API,通常结合 HTTP 方法表达操作。
例如,我们有一个任务管理服务,资源是 tasks。
4.1 查询任务
GET /tasks/1001含义:获取 ID 为 1001 的任务。
响应:
{ "id": 1001, "name": "Build project", "status": "running"}4.2 创建任务
POST /tasksContent-Type: application/json请求体:
{ "name": "Build project"}含义:创建一个任务。
4.3 修改任务
整体替换:
PUT /tasks/1001部分修改:
PATCH /tasks/1001Content-Type: application/json请求体:
{ "status": "completed"}4.4 删除任务
DELETE /tasks/1001含义:删除 ID 为 1001 的任务。
4.5 RESTful 常用 HTTP 方法
| HTTP 方法 | 常见用途 |
|---|---|
| GET | 查询资源 |
| POST | 创建资源或执行某些操作 |
| PUT | 整体替换资源 |
| PATCH | 部分修改资源 |
| DELETE | 删除资源 |
RESTful 是一种 API 架构风格,并不强制使用 JSON,JSON 只是常见的数据格式。
5. JSON-RPC 和 RESTful 的区别
假设现在要查询一个任务。
JSON-RPC 2.0
请求:
POST /rpcContent-Type: application/json请求体:
{ "jsonrpc": "2.0", "method": "tasks/get", "params": { "taskId": "1001" }, "id": 1}RESTful
请求:
GET /tasks/1001两者都能完成查询任务,但表达方式不同。
| 对比 | JSON-RPC 2.0 | RESTful |
|---|---|---|
| 核心思路 | 调用方法 | 操作资源 |
| 操作标识 | method | HTTP Method + URL |
| 参数位置 | params | URL、Query、Body |
| 常见请求 | POST | GET、POST、PUT、PATCH、DELETE |
| 数据格式 | JSON | 不限,常用 JSON |
| 典型场景 | 远程方法调用、协议交互 | Web API、资源管理 |
记住:
- JSON-RPC:我要调用哪个方法?
- RESTful:我要操作哪个资源?
6. A2A 中的 JSON-RPC 是怎么用的?
A2A(Agent2Agent Protocol)使用 JSON-RPC 2.0 作为一种常见的通信绑定。
假设 Agent A 想让 Agent B 执行一个任务。
6.1 提交任务:message/send
Agent A 向 Agent B 发送:
POST /a2aContent-Type: application/json请求体:
{ "jsonrpc": "2.0", "method": "message/send", "params": { "message": { "role": "user", "parts": [ { "kind": "text", "text": "帮我分析这个项目的架构" } ] } }, "id": 1}这里:
- HTTP POST:负责把请求发送到 Agent B。
method:告诉 Agent B 要执行message/send。params:携带消息内容。id:标识本次 JSON-RPC 请求。
6.2 查询任务:tasks/get
如果任务还没有完成,可以查询任务状态:
{ "jsonrpc": "2.0", "method": "tasks/get", "params": { "id": "task-001" }, "id": 2}Agent B 返回任务状态,例如:
{ "jsonrpc": "2.0", "result": { "id": "task-001", "status": { "state": "working" } }, "id": 2}6.3 流式获取进度:message/stream
如果希望实时接收 Agent B 的任务进度,可以使用:
{ "jsonrpc": "2.0", "method": "message/stream", "params": { "message": { "role": "user", "parts": [ { "kind": "text", "text": "分析项目架构" } ] } }, "id": 3}在 HTTP+JSON-RPC 绑定中,服务端可以通过 SSE(Server-Sent Events)持续推送事件。
6.4 常见 A2A 方法
| 方法 | 用途 |
|---|---|
| message/send | 发送消息或提交任务 |
| message/stream | 发送消息并流式接收事件 |
| tasks/get | 查询任务状态 |
| tasks/cancel | 取消任务 |
| tasks/resubscribe | 重新订阅任务事件 |
| tasks/pushNotificationConfig/set | 设置任务推送配置 |
WARNING
message/send、tasks/get等是 JSON-RPC 的 method 名称,不是 HTTP 的 GET、POST 方法。
7. 最后总结
| 名称 | 你应该怎么理解 |
|---|---|
| RPC | 远程调用函数的一种思想 |
| JSON-RPC 1.0 | 使用 JSON 表达远程方法调用 |
| JSON-RPC 2.0 | 增加版本标识、命名参数、通知和批量请求等规范 |
| RESTful | 通过资源 URL 和 HTTP 方法设计 API |
| HTTP | 网络传输协议,定义 GET、POST 等请求方法 |
一句话记忆
- RPC:远程调用函数。
- JSON-RPC:通过 JSON 传递方法名和参数。
- RESTful:通过 URL 和 HTTP 方法操作资源。
- HTTP GET/POST:HTTP 层的请求方法。
- JSON-RPC method:JSON-RPC 层的操作名称。
最重要的区别:
RESTful:GET /tasks/1001
JSON-RPC:POST /rpc{ "jsonrpc": "2.0", "method": "tasks/get", "params": { "id": "1001" }, "id": 1}前者通过 HTTP 方法和 URL 表达操作;后者通过 JSON-RPC 请求体中的 method 表达操作。