1. 从单点提示词到多 Agent 协作一个真实项目的踩坑记录如果你正在搜索“AI Agent 系统构建指南”或者“多 Agent 协作怎么落地”大概率已经翻过不少概念文章但真正动手时还是卡在几个地方提示词写了一大堆却没法复用、上下文塞满窗口后模型开始胡言乱语、工具函数调不通、多个 Agent 之间不知道怎么传数据。我最近带团队做一个代码审查 Agent 系统从最初一个 prompt 硬扛到后来拆成四个 Agent 协作中间踩的坑基本覆盖了这条学习路径上的所有关键节点。这篇文章不打算再重复“Agent 是什么”的定义而是按一条可跟做的路径来写先解决提示词工程的结构化问题再处理上下文工程与知识检索然后设计工具系统最后用 TaoToken 统一 Key 把多 Agent 协作跑通并验证。整条链路里TaoToken 承担的是统一 API 通道的角色——你不需要为每个模型单独申请 Key、单独配 Base URL一个 Key 就能在多个模型之间切换这对多 Agent 场景特别实用因为不同 Agent 可能适合不同模型。适合谁看已经写过基础 prompt、想系统化搭建 Agent 的开发者正在被上下文窗口和工具调用折磨的人想尝试多 Agent 协作但不知道从哪下手的人。下面每个环节我都会给出可复制的配置和命令你可以直接拿去改。2. 提示词工程的结构化设计从 PromptTemplate 到路由分发2.1 为什么你的提示词总是“这次好用下次崩”很多人写提示词的习惯是想到什么写什么把角色、任务、约束、输出格式全塞在一段话里。单次调用可能没问题但一旦要复用、要动态注入上下文、要按场景切换就彻底失控。我试过最夸张的一次一个 800 字的 prompt 里混了三种任务模型输出格式在 JSON 和 Markdown 之间反复横跳解析代码写了一堆 if-else 还是兜不住。结构化的核心就三件事输入结构化、输出结构化、任务可路由。输入结构化指的是用模板引擎动态拼装提示词。LangChain 用 Jinja2Spring AI 用 StringTemplate本质都是把变量和固定指令分离。比如一个代码审查 Agent 的模板from string import Template REVIEW_TEMPLATE Template( 你是一个资深代码审查员。 ## 角色 你只负责审查 $language 代码不处理其他语言。 ## 任务 审查以下代码片段找出$focus_areas ## 约束 - 每条问题必须给出文件行号 - 严重程度分为 blocker / major / minor - 不要提出与 $focus_areas 无关的建议 ## 输出格式 严格返回 JSON 数组每个元素包含 {line: int, severity: str, issue: str, suggestion: str} ## 待审查代码 $language $code_snippet)prompt REVIEW_TEMPLATE.substitute( languagepython, focus_areas空指针、资源泄漏、并发安全, code_snippetopen(target.py).read() )输出结构化则是让模型返回可解析的格式。JSON 适合程序消费YAML 对流式输出更友好XML 在嵌套结构上有优势。关键是要配 Schema 验证字段缺失时走默认值或触发重试。我一般会在解析层加一层兜底先尝试 json.loads失败则用正则提取代码块再解析再失败就记录原始输出并降级为纯文本展示。 ### 2.2 提示词路由让对的 Agent 处理对的任务 当系统里有多类任务时单个提示词会变得又长又模糊。提示词路由的思路是先判断输入属于哪一类再分发给对应的子提示词或子 Agent。典型实现是语义相似度路由或 LLM 分类路由。 python ROUTES { code_review: 审查代码质量问题, doc_qa: 回答文档相关问题, data_analysis: 分析数据并生成结论 } def route_query(user_input: str) - str: # 用轻量模型做意图分类 resp client.chat.completions.create( modelgpt-4o-mini, messages[{ role: user, content: f判断以下输入属于哪类任务只返回类别名{list(ROUTES.keys())}\n输入{user_input} }] ) return resp.choices[0].message.content.strip()路由之后每个子任务只加载自己需要的提示词模板和工具集上下文窗口的占用会大幅下降。这一步做完你的系统就从“一个万能 prompt”进化成了“多个专职 prompt”这是后面多 Agent 协作的基础。3. TaoToken 统一 Key 配置一个通道跑通多模型3.1 为什么多 Agent 场景需要统一 Key多 Agent 协作时不同 Agent 往往需要不同模型规划 Agent 用推理强的执行 Agent 用速度快的审查 Agent 用代码能力好的。如果每个模型都单独申请 Key、单独配 Base URL配置管理会变成噩梦而且切换模型时要改代码。TaoToken 的做法是提供一个统一的 API 通道你只需要一个 Key就能通过改 model 参数调用不同模型。官网入口在这里https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册后在控制台创建 API Key。API 地址是 https://taotoken.net/api 注意这个地址不加 UTM 参数直接用于代码里的 base_url。3.2 可复制的配置文件以 Python 的 openai SDK 为例创建一个config.py# config.py import os from openai import OpenAI client OpenAI( api_keyos.getenv(TAOTOKEN_API_KEY, sk-your-key-here), base_urlhttps://taotoken.net/api ) # 不同 Agent 用不同模型但共用同一个 client MODEL_PLANNER claude-sonnet-4-20250514 # 规划用推理强的 MODEL_EXECUTOR gpt-4o-mini # 执行用速度快的 MODEL_REVIEWER claude-sonnet-4-20250514 # 审查用代码能力好的如果你用 Claude Code 或 Cline 这类工具配置方式略有不同。以 Claude Code 为例需要在 settings 里指定 Base URL 和 Key{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: sk-your-key-here } }Cline 的 MCP 配置里Base URL 填https://taotoken.net/apiAPI Key 填你创建的那个Model ID 按你实际要用的模型填。这三件套——Base URL、Key、Model ID——是任何工具接入时必须对齐的缺一个都会报 401 或 model not found。3.3 验证 Key 是否可用配置完先别急着跑 Agent用一条最小请求验证通道# verify.py from config import client, MODEL_EXECUTOR resp client.chat.completions.create( modelMODEL_EXECUTOR, messages[{role: user, content: 只回复两个字通了}] ) print(resp.choices[0].message.content)如果返回“通了”说明 Key 和 Base URL 都正确。如果报 401检查 Key 是否复制完整如果报 model not found检查 Model ID 拼写。这一步花两分钟能省掉后面半小时的排查。4. 上下文工程与工具系统让 Agent 真正能干活4.1 上下文窗口的预算管理上下文工程的核心是在有限窗口里放最关键的信息。一个完整的上下文通常包含系统提示词、工具定义、对话历史、检索到的外部知识、临时工作状态。我的做法是给每一类分配 token 预算超了就按优先级裁剪。TOKEN_BUDGET { system_prompt: 2000, tool_definitions: 1500, retrieved_knowledge: 4000, conversation_history: 3000, working_memory: 1500 } def assemble_context(system, tools, knowledge, history, memory): # 按预算裁剪优先级低的先砍 if count_tokens(knowledge) TOKEN_BUDGET[retrieved_knowledge]: knowledge rerank_and_truncate(knowledge, TOKEN_BUDGET[retrieved_knowledge]) if count_tokens(history) TOKEN_BUDGET[conversation_history]: history summarize_old_turns(history) return build_prompt(system, tools, knowledge, history, memory)检索策略上纯向量检索在代码场景经常不够准。我一般用混合检索BM25 抓精确匹配函数名、API 名向量检索抓语义相关再用重排序模型对结果精排。这样既能找到getUserById这种精确符号也能找到语义相关但命名不同的实现。4.2 工具系统的设计原则工具是 Agent 的手脚。设计工具时记住三条语义清晰、单一职责、最小权限。每个工具的 description 要当成“给 AI 看的微提示词”来写因为模型就是靠这段描述决定什么时候调用它。tools [ { type: function, function: { name: search_codebase, description: 在代码库中搜索匹配的代码片段。适用于查找函数定义、类定义、变量引用。输入应为具体的符号名或关键词不要输入自然语言问题。, parameters: { type: object, properties: { query: {type: string, description: 搜索关键词如函数名或类名}, file_pattern: {type: string, description: 文件匹配模式如 *.py} }, required: [query] } } } ]注意 description 里明确写了“不要输入自然语言问题”这是为了防止模型把“这个函数是干嘛的”这种问题直接丢给搜索工具。工具编排上流程固定的场景用链式DAG动态决策的场景用意图分类后分发。5. 多 Agent 协作编排与常见报错排查5.1 主管-专家模式的编排示例多 Agent 协作最常见的拓扑是主管-专家模式一个规划 Agent 接收目标拆成子任务分发给执行 Agent最后汇总。下面是一个最小可运行的编排# orchestrator.py from config import client, MODEL_PLANNER, MODEL_EXECUTOR def planner_agent(goal: str) - list: resp client.chat.completions.create( modelMODEL_PLANNER, messages[{ role: user, content: f把以下目标拆成 3 个以内的子任务每行一个不要编号\n{goal} }] ) return [t.strip() for t in resp.choices[0].message.content.strip().split(\n) if t.strip()] def executor_agent(task: str) - str: resp client.chat.completions.create( modelMODEL_EXECUTOR, messages[{role: user, content: f完成以下任务并给出结果\n{task}}] ) return resp.choices[0].message.content def run_multi_agent(goal: str): tasks planner_agent(goal) results [] for t in tasks: results.append({task: t, result: executor_agent(t)}) return results if __name__ __main__: out run_multi_agent(审查项目中的异常处理并给出改进建议) for item in out: print(f任务{item[task]}\n结果{item[result][:200]}\n)跑通后你会看到规划 Agent 把目标拆成了几个子任务执行 Agent 逐个完成。如果某个子任务失败可以在 executor 层加重试或者把失败信息回传给 planner 重新规划。5.2 常见报错对照排查401 UnauthorizedKey 不对或没带上。检查api_key是否设置Base URL 是否是https://taotoken.net/api。注意 Base URL 结尾不要多加/v1SDK 会自己拼。local proxy failed / connection error网络层问题。先确认能否访问https://taotoken.net/api再检查是否有本地代理配置冲突。如果你在容器里跑检查容器的网络模式。reading choices 报错 / KeyError: choices通常是返回体不是标准格式可能是模型名写错导致返回了错误信息。打印完整resp看实际返回内容确认 Model ID 正确。OAuth 相关报错如果你用 Claude Code 这类工具OAuth 报错通常是因为认证方式冲突。改用 API Key 方式在 settings 里显式设置ANTHROPIC_API_KEY和ANTHROPIC_BASE_URL不要同时开 OAuth。模型返回空内容检查 max_tokens 是否设得太小或者 prompt 里要求了模型无法完成的格式。把 temperature 调到 0 再试一次排除随机性。6. 把整条链路串起来从验证到长期运行到这里你已经有了结构化提示词模板、统一 Key 配置、上下文预算管理、工具定义和多 Agent 编排。下一步是验证整条链路先用一条简单请求确认 TaoToken 通道可用再跑单 Agent 任务确认工具调用正常最后跑多 Agent 编排确认任务分发和结果汇总没问题。如果你要长期跑编码类 Agent建议用 Coding Plan 来管理调用配额和模型切换入口在 https://taotoken.net/api 对应的控制台里可以找到。模型对话调试可以用模型对话页面快速验证 prompt 效果接入文档里有各语言 SDK 的完整示例。一个实用技巧把每次 Agent 运行的完整上下文和输出落盘到本地日志格式用 JSONL每行一条记录。这样出问题时可以回放也能用来做后续的提示词优化。我现在的做法是每个 Agent 一个日志文件按日期切分排查时直接 grep 关键词比在控制台翻历史快得多。最后一步把config.py里的 Key 换成环境变量读取别硬编码在代码里。部署时用密钥管理服务注入本地开发用.env文件加.gitignore。这一步做完你的 Agent 系统就从“能跑”变成了“能安全地长期跑”。