ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Codex 配 TaoToken:前端工程师把 LangChain.js 的 Agent 跑通

Codex 配 TaoToken:前端工程师把 LangChain.js 的 Agent 跑通 1. 前端跑通 LangChain.js Agent卡点通常不在 ReAct而在换模型Codex 对话框里又跳出一个结果LangChain.js 的 Agent 在 ReAct 循环里反复调用同一个工具死循环跑不出去。TaoToken 解决的不只是这一晚的抓狂而是把模型入口收成一条到 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 创建 KeyCodex 的 Base URL 配成 https://taotoken.net/api之后每次换模型试成本都只改一个 ID。你不需要再为 DeepSeek、豆包、Kimi、Claude 各准备一把独立的 Key也不用在三个配置文件里来回找 base URL 到底写在哪。这份三个月路线图的第一阶段目标是调通 LLM API、写 Function Calling第二阶段目标是跑通 ReAct 循环和 LangChain.js 的 Agent。对前端工程师来说这两步真正难的不是概念而是“试错成本”。官方文档、各家控制台、不同的计费单位足以让一个想在周末跑通 Demo 的人把整个下午花在注册和复制 Key 上。Codex 作为命令行编程助手负责读写项目文件、生成 TypeScript 代码TaoToken 作为统一 API 通道负责让 Codex 和 LangChain.js 里的模型实例指向同一个入口。两者合在一起前端工程师只需要维护一套环境变量。1.1 前端的三项基本功正好是 Agent 的三个零件你每天在写的 TypeScript、React、Node和 Agent 工程并不是两套世界观。API 设计对应 Tool CallingAgent 调用工具本质上就是把你封装好的接口按约定暴露给模型让它决定什么时候调用、传什么参数。异步编程对应 ReAct 循环Reasoning 是发起一次请求Acting 是 await 一个工具函数Observation 是拿到结果后再更新对话状态整个过程就是一个更大的 async/await。状态管理对应 Agent Memory短期记忆是当前 messages 数组长期记忆是持久化到向量数据库和 Redux persist 要做的事属于同一类问题。组件化思维对应 Agent 的规划调度LLM 大脑负责决策工具调用负责执行记忆负责上下文每一块都可以独立替换和你拆 React 组件没有本质区别。1.2 ReAct 死循环不是模型笨是调试成本让人不想试第二个月最劝退人的时刻是 Agent 死循环。模型反复选择同一个工具、传同一个参数或者在两个工具之间来回横跳。常见的解法是换一个小一号的模型去试错便宜模型更容易暴露工具描述里的歧义等调通之后再切回主力模型。可如果手上有五个平台的 Key分别对应五个不同风格的 Base URL一次对比就要动五处配置大概率试到第二次就放弃了。统一通道把换模型变成改一个字符串后死循环调试才真正愿意多跑几轮。这就是接入配置这件事值得在进入 LangChain.js 之前先做干净的原因。1.3 这是统一接入层不是另一个模型账号需要先厘清定位TaoToken 不是让你绕过哪家模型的限制而是把各家模型的 HTTP 调用方式统一成 OpenAI 兼容的 chat 接口让 Codex、LangChain.js、Vercel AI SDK 这类前端熟悉的工具直接复用同一套配置。你要在落地页注册并创建 Key在工具里填的 Base URL 则是另一个地址。官网落地页和接口地址不要混用这是接 TaoToken 时最容易踩的坑后面的配置小节会专门展开。2. 第一个月地基把 Codex 的 Base URL 指到 TaoToken调通裸 API 和 Function Calling原文第一个月列了三件事调通 LLM 接口、写 Function Calling、用提示词控制输出。这三件事可以全部发生在 Codex 的配置与一个小型 TypeScript 文件里。把 Codex 指向 TaoToken 之后你在对话框里让它生成的每一段调用代码都会打到同一个 API 地址上省去反复解释“我的模型服务商是谁”的额外沟通成本。2.1 准备材料去 TaoToken 模型广场挑一个模型 ID开始配 Codex 之前先打开 TaoToken 注册并创建一个 API Key创建完你会得到一串以 YOUR_API_KEY 形式存在的占位符。这里有一个容易被忽略的动作顺便打开模型广场记下你要用的模型 ID。模型 ID 不要凭记忆填更不要猜一个带日期的版本号一切以 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 模型广场展示的为准。TaoToken 官网负责注册、创建 Key、查模型、看用量真正填进 Codex 的接口地址是 https://taotoken.net/api末尾没有 /v1。2.2 在 ~/.codex/config.toml 里注册 TaoToken ProviderCodex 的配置文件在 ~/.codex/config.toml。把下面这段追加进去。model需要替换成你在模型广场看到的真实 ID不要照抄model 模型广场上的模型ID [model_providers.taotoken] name TaoToken base_url https://taotoken.net/api env_key TAOTOKEN_API_KEY wire_api chat然后在当前终端导出 Keyexport TAOTOKEN_API_KEYYOUR_API_KEYCodex 会读取env_key指定的环境变量把它的值作为 Bearer Token 发给base_url。wire_api chat表示走 OpenAI 兼容的对话补全接口。如果你用 direnv 或 dotenv也可以把 Key 写进 .envrc 或 .env.local但不要提交到 git。截图、博客、聊天记录里的 Key 只要泄露过就去 TaoToken 控制台重新生成旧 Key 立即作废。2.3 第一个裸 API 调用连 JSON Mode 一起验证配置完成后不用急着上 Agent先让 Codex 帮你写一个最简的 chat 请求确认 Key 和 Base URL 已经打通。下面这段代码也对应原文第一个月的“调通 LLM API 提示词控制输出”import dotenv/config; async function chat(prompt: string) { const res await fetch(https://taotoken.net/api/chat/completions, { method: POST, headers: { Content-Type: application/json, Authorization: Bearer ${process.env.TAOTOKEN_API_KEY}, }, body: JSON.stringify({ model: process.env.MODEL_ID, messages: [ { role: system, content: 只输出 JSON不要解释。 }, { role: user, content: prompt }, ], }), }); const data await res.json(); return data.choices?.[0]?.message?.content; } console.log(await chat(把这句话转成 { emotion: string } 格式));把MODEL_ID导出为刚才记下的模型 ID跑一次。能拿到 JSON 输出说明 TaoToken 通道已经通了。System Prompt 里“只输出 JSON”就是 JSON Mode 的最简实现后续可以把它升级成 Few-shot 或 Chain of Thought 的模板。2.4 Function Calling把 TS 类型翻译成工具描述第一个月的第三个目标是 Function Calling。模型不直接执行函数它只是根据工具描述返回一个 JSON 片段由你的代码去真实调用。最朴素的理解方式是把 TS 类型翻译成 JSON Schema 喂给模型const getWeatherTool { type: function, function: { name: get_weather, description: 根据城市名查询当前天气, parameters: { type: object, properties: { city: { type: string, description: 城市中文名例如 杭州 }, }, required: [city], }, }, } as const;把这段描述发给 chat 接口后模型回包里会出现tool_calls。你执行get_weather函数再把结果作为role: tool的消息返回一轮工具调用就结束了。在 LangChain.js 里这个流程会被封装成更高级的tool()也就是下一章要用的东西。3. 第二个月核心用 LangChain.js 把 ReAct Agent 跑通并解决死循环第二个月的目标是搭一个能完成多步推理的 Agent。原文提到 LangChain 2026 已经用tool装饰器替代了老旧的 Chain 模式。用 LangChain.js 写工具最直观的写法是把输入 schema 和函数体放进同一个定义。下面的代码就是一个可运行的 LangChain.js Agent依赖如下npm i langchain/openai langchain/core langchain/langgraph zod3.1 用 tool() 把 TS 函数变成 Agent 的双手import { ChatOpenAI } from langchain/openai; import { tool } from langchain/core/tools; import { createAgent } from langchain/langgraph/prebuilt; import { z } from zod; const getStockPrice tool( async ({ symbol }) { const prices: Recordstring, number { AAPL: 228.4, MSFT: 412.1, TSLA: 248.9 }; return JSON.stringify({ symbol, price: prices[symbol] ?? 0 }); }, { name: get_stock_price, description: 查询美股当前价格返回 USD, schema: z.object({ symbol: z.string().describe(股票代码例如 AAPL), }), } ); const model new ChatOpenAI({ apiKey: process.env.TAOTOKEN_API_KEY, baseURL: https://taotoken.net/api, model: process.env.MODEL_ID, }); const agent createAgent({ model, tools: [getStockPrice], returnIntermediateSteps: true, }); const res await agent.invoke({ messages: [{ role: user, content: AAPL 和 MSFT 哪个更贵 }], }); console.log(res.messages.at(-1)?.content);createAgent内部已经实现了 ReAct 循环不需要手写while。你要做的只是提供 model 和 tools。baseURL指向 TaoToken 的 API 地址不需要加/v1model来自环境变量方便后面切换。3.2 死循环排查先看中间步骤再改描述returnIntermediateSteps: true打开后把整个res打印出来你能看到模型每一步的 reasoning、它选中了哪个工具、传了什么参数、拿到了什么结果。死循环最典型的原因是工具描述太宽泛。比如只说“查询美股价格”模型不知道价格单位是美元、返回的是数字还是字符串于是反复调用同一工具去试。把描述改成“返回 USD”并让 schema 里的字段名更明确问题通常会消失。提示如果模型在多个工具之间来回横跳优先检查是不是某个工具几乎不做任何事却总是匹配用户意图。一个工具只解决一个问题比一个大而全的工具更容易被模型正确选中。3.3 低成本换模型试错一个 Key 跑完所有候选如果工具描述改了两轮仍然死循环就需要换模型做对比。TaoToken 一个 Key 的好处在这里会放大你可以把所有候选模型 ID 放进数组用同一段 Agent 脚本批量跑看哪个模型能一次走到最终答案。const modelIds [模型广场上的ID-A, 模型广场上的ID-B]; for (const modelId of modelIds) { const candidate new ChatOpenAI({ apiKey: process.env.TAOTOKEN_API_KEY, baseURL: https://taotoken.net/api, model: modelId, }); const runner createAgent({ model: candidate, tools: [getStockPrice] }); const out await runner.invoke({ messages: [{ role: user, content: 查一下 MSFT 当前价格 }], }); console.log(modelId, , out.messages.at(-1)?.content); console.log(tokens:, out.usage_metadata?.total_tokens); }数组里的 ID 以 TaoToken 模型广场为准不要背别人博客里的旧 ID。这样跑一轮既能看出哪个模型最稳也能从usage_metadata里对比谁更省 Token。等你找到稳定组合再把它固化到 config.toml 的model字段里。3.4 RAG 与状态持久化给 Agent 接一个“搜索后端”RAG 在第二个月路线里出现频率很高但它没有想象中神秘当 Agent 不知道答案时先从外部索引里检索相关内容再把检索结果拼进上下文。前端工程师可以把 Embedding 理解成“给文档生成索引标签”向量数据库理解成“支持相似度搜索的后端”。LangChain.js 里可以用 MemoryVectorStore 快速体验import { MemoryVectorStore } from langchain/vectorstores/memory; import { OpenAIEmbeddings } from langchain/openai; const embeddings new OpenAIEmbeddings({ apiKey: process.env.TAOTOKEN_API_KEY, configuration: { baseURL: https://taotoken.net/api }, }); const store await MemoryVectorStore.fromDocuments( [ { pageContent: TaoToken 是面向 AI 编程工具的统一 API 通道, metadata: { source: blog }, }, { pageContent: Base URL 使用 https://taotoken.net/api末尾不要加 /v1, metadata: { source: docs }, }, ], embeddings ); const retriever store.asRetriever(1); const docs await retriever.invoke(统一 API 通道); console.log(docs[0].pageContent);这段代码需要模型广场上有可用的 Embedding 模型如果你的模型列表里没有就先跳过 RAG把精力放在 Agent 本身。状态持久化的思路与前端一致短期记忆就是当前会话的 messages长期记忆才是向量库或数据库。先把短期记忆调通再考虑“重启后 Agent 还记得上周的对话”否则调试范围会同时牵扯模型、工具、存储三层很难定位问题。4. 第三个月项目LangGraph MCP 可观测性以及三个容易走歪的弯路第三个月原文要求做一个能部署、能写进简历的完整 Agent 项目。这里不再铺开讲框架选型只提与前端工程师关系最大的三条项目选型、MCP 工具协议、可观测性。4.1 MCP 是 Agent 世界的 USB 接口前端写 MCP Server 的体感很像写一个 Express 中间件定义工具名、参数、处理函数然后让 Codex 这类支持 MCP 的客户端加载它。一个最小可运行的 MCP Server 是这样的import { McpServer } from modelcontextprotocol/sdk/server/mcp.js; import { StdioServerTransport } from modelcontextprotocol/sdk/server/stdio.js; import { z } from zod; const server new McpServer({ name: todo-mcp, version: 1.0.0 }); server.tool( create_todo, { title: z.string(), due: z.string().optional() }, async ({ title, due }) ({ content: [ { type: text, text: 已创建任务${title}${due ? 截止 ${due} : } }, ], }) ); await server.connect(new StdioServerTransport());MCP 跑通之后你的 Agent 就能读本地文件、操作浏览器、查内部系统。需要提醒的是如果 Agent 要诊断 SQL 或执行数据库查询正确姿势是让 Codex 先生成只读 SQL你在本地数据库客户端里执行完再把结果贴回对话不要让编程工具直接连生产库执行业务操作。Codex 擅长的是生成、解释、对照代码而不是代替你在生产环境里点“运行”。4.2 可观测性LangSmith 记推理链路TaoToken 记 Token 用量Agent 工程化离不开日志。LangSmith 可以记录模型每一步的 reasoning、工具调用、报错信息TaoToken 控制台则记录所有模型请求的 Token 消耗。两边对照你能看出“模型反复调用工具”究竟烧了多少钱也能定位是哪一轮 prompt 让模型跑偏。官网控制台在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 这个页面接口地址是 https://taotoken.net/api两者分开记才不会出错。建议每个项目单独创建 Key并在代码里通过usage_metadata把每次调用的 Token 数写进日志这样 Agent 上线后出了问题你能直接看到某一次死循环浪费了多少成本。4.3 避坑不要只学 Prompt不要转 Python不要只搭 Demo第一个弯路是只学 Prompt 不学 Function Calling。Prompt 决定模型怎么说工具调用决定模型能做什么没有 tools 的 Agent 只是一个高级聊天框。第二个弯路是跑去学 Python。算法岗确实用 Python但前端做 Agent 用 TypeScript 完全够LangChain.js、Vercel AI SDK 都是 TS 优先。第三个弯路是只搭 Demo 不做工程化。可观测性、错误处理、限流、Prompt 注入防护这些才是面试官能一直追问下去的地方。一个能在本地跑通的 Demo 和一份能上线不崩的 Agent 服务中间隔着的正是这些工程细节。5. 最后去控制台看这次调用的 Token 明细路线图走到这一步前两个月的目标已经落地裸 API 能通Function Calling 能写LangChain.js 的 Agent 能跑死循环也能有方法去验证和切换模型。剩下的动作不是再收藏一份资料包而是打开 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end创建 YOUR_API_KEY把上面那段createAgent代码真正跑一次然后去控制台的用量明细里看这次调用产生了多少 Token。对照代码里usage_metadata输出的total_tokens你会对“一次 Agent 循环到底多贵”有真实体感而不是停留在概念层面。这比收藏任何资料包都更接近那份三个月路线图真正想要的终点第一次由一个你自己写的 Agent烧掉真实的 Token吐出准确的答案。
返回列表