【AI】转载 Claude Agent SDK 技术规格说明

Claude Agent SDK 技术规格说明

版本: 1.0.0
协议版本: 2024-11-05
最后更新: 2026-01-10
原文: Claude Agent SDK Technical Specification

1. 概览

Claude Agent SDK 为 Claude Code 的智能体能力提供可编程访问方式。它使应用能够:

  • 使用 Claude 执行自然语言提示
  • 以逐 token 或逐消息的方式流式输出响应
  • 使用内置工具(文件操作、Shell 命令、Web 访问)
  • 通过模型上下文协议(MCP)定义自定义工具
  • 通过会话持久化管理多轮对话
  • 控制权限与沙箱行为

1.1 核心概念

概念描述
Query(查询)一次提示执行,可能跨越多个 turn
Turn(轮次)一次请求-响应循环,可能包含工具调用
Message(消息)一段离散的通信单元(system、assistant、user、result)
Tool(工具)Claude 可调用的能力(Read、Write、Bash、自定义 MCP 工具等)
Session(会话)由 UUID 标识的持久化对话上下文

1.2 交互模型

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
┌─────────────────┐                      ┌──────────────────┐
│  你的应用程序     │                      │   Claude Code    │
│     (SDK)       │                      │      CLI         │
└────────┬────────┘                      └────────┬─────────┘
         │                                        │
         │     使用参数启动子进程                    │
         │───────────────────────────────────────>│
         │                                        │
         │     stdout:JSON 消息(流式)            │
         │<───────────────────────────────────────│
         │                                        │
         │     [进程退出]                          │
         │<───────────────────────────────────────│
         │                                        │

2. 架构

2.1 组件图

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
┌─────────────────────────────────────────────────────────────────┐
│                          你的应用程序                             │
├─────────────────────────────────────────────────────────────────┤
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────────┐  │
│  │   Query     │  │   Options   │  │    Message Parser       │  │
│  │   Builder   │  │   Config    │  │                         │  │
│  └──────┬──────┘  └──────┬──────┘  └────────────┬────────────┘  │
│         │                │                      │               │
│         └────────────────┼──────────────────────┘               │
│                          │                                      │
│                          ▼                                      │
│                 ┌─────────────────┐                             │
│                 │  Process Spawn  │                             │
│                 │   (stdio)       │                             │
│                 └────────┬────────┘                             │
└──────────────────────────┼──────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────┐
│                       Claude Code CLI                            │
├──────────────────────────────────────────────────────────────────┤
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────────────┐  │
│  │  Claude  │  │  Tools   │  │  MCP     │  │  Session         │  │
│  │  API     │  │  Engine  │  │  Client  │  │  Manager         │  │
│  └──────────┘  └──────────┘  └──────────┘  └──────────────────┘  │
└──────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────┐
│                     MCP Servers(可选)                           │
│  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐   │
│  │  stdio server   │  │  HTTP server    │  │  SSE server     │   │
│  │  (你的工具)     │  │                 │  │                 │   │
│  └─────────────────┘  └─────────────────┘  └─────────────────┘   │
└──────────────────────────────────────────────────────────────────┘

2.2 数据流

  1. 应用程序:使用 prompt 与 options 构建 query
  2. SDK:以子进程方式启动 Claude Code CLI
  3. CLI:向 stdout 以流式方式输出 JSON 消息
  4. SDK:解析 JSON 行并产出强类型消息
  5. 应用程序:处理消息(展示、日志等)
  6. CLI:当 query 完成或发生错误时退出

3. CLI 接口

SDK 通过 Claude Code 的命令行接口与其通信。

3.1 基础命令

1
claude --print --output-format stream-json --verbose [OPTIONS] -- "prompt"

3.2 必需参数

参数描述
--print / -p非交互模式,输出到 stdout
--output-format stream-json输出换行分隔的 JSON 消息
--verbosestream-json 格式要求必须开启
--选项与 prompt 之间的分隔符

3.3 可选参数

参数类型描述
--model <model>string模型别名(opussonnethaiku)或完整名称
--max-turns <n>integer最大对话轮次数
--max-budget-usd <n>float最大预算(USD)
--system-prompt <text>string自定义 system prompt(替换默认)
--append-system-prompt <text>string追加到默认 system prompt
--allowed-tools <tools>string工具白名单(逗号分隔)
--disallowed-tools <tools>string工具黑名单(逗号分隔)
--mcp-config <path>stringMCP server 配置 JSON 路径
--include-partial-messagesboolean开启 token 级流式输出
--dangerously-skip-permissionsboolean跳过权限检查
--resume <session-id>string恢复指定会话
--continueboolean继续最近一次会话

3.4 输出格式

格式参数描述
Text--output-format text人类可读文本输出(默认)
JSON--output-format json完成时输出单个 JSON 对象
Stream JSON--output-format stream-json逐行输出 JSON 消息

4. 消息协议

所有消息均为带 type 字段的 JSON 对象。消息以换行分隔 JSON(NDJSON)形式输出。

4.1 消息类型

1
MessageType = "system" | "assistant" | "user" | "result" | "stream_event"

4.2 System 消息

在会话开始时只发送一次。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
{
  "type": "system",
  "subtype": "init",
  "uuid": "550e8400-e29b-41d4-a716-446655440000",
  "session_id": "550e8400-e29b-41d4-a716-446655440001",
  "cwd": "/path/to/working/directory",
  "model": "claude-sonnet-4-5-20250929",
  "tools": ["Task", "Bash", "Glob", "Grep", "Read", "Edit", "Write", ...],
  "mcp_servers": [
    {"name": "ruby-tools", "status": "connected"}
  ],
  "permissionMode": "default",
  "apiKeySource": "none",
  "slash_commands": ["compact", "context", "cost", ...],
  "agents": ["Bash", "general-purpose", "Explore", "Plan", ...],
  "claude_code_version": "2.1.3"
}

System 消息字段

字段类型描述
subtype"init"会话开始时固定为 “init”
uuidstring消息唯一标识
session_idstring会话标识(UUID)
cwdstring工作目录
modelstring当前模型名称
toolsstring[]可用的内置工具
mcp_serversobject[]已连接的 MCP servers 及其状态
permissionModestring当前权限模式
apiKeySourcestring认证来源(见下)
slash_commandsstring[]可用的斜杠命令
agentsstring[]可用子智能体类型
claude_code_versionstringCLI 版本

API Key Source 取值

描述
ANTHROPIC_API_KEY使用环境变量中的 API Key
none使用 OAuth 认证(通过 claude login 登录)
config使用配置文件中的 API Key

注意:apiKeySource"none" 时,Claude Code 会使用先前 claude login 保存的 OAuth token 进行认证,从而无需暴露 API Key。

4.3 Assistant 消息

Claude 的响应,可能包含文本与/或工具调用。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{
  "type": "assistant",
  "uuid": "550e8400-e29b-41d4-a716-446655440002",
  "session_id": "550e8400-e29b-41d4-a716-446655440001",
  "parent_tool_use_id": null,
  "message": {
    "model": "claude-sonnet-4-5-20250929",
    "id": "msg_01ABC123",
    "type": "message",
    "role": "assistant",
    "content": [
      {
        "type": "text",
        "text": "I'll help you with that."
      },
      {
        "type": "tool_use",
        "id": "toolu_01XYZ789",
        "name": "Glob",
        "input": {
          "pattern": "**/*.rb"
        }
      }
    ],
    "stop_reason": null,
    "usage": {
      "input_tokens": 150,
      "output_tokens": 42,
      "cache_creation_input_tokens": 500,
      "cache_read_input_tokens": 12000
    }
  }
}

Content block 类型

Text block:

1
2
3
4
{
  "type": "text",
  "text": "The response text..."
}

Tool use block:

1
2
3
4
5
6
{
  "type": "tool_use",
  "id": "toolu_01XYZ789",
  "name": "ToolName",
  "input": { ... }
}

4.4 User 消息

返回给 Claude 的工具结果。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
  "type": "user",
  "uuid": "550e8400-e29b-41d4-a716-446655440003",
  "session_id": "550e8400-e29b-41d4-a716-446655440001",
  "parent_tool_use_id": null,
  "message": {
    "role": "user",
    "content": [
      {
        "type": "tool_result",
        "tool_use_id": "toolu_01XYZ789",
        "content": "/path/to/file1.rb\n/path/to/file2.rb"
      }
    ]
  },
  "tool_use_result": {
    "filenames": ["/path/to/file1.rb", "/path/to/file2.rb"],
    "durationMs": 45,
    "numFiles": 2,
    "truncated": false
  }
}

4.5 Result 消息

指示一次 query 完成的最终消息。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
{
  "type": "result",
  "subtype": "success",
  "uuid": "550e8400-e29b-41d4-a716-446655440004",
  "session_id": "550e8400-e29b-41d4-a716-446655440001",
  "is_error": false,
  "duration_ms": 5432,
  "duration_api_ms": 12000,
  "num_turns": 2,
  "result": "I found 3 Ruby files in the directory...",
  "total_cost_usd": 0.0234,
  "usage": {
    "input_tokens": 200,
    "output_tokens": 150,
    "cache_creation_input_tokens": 500,
    "cache_read_input_tokens": 15000,
    "server_tool_use": {
      "web_search_requests": 0,
      "web_fetch_requests": 0
    }
  },
  "modelUsage": {
    "claude-sonnet-4-5-20250929": {
      "inputTokens": 200,
      "outputTokens": 150,
      "cacheReadInputTokens": 15000,
      "cacheCreationInputTokens": 500,
      "webSearchRequests": 0,
      "costUSD": 0.0234,
      "contextWindow": 200000,
      "maxOutputTokens": 64000
    }
  },
  "permission_denials": []
}

Result subtype

Subtype描述
successQuery 成功完成
error_max_turns超过最大轮次限制
error_during_execution执行期间发生运行时错误
error_max_budget_usd超过预算上限

Result 字段

字段类型描述
is_errorbooleanQuery 是否以错误结束
duration_msinteger总墙钟时间
duration_api_msintegerAPI 调用耗时
num_turnsinteger对话轮次数
resultstring最终文本结果
total_cost_usdfloat总花费(USD)
usageobject聚合 token 用量
modelUsageobject按模型拆分的用量
permission_denialsarray被拒绝的工具调用列表
structured_outputany若启用结构化输出则为解析后的 JSON
errorsstring[]错误信息列表(当 is_error: true

4.6 Stream event 消息

Token 级流式输出(需 --include-partial-messages)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
{
  "type": "stream_event",
  "uuid": "550e8400-e29b-41d4-a716-446655440005",
  "session_id": "550e8400-e29b-41d4-a716-446655440001",
  "parent_tool_use_id": null,
  "event": {
    "type": "content_block_delta",
    "index": 0,
    "delta": {
      "type": "text_delta",
      "text": "Hello"
    }
  }
}

Stream event 类型

Event Type描述
message_startAssistant 消息开始
content_block_startContent block 开始
content_block_deltaContent 增量更新
content_block_stopContent block 结束
message_delta消息元数据更新
message_stopAssistant 消息结束

5. 流式模式

5.1 消息级流式(默认)

未启用 --include-partial-messages 时,消息以完整形式送达:

1
system → assistant → user → assistant → user → assistant → result

消息序列示例:

1
2
3
{"type":"system","subtype":"init",...}
{"type":"assistant","message":{"content":[{"type":"text","text":"Full response here"}]},...}
{"type":"result","subtype":"success",...}

5.2 Token 级流式

启用 --include-partial-messages 后,token 将实时流出:

1
system → stream_event* → assistant → stream_event* → assistant → result

Token 序列示例:

1
2
3
4
5
6
7
8
{"type":"system","subtype":"init",...}
{"type":"stream_event","event":{"type":"message_start",...}}
{"type":"stream_event","event":{"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}}
{"type":"stream_event","event":{"type":"content_block_delta","delta":{"text":"Hello"}}}
{"type":"stream_event","event":{"type":"content_block_delta","delta":{"text":" world"}}}
{"type":"stream_event","event":{"type":"content_block_stop",...}}
{"type":"assistant","message":{"content":[{"type":"text","text":"Hello world"}]},...}
{"type":"result","subtype":"success",...}

5.3 抽取流式文本

实时展示文本的伪代码:

1
2
3
4
5
6
for each message in stream:
    if message.type == "stream_event":
        event = message.event
        if event.type == "content_block_delta":
            if event.delta.type == "text_delta":
                print(event.delta.text)  // 不换行,追加到输出

6. 工具系统

6.1 内置工具

工具描述关键参数
Read读取文件内容file_path, offset, limit
Write创建/覆盖文件file_path, content
Edit文件内查找替换file_path, old_string, new_string
Glob文件模式匹配pattern, path
Grep搜索文件内容pattern, path, output_mode
Bash执行 shell 命令command, timeout
WebFetch拉取 URL 内容url, prompt
WebSearchWeb 搜索query
Task启动子智能体prompt, subagent_type
TodoWrite管理任务列表todos

6.2 工具输入 Schema

Read 工具:

1
2
3
4
5
{
  "file_path": "/absolute/path/to/file",
  "offset": 0,
  "limit": 2000
}

Edit 工具:

1
2
3
4
5
6
{
  "file_path": "/absolute/path/to/file",
  "old_string": "text to find",
  "new_string": "replacement text",
  "replace_all": false
}

Bash 工具:

1
2
3
4
5
6
{
  "command": "ls -la",
  "timeout": 120000,
  "description": "List directory contents",
  "run_in_background": false
}

Glob 工具:

1
2
3
4
{
  "pattern": "**/*.rb",
  "path": "/search/directory"
}

Grep 工具:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
  "pattern": "function\\s+\\w+",
  "path": "/search/path",
  "glob": "*.js",
  "output_mode": "content",
  "-i": true,
  "-n": true,
  "-C": 3,
  "head_limit": 100
}

6.3 工具过滤

白名单(仅这些工具可用):

1
claude -p --allowed-tools "Read,Glob,Grep" -- "Find files"

黑名单(这些工具不可用):

1
claude -p --disallowed-tools "Bash,Write,Edit" -- "Analyze code"

7. MCP 集成

Model Context Protocol(MCP)用于接入自定义工具。

7.1 MCP Server 类型

类型传输方式使用场景
stdiostdin/stdout本地进程,自定义工具
sseServer-Sent Events远程流式 server
httpHTTP POST远程请求-响应 server

7.2 MCP 配置文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
{
  "mcpServers": {
    "my-tools": {
      "command": "python",
      "args": ["mcp_server.py"],
      "env": {
        "API_KEY": "secret"
      }
    },
    "remote-tools": {
      "type": "sse",
      "url": "https://mcp.example.com/sse",
      "headers": {
        "Authorization": "Bearer token"
      }
    }
  }
}

用法:

1
claude -p --mcp-config /path/to/config.json -- "Use my custom tools"

7.3 MCP 工具命名

MCP 工具采用命名空间形式:mcp__<server>__<tool>

示例:mcp__ruby-tools__calculator

7.4 MCP Server 协议(stdio)

MCP server 通过 stdin/stdout 以 JSON-RPC 2.0 通信。

Initialize 握手

客户端请求:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "clientInfo": {
      "name": "claude-code",
      "version": "2.1.3"
    }
  }
}

服务端响应:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2024-11-05",
    "serverInfo": {
      "name": "my-tools",
      "version": "1.0.0"
    },
    "capabilities": {
      "tools": {"listChanged": false}
    }
  }
}

列出工具(List Tools)

请求:

1
{"jsonrpc": "2.0", "id": 2, "method": "tools/list", "params": {}}

响应:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "tools": [
      {
        "name": "calculator",
        "description": "Performs arithmetic operations",
        "inputSchema": {
          "type": "object",
          "properties": {
            "operation": {"type": "string", "enum": ["add", "subtract", "multiply", "divide"]},
            "a": {"type": "number"},
            "b": {"type": "number"}
          },
          "required": ["operation", "a", "b"]
        }
      }
    ]
  }
}

调用工具(Call Tool)

请求:

1
2
3
4
5
6
7
8
9
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "calculator",
    "arguments": {"operation": "multiply", "a": 7, "b": 6}
  }
}

响应:

1
2
3
4
5
6
7
8
9
{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      {"type": "text", "text": "7 multiply 6 = 42"}
    ]
  }
}

7.5 实现一个 MCP Server

最小 stdio MCP server 的伪代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
function main():
    while line = read_stdin():
        request = json_parse(line)
        response = handle_request(request)
        if response:
            write_stdout(json_stringify(response))

function handle_request(request):
    match request.method:
        case "initialize":
            return {
                jsonrpc: "2.0",
                id: request.id,
                result: {
                    protocolVersion: "2024-11-05",
                    serverInfo: {name: "my-server", version: "1.0"},
                    capabilities: {tools: {listChanged: false}}
                }
            }
        case "initialized":
            return null  // 通知(notification),无需响应
        case "tools/list":
            return {
                jsonrpc: "2.0",
                id: request.id,
                result: {tools: get_tool_definitions()}
            }
        case "tools/call":
            result = call_tool(request.params.name, request.params.arguments)
            return {
                jsonrpc: "2.0",
                id: request.id,
                result: {content: [{type: "text", text: result}]}
            }

8. 会话管理

8.1 会话生命周期

1
2
3
4
5
6
7
8
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│    开始      │────>│    活跃      │────>│    结束      │
│ (新 UUID)  │     │  (queries) │     │  (已存储)   │
└─────────────┘     └──────┬──────┘     └──────┬──────┘
                           │                   │
                           │    resume/        │
                           │    continue       │
                           │<──────────────────┘

8.2 启动新会话

1
claude -p --output-format stream-json --verbose -- "Hello"

system 消息将包含新的 session_id

8.3 恢复会话

通过 Session ID:

1
claude -p --resume "550e8400-e29b-41d4-a716-446655440001" -- "Continue our work"

最近一次会话:

1
claude -p --continue -- "Continue where we left off"

8.4 会话存储

会话本地存储路径:

  • macOS/Linux: ~/.claude/sessions/
  • Windows: %USERPROFILE%\.claude\sessions\

9. 权限系统

9.1 权限模式

模式描述
default对敏感操作进行提示确认
acceptEdits自动批准文件编辑
bypassPermissions跳过所有权限检查
plan规划模式,不执行

9.2 使用权限模式

1
2
3
4
5
# 跳过所有权限检查(仅建议在沙箱环境使用)
claude -p --dangerously-skip-permissions -- "Do something"

# 自动接受编辑
claude -p --permission-mode acceptEdits -- "Refactor code"

9.3 权限拒绝(Permission Denials)

当工具被拒绝时,会在 result 中体现:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
  "type": "result",
  "permission_denials": [
    {
      "tool_name": "Bash",
      "tool_use_id": "toolu_01ABC",
      "tool_input": {"command": "rm -rf /"}
    }
  ]
}

10. 配置选项

10.1 完整选项参考

选项类型默认值CLI 参数描述
modelstringauto--model使用的模型
max_turnsintegerunlimited--max-turns最大对话轮次数
max_budget_usdfloatunlimited--max-budget-usd最大花费
system_promptstringbuilt-in--system-prompt自定义 system prompt
allowed_toolsstring[]all--allowed-tools工具白名单
disallowed_toolsstring[]none--disallowed-tools工具黑名单
permission_modestring“default”--permission-mode权限模式
mcp_serversobject{}--mcp-configMCP server 配置
include_partial_messagesbooleanfalse--include-partial-messagestoken 流式
resumestringnull--resume恢复会话 ID
continue_sessionbooleanfalse--continue继续最近一次会话
cwdstringprocess cwd(process cwd)工作目录

10.2 模型选择

别名完整名称特性
opusclaude-opus-4-5-20251101能力最强,成本最高
sonnetclaude-sonnet-4-5-20250929性能/成本平衡
haikuclaude-haiku-4-5-20251001最快,成本最低

10.3 System prompt 选项

替换默认:

1
claude -p --system-prompt "You are a helpful assistant" -- "Hello"

追加到默认:

1
claude -p --append-system-prompt "Focus on Ruby code" -- "Hello"

11. 错误处理

11.1 错误 result 类型

Subtype原因恢复方式
error_max_turns达到轮次上限增加 max_turns
error_max_budget_usd预算耗尽增加预算
error_during_execution运行时失败检查 errors 字段

11.2 错误响应示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
  "type": "result",
  "subtype": "error_during_execution",
  "is_error": true,
  "errors": [
    "Failed to connect to MCP server: connection refused"
  ],
  "total_cost_usd": 0.001,
  "num_turns": 0
}

11.3 JSON-RPC 错误(MCP)

CodeMessage含义
-32700Parse errorJSON 无法解析
-32600Invalid Request请求格式不正确
-32601Method not found方法不存在
-32602Invalid params参数不合法
-32603Internal error服务器内部错误

12. 实现指南

12.1 最小客户端(伪代码)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
function query(prompt, options):
    cmd = build_command(prompt, options)
    process = spawn(cmd)

    for line in process.stdout:
        if line is empty:
            continue

        message = json_parse(line)
        yield message

        if message.type == "result":
            break

function build_command(prompt, options):
    cmd = ["claude", "--print", "--output-format", "stream-json", "--verbose"]

    if options.model:
        cmd.append("--model", options.model)

    if options.max_turns:
        cmd.append("--max-turns", string(options.max_turns))

    if options.system_prompt:
        cmd.append("--system-prompt", options.system_prompt)

    if options.include_partial_messages:
        cmd.append("--include-partial-messages")

    if options.permission_mode == "bypassPermissions":
        cmd.append("--dangerously-skip-permissions")

    if options.mcp_config_path:
        cmd.append("--mcp-config", options.mcp_config_path)

    cmd.append("--")
    cmd.append(prompt)

    return cmd

12.2 消息处理器模式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
function handle_messages(stream):
    session_id = null

    for message in stream:
        match message.type:
            case "system":
                session_id = message.session_id
                log("Session started:", session_id)
                log("Model:", message.model)
                log("Tools:", message.tools)

            case "assistant":
                for block in message.message.content:
                    if block.type == "text":
                        print(block.text)
                    elif block.type == "tool_use":
                        log("[Tool:", block.name, "]")

            case "user":
                for block in message.message.content:
                    if block.type == "tool_result":
                        log("[Result received]")

            case "stream_event":
                event = message.event
                if event.type == "content_block_delta":
                    if event.delta.type == "text_delta":
                        print_no_newline(event.delta.text)

            case "result":
                print("")
                log("Completed:", message.subtype)
                log("Turns:", message.num_turns)
                log("Cost: $", message.total_cost_usd)
                return message

12.3 MCP Server 模板

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
class MCPServer:
    tools = {}

    function register_tool(name, description, schema, handler):
        tools[name] = {
            name: name,
            description: description,
            schema: schema,
            handler: handler
        }

    function run():
        while line = stdin.readline():
            request = json_parse(line)
            response = dispatch(request)
            if response:
                stdout.writeline(json_stringify(response))

    function dispatch(request):
        match request.method:
            case "initialize":
                return init_response(request.id)
            case "initialized":
                return null
            case "tools/list":
                return list_tools_response(request.id)
            case "tools/call":
                return call_tool_response(request.id, request.params)
            default:
                return error_response(request.id, -32601, "Method not found")

    function init_response(id):
        return {
            jsonrpc: "2.0",
            id: id,
            result: {
                protocolVersion: "2024-11-05",
                serverInfo: {name: "server", version: "1.0"},
                capabilities: {tools: {listChanged: false}}
            }
        }

    function list_tools_response(id):
        tool_list = []
        for name, tool in tools:
            tool_list.append({
                name: tool.name,
                description: tool.description,
                inputSchema: tool.schema
            })
        return {jsonrpc: "2.0", id: id, result: {tools: tool_list}}

    function call_tool_response(id, params):
        tool = tools[params.name]
        if not tool:
            return {
                jsonrpc: "2.0",
                id: id,
                result: {
                    content: [{type: "text", text: "Unknown tool"}],
                    isError: true
                }
            }

        try:
            result = tool.handler(params.arguments)
            return {
                jsonrpc: "2.0",
                id: id,
                result: {
                    content: [{type: "text", text: string(result)}]
                }
            }
        catch error:
            return {
                jsonrpc: "2.0",
                id: id,
                result: {
                    content: [{type: "text", text: error.message}],
                    isError: true
                }
            }

12.4 Token 成本计算

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
function calculate_cost(usage, model):
    // 每百万 token 的价格(示例费率)
    rates = {
        "claude-opus-4-5": {input: 15.00, output: 75.00},
        "claude-sonnet-4-5": {input: 3.00, output: 15.00},
        "claude-haiku-4-5": {input: 0.80, output: 4.00}
    }

    rate = rates[model]
    input_cost = (usage.input_tokens / 1_000_000) * rate.input
    output_cost = (usage.output_tokens / 1_000_000) * rate.output

    // Cache read 通常更便宜(一般是 input 成本的 10%)
    cache_read_cost = (usage.cache_read_input_tokens / 1_000_000) * (rate.input * 0.1)

    // Cache creation 的成本与 input 相同
    cache_create_cost = (usage.cache_creation_input_tokens / 1_000_000) * rate.input

    return input_cost + output_cost + cache_read_cost + cache_create_cost

附录 A:真实世界 JSON 示例

A.1 实际 System 消息

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
  "type": "system",
  "subtype": "init",
  "cwd": "/private/tmp/playing",
  "session_id": "5620625c-b4c7-4185-9b2b-8de430dd2184",
  "tools": [
    "Task", "TaskOutput", "Bash", "Glob", "Grep", "ExitPlanMode",
    "Read", "Edit", "Write", "NotebookEdit", "WebFetch", "TodoWrite",
    "WebSearch", "KillShell", "AskUserQuestion", "Skill", "EnterPlanMode"
  ],
  "mcp_servers": [
    {"name": "ruby-tools", "status": "connected"}
  ],
  "model": "claude-sonnet-4-5-20250929",
  "permissionMode": "default",
  "slash_commands": ["compact", "context", "cost", "init", "pr-comments", "release-notes", "review", "security-review"],
  "apiKeySource": "ANTHROPIC_API_KEY",
  "claude_code_version": "2.1.3",
  "output_style": "default",
  "agents": ["Bash", "general-purpose", "statusline-setup", "Explore", "Plan", "claude-code-guide"],
  "skills": [],
  "plugins": [{"name": "gopls-lsp", "path": "/Users/sam/.claude/plugins/cache/claude-plugins-official/gopls-lsp/1.0.0"}],
  "uuid": "95625b7e-3117-483b-95c9-47e54bb9ec70"
}

A.2 实际包含工具调用的 Assistant 消息

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{
  "type": "assistant",
  "message": {
    "model": "claude-sonnet-4-5-20250929",
    "id": "msg_01Rf5Yc8FdberfJBxNjTNk3W",
    "type": "message",
    "role": "assistant",
    "content": [
      {"type": "text", "text": "I'll use the ruby-tools MCP server to get the current time and generate a random number."},
      {"type": "tool_use", "id": "toolu_017K5vf", "name": "mcp__ruby-tools__current_time", "input": {}},
      {"type": "tool_use", "id": "toolu_018ABC", "name": "mcp__ruby-tools__random_number", "input": {"min": 1, "max": 100}}
    ],
    "stop_reason": null,
    "stop_sequence": null,
    "usage": {
      "input_tokens": 2,
      "cache_creation_input_tokens": 4722,
      "cache_read_input_tokens": 13367,
      "cache_creation": {"ephemeral_5m_input_tokens": 4722, "ephemeral_1h_input_tokens": 0},
      "output_tokens": 28,
      "service_tier": "standard"
    },
    "context_management": null
  },
  "parent_tool_use_id": null,
  "session_id": "5620625c-b4c7-4185-9b2b-8de430dd2184",
  "uuid": "eda52225-597f-4a1f-8ca6-a6bcd94934ac"
}

A.3 实际工具结果(Tool Result)消息

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
  "type": "user",
  "message": {
    "role": "user",
    "content": [
      {
        "tool_use_id": "toolu_01LsrzxpC42FnYPxepJfr9pg",
        "type": "tool_result",
        "content": "/private/tmp/playing/quick_start.rb\n/private/tmp/playing/advanced_examples.rb\n/private/tmp/playing/claude_agent_sdk_demo.rb"
      }
    ]
  },
  "parent_tool_use_id": null,
  "session_id": "c8775347-af93-45c7-b9bf-a6e009483fa5",
  "uuid": "4ffd3635-d0fb-4057-85e2-0f0a4c302fec",
  "tool_use_result": {
    "filenames": [
      "/private/tmp/playing/quick_start.rb",
      "/private/tmp/playing/advanced_examples.rb",
      "/private/tmp/playing/claude_agent_sdk_demo.rb"
    ],
    "durationMs": 345,
    "numFiles": 3,
    "truncated": false
  }
}

A.4 实际 Result 消息

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
{
  "type": "result",
  "subtype": "success",
  "is_error": false,
  "duration_ms": 7040,
  "duration_api_ms": 12311,
  "num_turns": 2,
  "result": "I found 3 Ruby files in the directory:\n\n1. `quick_start.rb`\n2. `advanced_examples.rb`\n3. `claude_agent_sdk_demo.rb`",
  "session_id": "c8775347-af93-45c7-b9bf-a6e009483fa5",
  "total_cost_usd": 0.0186724,
  "usage": {
    "input_tokens": 7,
    "cache_creation_input_tokens": 440,
    "cache_read_input_tokens": 35858,
    "output_tokens": 114,
    "server_tool_use": {"web_search_requests": 0, "web_fetch_requests": 0},
    "service_tier": "standard",
    "cache_creation": {"ephemeral_1h_input_tokens": 0, "ephemeral_5m_input_tokens": 440}
  },
  "modelUsage": {
    "claude-haiku-4-5-20251001": {
      "inputTokens": 2,
      "outputTokens": 170,
      "cacheReadInputTokens": 10531,
      "cacheCreationInputTokens": 0,
      "webSearchRequests": 0,
      "costUSD": 0.0019051,
      "contextWindow": 200000,
      "maxOutputTokens": 64000
    },
    "claude-sonnet-4-5-20250929": {
      "inputTokens": 9,
      "outputTokens": 143,
      "cacheReadInputTokens": 39900,
      "cacheCreationInputTokens": 439,
      "webSearchRequests": 0,
      "costUSD": 0.0157882,
      "contextWindow": 200000,
      "maxOutputTokens": 64000
    }
  },
  "permission_denials": [],
  "uuid": "34cf1a3e-8b9f-481e-ba6f-c9e934b09424"
}

A.5 实际 Stream event(Token delta)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
{
  "type": "stream_event",
  "event": {
    "type": "content_block_delta",
    "index": 0,
    "delta": {
      "type": "text_delta",
      "text": "Dogs are loyal"
    }
  },
  "session_id": "4a7c99c6-e08a-4e3c-b6ce-17c33ae8bb92",
  "parent_tool_use_id": null,
  "uuid": "2bc3e3c8-d9f2-48e8-bd72-b828bbbf3732"
}

附录 B:完整消息流示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# Query: "List Ruby files and count them"

# 1. System init
{"type":"system","subtype":"init","session_id":"abc-123","model":"claude-sonnet-4-5-20250929","tools":["Glob","Bash",...],...}

# 2. Claude responds with tool use
{"type":"assistant","message":{"content":[{"type":"text","text":"I'll find the Ruby files."},{"type":"tool_use","id":"toolu_1","name":"Glob","input":{"pattern":"**/*.rb"}}]},...}

# 3. Tool result
{"type":"user","message":{"content":[{"type":"tool_result","tool_use_id":"toolu_1","content":"file1.rb\nfile2.rb\nfile3.rb"}]},...}

# 4. Claude's final response
{"type":"assistant","message":{"content":[{"type":"text","text":"I found 3 Ruby files:\n1. file1.rb\n2. file2.rb\n3. file3.rb"}]},...}

# 5. Query complete
{"type":"result","subtype":"success","num_turns":2,"result":"I found 3 Ruby files...","total_cost_usd":0.0156,...}

附录 B(续):Token 流式输出流程示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# With --include-partial-messages

{"type":"system","subtype":"init",...}
{"type":"stream_event","event":{"type":"message_start","message":{"model":"claude-sonnet-4-5-20250929",...}}}
{"type":"stream_event","event":{"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}}
{"type":"stream_event","event":{"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Hello"}}}
{"type":"stream_event","event":{"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" world"}}}
{"type":"stream_event","event":{"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"!"}}}
{"type":"stream_event","event":{"type":"content_block_stop","index":0}}
{"type":"stream_event","event":{"type":"message_delta","delta":{"stop_reason":"end_turn"},...}}
{"type":"stream_event","event":{"type":"message_stop"}}
{"type":"assistant","message":{"content":[{"type":"text","text":"Hello world!"}]},...}
{"type":"result","subtype":"success",...}

附录 C:参考资料