我来对 Kimi CLI 的 Wire 协议 进行深度解析。Wire 协议是 Kimi Code CLI 的底层通信协议,用于与外部程序进行结构化的双向通信。
一、协议概述
1.1 协议基础信息
| 属性 | 值 |
|---|
| **协议名称** | Wire Protocol |
| **当前版本** | 1.3 |
| **旧版本** | 1.1 (向后兼容) |
| **传输格式** | JSON-RPC 2.0 |
| **传输方式** | stdin/stdout (stdio) |
| **消息格式** | 每行一个 JSON 对象 (JSONL) |
1.2 核心文件位置
src/kimi_cli/wire/
├── __init__.py # Wire 类:Soul 与 UI 之间的通道
├── types.py # 消息类型定义 (Pydantic 模型)
├── jsonrpc.py # JSON-RPC 消息格式定义
├── server.py # WireServer:处理 JSON-RPC 通信
├── serde.py # 序列化/反序列化工具
├── file.py # WireFile:消息持久化到 wire.jsonl
└── protocol.py # 协议版本常量
二、协议架构
2.1 通信模型
┌─────────────┐ JSON-RPC 2.0 ┌─────────────┐
│ Client │ ◄────────────────────────► │ WireServer │
│ (IDE/Web) │ stdin/stdout (line-based) │ (Kimi CLI) │
└─────────────┘ └──────┬──────┘
│
┌──────┴──────┐
│ Soul │
│ (Agent核心) │
└─────────────┘
2.2 消息流向
Client ──► Server: initialize / prompt / replay / cancel
Server ──► Client: event (通知) / request (需响应) / response
三、JSON-RPC 消息格式
3.1 基础结构
# JSON-RPC 2.0 请求
{
"jsonrpc": "2.0",
"method": "prompt", # 方法名
"id": "uuid-123", # 请求ID (通知无此字段)
"params": {...} # 参数
}
# JSON-RPC 2.0 响应
{
"jsonrpc": "2.0",
"id": "uuid-123",
"result": {...} # 成功结果
# 或
"error": {
"code": -32600,
"message": "Invalid request"
}
}
3.2 方法分类
| 方向 | 方法 | 类型 | 说明 |
|---|
| Client → Server | initialize | Request | 握手,协商版本,注册外部工具 |
| Client → Server | prompt | Request | 发送用户输入,启动 Agent 轮次 |
| Client → Server | replay | Request | 回放历史消息 (v1.3+) |
| Client → Server | cancel | Request | 取消当前轮次 |
| Server → Client | event | Notification | 事件通知 (无需响应) |
| Server → Client | request | Request | 审批/工具调用请求 (需响应) |
四、详细消息类型
4.1 Client → Server 请求
initialize (v1.1+)
// 请求
{
"jsonrpc": "2.0",
"method": "initialize",
"id": "init-1",
"params": {
"protocol_version": "1.3",
"client": {
"name": "my-ide",
"version": "1.0.0"
},
"external_tools": [
{
"name": "open_in_ide",
"description": "Open file in IDE",
"parameters": {
"type": "object",
"properties": {
"path": {"type": "string"}
},
"required": ["path"]
}
}
]
}
}
// 响应
{
"jsonrpc": "2.0",
"id": "init-1",
"result": {
"protocol_version": "1.3",
"server": {
"name": "Kimi Code CLI",
"version": "0.69.0"
},
"slash_commands": [
{
"name": "init",
"description": "Analyze the codebase...",
"aliases": []
}
],
"external_tools": {
"accepted": ["open_in_ide"],
"rejected": []
}
}
}
prompt
// 请求
{
"jsonrpc": "2.0",
"method": "prompt",
"id": "prompt-1",
"params": {
"user_input": "你好" // 或 ContentPart[] 数组
}
}
// 成功响应
{
"jsonrpc": "2.0",
"id": "prompt-1",
"result": {
"status": "finished" // "finished" | "cancelled" | "max_steps_reached"
}
}
// 错误响应
{
"jsonrpc": "2.0",
"id": "prompt-1",
"error": {
"code": -32001,
"message": "LLM is not set"
}
}
4.2 Server → Client 事件通知 (event)
| 事件类型 | 说明 | 关键字段 |
|---|
TurnBegin | 轮次开始 | user_input |
TurnEnd | 轮次结束 (v1.2+) | - |
StepBegin | 步骤开始 | n: 步骤编号 |
StepInterrupted | 步骤中断 | - |
CompactionBegin/End | 上下文压缩 | - |
StatusUpdate | 状态更新 | context_usage, token_usage |
ContentPart | 内容片段 | type: text/think/image_url/audio_url/video_url |
ToolCall | 工具调用 | id, function.name, function.arguments |
ToolCallPart | 工具参数流式片段 | arguments_part |
ToolResult | 工具结果 | tool_call_id, return_value |
ApprovalResponse | 审批响应 | request_id, response |
SubagentEvent | 子 Agent 事件 | task_tool_call_id, event |
4.3 Server → Client 请求 (request)
ApprovalRequest - 需要用户审批
// Server 发送
{
"jsonrpc": "2.0",
"method": "request",
"id": "req-1",
"params": {
"type": "ApprovalRequest",
"payload": {
"id": "approval-1",
"tool_call_id": "tc-1",
"sender": "Shell",
"action": "run shell command",
"description": "Run command `ls -la`",
"display": []
}
}
}
// Client 响应
{
"jsonrpc": "2.0",
"id": "req-1",
"result": {
"request_id": "approval-1",
"response": "approve" // "approve" | "approve_for_session" | "reject"
}
}
ToolCallRequest - 外部工具调用
// Server 发送
{
"jsonrpc": "2.0",
"method": "request",
"id": "req-2",
"params": {
"type": "ToolCallRequest",
"payload": {
"id": "tc-1",
"name": "open_in_ide",
"arguments": "{\"path\":\"README.md\"}"
}
}
}
// Client 响应
{
"jsonrpc": "2.0",
"id": "req-2",
"result": {
"tool_call_id": "tc-1",
"return_value": {
"is_error": false,
"output": "Opened",
"message": "Opened README.md in IDE",
"display": []
}
}
}
五、错误码定义
5.1 JSON-RPC 标准错误码
| 错误码 | 说明 |
|---|
-32700 | Parse Error - JSON 格式无效 |
-32600 | Invalid Request - 请求对象无效 |
-32601 | Method Not Found - 方法不存在 |
-32602 | Invalid Params - 参数无效 |
-32603 | Internal Error - 内部错误 |
5.2 Wire 协议自定义错误码
| 错误码 | 说明 |
|---|
-32000 | Invalid State - 服务器状态无效 (如已有轮次进行中) |
-32001 | LLM Not Set - 未配置 LLM |
-32002 | LLM Not Supported - 不支持的 LLM |
-32003 | Chat Provider Error - LLM 服务错误 |
六、核心类型详解
6.1 ContentPart 内容片段
type ContentPart =
| TextPart # {type: "text", text: string}
| ThinkPart # {type: "think", think: string, encrypted?: string}
| ImageURLPart # {type: "image_url", image_url: {url: string, id?: string}}
| AudioURLPart # {type: "audio_url", audio_url: {url: string, id?: string}}
| VideoURLPart # {type: "video_url", video_url: {url: string, id?: string}}
6.2 ToolReturnValue 工具返回值
{
"is_error": bool,
"output": string | ContentPart[], # 给模型的输出
"message": string, # 给模型的解释消息
"display": DisplayBlock[], # 给用户显示的内容
"extras": object | None # 额外调试信息
}
6.3 DisplayBlock 显示块
type DisplayBlock =
| {type: "brief", text: string}
| {type: "diff", path: string, old_text: string, new_text: string}
| {type: "todo", items: [{title: string, status: "pending"|"in_progress"|"done"}]}
| {type: "shell", language: string, command: string}
| {type: string, data: object} # UnknownDisplayBlock (fallback)
七、通信流程示例
7.1 完整对话流程
┌──────┐ ┌──────────┐
│Client│ │WireServer│
└──┬───┘ └────┬─────┘
│ │
│ {"method":"initialize","id":"1",...} │
│ ───────────────────────────────────────────────► │
│ │
│ {"id":"1","result":{"protocol_version":"1.3",...}}
│ ◄─────────────────────────────────────────────── │
│ │
│ {"method":"prompt","id":"2","params":{...}} │
│ ───────────────────────────────────────────────► │
│ │
│ {"method":"event","params":{"type":"TurnBegin",...}}
│ ◄─────────────────────────────────────────────── │
│ │
│ {"method":"event","params":{"type":"StepBegin","payload":{"n":1}}}
│ ◄─────────────────────────────────────────────── │
│ │
│ {"method":"event","params":{"type":"ContentPart",...}}
│ ◄─────────────────────────────────────────────── │
│ │
│ {"method":"request","id":"req-1","params":{"type":"ToolCallRequest",...}}
│ ◄─────────────────────────────────────────────── │
│ │
│ {"jsonrpc":"2.0","id":"req-1","result":{...}} │
│ ───────────────────────────────────────────────► │
│ │
│ {"method":"event","params":{"type":"ToolResult",...}}
│ ◄─────────────────────────────────────────────── │
│ │
│ {"method":"event","params":{"type":"StepBegin","payload":{"n":2}}}
│ ◄─────────────────────────────────────────────── │
│ │
│ {"method":"event","params":{"type":"TurnEnd"}} │
│ ◄─────────────────────────────────────────────── │
│ │
│ {"id":"2","result":{"status":"finished"}} │
│ ◄─────────────────────────────────────────────── │
│ │
八、持久化存储 (wire.jsonl)
8.1 文件格式
每条消息以 JSON 行格式存储:
{"type":"metadata","protocol_version":"1.3"}
{"timestamp":1234567890.123,"message":{"type":"TurnBegin","payload":{...}}}
{"timestamp":1234567890.456,"message":{"type":"StepBegin","payload":{"n":1}}}
...
8.2 文件位置
~/.kimi/sessions/<session-id>/wire.jsonl
九、设计特点总结
9.1 架构优势
| 特点 | 说明 |
|---|
| **双向通信** | 基于 JSON-RPC 2.0,支持请求-响应和通知模式 |
| **流式传输** | 支持 ContentPart 和 ToolCallPart 的流式输出 |
| **可扩展性** | 通过 external_tools 允许客户端注册自定义工具 |
| **持久化** | 自动记录到 wire.jsonl,支持 replay 回放 |
| **向后兼容** | 版本协商机制,旧客户端可降级使用 |
9.2 使用场景
- IDE 集成 - ACP (Agent Client Protocol) 通过 Wire 与 Agent 通信
- 自定义 UI - Web、桌面或移动端前端
- 自动化测试 - 程序化测试 Agent 行为
- Rust 实现 -
kimi-agent-rs 提供轻量级 Wire 服务器
十、版本演进
| 版本 | 新增功能 |
|---|
| 1.1 | 新增 initialize 握手、ApprovalResponse 重命名 |
| 1.2 | 新增 TurnEnd 事件 |
| 1.3 | 新增 replay 方法 |
这就是 Kimi CLI Wire 协议的完整深度解析。该协议设计简洁、扩展性强,是构建 AI Agent 客户端-服务器通信的优秀范例。