1. 为什么要把 LangChain 智能体塞进 ChatboxLangChain 写出来的智能体跑通agent.invoke()只是第一步。真正用起来你会发现一个尴尬的现实每次测试都要开终端、敲 Python、看日志调一句天气问一句效率低得离谱。而 LangChain 官方推荐的 agent-chat-ui 又要额外起一个前端服务端口、依赖、构建一套下来比写智能体本身还费劲。Chatbox 这类客户端的好处就在这里——它本身就是一个成熟的对话界面支持 OpenAI 兼容的 API 调用方式只要你的后端能吐出符合 OpenAI 格式的响应它就能像连 GPT 一样连你的智能体。换句话说你不需要写任何前端代码也不需要懂 React只要把智能体包装成一个/chat/completions接口Chatbox 就能直接对话。这篇要解决的问题很具体用 Trae Solo 把已有的 LangChain 智能体通过 FastAPI 封装成 OpenAI 风格接口再接入 Chatbox 客户端。全程零前端代码核心工作交给 Trae Solo 自动生成你只需要描述需求、检查代码、配置客户端。适合已经写过 LangChain 智能体、想快速验证效果、又不想折腾前端的开发者。下面会给出可复制的 FastAPI 服务骨架、Chatbox 自定义接口配置以及用 TaoToken 统一管理 Key 的 settings.json 片段。2. 前置准备TaoToken 统一 Key 与 Trae Solo 环境在动手之前先把两个基础设施准备好后面配置才不会卡壳。2.1 TaoToken 统一 Key 通道智能体背后要调模型Chatbox 本身也可能要调模型。如果每个地方都填一遍 API Key管理起来很乱。TaoToken 的作用就是提供一个统一的 API 通道你只需要在它那里拿一个 Key就能在多个工具里复用。具体操作访问官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册后进入控制台 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 创建 API Key。拿到 Key 之后在 API Keys 页面 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 可以随时查看和轮换。注意API 基础地址是 https://taotoken.net/api这个地址在后面的 settings.json 和 FastAPI 代码里都会用到不要加多余的路径。2.2 Trae Solo 安装与模式切换Trae 国内版已经上线 SOLO 模式免费可用。去官网下载安装包Windows 平台一路下一步即可。安装完成后打开界面风格接近 VS Code默认进入 Build 模式。在左上角模式切换处选择 SOLO就进入了本文要用的自动化开发模式。SOLO 模式的特点是你用自然语言描述需求它自主完成需求分析、代码编写、测试、启动服务的全流程。对于“把智能体包装成 API”这种目标明确、代码量不大的任务正好合适。3. 可复制配置FastAPI 服务骨架与 settings.json这一节是全文的核心给出可以直接复制运行的代码和配置。建议先建一个项目目录把智能体文件和 FastAPI 服务文件放在一起。3.1 智能体文件 langchain_weather.py假设你已经有一个用 LangChain 写的天气助手智能体核心结构如下。这里用 TaoToken 作为模型通道把 base_url 指向 TaoToken 的 API 地址from langchain.chat_models import init_chat_model from langchain.tools import tool from langchain.agents import create_agent import requests tool def get_weather(loc: str) - str: 查询指定城市的即时天气loc 为城市名称 url https://api.seniverse.com/v3/weather/now.json params { key: 你注册的心知天气api key, location: loc, language: zh-Hans, unit: c, } response requests.get(url, paramsparams) return str(response.json()[results][0][now]) SYSTEM_PROMPT 你是一名天气预报播报员可以调用 get_weather 获取指定地点天气 model init_chat_model( modeldeepseek-chat, base_urlhttps://taotoken.net/api, api_key你的TaoToken API Key ) agent create_agent( modelmodel, tools[get_weather], system_promptSYSTEM_PROMPT )关键点base_url填https://taotoken.net/apiapi_key填你在 TaoToken 控制台创建的 Key。这样智能体调模型走的是统一通道后面 Chatbox 也可以复用同一个 Key。3.2 FastAPI 服务骨架 main.py这是 Trae Solo 生成后我整理过的版本结构清晰支持流式和非流式两种响应from fastapi import FastAPI, HTTPException from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import StreamingResponse from pydantic import BaseModel from typing import List, Optional, Generator import uvicorn import time import json from langchain_weather import agent app FastAPI(titleWeather Assistant API, version1.0.0) app.add_middleware( CORSMiddleware, allow_origins[*], allow_credentialsTrue, allow_methods[*], allow_headers[*], ) class Message(BaseModel): role: str content: str class ChatCompletionRequest(BaseModel): model: str deepseek-chat messages: List[Message] temperature: Optional[float] 0.7 max_tokens: Optional[int] None stream: Optional[bool] False app.post(/chat/completions) async def chat_completions(request: ChatCompletionRequest): try: user_message request.messages[-1].content response_id fchatcmpl-{int(time.time())} created_time int(time.time()) result agent.invoke({messages: [{role: user, content: user_message}]}) assistant_content if isinstance(result, dict) and messages in result: last_message result[messages][-1] assistant_content last_message.content if hasattr(last_message, content) else last_message.get(content, ) else: assistant_content result.content if request.stream: def generate_stream() - Generator[str, None, None]: for char in assistant_content: chunk { id: response_id, object: chat.completion.chunk, created: created_time, model: request.model, choices: [{index: 0, delta: {content: char}, finish_reason: None}] } yield fdata: {json.dumps(chunk, ensure_asciiFalse)}\n\n time.sleep(0.03) yield fdata: {json.dumps({id: response_id, object: chat.completion.chunk, created: created_time, model: request.model, choices: [{index: 0, delta: {}, finish_reason: stop}]}, ensure_asciiFalse)}\n\n yield data: [DONE]\n\n return StreamingResponse(generate_stream(), media_typetext/event-stream) return { id: response_id, object: chat.completion, created: created_time, model: request.model, choices: [{index: 0, message: {role: assistant, content: assistant_content}, finish_reason: stop}] } except Exception as e: raise HTTPException(status_code500, detailstr(e)) if __name__ __main__: uvicorn.run(app, host0.0.0.0, port8001)启动命令uv run main.py或者直接用 uvicornuvicorn main:app --host 0.0.0.0 --port 8001 --reload3.3 TaoToken settings.json 配置片段如果你在 Trae Solo 或其他支持 settings.json 的工具里配置模型通道可以这样写{ models: { provider: openai-compatible, base_url: https://taotoken.net/api, api_key: 你的TaoToken API Key, model: deepseek-chat } }这个配置和 FastAPI 里的init_chat_model用的是同一个 Key 和 base_url保持统一后面换模型或轮换 Key 只需要改一处。4. 验证请求从 curl 到 Chatbox 对话连通服务起来之后先别急着开 Chatbox用 curl 确认接口本身是通的。4.1 curl 验证非流式接口curl -X POST http://localhost:8001/chat/completions \ -H Content-Type: application/json \ -d { model: deepseek-chat, messages: [{role: user, content: 北京天气怎么样}], stream: false }如果返回的 JSON 里choices[0].message.content包含天气信息说明智能体调用链是通的。4.2 curl 验证流式接口curl -X POST http://localhost:8001/chat/completions \ -H Content-Type: application/json \ -d { model: deepseek-chat, messages: [{role: user, content: 上海天气怎么样}], stream: true }你会看到逐字返回的data:行最后以data: [DONE]结束。流式通了Chatbox 的体验才会顺滑。4.3 Chatbox 自定义接口配置打开 Chatbox点击设置 → 模型 → 添加自定义模型提供方。关键参数配置项填写值API 主机http://localhost:8001API 路径/chat/completionsAPI Key随便填一个非空值即可模型名称deepseek-chat保存后新建对话输入“北京天气”如果能看到智能体以播报员语气返回天气信息说明整条链路打通了。提示Chatbox 的 API Key 字段这里只是占位因为你的 FastAPI 服务没有做鉴权。如果服务暴露在公网务必加上 Key 校验。5. 本篇常见错排查接入过程中最容易卡在几个地方这里按现象给出排查路径。现象一curl 返回 500detail 里提示模型调用失败。先检查langchain_weather.py里的base_url和api_key是否正确。TaoToken 的 base_url 是https://taotoken.net/api不要写成带/v1的路径。Key 如果复制时带了空格也会导致 401。现象二Chatbox 里发消息没反应但 curl 是通的。大概率是 API 路径填错了。Chatbox 的 API 主机填http://localhost:8001路径填/chat/completions不要重复拼成http://localhost:8001/chat/completions/chat/completions。现象三流式输出在 Chatbox 里显示为一大段没有逐字效果。检查 FastAPI 返回的media_type是否为text/event-stream以及每个 chunk 是否以\n\n结尾。Chatbox 对 SSE 格式比较敏感少一个换行都可能退化成非流式。现象四端口 8001 被占用服务起不来。用lsof -i:8001或netstat -ano | findstr 8001找到占用进程换端口或者杀掉进程。Trae Solo 在自动化流程里会自动处理端口冲突但手动启动时需要自己确认。现象五智能体返回的内容是空字符串。这通常是agent.invoke的返回结构和你解析的字段不匹配。不同 LangChain 版本返回的 messages 结构有差异建议先print(result)看实际结构再调整解析逻辑。6. 长期编码与 Agent 场景的通道选择把智能体接入 Chatbox 只是第一步。如果你后续要长期做 LangChain 智能体开发、频繁调试 Agent 工具链、或者跑 Coding Agent 类的任务建议把模型通道固定下来避免每次换项目都重新配 Key。TaoToken 的 Coding Plan 就是为这类长期编码场景准备的模型对话入口在 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。如果你用的是 Claude Code 这类工具对应的配置参考 https://taotoken.net/claude-code-anthropic?utm_sourcetaotoken_aicg_blog_endutm_contentclaudecodeutm_campaignrewrite 。我自己的做法是智能体项目里所有模型调用都走同一个 base_url 和 KeyFastAPI 服务、Chatbox、Trae Solo 的 settings.json 三处保持一致。这样换模型只改一个 model 字段轮换 Key 也只改一处不会出现“这个服务能跑那个服务 401”的混乱。实测下来这套组合在本地开发和轻量部署场景里足够稳剩下的精力可以放在智能体逻辑本身而不是环境配置上。
