当前位置: 首页 > 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.gsyq.cn/news/1333968.html

相关文章:

  • HC7252晨芯阳内置MOS开关降压型LED恒流驱动器
  • AGI落地第一步:在宝马工厂里‘打工’的Figure 01,离替代产线工人还有多远?
  • 别再复制官方文档了!用Python把文心一言API集成到你的本地应用(附完整代码)
  • 书匠策AI降重降AIGC实测|官网www.shujiangce.com |微信公众号搜一搜 书匠策AI
  • 科研学术篇---文献引用格式
  • RK3588开发板量产前必做:深度解析ArmSoM-W3的DDR压力测试方案与工具选型
  • 别再只用真彩色了!Landsat8这5个宝藏波段组合,让你的遥感分析效率翻倍
  • 运放输入电压超了怎么办?手把手教你用ESD二极管做保护(附计算实例)
  • 别只刷固件了!用MissionPlanner搞定四旋翼‘飘移’问题,校准compass_mot全流程
  • 别再只发AT指令了!深入聊聊ESP8266的AP模式:从WiFi热点到TCP服务器的完整配置逻辑
  • 聊天记录丢失别慌!这几招教会你
  • 团队协作第一步:如何为你的新电脑快速配置TortoiseGit/SVN开发环境(含汉化包)
  • 强强联合,共绘未来 | 葛兰创智与中建东北院签署战略合作协议
  • 手持式雷达车辆测速仪:基于多普勒效应的移动测速工具
  • 避开HAL库的坑:STM32低功耗LPUART高波特率通信的稳定性实战优化
  • 避坑指南:在Windows 10上从源码编译奥比中光pyorbbecsdk(Python 3.9环境)
  • 数据结构:3.包装类和泛型
  • Agent工程2026:从提示词堆砌到生产级智能体的完整跃迁路径
  • Creo 8.0 + Matlab 2022b 联调实战:手把手搞定Simscape Multibody Link插件(附完整配置文件)
  • 告别混乱!手把手教你用Python脚本整理RAF-DB人脸表情数据集(附Jupyter Notebook代码)
  • WPF文本框Placeholder的进阶玩法:结合ValidationRule,实现带验证状态的输入提示
  • Vivado时序报告里setup/hold的Requirement值到底怎么算?一个例子讲透时钟边沿选取
  • 把Milvus向量检索封装成一个Python工具类,让你的AI项目代码更整洁
  • RT-Thread Studio + STM32CubeMX 联调ADC避坑指南:从配置到读取数据的完整流程
  • AI编程在前后端分离中的最新进展(2026年5月)
  • FPGA资源吃紧?看Artix7-35T如何“精打细算”实现MIPI视频解码与HDMI输出
  • 别再傻傻分不清了!用一张图看懂SRE、DevOps工程师和传统运维到底差在哪
  • 现货TJA1101AHN/0Z是NXP推出的一款高性能、低功耗的汽车以太网PHY芯片,作为TJA1101A的改进版本,专为车载电子系统设计,支持100BASE-T1标准,具备出色的可靠性与集成度
  • 铝基板焊点氧化、发黑、腐蚀故障原因与长效防护
  • 5分钟解锁A股数据宝藏:Python通达信接口的量化交易实战指南