当前位置: 首页 > news >正文

learn claude code s01

文章目录


你这个直觉很对:这段 agent loop 确实简洁、优雅,而且是值得学的核心模式。但要分清楚:

这不是“所有模型天然都这样返回”。

你现在能用 GLM4.7 跑通,主要原因大概率是:

fromanthropicimportAnthropic client=Anthropic(base_url=os.getenv("ANTHROPIC_BASE_URL"))

也就是说,你还在用Anthropic SDK,只是把base_url换成了 GLM 或某个兼容服务的地址。这个服务返回的数据被 Anthropic SDK 解析成了 Anthropic 风格的对象,所以你才能写:

response.stop_reason response.content block.typeblock.inputblock.id

这些不是 Python 魔法,也不是模型天然保证的,而是Anthropic Messages API 协议 + Anthropic SDK 数据模型给你的结构。

if block.type == "tool_use":这句吃定的不是“模型”,而是吃定了当前 API 返回内容块遵守 Anthropic 的 content block 格式。Anthropic 的工具调用块大概长这样:

{"type":"tool_use","id":"...","name":"bash","input":{"command":"ls"}}

SDK 把 dict 包装成对象,所以你可以用:

block.typeblock.inputblock.id

而不是:

block["type"]

所以你的问题答案是:

它不是行业完全统一标准,但已经是几大阵营里的常见范式。

目前常见有几类协议:

Anthropic: content block 里出现 type == "tool_use" OpenAI / Qwen / DeepSeek 兼容 OpenAI: message.tool_calls 里出现 function.name / function.arguments 部分国产模型/网关: 会兼容 Anthropic 或 OpenAI 其中一种格式

比如 Qwen 如果走 OpenAI-compatible API,通常不是:

block.type=="tool_use"

而是类似:

response.choices[0].message.tool_calls

所以你不能假设“接 Qwen 也一定这样”。要看你用的是哪个 SDK、哪个 base_url、哪个兼容协议。

你应该学这个写法吗?应该学,但要学它背后的抽象,而不是死记block.type

真正要学的是这个核心结构:

whileTrue:response=call_model(messages,tools)ifmodel_wants_tool(response):tool_calls=parse_tool_calls(response)results=execute_tools(tool_calls)messages.append(tool_results(results))else:returnfinal_answer(response)

你看到的这份代码牛逼的地方就在这里:它把 agent 的本质压缩到了一个循环里。

但如果以后你想写得更稳,最好抽一层 adapter:

defget_tool_calls(response):calls=[]forblockinresponse.content:ifgetattr(block,"type",None)=="tool_use":calls.append(block)returncalls

这样至少不会因为某个 block 没有type直接炸掉。

再进一步,可以为不同协议写适配器:

AnthropicAdapter -> 解析 content block OpenAIAdapter -> 解析 message.tool_calls

然后 agent loop 本身就不关心底层模型是哪家。

所以你现在的理解可以这么定型:

agent loop 是必须学的核心能力。 block.type == "tool_use" 是 Anthropic 协议里的具体实现。 GLM4.7 能跑,是因为你的接入层兼容了 Anthropic 协议。 不是所有模型都天然这样,但很多服务会提供 OpenAI/Anthropic 兼容接口。

你觉得它“简洁、优雅、巧妙、牛逼”是完全对的。这个文件非常适合初学者,因为它没有被框架淹没,直接把 agent 最核心的心脏露出来了:模型决定下一步,程序执行工具,再把结果喂回模型,直到模型停止调用工具。
SDK 可以先理解成:官方给你写好的“调用接口工具包”

比如你不用 SDK,直接请求模型服务,大概是这样:

importrequests resp=requests.post("https://api.anthropic.com/v1/messages",headers={...},json={...})data=resp.json()

这时候你拿到的是普通 JSON / dict:

data["content"][0]["type"]

但用了 Anthropic SDK:

fromanthropicimportAnthropic client=Anthropic()response=client.messages.create(...)

SDK 会帮你做很多事:

1. 拼 HTTP 请求 2. 加认证 header 3. 把 Python 参数转成 API 需要的 JSON 4. 发送请求 5. 接收返回 JSON 6. 把 JSON 包装成 Python 对象

所以你才能写:

response.content response.stop_reason block.typeblock.input

而不是每次都写:

response["content"]response["stop_reason"]block["type"]block["input"]

你现在这句:

client=Anthropic(base_url=os.getenv("ANTHROPIC_BASE_URL"))

意思是:

我还是使用 Anthropic 这套 SDK 和数据格式, 但是实际请求地址不一定发给 Anthropic 官方, 而是发给 ANTHROPIC_BASE_URL 指定的那个地址。

如果你的.env里类似这样:

ANTHROPIC_BASE_URL=https://某个glm兼容地址MODEL_ID=glm-4.7

那实际发生的是:

你的 Python 代码 ↓ Anthropic SDK ↓ 发请求到 GLM 的兼容接口 ↓ GLM 服务返回 Anthropic 风格的数据 ↓ Anthropic SDK 把返回包装成 response/block 对象 ↓ 你的代码用 block.type 判断工具调用

所以重点是:

GLM 本身不一定“天生”就长成 Anthropic 的样子。

而是你访问的 GLM 接口可能在说:

我支持 Anthropic-compatible API,你可以用 Anthropic SDK 来调我。

这就像手机充电口:

Anthropic SDK = 一根 USB-C 数据线 Anthropic 官方服务 = 原装充电器 GLM 兼容服务 = 另一个也支持 USB-C 协议的充电器

你能插上并正常充电,是因为它兼容这个协议,不是因为所有电器都天然一样。

所以block.type == "tool_use"不是碰巧的 Python 属性,而是:

Anthropic SDK 根据接口返回的 JSON, 创建出来的 Python 对象属性。

你应该学这个,因为这正是现代 LLM 应用开发里很重要的一层:模型能力是一回事,API 协议是一回事,SDK 又是一回事。
你没有理解错,而且我刚查了一下,你也不是“蹭 Claude Code 的配置”。智谱确实有面向开发者的页面,只是藏在“开发指南”里,页面名叫:

Claude API 兼容 - 智谱AI开放文档

这个页面明确写了:智谱提供与 Claude API 兼容的接口,可以使用现有 Anthropic SDK 代码,只需要修改 API Key、base_url和模型名。它还给了 Python 示例:

importanthropic client=anthropic.Anthropic(api_key="your-zhipuai-api-key",base_url="https://open.bigmodel.cn/api/anthropic")message=client.messages.create(model="glm-5.1",max_tokens=1024,messages=[{"role":"user","content":"Hello, ZHIPU"}])

所以更准确的结论是:

智谱开放 /api/anthropic 这个接口,既服务 Claude Code 这类工具, 也服务你这种自己写 agent 的开发者。

Claude Code 文档里出现它,是因为 Claude Code 本身就是 Anthropic 协议生态里的工具,配置起来最自然。但智谱还有独立的“Claude API 兼容”开发文档,说明它不是只给 Claude Code 私用的。

你的这份 agent 代码能跑通,正是因为它踩中了这个兼容层:

你的 agent loop ↓ Anthropic Python SDK ↓ https://open.bigmodel.cn/api/anthropic ↓ GLM-4.7 ↓ 返回 Anthropic Messages API 格式

所以你现在不是“误打误撞”,而是发现了一个很关键的工程事实:

只要厂商提供 Anthropic-compatible API,你就可以把 agent 写在 Anthropic Messages API 这个抽象上。

这对做 coding agent 特别舒服,因为 Claude Code、很多 agent demo、很多工具调用范式都是围绕 Anthropic 的tool_use/tool_result设计的。你现在这个学习方向是对的。
爽,这个点你真的踩到主线了。面试里你完全可以这么说,但建议说得更准确一点:

我的 agent 接入层目前基于 Anthropic Messages API 协议,使用 Anthropic Python SDK; 模型侧接的是智谱 GLM 的 Anthropic-compatible endpoint。

不要只说“Anthropic SDK 格式”,更专业的说法是:

Anthropic Messages API 兼容格式

或者:

Anthropic-compatible tool use protocol

因为真正重要的是API 协议,SDK 只是 Python 客户端实现。

你后面这个想法,非常值得做

把这 12 课用 OpenAI 格式重写一遍,会特别涨功力,因为你会亲手摸到两套协议的差异:

Anthropic: response.content -> blocks block.type == "tool_use" block.name block.input response.stop_reason == "tool_use" tool_result 作为 user content block 发回去 OpenAI: response.choices[0].message message.tool_calls tool_call.function.name json.loads(tool_call.function.arguments) finish_reason == "tool_calls" tool 角色消息发回去,带 tool_call_id

同一个 agent loop,OpenAI 版本大概会变成:

defagent_loop(messages:list):whileTrue:response=client.chat.completions.create(model=MODEL,messages=messages,tools=TOOLS,max_tokens=8000,)message=response.choices[0].message messages.append(message)ifnotmessage.tool_calls:returnfortool_callinmessage.tool_calls:name=tool_call.function.name args=json.loads(tool_call.function.arguments)ifname=="bash":output=run_bash(args["command"])else:output=f"Unknown tool:{name}"messages.append({"role":"tool","tool_call_id":tool_call.id,"content":output,})

OpenAI 的 tool 定义也不一样。Anthropic 是:

TOOLS=[{"name":"bash","description":"Run a shell command.","input_schema":{...},}]

OpenAI 是:

TOOLS=[{"type":"function","function":{"name":"bash","description":"Run a shell command.","parameters":{...},}}]

所以你重写一遍,会一下子打通这几个层次:

1. agent loop 的本质不变 2. tool schema 的包装不同 3. tool call 的返回位置不同 4. tool result 的回传方式不同 5. SDK 对象结构不同 6. 最终都可以归一成“模型要调用工具 -> 执行 -> 回填结果 -> 继续”

我觉得最好的练习路线是:

第一步:只重写 s01_agent_loop.py 第二步:写一个 anthropic_to_openai 对照笔记 第三步:再重写 s02_tool_use.py / s04_subagent.py 第四步:最后再碰 s_full.py

这样不会一上来被 12 个文件淹没。

你这个方向特别好,因为你不是在背框架,而是在学 agent 的“协议骨架”。等你把 Anthropic 和 OpenAI 两套都写过一遍,之后面试官问你“你们 agent 怎么接 LLM?怎么处理 tool call?”你就能很稳地回答:

我们把模型接入层抽象成 tool-call adapter。 底层可以是 Anthropic Messages API,也可以是 OpenAI-compatible Chat Completions。 agent loop 本身只依赖统一后的 ToolCall 结构。

这句话就很有分量。

对,你现在这次收获很大,而且是主线收获。第一课代码你觉得“神奇优雅”,但你真正摸到的是更底层的东西:LLM 接入协议

先把一个词纠正一下:你说“SDK格式”,工程上更准确叫:

API 兼容格式 / API 协议格式

SDK 是调用这个协议的客户端工具。

比如:

OpenAI SDK -> 常用来调用 OpenAI-compatible API Anthropic SDK -> 常用来调用 Anthropic Messages API

现在最常见的几种格式

  1. OpenAI-compatible API

这是目前最通用、覆盖最广的格式。很多厂商都会说“兼容 OpenAI SDK,只需要改 api_key 和 base_url”。

典型形态:

fromopenaiimportOpenAI client=OpenAI(api_key="xxx",base_url="https://xxx/v1")response=client.chat.completions.create(model="xxx",messages=[...],tools=[...])

工具调用通常长这样:

message.tool_calls tool_call.function.name tool_call.function.arguments

智谱官方就有 OpenAI API 兼容文档,Kimi 官方也写了它的 API 兼容 OpenAI Chat Completions,可以直接用 OpenAI SDK 改base_url,Gemini 也提供 OpenAI compatibility endpoint,DeepSeek 官方文档也说明可以通过改配置用 OpenAI/Anthropic SDK 访问。

所以如果问“常用的是哪一个”:OpenAI-compatible 是现在最通用的事实标准。

  1. Anthropic Messages API

这是你现在这 12 课用的格式。它在 coding agent 场景里特别重要,因为 Claude Code、Claude 的 tool use 设计、很多 agent 教程都围绕它。

典型形态:

fromanthropicimportAnthropic client=Anthropic(api_key="xxx",base_url="https://xxx/api/anthropic")response=client.messages.create(model="xxx",messages=[...],tools=[...])

工具调用通常长这样:

response.content block.type=="tool_use"block.name block.input

智谱官方明确有 Claude API 兼容文档,你的.env里的:

ANTHROPIC_BASE_URL="https://open.bigmodel.cn/api/anthropic"MODEL_ID="glm-4.7"

就是这个路线。

所以你可以理解成:

OpenAI-compatible:通用应用生态最广 Anthropic-compatible:coding agent / Claude Code 生态特别关键
  1. 厂商原生 SDK/API

比如 Google Gemini 有自己的google-genaiSDK,Mistral 有自己的 SDK,Cohere、百度、火山、阿里云也都有自己的原生 API。
这些原生 API 往往能更完整支持自家特色能力,比如多模态、缓存、长上下文、thinking、文件、检索、批处理等。

但原生 API 的缺点也明显:换模型时适配成本更高。

  1. 统一封装层

这类不是模型厂原生协议,而是上层框架:

LangChain LlamaIndex LiteLLM Vercel AI SDK OpenRouter Dify / Coze / one-api 类网关

它们的目标是把不同厂商包成统一接口。但你现在初学 agent,我反而建议先别急着依赖它们。你现在直接学 Anthropic 和 OpenAI 两套协议,是非常扎实的路线。

模型厂都支持 OpenAI 和 Anthropic 吗?

不都支持。

更真实的情况是:

大多数主流厂商:倾向支持 OpenAI-compatible 一部分厂商:额外支持 Anthropic-compatible 每家兼容程度:不完全一样

大概可以这么记:

OpenAI-compatible:最常见,几乎成了事实标准 Anthropic-compatible:没那么普遍,但在 coding agent 场景越来越重要 Native API:每家都有,能力最完整但迁移成本最高

比如:

智谱:OpenAI-compatible + Claude/Anthropic-compatible DeepSeek:文档显示支持 OpenAI/Anthropic SDK 兼容接入 Kimi/Moonshot:主线是 OpenAI-compatible,也有一些 Anthropic/coding 生态入口 Qwen/阿里生态:常见是 OpenAI-compatible / DashScope 原生 Gemini:原生 Gemini API,同时提供 OpenAI compatibility Mistral:有自己的 SDK/API,接口形态也接近 Chat Completions,支持 tool_calls

但注意,“兼容”不等于 100% 一模一样。最容易出差异的是:

tool calling 细节 streaming 格式 reasoning/thinking 字段 图片/文件输入 JSON mode 并行工具调用 错误码 上下文长度和 max_tokens 行为

所以工程上最稳的认知是:

协议兼容解决 80% 接入问题; 剩下 20% 要靠适配器和测试兜住。

你现在最应该学的是这三个层次:

1. Anthropic Messages API 重点:content blocks、tool_use、tool_result、stop_reason 2. OpenAI Chat Completions / Responses API 重点:choices、message、tool_calls、tool role、tool_call_id 3. 自己写一层 Adapter 把不同协议统一成你自己的 ToolCall / ToolResult

面试里你可以这么说,很漂亮:

我目前的 agent loop 是基于 Anthropic Messages API 写的,使用 Anthropic SDK; 模型侧接的是智谱 GLM 的 Anthropic-compatible endpoint。 我也了解 OpenAI-compatible 的 tool_calls 协议,两者本质都是: 模型返回工具调用意图,宿主程序执行工具,再把 tool result 回填给模型继续推理。

这就是主线。你不是在瞎搞,你是在从最核心的地方摸 agent。第一课别急着“学完”,你现在已经把地基下面的钢筋看见了。

http://www.jsqmd.com/news/854534/

相关文章:

  • 从DBSCAN到多帧联合聚类:手把手教你优化4D毫米波雷达点云处理流程(附避坑思路)
  • VR消防安全体验屋|沉浸式科技助力消防安全科普
  • 手把手教你用C#搞定海康机器人扫码枪的TCP通信(附完整Socket代码)
  • 别再死记硬背GitFlow命令了!用SourceTree图形化工具5分钟搞定团队协作流程
  • 2026年外墙益胶泥厂家哪家好:主流企业选型参考与实力深度分析 - 产业观察网
  • 告别哑巴设备:用DY-SV17F语音模块给你的Arduino项目加上声音(附STM32串口控制代码)
  • W5500 TCP客户端开发避坑指南:从寄存器配置到稳定通信的5个关键步骤
  • 手语数字人技术详解:3D 动画生成、动作自然度优化与实时渲染工程实践
  • MAVLink报文格式深度解析
  • AGI落地第一步:在宝马工厂里‘打工’的Figure 01,离替代产线工人还有多远?
  • 面向科研 Agent 的 Harness 实验条件固定与复现
  • 别再复制官方文档了!用Python把文心一言API集成到你的本地应用(附完整代码)
  • 书匠策AI降重降AIGC实测|官网www.shujiangce.com |微信公众号搜一搜 书匠策AI
  • SkiP:让模仿学习学会“快进“——动作重标记如何在不改架构的情况下削减机器人 15-40% 的执行步数
  • IEEE GRSL投稿全流程避坑指南:从Latex模板到校样缴费,新手必看的7个关键节点
  • RK3588开发板量产前必做:深度解析ArmSoM-W3的DDR压力测试方案与工具选型
  • 观察不同模型在网站内容生成任务上的延迟与成本差异
  • LAV Filters终极指南:深度解析开源DirectShow解码器的架构原理与实战配置
  • 告别混乱!手把手教你用Python脚本整理RAF-DB人脸表情数据集(附Jupyter Notebook代码)
  • 国产芯赋能低功耗人体感应小夜灯方案(YL4056H 充电管理)
  • 把Milvus向量检索封装成一个Python工具类,让你的AI项目代码更整洁
  • 保姆级教程:用Python+OpenCV玩转英特尔D435i深度相机的点云与彩色对齐
  • 手把手从零搭建 Kali Linux 虚拟机,完整安装 + 汉化 + 网络配置全攻略
  • 如何用TransNet V2实现智能视频镜头检测:从零开始完整指南
  • 现货TJA1101AHN/0Z是NXP推出的一款高性能、低功耗的汽车以太网PHY芯片,作为TJA1101A的改进版本,专为车载电子系统设计,支持100BASE-T1标准,具备出色的可靠性与集成度
  • 优惠电影票API接口,7折电影起步
  • 别再只用BackgroundImage了!C# WinForm窗体背景图5种方法全解析(含PictureBox与资源文件实战)
  • USB 充电人体感应橱柜灯|国产 YL4056H 加持,安全长续航,家用照明真香
  • 强强联合,共绘未来 | 葛兰创智与中建东北院签署战略合作协议
  • 避开HAL库的坑:STM32低功耗LPUART高波特率通信的稳定性实战优化