Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

RPC 套接字传输

守护进程通过本地 IPC 流暴露一个 JSON-RPC 2.0 接口,在 Unix 上使用 Unix 域套接字,在 Windows 上使用命名管道。这是 zerocode 等本地客户端的主要传输方式。HTTP/WS 网关则保留用于 webhook、Web 仪表板和远程 REST 使用方。

端点解析

每个数据目录都有自己的端点,因此同一台机器上的多个守护进程实例不会发生冲突。数据目录派生自配置目录(--config-dir / ZEROCLAW_CONFIG_DIR,或 ZEROCLAW_DATA_DIR)。

操作系统默认端点
Linux<data_dir>/daemon.sock(Unix 域套接字)
macOS<data_dir>/daemon.sock(Unix 域套接字)
Windows\\.\pipe\zeroclaw-<hash>,其中 <hash> 派生自 data_dir

在任意平台上均可通过 ZEROCLAW_SOCKET 环境变量进行覆盖:

sh

export ZEROCLAW_SOCKET=/tmp/my-zeroclaw.sock
zeroclaw daemon

PowerShell

$env:ZEROCLAW_SOCKET = '\\.\pipe\my-zeroclaw'
zeroclaw daemon

线路协议

NDJSON(以换行符分隔的 JSON)。每一行都是一条完整的 JSON-RPC 2.0 消息。没有 HTTP 帧,也没有长度前缀。各平台的帧格式完全一致;命名管道传输的字节流与 Unix 套接字相同。

{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":1},"id":1}\n
{"jsonrpc":"2.0","result":{"protocolVersion":1,"serverVersion":"0.8.5"},"id":1}\n

握手

第一个 RPC 调用必须是 initialize。在 initialize 成功之前,守护进程会拒绝所有其他方法。协议版本不匹配会产生一个错误码为 -32011 的结构化错误。

{
  `jsonrpc`: "2.0",
  方法: 初始化,
  "参数": {
    protocolVersion: 1
  },
  "id": 1
}

该端点不需要配对令牌。访问控制由操作系统处理:

  • Unix:套接字为 0o600,父目录为 0o700
  • Windows:命名管道 ACL 默认授予创建用户和 SYSTEM

方法

方法方向描述
initialize客户端 -> 守护进程验证身份并协商协议版本
session/new客户端 -> 守护进程创建代理会话(需要 agentAlias,可选 cwdsessionId;可选的 keep_siblings 会禁止空闲的同模式兄弟会话驱逐,适用于自行管理兄弟会话生命周期的多会话客户端)
session/close客户端 -> 守护进程关闭并清理会话
session/prompt客户端 -> 守护进程运行一个回合(通过 session/update 通知进行流式传输)
session/cancel客户端 -> 守护进程取消正在进行的回合
status客户端 -> 守护进程服务器版本、协议版本、活动会话列表
session/update守护进程 -> 客户端回合期间的流式通知(文本块、工具调用、审批)
elicitation/create守护进程 -> 客户端为 ask-user 和 poll 流程请求交互式输入

双向请求

任一方都可以通过已建立的套接字发送请求。接收方必须使用相同的 id 进行响应,并且只能包含 resulterror 二者之一。每个对等方都使用各自的 zc-out-<number> 序列发送出站请求;此前缀不是全局唯一的命名空间。关联仍然具有方向性:每个对等方仅根据自己的待处理请求映射匹配响应,因此相同的文本 ID 可以在相反方向上独立处于进行中状态。

{`jsonrpc`:"2.0",方法:"elicitation/create","参数":{"消息":"是否继续?"},"id":zc-out-0}
{`jsonrpc`:"2.0","结果":{action:"接受","内容":{答案:"yes"}},"id":zc-out-0}

显式的 "result": null 表示响应成功,并且仍会解析挂起的调用方。error 对象会将其解析为失败。如果对端没有响应,发起请求的 ask-user 或 poll 操作仍保持现有的超时行为。

每个帧都必须是带有 "jsonrpc": "2.0" 的 JSON 对象。请求必须包含字符串类型的 method;如果存在,params 必须是对象或数组。响应必须包含字符串、数字或 null 类型的 id,并且必须恰好包含一个响应成员。无效 JSON 会产生 -32700(解析错误)。格式错误的请求形信封会产生 -32600(无效请求);如果能够恢复出有效的请求 ID,则使用该 ID。格式错误的响应形信封会在不记录帧内容的情况下记录日志,并在不回复的情况下丢弃,因为回显其 ID 可能会在相反方向完成一个无关请求。无法判定方向的信封使用 id: null。同样会记录日志并忽略未知的有效响应 ID,而不是回复它们,从而防止响应循环。

开启流式传输

session/prompt 在回合完成时返回最终结果。在执行过程中,守护进程会发送 session/update 通知以传递增量事件:

{`jsonrpc`:"2.0",方法:"session/update","参数":{"会话ID":"...",类型:agent_message_chunk,"文本":"Hello"}}
{`jsonrpc`:"2.0",方法:"session/update","参数":{"会话ID":"...",类型:"tool_call",toolCallId:tc_1,"name":bash,rawInput:{...}}}
{`jsonrpc`:"2.0",方法:"session/update","参数":{"会话ID":"...",类型:"tool_result",toolCallId:tc_1,"name":bash,rawOutput:"..."}}

事件类型:agent_message_chunkagent_thought_chunktool_calltool_resultapproval_request

临时模式

zeroclaw daemon --ephemeral 会跟踪已连接的客户端,并在最后一个客户端断开连接时自行终止(在 1 秒的宽限期之后)。在宽限期内重新连接将取消关闭操作。在至少有一个客户端连接之前,该守护进程不会退出。

未使用 --ephemeral 启动的守护进程会忽略客户端数量,并持续运行直到被显式停止。

安全

  • Unix 套接字目录:0o700(仅所有者)
  • Unix socket 文件:0o600(仅所有者)
  • Windows 命名管道:默认 ACL 向创建用户和 SYSTEM 授予权限
  • Linux 上的 SO_PEERCRED 提供连接进程的 PID 和 UID 用于审计日志;Windows 则将 pipe:local 记录为对端标签

快速测试

在一个终端中启动守护进程:

sh

zeroclaw daemon

在 Unix 上的第二个终端中,使用 socat 连接:

sh

socat READLINE UNIX-CONNECT:~/.zeroclaw/data/daemon.sock

请逐行粘贴:

{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":1},"id":1}
{"jsonrpc":"2.0","method":"status","params":{},"id":2}

在 Windows 上,使用任意命名管道客户端(PowerShell [System.IO.Pipes.NamedPipeClientStream]、通过 WSL 使用 nc,或直接运行 zerocode)。

内部原理

调度层位于 crates/zeroclaw-runtime/src/rpc/

文件角色
transport.rsRpcTransport trait
turn.rsexecute_turn() 共享回合执行器
session.rsRpcSessionSessionStore
dispatch.rsRpcDispatcher 方法路由
local.rsLocalTransport + 监听器(Unix 套接字 / Windows 命名管道)
wss.rsWSS(WebSocket Secure)传输 + TLS 接收器
attachments.rs文件上传处理、去重、标记生成

RpcTransport trait 的设计使得额外的传输方式(vsock、自定义 IPC)能够无缝接入,而无需改动分发或会话逻辑。local.rs 模块使用 tokio::io::split 将 Unix 和 Windows 原语封装在单个 LocalTransport struct 之后,因此读写循环可在两个平台间共享。