先放结论:部署不是"把代码扔上服务器",而是从"脚本思维"切换到"服务思维"。 脚本跑一次就完事,服务要面对并发、超时、状态持久化、故障恢复。搞懂这三层,你的 Agent 才算真正能用。
第一层:从脚本到 API 服务
你在本地跑 Agent 的方式通常是:
ini
const result = await agent.invoke({ messages: [...] });
console.log(result);
这没问题,但别人怎么用?总不能让你同事 clone 你的代码、装依赖、配环境变量、再跑一遍。正确的做法是:把 Agent 包装成一个 HTTP 服务,别人通过 API 调用。
方案一:LangServe(LangChain 官方推荐)
LangServe 是 LangChain 官方的"一键部署神器",核心就一个函数 add_routes,把你的 Chain 或 Agent 自动变成 REST API。
python
# server.py
from fastapi import FastAPI
from langserve import add_routes
from my_agent import my_agent # 你写好的 Agent
app = FastAPI(title="My Agent API", version="1.0.0")
# 一行代码注册 API
add_routes(app, my_agent, path="/agent")
启动:
lua
pip install langserve fastapi uvicorn
uvicorn server:app --host 0.0.0.0 --port 8000
访问 http://localhost:8000/docs 就能看到自动生成的 Swagger 文档,直接在浏览器里测试接口。
优点 :零代码适配,自动文档,支持流式输出、批量请求。 缺点:只适合 LangChain 生态,Python 专属。
方案二:FastAPI 手写(更灵活)
如果你需要自定义请求校验、权限控制、响应格式,手写 FastAPI 更灵活:
python
# app/main.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, Field
app = FastAPI(title="Agentic Helpdesk API", version="0.1.0")
class QueryRequest(BaseModel):
input: str = Field(description="用户输入", min_length=1, max_length=2000)
class QueryResponse(BaseModel):
answer: str
tool_calls: list[str] = Field(default_factory=list)
@app.post("/agent", response_model=QueryResponse)
async def run_agent(req: QueryRequest) -> QueryResponse:
try:
result = await agent_executor.ainvoke({"input": req.input})
used_tools = [
s["tool"] for s in result.get("intermediate_steps", [])
if isinstance(s, tuple) and s and hasattr(s[0], "tool")
]
return QueryResponse(answer=result["output"], tool_calls=used_tools)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.get("/health")
def health() -> dict:
return {"status": "ok"}
关键点:
async def+ainvoke:异步非阻塞,吞吐量远优于同步阻塞- Pydantic 模型:约束请求和响应,类型安全
/health端点:健康检查,给负载均衡器用
方案三:LangGraph 独立服务器(适合有状态 Agent)
如果你的 Agent 基于 LangGraph(有状态、有循环),LangGraph 提供了专门的部署方式:
bash
# 本地开发
langgraph dev # 启动开发服务器,默认监听 http://127.0.0.1:2024
生产环境打包成 Docker 镜像:
perl
langgraph build -t my-agent:latest
然后部署到 Kubernetes 或 Docker Swarm。
优点 :原生支持状态持久化、断点续跑、Studio 可视化调试。 缺点:需要 PostgreSQL/Redis 作为后端存储,运维成本略高。
第二层:容器化部署
脚本跑在本地没问题,但上生产环境必须容器化。为什么?
- 环境隔离:避免"在我机器上能跑"的问题
- 资源限制:CPU、内存可控,不会把服务器跑崩
- 快速扩缩容:一个命令启动 10 个实例
最小 Dockerfile
bash
FROM python:3.11-slim
WORKDIR /app
# 安装依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 复制代码
COPY . .
# 启动服务
CMD ["uvicorn", "server:app", "--host", "0.0.0.0", "--port", "8000"]
docker-compose 编排(含数据库)
如果你的 Agent 需要持久化状态(LangGraph Checkpointer),需要配套数据库:
yaml
# docker-compose.yml
version: '3.8'
services:
agent-api:
build: .
ports:
- "8000:8000"
environment:
- DATABASE_URI=postgresql://user:pass@postgres:5432/agentdb
- REDIS_URI=redis://redis:6379
depends_on:
- postgres
- redis
postgres:
image: postgres:16
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: agentdb
volumes:
- pgdata:/var/lib/postgresql/data
redis:
image: redis:7-alpine
volumes:
- redisdata:/data
volumes:
pgdata:
redisdata:
启动:
docker compose up -d
关键点:
- 生产环境禁止用
MemorySaver:容器重启后状态全丢,必须用PostgresSaver或RedisSaver - 环境变量管理 :API Key、数据库密码放
.env文件,通过env_file注入容器,禁止硬编码 - 数据卷挂载:PostgreSQL 和 Redis 的数据要持久化,否则容器重启数据丢失
第三层:生产环境架构选型
到了生产环境,问题就不只是"跑起来"了。你需要考虑:并发、高可用、监控、成本。
架构选型决策树
| 场景 | 推荐架构 | 理由 |
|---|---|---|
| 简单任务(步骤≤3、规则明确) | LangChain + LangServe | 开发快、成本低、稳定性高 |
| 中等复杂(步骤 3-5、流程固定) | LangChain + FastAPI | 平衡灵活性与开发效率 |
| 高复杂(步骤>5、需循环/分支) | LangGraph + 独立服务器 | 支持流程回溯、状态持久化 |
| 高并发(QPS>1000) | LangGraph + Kubernetes + 负载均衡 | 水平扩展、弹性伸缩 |
| 多 Agent 协作 | LangGraph + Bedrock AgentCore / AWS Lambda | 无服务器运行时,自动扩缩容 |
| 非技术团队快速上线 | Dify / CrewAI | 低代码、开箱即用 |
生产环境必须做的五件事
1. 超时防护
LLM 调用可能卡住,工具调用可能超时。不配超时,一个请求就能拖垮整个服务。
三层超时:
- 模型层超时 :
ChatOpenAI(timeout=30) - 工具层超时:每个工具设置独立超时
- 节点层超时:LangGraph 节点设置超时,超时后走降级路由
2. 重试与熔断
网络抖动是常态。无脑重试会加重下游压力,甚至引发雪崩。
精准重试策略:
- 瞬时故障(超时、限流、网络抖动):指数退避 + jitter 重试
- 永久故障(参数错误、权限不足、接口不存在):直接拦截,不重试
熔断:连续失败 N 次后触发熔断,暂停请求下游,等待恢复后再半开探测。
3. 降级策略
当模型挂了、工具不可用时,不能直接返回 500。要有降级方案:
- 模型切换:GPT-4 挂了切 GPT-3.5,再挂了切本地 Ollama
- 逻辑裁剪:跳过非核心步骤,只保留主流程
- 结果兜底:返回预设的友好提示,而不是堆栈信息
4. 可观测性
生产环境出问题,你不能靠"猜"。需要完整的监控体系:
- 链路追踪:LangSmith Trace 或 OpenTelemetry,可视化整个工作流的调用链和耗时
- 指标监控:Prometheus + Grafana,监控请求量、延迟、错误率、Token 消耗
- 集中化日志:ELK 或 Loki,汇总所有实例的日志,便于检索和分析
5. 水平扩展
单实例扛不住高并发。需要:
- 无状态计算层:LangGraph 执行器部署为无状态微服务,任何实例都能处理任何请求
- 共享状态存储:PostgreSQL 或 Redis 持久化状态,实例故障后其他实例能接管
- 负载均衡:Nginx 或 Kubernetes Service 分发请求
- 弹性伸缩:Kubernetes HPA 根据 CPU/内存使用率自动增减实例
参考架构图
css
用户请求
↓
[API 网关 / 负载均衡器] ← 限流、鉴权、SSL 终端
↓
[Agent 服务集群] ← 无状态,可水平扩展
├── 实例 1
├── 实例 2
└── 实例 N
↓
[状态存储] ← PostgreSQL(Checkpointer)+ Redis(缓存)
↓
[外部依赖]
├── LLM API(OpenAI / 本地 Ollama)
├── 向量数据库(RAG)
└── 第三方工具(天气、邮件、数据库...)
部署的三个阶段
| 阶段 | 目标 | 推荐方案 |
|---|---|---|
| 开发期 | 快速验证,本地调试 | langgraph dev 或 uvicorn 本地启动 |
| 测试期 | 模拟生产环境,压测 | Docker Compose 本地编排,含数据库 |
| 生产期 | 高可用、可扩展、可监控 | Kubernetes + PostgreSQL + Redis + LangSmith + Prometheus |
不要一开始就上 Kubernetes。先从 LangServe 或 FastAPI 跑起来,验证价值后再逐步升级架构。
一个实用建议:从"最小可部署单元"开始
不要一上来就搞复杂的微服务架构。先做一件事:把你的 Agent 包装成一个 FastAPI 服务,用 Docker 跑起来,能被人通过 HTTP 调用。
做到这一步,你就已经超过了 80% 的 Agent 开发者。剩下的并发、监控、扩缩容,等真正需要的时候再加。
小结
- 部署的本质:从"脚本思维"切换到"服务思维"
- 三种 API 方案:LangServe(零代码)、FastAPI 手写(灵活)、LangGraph 独立服务器(有状态)
- 容器化必做:Docker 隔离环境,docker-compose 编排数据库
- 生产五件事:超时防护、重试熔断、降级策略、可观测性、水平扩展
- 架构选型原则:简单场景用 LangServe,复杂场景用 LangGraph,高并发上 Kubernetes
- 从最小可部署单元开始:先跑起来,再优化
到这里实战系列的七篇内容全部完结。我们从最基础的 Agent 工具调用出发,一路走到 LangGraph 框架、记忆持久化、RAG 外挂知识库、科学评估、生产部署------覆盖了构建一个生产级 Agent 的完整链路。
但故事还没结束。Agent 技术还在快速演进,Multi-Agent 协作、自主规划、长程记忆、具身智能......这些方向值得持续关注。保持学习,保持动手,我们下一个系列见。