1. 从零手搓 Presentation Agent我到底卡在哪先说结论用 Claude Code 做一个能跑通的 Presentation Agent前端部分几乎可以端到端交给模型真正拖慢进度的是三件事——Key 管理混乱、Agent 上下文失控、生成结果没法自动评估。这篇就把这三件事拆开讲给你一份能直接复制的 settings.json 骨架以及一套可复现的验证动作。Presentation Agent 是什么简单说用户输入一句「帮我做一个关于新能源汽车出海趋势的演示」Agent 自动完成大纲生成、内容检索、页面渲染最后吐出一套可翻页的 HTML 演示页面。它和传统 PPT 生成最大的区别是不生成 .pptx 文件而是直接生成网页靠浏览器翻页。这样做的好处是排版自由度高、移动端适配容易、部署就是静态托管。适合谁看三类人一是想用 Claude Code 做前端 Agent 但被配置卡住的开发者二是已经在写 Agent 但 token 消耗失控、想找优化思路的人三是想理解「代码工具 大模型」这套组合拳到底能省多少工程量的技术负责人。我自己的落地链路是这样的Claude Code 负责写代码和调 promptTaoToken 提供统一的模型接入 Keysettings.json 管住工具链和权限边界最后用三个 AgentOutline / Search / HTML串成 workflow。下面按这个顺序展开每一步都给可复制的配置和验证命令。2. TaoToken 前置统一 Key 接入与项目初始化在动手写 Agent 之前先把模型接入这层理顺。我踩过的第一个坑就是一开始每个 Agent 各写一套请求逻辑Key 散落在环境变量、配置文件、甚至硬编码里改一次模型要翻五个文件。后来统一走 TaoToken 的 API 网关所有 Agent 共用一个 base_url 和一个 Key切换模型只改一个字段。TaoToken 在这里扮演的角色是「统一入口」它兼容 OpenAI 风格的接口协议所以 Claude Code 生成的代码里只要把 base_url 指向https://taotoken.net/api再用标准的 chat completions 调用方式就能对接上。你不需要为每个模型单独写适配层。第一步去控制台创建一个 API Key。地址是 https://taotoken.net/api-keys 登录后新建 Key复制出来。注意这个 Key 只在创建时完整显示一次丢了就得重建。第二步把 Key 写进项目根目录的.env文件不要提交到 git# .env TAOTOKEN_API_KEYsk-你的key TAOTOKEN_BASE_URLhttps://taotoken.net/api第三步在.gitignore里加上.env这一步很多人会忘一旦 Key 推到公开仓库基本等于报废。# .gitignore .env node_modules/ dist/第四步验证 Key 是否可用。用 curl 发一个最小请求确认能拿到返回curl https://taotoken.net/api/chat/completions \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json \ -d { model: claude-sonnet-4-20250514, messages: [{role: user, content: 回复 OK 两个字母}], max_tokens: 16 }如果返回里有choices[0].message.content说明接入通了。如果返回 401检查 Key 有没有多余空格返回 404检查 base_url 是不是写成了带/v1的旧格式——TaoToken 的路径就是/api/chat/completions不要自己加/v1。提示把 base_url 和 Key 都放进环境变量代码里用process.env.TAOTOKEN_BASE_URL读取。这样本地、CI、线上三套环境可以共用一份代码只换环境变量。3. 可复制配置settings.json 骨架与工具链Claude Code 的 settings.json 是整个项目的控制中枢它决定了模型能用哪些工具、能读写哪些目录、单次会话的 token 上限。我最初的版本几乎是空的结果 Claude Code 在生成代码时反复去读 node_modules白白烧掉大量 token。下面这份是我调了多轮之后稳定下来的骨架。{ model: claude-sonnet-4-20250514, env: { TAOTOKEN_API_KEY: ${TAOTOKEN_API_KEY}, TAOTOKEN_BASE_URL: https://taotoken.net/api }, permissions: { allow: [ Read(src/**), Read(prompts/**), Write(src/**), Write(prompts/**), Bash(npm run build), Bash(npm run test) ], deny: [ Read(node_modules/**), Read(.env), Write(.env), Bash(rm -rf *) ] }, tools: { search: { provider: serper, maxCalls: 8 }, fetch: { maxCalls: 12, maxContentLength: 8000 } }, limits: { maxAgentTurns: 6, maxTokensPerSession: 200000 } }几个关键点解释一下。permissions.deny里把node_modules和.env挡掉是防止模型在探索代码库时把无关文件读进来这一条直接把我单次会话的输入 token 砍掉了将近四成。tools.fetch.maxContentLength限制单页抓取长度避免一个长网页把上下文撑爆。limits.maxAgentTurns是防死循环的保险丝Agent 在搜索和抓取之间来回横跳时超过 6 轮就强制停。工具链这边我用了两个外部工具搜索走 serper.dev抓取走一个 MCP fetch 工具。MCP 的配置放在项目根目录的.mcp.json{ mcpServers: { fetch: { command: npx, args: [-y, modelcontextprotocol/server-fetch], env: { MAX_CONTENT_LENGTH: 8000 } } } }配好之后Claude Code 启动时会自动加载这个 MCP serverAgent 就能通过标准接口调用 fetch。这里有个坑MCP server 首次启动要下载依赖如果网络慢会卡住建议先在终端手动跑一次npx -y modelcontextprotocol/server-fetch把包缓存下来。注意settings.json 里的${TAOTOKEN_API_KEY}是引用系统环境变量不是字面量。如果你直接写死 Key一旦这个文件被分享出去就泄露了。4. 验证请求三个 Agent 的串联与成功结果配置就绪后开始写 Agent 主流程。我的设计是三个 Agent 串行加并行混合Outline Agent 先跑产出结构化大纲Search Agent 按大纲的每个子主题并行执行HTML Agent 拿到全部内容后生成页面。先看 Outline Agent 的核心 prompt。这里用 JSON schema 约束输出方便后续解析OUTLINE_PROMPT 你的任务是根据用户描述生成演示大纲。 大纲包含 {num_topics} 个子主题每个子主题包含 3-5 个要点。 要求 - 如果涉及时效性信息使用搜索工具获取最新内容 - 搜索到链接后可用 fetch 工具阅读详情 - 最终必须返回符合以下 schema 的 JSON {schema} 调用时把Outline.model_json_schema()塞进{schema}占位符。实测下来加了 schema 约束之后模型返回非法 JSON 的概率从大概三成降到几乎为零。Search Agent 并行执行的部分用 asyncio 控制import asyncio async def run_search_agents(topics): tasks [search_one(topic) for topic in topics] results await asyncio.gather(*tasks, return_exceptionsTrue) return [r for r in results if not isinstance(r, Exception)]每个search_one内部限制最多 3 次搜索加 4 次 fetch超过就返回已有内容。这个限制很关键不加的话单个 Agent 能把 token 烧到失控。HTML Agent 内部再分四步主题样式设计、封面页、目录页、内容页。样式设计先产出一份 CSS 变量表后面所有页面复用保证视觉一致:root { --primary: #2563eb; --bg: #0f172a; --text: #e2e8f0; --radius: 12px; }验证成功的标志是什么跑完一次完整流程后你应该得到一个outline.json含 5 个子主题、五个content-*.json每个含要点和配图链接、一个index.html能在浏览器打开并翻页。我用一个「2025 新能源汽车出海」的输入实测从触发到生成完毕大约 90 秒消耗约 180K token其中输入占七成。如果你想先单独验证模型对话链路是否通可以直接用模型对话页面发一条测试消息确认返回正常再跑完整 Agent。地址是 https://taotoken.net/chat 。5. 本篇常见错排查这一节把我实际撞过的报错按现象归类你遇到时可以直接对号入座。报错一401 Unauthorized。九成是 Key 问题。先确认.env里的 Key 没有首尾空格再确认代码读取环境变量的时机——如果你在模块顶层就读了process.env而 dotenv 还没加载拿到的就是 undefined。把dotenv.config()放到所有 import 之前。报错二Agent 陷入搜索死循环。现象是 token 飞快消耗但迟迟不返回。原因是 prompt 里没给终止条件。解决方法是双保险prompt 里写明「最多搜索 3 次」代码里用maxAgentTurns硬截断。我试过只靠 prompt 约束模型偶尔会无视加上代码层截断才彻底稳住。报错三生成的 HTML 图片全部裂开。因为 Search Agent 返回的是外链源站做了防盗链或者链接过期。两个解法一是把图片下载到本地public/images/再引用相对路径二是至少加referrerpolicyno-referrer和onerror兜底。我后来选了下载到本地顺便还能拿到图片真实尺寸排版时能提前预留位置。报错四内容页布局错位。典型表现是文字溢出容器或者图片被截断。根因是没限制页面尺寸。给每个内容页加固定宽高比容器内部用 flex 布局超出部分用overflow: hidden加省略号。别指望模型一次生成完美布局先保证不崩再谈美观。报错五MCP fetch 工具调用超时。检查.mcp.json里的 command 路径是否正确以及 npx 能否正常拉包。如果公司网络有限制先在本地把包装好再把 command 改成绝对路径。报错六不同 Agent 重复抓同一个来源。这是并行执行的副作用。缓解办法是在 Search Agent 之间共享一个已访问 URL 集合抓之前先查重。更彻底的做法是先用一个 Agent 做全局信息收集再分发给下游但那样对单 Agent 能力要求更高。提示排查 token 异常时用 claude-monitor 这类工具看实时用量能快速定位是哪个 Agent 在烧钱。我最初就是靠它发现 Search Agent 的输入 token 占了总量的七成。6. 语义一致收尾把这条链路跑成你自己的整套流程跑通之后你会发现真正省时间的不是「模型帮你写代码」而是「模型帮你把不熟悉的领域趟平」。前端我不算熟但靠 Claude Code 端到端生成从零到部署上线也就断断续续花了一个多月其中大部分时间是在调 prompt 和排查上面那些报错。如果你打算复现建议按这个顺序推进先把 TaoToken 的 Key 和 base_url 配好用 curl 验证通再把 settings.json 和 .mcp.json 落地确认权限和工具链生效然后单独跑 Outline Agent确认 JSON 输出稳定最后再串 Search 和 HTML。每一步都验证过再往下走比一口气写完再调试省事得多。长期做编码类 Agent 的话可以考虑 Coding Plan 这类按周期计费的方案比按量付费在密集开发期更划算具体在 https://taotoken.net/coding-plan 看。接入文档在 https://taotoken.net/doc 里面把接口参数和错误码列得比较全排障时对着查比瞎猜快。最后留一句实在话Agent 的输出质量七分靠上下文管理三分靠模型能力。你把 settings.json 的权限边界收窄、把 prompt 的终止条件写死、把工具调用次数卡住效果自然就稳了。剩下的美学问题那是另一个战场。