# Anthropic Messages API 端到端测试用例与 Mock 设计 本文档针对 `POST /v1/messages` 接口,设计端到端测试用例及对应的 Mock 返回值结构。 --- ## 一、测试场景总览 | 分类 | 测试用例 | 优先级 | |------|----------|--------| | 基础对话 | 1. 单轮纯文本对话 | P0 | | 基础对话 | 2. 多轮对话(user + assistant + user) | P0 | | 系统消息 | 3. 字符串 system prompt | P0 | | 系统消息 | 4. 数组 system prompt(多文本块) | P1 | | 消息内容 | 5. 用户消息含图片(base64 source) | P1 | | 消息内容 | 6. 用户消息含图片(URL source) | P1 | | 消息内容 | 7. 用户消息含 tool_result 内容块 | P0 | | 工具调用 | 8. 单工具调用 | P0 | | 工具调用 | 9. 并行多工具调用 | P1 | | 工具调用 | 10. tool_choice 为 "none" | P2 | | 工具调用 | 11. tool_choice 指定具体工具名 | P2 | | 工具调用 | 12. tool_choice 为 "any"(强制调用) | P2 | | 参数控制 | 13. temperature + top_p + top_k | P1 | | 参数控制 | 14. max_tokens 截断 | P1 | | 参数控制 | 15. stop_sequences 截断 | P2 | | 扩展思考 | 16. thinking enabled(extended thinking) | P1 | | 扩展思考 | 17. thinking adaptive | P2 | | 输出格式 | 18. output_config 为 json_object | P1 | | 输出格式 | 19. output_config 为 json_schema(structured output) | P1 | | 流式响应 | 20. 流式文本响应(SSE) | P0 | | 流式响应 | 21. 流式工具调用 | P1 | | 流式响应 | 22. 流式 + thinking 内容 | P1 | | 缓存控制 | 23. system prompt cache_control(ephemeral) | P2 | | 元数据 | 24. metadata.user_id | P2 | | 错误处理 | 25. 无效 model 返回 400 | P1 | | 错误处理 | 26. 缺少 max_tokens 返回 400 | P1 | | 错误处理 | 27. 缺少 messages 返回 400 | P1 | | 错误处理 | 28. 内容安全策略拒绝(refusal) | P2 | | 其他 | 29. disable_parallel_tool_use | P2 | | 其他 | 30. container 复用 | P2 | --- ## 二、测试用例详情 ### 用例 1:单轮纯文本对话 **请求:** ```json { "model": "claude-opus-4-7", "max_tokens": 1024, "messages": [ { "role": "user", "content": "你好,请介绍一下你自己" } ] } ``` **期望 Mock 响应(200 OK):** ```json { "id": "msg_01test001", "type": "message", "role": "assistant", "content": [ { "type": "text", "text": "你好!我是 Claude,由 Anthropic 开发的 AI 助手。我可以帮你回答问题、写作、编程、数学推理、数据分析等多种任务。我的知识截止到 2025 年 1 月。请问有什么我可以帮你的?" } ], "model": "claude-opus-4-7", "stop_reason": "end_turn", "stop_sequence": null, "usage": { "input_tokens": 15, "output_tokens": 68 } } ``` **验证点:** - `content[0].type` == `"text"` - `stop_reason` == `"end_turn"` - `usage` 字段完整 --- ### 用例 2:多轮对话 **请求:** ```json { "model": "claude-opus-4-7", "max_tokens": 1024, "messages": [ { "role": "user", "content": "什么是 Go 语言的 interface?" }, { "role": "assistant", "content": "Go 语言的 interface 是一种类型,它定义了一组方法签名。任何实现了这些方法的类型都自动实现了该 interface,无需显式声明。这是 Go 语言"隐式接口"设计的核心特点。" }, { "role": "user", "content": "能举个例子吗?" } ] } ``` **期望 Mock 响应(200 OK):** ```json { "id": "msg_01test002", "type": "message", "role": "assistant", "content": [ { "type": "text", "text": "当然。例如定义一个 `Reader` interface:\n\n```go\ntype Reader interface {\n Read(p []byte) (n int, err error)\n}\n```\n\n`os.File` 和 `bytes.Buffer` 都实现了 `Read` 方法,所以它们都自动实现了 `Reader` interface,无需显式声明 `implements Reader`。" } ], "model": "claude-opus-4-7", "stop_reason": "end_turn", "stop_sequence": null, "usage": { "input_tokens": 120, "output_tokens": 85 } } ``` --- ### 用例 3:字符串 system prompt **请求:** ```json { "model": "claude-opus-4-7", "max_tokens": 1024, "system": "你是一个专业的编程助手,请用简洁的语言回答问题。", "messages": [ { "role": "user", "content": "什么是递归?" } ] } ``` **期望 Mock 响应(200 OK):** ```json { "id": "msg_01test003", "type": "message", "role": "assistant", "content": [ { "type": "text", "text": "递归是一种函数调用自身来解决问题的方法。它包含两个关键部分:\n\n1. **基准情况**:直接返回结果的终止条件\n2. **递归情况**:将问题分解为更小的子问题,调用自身解决\n\n例如计算阶乘:`n! = n × (n-1)!`,基准情况是 `0! = 1`。" } ], "model": "claude-opus-4-7", "stop_reason": "end_turn", "stop_sequence": null, "usage": { "input_tokens": 45, "output_tokens": 72 } } ``` --- ### 用例 4:数组 system prompt(多文本块) **请求:** ```json { "model": "claude-opus-4-7", "max_tokens": 1024, "system": [ { "type": "text", "text": "你是一个专业的编程助手。" }, { "type": "text", "text": "请用简洁的语言回答问题,并尽量提供代码示例。" } ], "messages": [ { "role": "user", "content": "什么是闭包?" } ] } ``` **期望 Mock 响应(200 OK):** ```json { "id": "msg_01test004", "type": "message", "role": "assistant", "content": [ { "type": "text", "text": "闭包是指函数可以访问并"记住"其定义时所在作用域中的变量,即使在该作用域已经执行完毕后仍然可以访问。\n\n```javascript\nfunction makeCounter() {\n let count = 0;\n return function() {\n count++;\n return count;\n };\n}\nconst counter = makeCounter();\nconsole.log(counter()); // 1\nconsole.log(counter()); // 2\n```\n\n`count` 变量被内部函数"捕获",形成了闭包。" } ], "model": "claude-opus-4-7", "stop_reason": "end_turn", "stop_sequence": null, "usage": { "input_tokens": 85, "output_tokens": 95 } } ``` --- ### 用例 5:用户消息含图片(base64 source) **请求:** ```json { "model": "claude-opus-4-7", "max_tokens": 1024, "messages": [ { "role": "user", "content": [ { "type": "text", "text": "这张图片里有什么?" }, { "type": "image", "source": { "type": "base64", "media_type": "image/jpeg", "data": "/9j/4AAQSkZJRgABAQEAYABgAAD..." } } ] } ] } ``` **期望 Mock 响应(200 OK):** ```json { "id": "msg_01test005", "type": "message", "role": "assistant", "content": [ { "type": "text", "text": "图片中有一只橘色的猫,它正躺在棕色的沙发上晒太阳。猫的毛色是橘白相间的,眼睛是绿色的,看起来非常放松和满足。" } ], "model": "claude-opus-4-7", "stop_reason": "end_turn", "stop_sequence": null, "usage": { "input_tokens": 1280, "output_tokens": 45 } } ``` --- ### 用例 6:用户消息含图片(URL source) **请求:** ```json { "model": "claude-opus-4-7", "max_tokens": 1024, "messages": [ { "role": "user", "content": [ { "type": "text", "text": "请描述这张图片" }, { "type": "image", "source": { "type": "url", "url": "https://example.com/images/landscape.jpg" } } ] } ] } ``` **期望 Mock 响应(200 OK):** ```json { "id": "msg_01test006", "type": "message", "role": "assistant", "content": [ { "type": "text", "text": "这是一幅美丽的自然风景图。前景是一片翠绿的草地,点缀着野花。中景有一条蜿蜒的小河,河水清澈见底。远处是连绵起伏的青山,山顶覆盖着白雪。天空湛蓝,飘着几朵白云。整体画面给人一种宁静祥和的感觉。" } ], "model": "claude-opus-4-7", "stop_reason": "end_turn", "stop_sequence": null, "usage": { "input_tokens": 1520, "output_tokens": 82 } } ``` --- ### 用例 7:用户消息含 tool_result 内容块 **请求:** ```json { "model": "claude-opus-4-7", "max_tokens": 1024, "messages": [ { "role": "user", "content": "北京天气怎么样?" }, { "role": "assistant", "content": [ { "type": "tool_use", "id": "toolu_01test001", "name": "get_weather", "input": {"city": "北京"} } ] }, { "role": "user", "content": [ { "type": "tool_result", "tool_use_id": "toolu_01test001", "content": "北京今天晴,气温 25°C,东南风 2 级。" } ] } ], "tools": [ { "name": "get_weather", "description": "获取指定城市的天气信息", "input_schema": { "type": "object", "properties": { "city": { "type": "string", "description": "城市名称" } }, "required": ["city"] } } ] } ``` **期望 Mock 响应(200 OK):** ```json { "id": "msg_01test007", "type": "message", "role": "assistant", "content": [ { "type": "text", "text": "北京今天天气很好,晴天,气温 25°C,东南风 2 级,非常适合外出活动。" } ], "model": "claude-opus-4-7", "stop_reason": "end_turn", "stop_sequence": null, "usage": { "input_tokens": 250, "output_tokens": 35 } } ``` **验证点:** - 能正确理解 tool_result 内容 - 基于工具返回结果生成自然语言回复 --- ### 用例 8:单工具调用 **请求:** ```json { "model": "claude-opus-4-7", "max_tokens": 1024, "messages": [ { "role": "user", "content": "北京天气怎么样?" } ], "tools": [ { "name": "get_weather", "description": "获取指定城市的天气信息", "input_schema": { "type": "object", "properties": { "city": { "type": "string", "description": "城市名称" } }, "required": ["city"] } } ], "tool_choice": { "type": "auto" } } ``` **期望 Mock 响应(200 OK):** ```json { "id": "msg_01test008", "type": "message", "role": "assistant", "content": [ { "type": "tool_use", "id": "toolu_01test008", "name": "get_weather", "input": { "city": "北京" } } ], "model": "claude-opus-4-7", "stop_reason": "tool_use", "stop_sequence": null, "usage": { "input_tokens": 180, "output_tokens": 42 } } ``` **验证点:** - `stop_reason` == `"tool_use"` - `content[0].type` == `"tool_use"` - `input` 包含正确的参数 --- ### 用例 9:并行多工具调用 **请求:** ```json { "model": "claude-opus-4-7", "max_tokens": 1024, "messages": [ { "role": "user", "content": "帮我查一下北京、上海、广州三个城市的天气" } ], "tools": [ { "name": "get_weather", "description": "获取指定城市的天气信息", "input_schema": { "type": "object", "properties": { "city": {"type": "string"} }, "required": ["city"] } } ] } ``` **期望 Mock 响应(200 OK):** ```json { "id": "msg_01test009", "type": "message", "role": "assistant", "content": [ { "type": "tool_use", "id": "toolu_01test009a", "name": "get_weather", "input": {"city": "北京"} }, { "type": "tool_use", "id": "toolu_01test009b", "name": "get_weather", "input": {"city": "上海"} }, { "type": "tool_use", "id": "toolu_01test009c", "name": "get_weather", "input": {"city": "广州"} } ], "model": "claude-opus-4-7", "stop_reason": "tool_use", "stop_sequence": null, "usage": { "input_tokens": 200, "output_tokens": 120 } } ``` **验证点:** - `content` 数组包含 3 个 tool_use 块 - 每个 tool_use 有不同的 ID --- ### 用例 10:tool_choice 为 "none" **请求:** ```json { "model": "claude-opus-4-7", "max_tokens": 1024, "messages": [ { "role": "user", "content": "随便聊聊" } ], "tools": [ { "name": "get_weather", "description": "获取天气", "input_schema": { "type": "object", "properties": { "city": {"type": "string"} } } } ], "tool_choice": { "type": "none" } } ``` **期望 Mock 响应(200 OK):** ```json { "id": "msg_01test010", "type": "message", "role": "assistant", "content": [ { "type": "text", "text": "好的!今天天气不错,很适合聊天。你想聊些什么话题呢?可以是技术、生活、娱乐等任何你感兴趣的内容。" } ], "model": "claude-opus-4-7", "stop_reason": "end_turn", "stop_sequence": null, "usage": { "input_tokens": 150, "output_tokens": 42 } } ``` **验证点:** - 尽管定义了 tools,响应中不包含 tool_use 块 - 纯文本回复 --- ### 用例 11:tool_choice 指定具体工具名 **请求:** ```json { "model": "claude-opus-4-7", "max_tokens": 1024, "messages": [ { "role": "user", "content": "查天气" } ], "tools": [ { "name": "get_weather", "description": "获取天气", "input_schema": {"type": "object", "properties": {"city": {"type": "string"}}} }, { "name": "get_news", "description": "获取新闻", "input_schema": {"type": "object", "properties": {"topic": {"type": "string"}}} } ], "tool_choice": { "type": "tool", "name": "get_weather" } } ``` **期望 Mock 响应(200 OK):** ```json { "id": "msg_01test011", "type": "message", "role": "assistant", "content": [ { "type": "tool_use", "id": "toolu_01test011", "name": "get_weather", "input": {} } ], "model": "claude-opus-4-7", "stop_reason": "tool_use", "stop_sequence": null, "usage": { "input_tokens": 200, "output_tokens": 35 } } ``` **验证点:** - 强制使用了 `get_weather` 而非 `get_news` --- ### 用例 12:tool_choice 为 "any"(强制调用) **请求:** ```json { "model": "claude-opus-4-7", "max_tokens": 1024, "messages": [ { "role": "user", "content": "帮我做点什么" } ], "tools": [ { "name": "get_weather", "description": "获取天气", "input_schema": {"type": "object", "properties": {"city": {"type": "string"}}} } ], "tool_choice": { "type": "any" } } ``` **期望 Mock 响应(200 OK):** ```json { "id": "msg_01test012", "type": "message", "role": "assistant", "content": [ { "type": "tool_use", "id": "toolu_01test012", "name": "get_weather", "input": {} } ], "model": "claude-opus-4-7", "stop_reason": "tool_use", "stop_sequence": null, "usage": { "input_tokens": 150, "output_tokens": 30 } } ``` **验证点:** - 模型必须调用至少一个工具 --- ### 用例 13:temperature + top_p + top_k **请求:** ```json { "model": "claude-opus-4-7", "max_tokens": 1024, "messages": [ { "role": "user", "content": "写一首关于春天的短诗" } ], "temperature": 0.9, "top_p": 0.95, "top_k": 50 } ``` **期望 Mock 响应(200 OK):** ```json { "id": "msg_01test013", "type": "message", "role": "assistant", "content": [ { "type": "text", "text": "春风拂面花自开,\n柳絮飞舞满园香。\n燕归巢中呢喃语,\n万物复苏迎朝阳。" } ], "model": "claude-opus-4-7", "stop_reason": "end_turn", "stop_sequence": null, "usage": { "input_tokens": 25, "output_tokens": 32 } } ``` --- ### 用例 14:max_tokens 截断 **请求:** ```json { "model": "claude-opus-4-7", "max_tokens": 20, "messages": [ { "role": "user", "content": "请详细介绍一下人工智能的发展历史" } ] } ``` **期望 Mock 响应(200 OK):** ```json { "id": "msg_01test014", "type": "message", "role": "assistant", "content": [ { "type": "text", "text": "人工智能起源于1950年代,图灵提出了机器能否思考的问题。1956年达特茅斯会议正式确立了AI领域。" } ], "model": "claude-opus-4-7", "stop_reason": "max_tokens", "stop_sequence": null, "usage": { "input_tokens": 22, "output_tokens": 20 } } ``` **验证点:** - `stop_reason` == `"max_tokens"` - `output_tokens` == 20(等于 max_tokens) - 内容被截断 --- ### 用例 15:stop_sequences 截断 **请求:** ```json { "model": "claude-opus-4-7", "max_tokens": 1024, "messages": [ { "role": "user", "content": "从1数到10,每行一个数字" } ], "stop_sequences": ["5"] } ``` **期望 Mock 响应(200 OK):** ```json { "id": "msg_01test015", "type": "message", "role": "assistant", "content": [ { "type": "text", "text": "1\n2\n3\n4\n" } ], "model": "claude-opus-4-7", "stop_reason": "stop_sequence", "stop_sequence": "5", "usage": { "input_tokens": 22, "output_tokens": 10 } } ``` **验证点:** - `stop_reason` == `"stop_sequence"` - `stop_sequence` 字段包含触发截断的序列 --- ### 用例 16:thinking enabled(extended thinking) **请求:** ```json { "model": "claude-opus-4-7", "max_tokens": 4096, "messages": [ { "role": "user", "content": "一个房间里有3个灯泡,房间外有3个开关,每个开关控制一个灯泡。你只能进房间一次,如何确定哪个开关控制哪个灯泡?" } ], "thinking": { "type": "enabled", "budget_tokens": 2048 } } ``` **期望 Mock 响应(200 OK):** ```json { "id": "msg_01test016", "type": "message", "role": "assistant", "content": [ { "type": "thinking", "thinking": "这是一个经典的逻辑推理问题。我需要找到一种方法,通过一次观察来区分三个开关。关键是灯泡有两种可观察的状态:亮或灭。但如果只用亮灭,我只能区分一个开关(开的那个)。我需要找到另一种可观察的属性...温度!灯泡开着会发热。所以我可以:先开一个开关等一会儿,然后关掉,再开另一个开关,然后进房间。亮着的是第二个开关,热的是第一个开关,冷且灭的是第三个开关。" }, { "type": "text", "text": "解决方案如下:\n\n1. **打开第一个开关**,等待几分钟\n2. **关闭第一个开关**,**打开第二个开关**\n3. **立即进入房间**\n\n此时观察:\n- **亮着的灯** → 由第二个开关控制\n- **摸起来发热的灯** → 由第一个开关控制(因为开过几分钟)\n- **既不亮也不热的灯** → 由第三个开关控制" } ], "model": "claude-opus-4-7", "stop_reason": "end_turn", "stop_sequence": null, "usage": { "input_tokens": 95, "output_tokens": 280 } } ``` **验证点:** - `content` 包含 `thinking` 块和 `text` 块 - `output_tokens` 包含 thinking tokens --- ### 用例 17:thinking adaptive **请求:** ```json { "model": "claude-opus-4-7", "max_tokens": 4096, "messages": [ { "role": "user", "content": "请帮我分析一下这个算法问题" } ], "thinking": { "type": "adaptive", "budget_tokens": 1024 } } ``` **期望 Mock 响应(200 OK):** ```json { "id": "msg_01test017", "type": "message", "role": "assistant", "content": [ { "type": "thinking", "thinking": "用户提到了一个算法问题,但没有具体说明是什么问题。我需要请用户提供更多细节。" }, { "type": "text", "text": "我很乐意帮你分析算法问题!不过你没有具体说明是什么问题。请详细描述一下:\n\n1. 问题的具体要求是什么?\n2. 输入输出的格式是怎样的?\n3. 有没有什么约束条件?\n\n有了这些信息后,我可以帮你分析解题思路和最优解法。" } ], "model": "claude-opus-4-7", "stop_reason": "end_turn", "stop_sequence": null, "usage": { "input_tokens": 35, "output_tokens": 95 } } ``` --- ### 用例 18:output_config 为 json_object **请求:** ```json { "model": "claude-opus-4-7", "max_tokens": 1024, "messages": [ { "role": "user", "content": "提取以下信息的姓名和年龄:张三,今年25岁,是一名工程师" } ], "output_config": { "format": { "type": "json_object" } } } ``` **期望 Mock 响应(200 OK):** ```json { "id": "msg_01test018", "type": "message", "role": "assistant", "content": [ { "type": "text", "text": "{\"name\": \"张三\", \"age\": 25, \"occupation\": \"工程师\"}" } ], "model": "claude-opus-4-7", "stop_reason": "end_turn", "stop_sequence": null, "usage": { "input_tokens": 45, "output_tokens": 28 } } ``` **验证点:** - `content[0].text` 是合法的 JSON 字符串 --- ### 用例 19:output_config 为 json_schema(structured output) **请求:** ```json { "model": "claude-opus-4-7", "max_tokens": 1024, "messages": [ { "role": "user", "content": "创建一个用户信息记录,姓名李四,年龄30岁" } ], "output_config": { "format": { "type": "json_schema", "schema": { "type": "object", "properties": { "name": {"type": "string"}, "age": {"type": "integer"}, "email": {"type": "string"} }, "required": ["name", "age"] } } } } ``` **期望 Mock 响应(200 OK):** ```json { "id": "msg_01test019", "type": "message", "role": "assistant", "content": [ { "type": "text", "text": "{\"name\": \"李四\", \"age\": 30}" } ], "model": "claude-opus-4-7", "stop_reason": "end_turn", "stop_sequence": null, "usage": { "input_tokens": 120, "output_tokens": 22 } } ``` **验证点:** - 输出严格符合 JSON schema 定义 - 不包含 schema 未定义的字段 --- ### 用例 20:流式文本响应(SSE) **请求:** ```json { "model": "claude-opus-4-7", "max_tokens": 1024, "messages": [ { "role": "user", "content": "你好" } ], "stream": true } ``` **期望 Mock 响应(200 OK, Content-Type: text/event-stream):** ``` event: message_start data: {"type":"message","id":"msg_01stream001","role":"assistant","content":[],"model":"claude-opus-4-7","stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":10,"output_tokens":0}} event: content_block_start data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}} event: content_block_delta data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"你"}} event: content_block_delta data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"好"}} event: content_block_delta data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"!"}} event: content_block_delta data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"我"}} event: content_block_delta data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"是"}} event: content_block_delta data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Claude"}} event: content_block_delta data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":","}} event: content_block_delta data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"很高兴"}} event: content_block_delta data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"为你"}} event: content_block_delta data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"服务"}} event: content_block_delta data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"。"}} event: content_block_stop data: {"type":"content_block_stop","index":0} event: message_delta data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"output_tokens":8}} event: message_stop data: {"type":"message_stop"} ``` **验证点:** - 事件顺序:message_start → content_block_start → content_block_delta* → content_block_stop → message_delta → message_stop - `message_start` 包含完整的 message 对象 - 每个 `content_block_delta` 包含增量文本 - `message_delta` 包含 stop_reason 和最终 usage - 以 `message_stop` 结束 --- ### 用例 21:流式工具调用 **请求:** ```json { "model": "claude-opus-4-7", "max_tokens": 1024, "messages": [ { "role": "user", "content": "北京天气怎么样?" } ], "tools": [ { "name": "get_weather", "description": "获取天气", "input_schema": { "type": "object", "properties": { "city": {"type": "string"} }, "required": ["city"] } } ], "stream": true } ``` **期望 Mock 响应(200 OK, Content-Type: text/event-stream):** ``` event: message_start data: {"type":"message","id":"msg_01stream003","role":"assistant","content":[],"model":"claude-opus-4-7","stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":180,"output_tokens":0}} event: content_block_start data: {"type":"content_block_start","index":0,"content_block":{"type":"tool_use","id":"toolu_01stream003","name":"get_weather"}} event: content_block_delta data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":""}} event: content_block_delta data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"{\""}} event: content_block_delta data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"city"}} event: content_block_delta data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"\":\""}} event: content_block_delta data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"北京"}} event: content_block_delta data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"}\""}} event: content_block_stop data: {"type":"content_block_stop","index":0} event: message_delta data: {"type":"message_delta","delta":{"stop_reason":"tool_use","stop_sequence":null},"usage":{"output_tokens":42}} event: message_stop data: {"type":"message_stop"} ``` **验证点:** - `content_block_start` 包含 tool_use 类型和工具名 - `input_json_delta` 逐步拼接完整的 JSON 输入 - `stop_reason` == `"tool_use"` --- ### 用例 22:流式 + thinking 内容 **请求:** ```json { "model": "claude-opus-4-7", "max_tokens": 4096, "messages": [ { "role": "user", "content": "1+1=?" } ], "thinking": { "type": "enabled", "budget_tokens": 1024 }, "stream": true } ``` **期望 Mock 响应(200 OK, Content-Type: text/event-stream):** ``` event: message_start data: {"type":"message","id":"msg_01stream004","role":"assistant","content":[],"model":"claude-opus-4-7","stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":30,"output_tokens":0}} event: content_block_start data: {"type":"content_block_start","index":0,"content_block":{"type":"thinking","thinking":""}} event: content_block_delta data: {"type":"content_block_delta","index":0,"delta":{"type":"thinking_delta","thinking":"这是一个简单的"}} event: content_block_delta data: {"type":"content_block_delta","index":0,"delta":{"type":"thinking_delta","thinking":"数学问题。"}} event: content_block_stop data: {"type":"content_block_stop","index":0} event: content_block_start data: {"type":"content_block_start","index":1,"content_block":{"type":"text","text":""}} event: content_block_delta data: {"type":"content_block_delta","index":1,"delta":{"type":"text_delta","text":"1+1=2"}} event: content_block_stop data: {"type":"content_block_stop","index":1} event: message_delta data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"output_tokens":25}} event: message_stop data: {"type":"message_stop"} ``` **验证点:** - 先有 thinking 块,再有 text 块 - `thinking_delta` 类型正确 - 两个内容块有不同的 index --- ### 用例 23:system prompt cache_control(ephemeral) **请求:** ```json { "model": "claude-opus-4-7", "max_tokens": 1024, "system": [ { "type": "text", "text": "你是一个专业的编程助手。", "cache_control": { "type": "ephemeral" } } ], "messages": [ { "role": "user", "content": "你好" } ] } ``` **期望 Mock 响应(200 OK):** ```json { "id": "msg_01test023", "type": "message", "role": "assistant", "content": [ { "type": "text", "text": "你好!我是 Claude,很高兴为你服务。我是由 Anthropic 开发的 AI 助手,可以帮你解答问题、写作、编程等各种任务。请问有什么我可以帮你的?" } ], "model": "claude-opus-4-7", "stop_reason": "end_turn", "stop_sequence": null, "usage": { "input_tokens": 25, "output_tokens": 52, "cache_creation_input_tokens": 15, "cache_read_input_tokens": 0 } } ``` **验证点:** - `cache_creation_input_tokens` 反映缓存创建的 token 数 --- ### 用例 24:metadata.user_id **请求:** ```json { "model": "claude-opus-4-7", "max_tokens": 1024, "messages": [ { "role": "user", "content": "你好" } ], "metadata": { "user_id": "user_12345" } } ``` **期望 Mock 响应(200 OK):** ```json { "id": "msg_01test024", "type": "message", "role": "assistant", "content": [ { "type": "text", "text": "你好!我是 Claude,很高兴为你服务。请问有什么我可以帮你的?" } ], "model": "claude-opus-4-7", "stop_reason": "end_turn", "stop_sequence": null, "usage": { "input_tokens": 12, "output_tokens": 18 } } ``` --- ### 用例 25:无效 model 返回 400 **请求:** ```json { "model": "nonexistent-model-xyz", "max_tokens": 1024, "messages": [ { "role": "user", "content": "你好" } ] } ``` **期望 Mock 响应(400 Bad Request):** ```json { "type": "error", "error": { "type": "invalid_request_error", "message": "The model 'nonexistent-model-xyz' does not exist or is not available." } } ``` --- ### 用例 26:缺少 max_tokens 返回 400 **请求:** ```json { "model": "claude-opus-4-7", "messages": [ { "role": "user", "content": "你好" } ] } ``` **期望 Mock 响应(400 Bad Request):** ```json { "type": "error", "error": { "type": "invalid_request_error", "message": "'max_tokens' is a required parameter for the Messages API." } } ``` --- ### 用例 27:缺少 messages 返回 400 **请求:** ```json { "model": "claude-opus-4-7", "max_tokens": 1024 } ``` **期望 Mock 响应(400 Bad Request):** ```json { "type": "error", "error": { "type": "invalid_request_error", "message": "'messages' is a required parameter and must be a non-empty array." } } ``` --- ### 用例 28:内容安全策略拒绝(refusal) **请求:** ```json { "model": "claude-opus-4-7", "max_tokens": 1024, "messages": [ { "role": "user", "content": "生成违法内容..." } ] } ``` **期望 Mock 响应(200 OK):** ```json { "id": "msg_01test028", "type": "message", "role": "assistant", "content": [ { "type": "text", "text": "抱歉,我无法协助生成此类内容。我的设计原则是提供有益、安全和负责任的帮助。如果你有其他问题或需要帮助的地方,我很乐意为你服务。" } ], "model": "claude-opus-4-7", "stop_reason": "refusal", "stop_sequence": null, "stop_details": { "type": "refusal", "category": "cyber", "explanation": "请求内容违反了使用政策。" }, "usage": { "input_tokens": 18, "output_tokens": 42 } } ``` **验证点:** - `stop_reason` == `"refusal"` - `stop_details` 包含 refusal 详情 --- ### 用例 29:disable_parallel_tool_use **请求:** ```json { "model": "claude-opus-4-7", "max_tokens": 1024, "messages": [ { "role": "user", "content": "帮我查北京和上海的天气" } ], "tools": [ { "name": "get_weather", "description": "获取天气", "input_schema": {"type": "object", "properties": {"city": {"type": "string"}}} } ], "disable_parallel_tool_use": true } ``` **期望 Mock 响应(200 OK):** ```json { "id": "msg_01test029", "type": "message", "role": "assistant", "content": [ { "type": "tool_use", "id": "toolu_01test029", "name": "get_weather", "input": {"city": "北京"} } ], "model": "claude-opus-4-7", "stop_reason": "tool_use", "stop_sequence": null, "usage": { "input_tokens": 120, "output_tokens": 35 } } ``` **验证点:** - 只调用了一个工具(而非并行调用两个) --- ### 用例 30:container 复用 **请求:** ```json { "model": "claude-opus-4-7", "max_tokens": 1024, "messages": [ { "role": "user", "content": "运行一段 Python 代码" } ], "tools": [ { "type": "code_execution_20250825", "name": "code_execution", "container": { "type": "python", "version": "3.11" } } ] } ``` **期望 Mock 响应(200 OK):** ```json { "id": "msg_01test030", "type": "message", "role": "assistant", "content": [ { "type": "server_tool_use", "id": "toolu_01test030", "name": "code_execution", "input": { "code": "print('Hello, World!')", "language": "python" }, "caller": { "type": "direct" } } ], "model": "claude-opus-4-7", "stop_reason": "tool_use", "stop_sequence": null, "usage": { "input_tokens": 150, "output_tokens": 55 } } ``` --- ## 三、Mock 响应通用结构规范 ### 非流式响应通用结构 ```json { "id": "msg_", "type": "message", "role": "assistant", "content": [ { "type": "text" | "tool_use" | "thinking" | "redacted_thinking" | "server_tool_use" | "web_search_tool_result" | "web_fetch_tool_result" | "code_execution_tool_result" | "bash_code_execution_tool_result" | "text_editor_code_execution_tool_result" | "tool_search_tool_result", "text": "" | null, "id": "toolu_" | null, "name": "" | null, "input": { /* tool input */ } | null, "thinking": "" | null, "data": "" | null } ], "model": "", "stop_reason": "end_turn" | "max_tokens" | "stop_sequence" | "tool_use" | "pause_turn" | "refusal", "stop_sequence": "" | null, "stop_details": { "type": "refusal", "category": "cyber" | "bio", "explanation": "" } | null, "usage": { "input_tokens": , "output_tokens": , "cache_read_input_tokens": | null, "cache_creation_input_tokens": | null } } ``` ### 流式 Event 通用结构 | Event Type | Key Fields | |------------|-----------| | `message_start` | `type: "message"`, `id`, `role`, `content: []`, `model`, `stop_reason: null`, `usage` | | `content_block_start` | `type: "content_block_start"`, `index`, `content_block: {type, ...}` | | `content_block_delta` | `type: "content_block_delta"`, `index`, `delta: {type, text/partial_json/thinking}` | | `content_block_stop` | `type: "content_block_stop"`, `index` | | `message_delta` | `type: "message_delta"`, `delta: {stop_reason, stop_sequence}`, `usage: {output_tokens}` | | `message_stop` | `type: "message_stop"` | ### 错误响应通用结构 ```json { "type": "error", "error": { "type": "invalid_request_error" | "authentication_error" | "permission_error" | "not_found_error" | "rate_limit_error" | "api_error", "message": "" } } ``` ### 请求必需参数 | 参数 | 类型 | 说明 | |------|------|------| | `model` | string | 模型标识符(如 `claude-opus-4-7`) | | `max_tokens` | integer | 最大生成 token 数(必需) | | `messages` | array | 消息数组,至少包含一条(必需) | ### 请求可选参数 | 参数 | 类型 | 默认值 | 说明 | |------|------|--------|------| | `system` | string/array | - | 系统 prompt | | `temperature` | number | 1.0 | 采样温度(0.0-1.0) | | `top_p` | number | - | 核采样阈值 | | `top_k` | number | - | 从 top K 采样 | | `stop_sequences` | array | - | 停止序列 | | `tools` | array | - | 工具定义 | | `tool_choice` | object | auto | 工具选择策略 | | `thinking` | object | - | 扩展思考配置 | | `output_config` | object | - | 输出格式配置 | | `stream` | boolean | false | 是否流式 | | `metadata` | object | - | 请求元数据 | | `disable_parallel_tool_use` | boolean | false | 禁用并行工具调用 | | `container` | any | - | 容器标识符 | ### Stop Reason 枚举 | 值 | 含义 | |----|------| | `end_turn` | 自然结束 | | `max_tokens` | 达到 max_tokens 限制 | | `stop_sequence` | 遇到自定义停止序列 | | `tool_use` | 模型调用了工具 | | `pause_turn` | 长运行 turn 暂停 | | `refusal` | 安全策略拒绝 |