1. 为什么我要用 Python 手搓一个迷你 Claude CodeClaude Code 这类工具最让人上头的地方不是它能补全几行代码而是它把「模型 工具 循环」这三件事拼成了一个能自己干活的 Agent。你给它一句需求它会读文件、跑命令、看报错、再改代码整个过程像一个坐在终端里的搭档。但真到自己动手复刻时第一个卡住大多数人的往往不是 Agent 循环怎么写而是 Key 和 API 通道太散Anthropic 一套、OpenAI 一套、本地模型又一套环境变量改来改去换个模型就得重配一遍。这篇就聚焦这个痛点。我会用 Python 从零搭一个迷你 Claude Code 的 Agent 骨架核心是 agent loop 工具调用然后通过 TaoToken 的统一 Key 和 API 通道把 LLM 接进来让你只维护一份配置就能切换模型。适合已经会一点 Python、想搞懂 Agent 内部结构、又不想被多套 Key 折腾的人。全程可跟做配置骨架直接复制就能跑。2. TaoToken 前置准备一份 Key 打通多模型通道TaoToken 在这里扮演的角色是「统一入口」你不需要为每个模型厂商单独申请 Key、单独记 Base URL而是拿一个 TaoToken 的 Key通过它的 API 通道去调用不同模型。对写 Agent 的人来说这省掉的是配置层的重复劳动——你的代码里只认一个base_url和一个api_key换模型只改model字段。先做两件事。第一去官网注册并拿到 Key入口在控制台的 API Keys 页面官网https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentAPI Keys 管理https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite第二确认你要用的模型名。TaoToken 的 API 地址是https://taotoken.net/api兼容 OpenAI 风格的/v1/chat/completions调用方式所以 Python 里用openai这个 SDK 就能直接对接不用额外装 Anthropic 的库。这一点对迷你 Claude Code 很关键Agent 骨架只依赖一个统一的 chat 接口工具调用的解析逻辑也只需要写一套。注意Key 只放在本地.env或环境变量里不要写进代码提交到 Git。后面配置骨架里我会用os.getenv读取。3. 可复制配置config.toml 与 settings.json 骨架我习惯把「模型通道配置」和「Agent 行为配置」分开。前者放config.toml后者放settings.json这样换模型不动 Agent 逻辑调 Agent 行为不动 Key。先建项目目录mkdir mini-claude-code cd mini-claude-code python -m venv .venv source .venv/bin/activate # Windows 用 .venv\Scripts\activate pip install openai python-dotenv tomliconfig.toml负责通道和模型# config.toml [provider] base_url https://taotoken.net/api api_key_env TAOTOKEN_API_KEY [model] name claude-sonnet-4-20250514 max_tokens 4096 temperature 0.2 [agent] max_turns 12 workdir .settings.json负责 Agent 的工具白名单和循环上限{ agent: { name: mini-claude-code, system_prompt: 你是一个终端里的编程 Agent。你可以调用工具读写文件、执行命令。先规划再行动每次只做一步观察结果后再决定下一步。, tools: [read_file, write_file, run_bash], max_turns: 12 }, safety: { bash_timeout_sec: 30, allow_write: true } }.env里只放 KeyTAOTOKEN_API_KEY你的Key这里的设计意图是config.toml里的base_url固定指向 TaoToken 的 API 通道api_key_env告诉代码从哪个环境变量读 Key。以后你想换模型只改[model].name想换通道只改base_url。Agent 代码完全不用动。4. Agent 骨架与一次本地调用验证核心就是一个 while 循环把消息发给模型模型要么直接回文本要么返回工具调用执行工具后把结果塞回消息列表继续下一轮。下面是最小可跑版本。# agent.py import os, json, subprocess, tomllib from openai import OpenAI from dotenv import load_dotenv load_dotenv() with open(config.toml, rb) as f: cfg tomllib.load(f) client OpenAI( base_urlcfg[provider][base_url], api_keyos.getenv(cfg[provider][api_key_env]), ) TOOLS [ { type: function, function: { name: read_file, description: 读取指定路径的文件内容, parameters: { type: object, properties: {path: {type: string}}, required: [path], }, }, }, { type: function, function: { name: run_bash, description: 在终端执行一条 shell 命令并返回输出, parameters: { type: object, properties: {cmd: {type: string}}, required: [cmd], }, }, }, ] def dispatch(name, args): if name read_file: with open(args[path], r, encodingutf-8) as f: return f.read()[:4000] if name run_bash: r subprocess.run( args[cmd], shellTrue, capture_outputTrue, textTrue, timeout30, ) return (r.stdout r.stderr)[:4000] return funknown tool: {name} def run_agent(user_input): messages [ {role: system, content: 你是一个终端里的编程 Agent。}, {role: user, content: user_input}, ] for turn in range(cfg[agent][max_turns]): resp client.chat.completions.create( modelcfg[model][name], messagesmessages, toolsTOOLS, temperaturecfg[model][temperature], ) msg resp.choices[0].message messages.append(msg) if not msg.tool_calls: print(最终回复:, msg.content) return msg.content for call in msg.tool_calls: args json.loads(call.function.arguments) print(f[tool] {call.function.name} {args}) result dispatch(call.function.name, args) messages.append({ role: tool, tool_call_id: call.id, content: result, }) print(达到最大轮数停止。) if __name__ __main__: run_agent(看一下当前目录有哪些文件然后告诉我这个项目是做什么的)跑起来python agent.py成功的话你会看到类似输出模型先调用run_bash执行ls拿到文件列表再调用read_file读config.toml最后用一段文字总结项目用途。整个过程不需要你手动干预这就是最小 Agent 循环的样子。验证通道是否打通其实看第一次工具调用有没有正常返回就够了——如果模型能发起tool_calls说明 TaoToken 的 API 通道和 Key 都是通的。5. 本篇常见报错排查清单接入阶段最容易踩的坑基本集中在 Key、模型名和工具调用解析三处我按出现频率列一下。报 401 / authentication_error九成是 Key 没读到。先确认.env和agent.py在同一目录且load_dotenv()在OpenAI(...)之前执行。再确认config.toml里api_key_env写的变量名和.env里的一致大小写敏感。报 model_not_found[model].name填的模型名在通道里不存在。去接入文档核对可用模型名别凭记忆写。换模型只改这一行其他不动。报 base_url 相关连接错误检查base_url是不是https://taotoken.net/api注意不要多加/v1后缀SDK 会自己拼/v1/chat/completions。多写一层路径就会 404。模型不调用工具只回文本两个原因。一是tools参数没传或格式不对确认是[{type: function, function: {...}}]结构二是 system prompt 没告诉它可以用工具把「你可以调用工具」写清楚。有些模型对工具调用支持较弱换一个工具能力强的模型即可。tool_calls 解析报 JSONDecodeErrorcall.function.arguments偶尔会带多余空白或截断。加一层 try/except解析失败时把原始字符串回给模型让它重发比直接崩掉更稳。run_bash 卡住不返回命令进了交互式等待。subprocess.run里务必带timeout并在 system prompt 里提醒模型「不要执行需要交互输入的命令」。达到最大轮数还没结束max_turns太小或任务太复杂。先调到 20 试试如果还是循环多半是工具返回结果太长把上下文撑爆了把dispatch里的截断从 4000 调到 2000。6. 把统一 Key 用顺之后下一步往哪走这套骨架跑通后你会发现真正值钱的不是那几十行循环代码而是「配置和逻辑分离」这个习惯。config.toml管通道、settings.json管行为、.env管密钥三者互不干扰你换模型、加工具、调轮数都不会牵一发动全身。TaoToken 在这里的价值就是把多模型通道收敛成一个base_url让你的 Agent 代码从第一天起就不用为厂商差异写分支。如果你接下来想验证不同模型在这个 Agent 里的表现可以直接在模型对话页面试模型对话https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentchatutm_campaignrewrite想把这个迷你 Agent 往长期编码助手方向做比如加子 Agent、任务持久化、后台任务那更适合用 Coding Plan 来跑持续调用Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite接入过程中如果遇到通道或 Key 的问题先翻接入文档大部分报错那里都有对应说明接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite我自己的做法是先把run_bash和read_file两个工具打磨稳再往上加write_file和子 Agent。工具越少Agent 循环越容易调试等循环稳定了加工具就只是往TOOLS列表里追加一项、往dispatch里加一个分支的事。