Pixiv - おむたつ/omutatsu
从 0 开始搭建一个 claude code
933 字
5 分钟
从 0 开始搭建一个 claude code
Important
本篇博客大部分内容来源于 Learn Claude Code 项目。
当一个人说“我在开发 Agent”时,他只可能是两个意思之一:
- 训练模型。通过强化学习、微调、RLHF 或其他梯度的方法调整权重。收集任务过程数据 —— 真实领域中感知、推理、行动的实际序列 —— 用它们来塑造模型的行为。这是 DeepMind、OpenAI、腾讯 AI Lab、Anthropic 在做的事。这是最本义的 Agent 开发。
- 构建 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 的报文截图:


Step 1: 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/