从 0 开始搭建一个 claude code

933 字
5 分钟
从 0 开始搭建一个 claude code
2026-06-22
Important

本篇博客大部分内容来源于 Learn Claude Code 项目。

当一个人说“我在开发 Agent”时,他只可能是两个意思之一:

  1. 训练模型。通过强化学习、微调、RLHF 或其他梯度的方法调整权重。收集任务过程数据 —— 真实领域中感知、推理、行动的实际序列 —— 用它们来塑造模型的行为。这是 DeepMind、OpenAI、腾讯 AI Lab、Anthropic 在做的事。这是最本义的 Agent 开发。
  2. 构建 Harness。编写代码,为模型提供一个可操作的环境。这是我们大多数人在做的事。

Harness 是 agent 在特定领域工作所需要的一切:

Harness = Tools + Knowledge + Observation + Action Interfaces + Permissions
Tools: 文件读写、Shell、网络、数据库、浏览器
Knowledge: 产品文档、领域资料、API 规范、风格指南
Observation: git diff、错误日志、浏览器状态、传感器数据
Action: CLI 命令、API 调用、UI 交互
Permissions: 沙箱隔离、审批流程、信任边界

Step 0: 接入 DeepSeek 模型#

通过 Anthropic API 接入 DeepSeek 模型。

核心是 client.messages.create,它向大语言模型发送请求,并获取模型的生成结果。通过调用这个方法,可以实现以下功能:

  • 基础文本生成
  • 多轮对话:通过传入历史 messages,让大模型记住上下文,进行连贯的聊天。
  • 角色扮演/定制人格:通过 system 参数,让大模型扮演特定的专家(如资深律师、Python 导师)。
  • 构建 AI Agent(智能体):通过 tools 参数,赋予大模型调用外部 API、查询数据库或执行数学计算的能力,让它完成复杂的自动化任务。

这个方法返回的 response 对象包含了大模型的“思考结果”,通常会用到以下属性:

  • response.content[0].text:获取模型生成的纯文本回复
  • response.stop_reason:了解模型为什么停止生成(是正常结束end_turn,还是因为到达了长度限制max_tokens,或者是请求使用工具tool_use)。
  • response.usage:查看本次请求消耗了多少 Token(输入和输出),用于计算 API 调用成本。
  • response.id:本次对话的唯一标识符,可用于后续的日志追踪或 API 调试。
from anthropic import Anthropic
client = Anthropic(base_url=os.getenv("ANTHROPIC_BASE_URL"))
MODEL = os.environ["MODEL_ID"]
SYSTEM = f"You are a coding agent at {os.getcwd()}. Use bash to solve tasks. Act, don't explain."
TOOLS = [{
"name": "bash",
"description": "Run a shell command.",
"input_schema": {
"type": "object",
"properties": {"command": {"type": "string"}},
"required": ["command"],
},
}]
messages = [{"role": "user", "content": "What is the current git branch?"}]
response = client.messages.create(
model=MODEL,
system=SYSTEM,
messages=messages,
tools=TOOLS,
max_tokens=8000,
)
messages.append({"role": "assistant", "content": response.content})
Note

拦截 HTTP 报文信息

我们可以进行如下修改来实现 HTTP 报文拦截:

client = Anthropic(base_url=os.getenv("ANTHROPIC_BASE_URL"))
# ── HTTP 报文拦截 ──────────────────────────────────────────
def _log_request(req: httpx.Request) -> None:
headers = "\n".join(
f" {k}: {'***' if k.lower() in ('x-api-key', 'authorization') else v}"
for k, v in req.headers.items()
)
body = req.content.decode(errors="replace")
print(f"\n{'='*60}\n[REQUEST] {req.method} {req.url}\n{headers}\n\n{body}\n{'='*60}\n")
def _log_response(resp: httpx.Response) -> None:
resp.read() # 确保 body 已缓冲(非流式时无副作用)
headers = "\n".join(f" {k}: {v}" for k, v in resp.headers.items())
body = resp.content.decode(errors="replace")
print(f"\n{'='*60}\n[RESPONSE] {resp.status_code}\n{headers}\n\n{body}\n{'='*60}\n")
_http_client = httpx.Client(event_hooks={"request": [_log_request], "response": [_log_response]})
client = Anthropic(base_url=os.getenv("ANTHROPIC_BASE_URL"), http_client=_http_client)

下面是 request/response 的报文截图:

request
request
response
response

Step 1: Agent Loop#

Agent Loop
Agent Loop

一个简单的 while True 循环,模型调用工具就继续,不调用就停。整个过程只有两个信号:

信号含义循环动作
stop_reason == "tool_use"模型举手说“我要用工具”执行 -> 结果喂过去 -> 继续
stop_reason != "tool_use"模型说“我做完了”退出循环

Agent Loop 代码如下,目前的工具只有 run_bash 运行 bash 命令。

def agent_loop(messages):
while True:
response = client.messages.create(
model=MODEL, system=SYSTEM, messages=messages,
tools=TOOLS, max_tokens=8000,
)
messages.append({"role": "assistant", "content": response.content})
if response.stop_reason != "tool_use":
return
results = []
for block in response.content:
if block.type == "tool_use":
output = run_bash(block.input["command"])
results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": output,
})
messages.append({"role": "user", "content": results})
Note

完整代码见 s01_agent_loop/code.py

Step 2: Tool Use#

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或赞助支持!

赞助
从 0 开始搭建一个 claude code
https://llm-tech.com.cn/posts/learn-claude-code/
作者
Ming
发布于
2026-06-22
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
Ming
你是来找 Ming 学习的吗
🎉 欢迎来到 Ming 的博客
这里是我的个人博客,分享 AI Infra、LLM 等技术内容。欢迎关注交流!
分类
标签
站点统计
文章
17
分类
10
标签
16
总字数
52,871
运行时长
0
最后活动
0 天前

目录