1. 为什么我要用 Claude Code 手搓一个 Presentation Agent
先说清楚这个东西是什么。Presentation Agent,直译就是演示文稿智能体,你给它一句话需求,比如“帮我做一份 2025 年新能源汽车出海趋势的汇报”,它自己拆大纲、自己搜资料、自己生成一页页 HTML 幻灯片,最后你在浏览器里翻页就能看。它适合谁?适合经常要做技术分享、周报汇报、方案评审,但又不想在 PPT 排版上耗掉半天的开发者;也适合想入门 Agent 编排、想找一个“有真实产出”的练手项目的同学。
我为什么不用现成的 PPT 工具?因为传统 PPT 是二进制格式,模型很难直接操控版式,而 HTML 天生就是文本,模型生成静态页面的能力又强,所以“生成 HTML 演示页面”这条路,比“生成 .pptx”顺得多。整套流程我用 Claude Code 来写,它负责读需求、改代码、跑命令、修报错,我负责 review 和定方向。
这篇文章不讲空话,我会把三件事讲透:第一,怎么用 TaoToken 拿到一个统一 Key,把 Claude Code 接上;第二,Presentation Agent 的三个 Agent(Outline / Search / HTML)怎么编排;第三,本地怎么跑起来验证,以及我踩过的那些报错怎么排。你跟着做,能复现一个最小可用的版本。
核心检索词先埋在这:Claude Code 接入、Presentation Agent 开发、大模型 Agent 编排、HTML 幻灯片生成。这四个词贯穿全文,你搜哪个都能落到这篇。
我试过纯手写这套编排,后来发现用 Claude Code 边聊边生成效率高太多,尤其是前端那部分,我基本没自己写 CSS。下面从环境准备开始,一步步来。
2. TaoToken 前置准备:统一 Key 与 Claude Code 接入配置
这一章是地基,地基不稳后面全白搭。TaoToken 的作用是给你一个统一的 API 入口和 Key,让你不用在多个模型供应商之间来回切换配置。官网地址是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 根地址是 https://taotoken.net/api ,注意 API 地址后面不加任何参数。
第一步,注册并拿到 Key。打开官网,进控制台,找到 API Keys 页面(deep link:https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api_keys&utm_campaign=rewrite ),新建一个 Key,复制出来。这个 Key 就是你后面所有配置里要填的东西,形如sk-xxxxxxxx。别把它提交到 Git,我一般放.env里然后加进.gitignore。
第二步,确认你要用的模型 ID。TaoToken 支持多种模型,你在模型对话页面(deep link:https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite )能看到当前可用的模型列表。做 Presentation Agent 我建议用长上下文、代码能力强的模型,因为要生成大量 HTML。记下你选的 Model ID,比如claude-sonnet-4-5这类,后面配置要用。
第三步,配置 Claude Code。Claude Code 读取的是环境变量,你需要设置三个东西:Base URL、API Key、Model。在终端里这样写(macOS / Linux):
export ANTHROPIC_BASE_URL="https://taotoken.net/api" export ANTHROPIC_API_KEY="sk-你的Key" export ANTHROPIC_MODEL="claude-sonnet-4-5"Windows PowerShell 用这个:
$env:ANTHROPIC_BASE_URL="https://taotoken.net/api" $env:ANTHROPIC_API_KEY="sk-你的Key" $env:ANTHROPIC_MODEL="claude-sonnet-4-5"如果你想让配置持久化,写进~/.zshrc或~/.bashrc,然后source一下。这里有个坑:Base URL 千万别写成https://taotoken.net/api/带尾斜杠,有些客户端拼接路径时会变成双斜杠导致 404。我踩过这个坑,排查了半小时。
第四步,验证 Claude Code 能不能连上。在项目目录里直接跑claude,进去后随便问一句“你好”,能正常回就说明通了。如果报 401,八成是 Key 错了或者没生效,重新echo $ANTHROPIC_API_KEY确认一下。
关于 Coding Plan,如果你打算长期用 Claude Code 做开发、跑 Agent,可以看下 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding_plan&utm_campaign=rewrite ,它更适合高频编码场景,比按量付费省心。接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite ,遇到配置细节可以对照看。
这一章做完,你应该有一个能正常对话的 Claude Code。下一章开始写真正的 Agent 代码。
3. 可复制配置:Presentation Agent 的目录结构与核心配置片段
这一章给你能直接抄的配置。先说目录结构,我习惯这样组织:
presentation-agent/ ├── .env ├── config/ │ └── settings.toml ├── agents/ │ ├── outline_agent.py │ ├── search_agent.py │ └── html_agent.py ├── tools/ │ ├── search_tool.py │ └── fetch_tool.py ├── output/ └── main.py.env文件内容:
TAOTOKEN_BASE_URL=https://taotoken.net/api TAOTOKEN_API_KEY=sk-你的Key TAOTOKEN_MODEL=claude-sonnet-4-5 SERPER_API_KEY=你的搜索Keyconfig/settings.toml是核心,把模型参数、Agent 限制都放这:
[llm] base_url = "https://taotoken.net/api" model = "claude-sonnet-4-5" temperature = 0.7 max_tokens = 8192 [outline_agent] num_topics = 5 max_tool_calls = 6 [search_agent] max_tool_calls = 8 max_fetch_length = 4000 parallel = true [html_agent] page_width = 1280 page_height = 720 theme = "modern" [output] dir = "./output"注意max_fetch_length这个参数,它控制每次抓网页后截断的长度。我一开始没限制,结果一个 Search Agent 就烧了 900K token,大部分是输入 token。限制到 4000 字符后,成本直接降下来。
如果你用 Claude Code 的 settings 文件(~/.claude/settings.json),可以这样写,把 TaoToken 作为统一入口:
{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_API_KEY": "sk-你的Key", "ANTHROPIC_MODEL": "claude-sonnet-4-5" }, "permissions": { "allow": ["Bash(python:*)", "Read", "Write"] } }这里三件套必须齐全:Base URL 是https://taotoken.net/api,Key 是你的sk-开头那串,Model ID 是你在模型列表里选的那个。少一个都连不上。
如果你用 Cline 或 CC Switch 这类工具,配置逻辑一样,都是填这三项。Cline 的 MCP 配置里,把 TaoToken 当成一个 provider 填进去即可。Codex 的auth.json也是同理,把 base_url 和 api_key 换成 TaoToken 的。
配置写完,跑一句python -c "import tomllib; print(tomllib.load(open('config/settings.toml','rb')))"确认 TOML 没语法错。这一步别省,我见过太多人因为 TOML 少个引号卡半天。
4. 三个 Agent 的编排与本地运行验证
现在写核心逻辑。整个 Presentation Agent 是一个 workflow,分三步:Outline Agent 生成大纲,Search Agent 并行收集内容,HTML Agent 生成页面。每个 Agent 只配两个工具:搜索和 fetch。
先看 Outline Agent 的 prompt,这是纯 prompt 驱动的:
OUTLINE_PROMPT = """ 你的任务是根据用户的描述生成大纲。 大纲包含 {num_topics} 个子主题,每个子主题包含 3-5 个要点。 要求: - 如果对用户描述不清楚,或涉及时效性信息,使用搜索工具获取最新信息 - 搜索到相关链接后,可用 fetch 工具阅读页面详细内容 - 最终必须返回有效的 JSON 格式,严格遵循以下 schema: {schema} 重要:无论如何都必须输出符合上述 schema 的 JSON 对象。 """关键点是强制 JSON 输出,用 Pydantic 模型生成 schema 塞进 prompt,解析时就不会崩。Outline Agent 跑完,你得到一个结构化的主题列表。
Search Agent 是并行的,每个子主题一个 Agent,各自去搜。这里我踩的坑最多:并行 Agent 之间缺乏全局把控,会重复抓同一个来源,token 浪费严重。后来我加了一个汇总步骤,把各 Agent 的结果去重再合并。另外图片问题很头疼,模型自己判断的图片链接经常失效或带水印,我的建议是把图片下载到本地,顺便拿到尺寸,这样 HTML 排版时能预留位置。
HTML Agent 内部也是 workflow:先定主题样式,再生成封面页、目录页、内容页。封面和目录好搞,prompt 调好基本没问题;内容页难,容易出现布局不对齐、内容分布不均、图片截断。我的做法是给每页固定 1280x720 的画布,内容溢出就自动缩字号,二者做权衡。
本地运行验证,先跑最小闭环:
python main.py --topic "2025年新能源汽车出海趋势" --pages 8跑完去output/目录看,应该有一个index.html。用浏览器打开:
python -m http.server 8000 --directory output然后访问http://localhost:8000,能翻页就说明成功了。我实测下来,第一次跑通常会有一两页排版崩,这是正常的,调 prompt 迭代就行。
验证请求是否真的走了 TaoToken,可以在代码里打印 response 的 usage 字段,看 token 消耗。如果 usage 一直是 0 或者报错,说明请求没发出去,回去检查 Base URL 和 Key。
如果你想先单独验证模型通不通,用模型对话页面(deep link:https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=chat&utm_campaign=rewrite )发一句话测试,比在代码里 debug 快。
5. 常见报错排查:401、local proxy failed、reading choices、OAuth
这一章全是真实报错,对照着排。
401 Unauthorized。最常见,原因就三个:Key 错了、Key 没生效、Base URL 写错。先echo $ANTHROPIC_API_KEY看有没有值,再确认 Base URL 是https://taotoken.net/api不带尾斜杠。如果用的是 settings.json,检查 JSON 有没有语法错,逗号多了少了都会导致整个配置不生效。
local proxy failed / connection refused。这个通常是你本地起了代理但没配对,或者环境变量里残留了旧的代理设置。检查echo $HTTP_PROXY $HTTPS_PROXY,如果有值且不是你想要的,unset掉。注意,这里说的是清理本地环境变量,不是让你去搞什么网络工具,纯粹是配置冲突问题。
reading choices 报错 / choices 字段为空。这是响应解析问题,多半是模型返回的不是标准 OpenAI 格式,或者你用的 SDK 版本和 API 不匹配。解决办法:打印原始 response 看结构,确认choices[0].message.content存在。如果用的是 Anthropic 格式的 SDK,字段是content[0].text,别搞混。
OAuth 相关报错。Claude Code 有时会走 OAuth 流程,如果你用 API Key 模式,确保没有同时开着 OAuth 登录态。清掉~/.claude/下的凭证缓存,重新用 Key 登录。如果报OAuth token expired,直接重新配置环境变量即可。
模型 ID 不存在。报错形如model not found。回去模型列表确认你填的 ID 和平台上一致,大小写、连字符都要对。我见过有人把claude-sonnet-4-5写成claude-sonnet-4.5,直接 404。
token 超限。长文档生成 HTML 时容易触发。调小max_fetch_length,或者把内容页拆成多次请求。别一次性把几万字塞进去。
排障时如果拿不准,接入文档(deep link:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite )里有完整的错误码对照。API Keys 页面可以随时重新生成 Key 排除 Key 本身的问题。
6. 继续迭代:把 Agent 用起来
跑通最小闭环只是开始。我后来做的几件事,你可以参考:把 Search Agent 的网页内容先用小模型总结再喂给主模型,token 直接降一个量级;把图片下载到本地并记录尺寸,HTML 排版稳定很多;给 HTML Agent 加一个自动评估步骤,用多模态模型看渲染截图,判断布局有没有崩,这样迭代快得多。
Agent 模式的好处是省工程,坏处是不可控,prompt 写得再细,产出也像开盲盒。所以评估标准一定要提前定义好,最好能自动化。这套东西我断断续续搞了一两个月,大部分时间花在调 prompt 和排错上,代码本身反而不多。
如果你要长期跑这类编码和 Agent 任务,Coding Plan(deep link:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding_plan&utm_campaign=rewrite )比按量付费更划算。想先验证模型效果,就去模型对话页面发几条测试。配置过程中卡住了,接入文档和 API Keys 页面是你最该先看的两个地方。
最后留一个实用技巧:每次改完 prompt,别急着跑全流程,先用一页内容做单页测试,确认 HTML 渲染没问题再跑整份。这样迭代一轮只要几十秒,比跑完整流程快十倍。