
1. 从零到一AI Agent 开发与上线的全局拆解这两年“AI Agent”这个词被炒得火热但真正动手做过一个能上线、能扛住真实流量、还能持续迭代的 Agent 项目的人其实并不多。我前后参与过三个不同规模的 Agent 项目从最初用 Coze 这类低代码平台快速搭原型到后来用 FastAPI LangChain LangGraph 自己撸一套完整后端踩过的坑可以说能写一本小册子。这篇文章不打算跟你聊“Agent 是什么”这种概念性的东西而是把我从开发到上线整个链路上真正遇到的问题、做过的取舍、以及那些文档里不会写的经验一次性摊开来讲。先明确一下这篇文章适合谁看。如果你是完全没接触过 Agent 开发的小白我会在关键节点补充基础概念保证你能跟上如果你已经写过一些 Demo但卡在“怎么让它稳定跑起来”“怎么部署到线上”“并发一上来就崩”这些环节那这篇内容应该能帮你省下不少试错时间。核心关键词就三个AI Agent、开发、上线。我会围绕这三个词把架构选型、核心模块实现、并发处理、部署方案、以及上线后的监控与迭代全部串一遍。需要提前说明的是Agent 开发这个领域变化极快今天的最佳实践可能三个月后就被推翻。所以我不会给你一套“标准答案”而是把决策逻辑和判断依据讲清楚让你能根据自己项目的实际情况做选择。这比直接抄一套配置要有价值得多。2. 架构选型别一上来就追求“全自研”2.1 低代码平台 vs 自研框架到底怎么选我见过太多团队在项目启动阶段就陷入“技术选型焦虑”花两周时间对比各种框架结果一行业务代码没写。我的建议很直接先用最低成本验证核心逻辑再决定要不要自研。如果你要做的是一个内部工具、或者验证一个想法Coze、Dify 这类平台完全够用。它们的优势在于可视化编排、内置工具调用、自带知识库管理基本上拖拖拽拽就能跑通一个 Agent 的完整链路。我最早做的一个客服问答 Agent用 Coze 从零到能用只花了半天时间。但问题也很明显定制化能力有限、性能天花板低、数据不在自己手里、复杂业务逻辑很难表达。当你遇到以下情况时就该考虑自研了需要接入内部私有系统且平台不支持自定义工具、需要处理高并发场景、需要对 Prompt 和上下文做精细控制、需要把 Agent 能力嵌入到已有产品中。这时候FastAPI LangChain/LangGraph是目前比较主流的一套组合。FastAPI 负责 API 层和并发处理LangChain 提供 LLM 调用和工具链的抽象LangGraph 则用来编排多步骤、有状态的工作流。选 LangGraph 而不是自己写状态机的原因很简单Agent 的核心难点不在于调用 LLM而在于多轮对话中的状态管理、工具调用的错误恢复、以及条件分支的流转。LangGraph 把这些东西抽象成了图结构节点是操作边是流转条件状态在节点间传递。自己实现一套不是不行但容易在边界情况上翻车。2.2 主流 Agent 架构模式与适用场景目前市面上常见的 Agent 架构大概有这么几种我整理了一个对比表方便你根据场景选择架构模式核心思路适用场景复杂度ReAct推理行动交替边想边做工具调用类任务如搜索、计算低Plan-and-Execute先规划完整步骤再逐步执行多步骤复杂任务如报告生成中Multi-Agent多个 Agent 分工协作需要不同角色配合的场景高Reflexion执行后自我反思并修正对结果质量要求高的任务中我个人的经验是80% 的场景用 ReAct 就够了。很多人一上来就想搞 Multi-Agent觉得多个 Agent 协作听起来更高级但实际上调试难度呈指数级上升而且效果未必比单 Agent 好。除非你的任务确实需要不同领域的专业知识分工否则别碰 Multi-Agent。2.3 技术栈选型的几个关键决策点除了框架还有几个选型决策会影响后续开发和上线LLM 供应商的选择。不要绑定单一供应商至少在代码层面做好抽象。我吃过这个亏——早期项目直接调某家的 SDK后来因为成本和稳定性问题想换发现代码里到处都是耦合。后来统一用 OpenAI 兼容的接口格式切换成本就低多了。向量数据库的选择。如果 Agent 需要 RAG检索增强生成向量库是绕不开的。小规模用 Chroma 或 FAISS 本地跑就行上了规模再考虑 Milvus 或 Qdrant。别一上来就上分布式向量库运维成本很高。状态存储的选择。Agent 的对话状态、工具调用记录需要持久化。Redis 做短期缓存PostgreSQL 做长期存储这个组合基本能覆盖大部分场景。3. 核心模块开发把每个环节做扎实3.1 Prompt 工程Agent 的大脑Prompt 是 Agent 的灵魂但很多人对它的重视程度远远不够。我见过把 Prompt 随便写几句就上线的结果 Agent 行为完全不可控。一个好的 Agent Prompt 通常包含这几个部分角色定义明确 Agent 的身份和能力边界任务描述清晰说明要完成什么工具说明每个工具的功能、参数、使用时机输出格式规定返回结果的结构约束条件什么能做、什么不能做示例Few-shot 示例帮助模型理解预期行为这里有个实操技巧把 Prompt 当成代码来管理。用版本控制工具管理 Prompt 的每次修改记录每次修改的原因和效果。我在项目里专门建了一个 prompts 目录每个 Prompt 一个文件配合 Git 做版本管理。这样当效果回退时能快速定位是哪次修改导致的。另一个坑是 Prompt 过长导致的性能问题。当工具数量多、示例多的时候Prompt 可能膨胀到几千甚至上万 token不仅增加成本还会稀释关键信息的权重。解决办法是动态组装 Prompt——根据当前对话上下文只注入相关的工具说明和示例而不是把所有东西都塞进去。3.2 工具调用Agent 的手脚工具调用是 Agent 区别于普通 Chatbot 的核心能力。实现工具调用时有几个关键点需要注意工具描述的准确性。LLM 是根据工具的名称和描述来决定是否调用的。如果描述模糊模型就会误用或漏用。我一般会写清楚这个工具做什么、什么时候用、参数是什么格式、返回什么。比如一个查询订单的工具描述里要明确“当用户询问订单状态、物流信息时使用此工具”。参数校验与错误处理。LLM 生成的参数不一定合法必须在执行前做校验。我通常用 Pydantic 定义参数模型自动做类型检查和格式验证。校验失败时把错误信息返回给 LLM让它重新生成参数而不是直接报错给用户。超时与重试。外部工具调用可能超时或失败必须设置合理的超时时间和重试策略。我的经验是单个工具调用超时设 10 秒最多重试 2 次重试间隔用指数退避。超过重试次数后把失败信息返回给 Agent让它决定是换工具还是告知用户。幂等性设计。有些工具调用是有副作用的比如创建订单、发送消息。这类工具必须做幂等处理防止 LLM 重复调用导致重复操作。通常的做法是让 LLM 生成一个唯一请求 ID服务端根据这个 ID 去重。3.3 记忆管理让 Agent 记住上下文Agent 的记忆分为短期记忆和长期记忆。短期记忆就是当前对话的历史长期记忆则是跨对话的知识积累。短期记忆的管理核心是上下文窗口的合理利用。LLM 的上下文窗口有限不可能把所有历史都塞进去。常见的策略有滑动窗口只保留最近 N 轮、摘要压缩把早期对话总结成一段话、关键信息提取只保留实体和意图。我一般用组合策略最近 5 轮保留原文更早的做摘要同时把对话中出现的关键实体单独存一份。长期记忆的实现通常依赖向量数据库。把重要的对话内容、用户偏好、历史决策向量化存储需要时通过相似度检索召回。这里有个容易忽略的点不是所有信息都值得存。我见过把每轮对话都存进向量库的结果检索出来的全是噪音。应该只存那些有长期价值的信息比如用户的明确偏好、重要的业务决策、反复出现的问题。3.4 多轮对话与状态机设计复杂的 Agent 往往需要多轮交互才能完成任务这就涉及到状态管理。LangGraph 的 StateGraph 是比较好用的工具它把整个流程定义成一张图每个节点是一个操作边定义了流转条件。设计状态机时我遵循几个原则状态尽量扁平避免嵌套过深导致难以追踪每个状态转换要有明确的触发条件不能模糊异常状态要有兜底处理不能让 Agent 卡死。比如用户中途改变意图、工具连续失败、超时等情况都要有对应的处理分支。4. 并发与性能上线前的必修课4.1 AI Agent 的并发瓶颈到底在哪很多人以为 Agent 的并发瓶颈在 LLM 调用其实不完全是。我实测下来瓶颈通常出现在这几个地方LLM API 的速率限制。这是最直接的瓶颈。大部分 LLM 供应商都有 RPM每分钟请求数和 TPM每分钟 token 数限制。当并发请求超过限制时要么被限流要么排队等待。解决办法一是申请更高的配额二是做请求队列和限流控制。工具调用的响应时间。如果 Agent 依赖外部 API 或数据库查询这些调用的延迟会直接叠加到整体响应时间上。一个涉及 3 次工具调用的 Agent如果每次调用 2 秒光工具调用就 6 秒了。上下文长度带来的计算开销。上下文越长LLM 的推理时间越长成本也越高。长上下文场景下单次请求可能就要十几秒。状态存储的读写延迟。每次对话都要读写状态如果存储层性能不够也会成为瓶颈。4.2 异步处理与请求队列的实操方案FastAPI 天生支持异步这是它的优势。但要注意异步不等于并发。如果代码里有同步阻塞的操作整个事件循环都会被卡住。我踩过的坑是在异步函数里直接调用了同步的数据库驱动结果并发一上来全部超时。后来全部换成了异步驱动asyncpg、aioredis问题才解决。请求队列方面我一般用 Redis 做简单的队列配合 Celery 或 ARQ 做任务分发。对于 Agent 这种长耗时任务同步等待返回结果体验很差更好的做法是提交任务后立即返回一个 task_id客户端轮询或通过 WebSocket 获取结果。这样既能控制并发又能提升用户体验。限流策略上我用的是令牌桶算法。根据 LLM 供应商的配额设置合适的令牌生成速率请求前先获取令牌获取不到就排队或拒绝。这样能保证不会因为突发流量触发供应商的限流。4.3 缓存策略哪些能缓存哪些不能缓存是提升性能的利器但 Agent 场景下的缓存要特别小心。LLM 的调用结果不能简单缓存因为同样的输入在不同上下文下可能有不同的输出。但以下几类内容是可以缓存的工具调用结果对于查询类工具如果参数相同且数据时效性要求不高可以缓存几分钟向量检索结果相同的查询向量检索结果可以缓存Prompt 模板组装好的 Prompt 可以缓存避免重复拼接用户会话状态用 Redis 缓存减少数据库读写缓存的失效策略也很关键。我一般用 TTL 主动失效的组合设置一个合理的过期时间同时在数据更新时主动清除相关缓存。4.4 压测与容量规划上线前必须做压测这是铁律。我一般用 Locust 或 k6 做压测重点关注这几个指标P50/P95/P99 响应时间、吞吐量、错误率、资源利用率。容量规划的思路是先确定单实例能承载的 QPS然后根据预期流量计算需要的实例数再留 30% 的余量应对突发。但 Agent 场景有个特殊之处不同请求的耗时差异很大。简单的问答可能 1 秒返回复杂的多步任务可能要 30 秒。所以不能简单按 QPS 来算要按“并发处理中的请求数”来算。我的经验值是单个 FastAPI 实例2 核 4G如果 Agent 平均响应时间 5 秒大概能支撑 20-30 个并发请求。超过这个数响应时间会明显上升。当然这跟具体实现关系很大一定要自己压测。5. 部署上线从开发环境到生产环境5.1 环境配置与依赖管理开发环境和生产环境的配置差异是很多问题的根源。我坚持的原则是环境配置全部通过环境变量注入代码里不硬编码任何环境相关的值。用 pydantic-settings 管理配置不同环境用不同的 .env 文件。依赖管理用 Poetry 或 uv锁定版本号。我见过因为依赖版本不一致导致线上行为跟开发环境不同的案例排查了大半天。requirements.txt 或 lock 文件必须提交到版本控制部署时严格按照 lock 文件安装。Docker 化是标配。Dockerfile 要遵循多阶段构建减小镜像体积。基础镜像选择上python:3.11-slim 是个不错的起点。注意把依赖安装和代码复制分开利用 Docker 的层缓存加速构建。5.2 容器化与编排方案单机部署用 Docker Compose 就够了把 API 服务、Redis、PostgreSQL、向量库都编排在一起。上了规模再考虑 Kubernetes。K8s 部署时有几个 Agent 场景特有的注意点健康检查要区分 liveness 和 readiness。liveness 检查进程是否存活readiness 检查是否准备好接收流量。Agent 服务启动时可能需要加载模型或建立连接这段时间 readiness 应该返回未就绪。资源限制要合理。Agent 服务通常是 IO 密集型而非 CPU 密集型CPU 限制可以低一些但内存要给够因为上下文和缓存都占内存。优雅关闭。收到终止信号后要等待正在处理的请求完成再退出避免请求中断。FastAPI 配合 uvicorn 的 graceful shutdown 可以做到这点。5.3 域名、SSL 与反向代理配置生产环境必须用 HTTPS这是底线。Nginx 做反向代理是标配配置时注意这几点upstream agent_backend { server 127.0.0.1:8000; keepalive 32; } server { listen 443 ssl http2; server_name agent.example.com; ssl_certificate /path/to/cert.pem; ssl_certificate_key /path/to/key.pem; location / { proxy_pass http://agent_backend; proxy_http_version 1.1; proxy_set_header Connection ; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; # Agent 响应可能较慢超时时间要设长 proxy_read_timeout 120s; proxy_send_timeout 120s; } }注意Agent 的响应时间通常比普通 API 长Nginx 的 proxy_read_timeout 默认 60 秒很容易超时。根据你的 Agent 最长响应时间设置建议至少 120 秒。如果是流式输出SSE还需要额外配置关闭 proxy_buffering设置 chunked_transfer_encoding。5.4 灰度发布与回滚机制Agent 的上线不能一刀切因为 Prompt 或模型的微小改动都可能导致行为变化。我一般用灰度发布先放 5% 的流量到新版本观察关键指标响应时间、错误率、用户反馈没问题再逐步扩大比例。回滚机制必须提前准备好。除了代码回滚还要考虑Prompt 回滚、模型版本回滚、配置回滚。我习惯把每次上线的 Prompt、配置、代码版本打成一个 release 包回滚时整体切换。6. 上线后的监控、迭代与避坑6.1 关键监控指标与告警设置上线只是开始监控才是保证稳定运行的关键。我重点监控这几类指标业务指标请求量、成功率、平均响应时间、Token 消耗量、工具调用成功率。这些指标反映 Agent 的整体健康度。技术指标CPU、内存、网络 IO、数据库连接数、Redis 命中率。这些反映基础设施的状态。质量指标用户满意度点赞/点踩、对话轮次、任务完成率、异常终止率。这些反映 Agent 的实际效果。告警设置上我遵循“少而精”的原则。告警太多会导致麻木真正的问题反而被忽略。我一般只对这几项设告警错误率超过 5%、P95 响应时间超过阈值、Token 消耗异常增长、工具调用连续失败。6.2 日志、追踪与问题定位Agent 的问题定位比普通服务难因为涉及 LLM 这个黑盒。我的做法是全链路追踪每次请求生成一个 trace_id把 Prompt、LLM 响应、工具调用、状态变化全部记录下来关联到同一个 trace_id 下。日志要结构化用 JSON 格式方便检索和分析。关键字段包括trace_id、用户 ID、对话轮次、当前节点、输入输出、耗时、Token 数。有个实用技巧把每次 LLM 调用的完整 Prompt 和响应存下来。当用户反馈问题时能直接看到当时 LLM 看到了什么、返回了什么定位效率高很多。当然要注意脱敏和存储成本。6.3 常见问题速查与避坑清单下面这张表是我在实际项目中遇到的高频问题及解决方案直接可以当速查表用问题现象可能原因排查方向解决方案Agent 不调用工具工具描述不清、Prompt 未强调检查工具描述和 Prompt优化描述增加调用示例工具调用参数错误参数定义不清晰查看 LLM 生成的参数用 Pydantic 严格校验返回错误让 LLM 重试响应时间过长上下文过长、工具调用慢分析各环节耗时压缩上下文、工具调用加缓存并发上不去同步阻塞、连接池不足检查代码是否有阻塞操作改异步、扩大连接池对话状态丢失状态存储失败检查 Redis/DB 连接加持久化、做状态恢复输出格式不稳定Prompt 约束不够检查输出解析逻辑用结构化输出、加格式校验Token 消耗过高Prompt 冗余、上下文未压缩统计各环节 Token 消耗精简 Prompt、做上下文摘要重复调用工具缺少幂等设计检查工具调用记录加请求 ID 去重6.4 持续迭代Prompt 优化与效果评估Agent 上线后迭代的重点通常从“能不能用”转向“好不好用”。Prompt 优化是主要手段但不能凭感觉改。我一般用 A/B 测试把流量分成两组一组用旧 Prompt一组用新 Prompt对比关键指标。评估指标的设计很关键。对于问答类 Agent可以用准确率、召回率对于任务类 Agent用任务完成率、平均轮次对于对话类 Agent用用户满意度、对话时长。有条件的话建一个标注数据集定期做离线评估这样迭代有据可依。还有个容易被忽略的点收集 bad case 并分类。把用户反馈的问题、异常终止的对话、效果差的案例收集起来归类分析。往往改一个 Prompt 能解决一类问题比盲目优化效率高得多。6.5 成本控制Token 消耗的优化技巧Token 成本是 Agent 项目的主要运营成本之一尤其是上了规模之后。我总结了几条实用的优化技巧Prompt 精简。去掉冗余的描述和示例用更简洁的表达。我做过一次 Prompt 优化把系统 Prompt 从 2000 token 压到 800 token效果基本不变成本降了 60%。上下文压缩。早期对话做摘要只保留关键信息。摘要本身也消耗 Token但比保留原文便宜得多。模型分级。简单任务用小模型复杂任务用大模型。比如意图识别用便宜的小模型复杂推理用大模型。这样能在保证效果的前提下降低成本。缓存复用。前面提到的缓存策略对成本控制也有帮助。相同的查询直接返回缓存结果省去 LLM 调用。流式输出。虽然不直接降低成本但能提升用户体验让用户感觉响应更快间接减少重复请求。7. 一些掏心窝子的经验做 Agent 项目这两年多最大的感受是技术只是其中一部分更多时候是在跟不确定性打交道。LLM 的行为不像传统代码那样确定同样的输入可能得到不同的输出。这就要求我们在设计时留足容错空间在监控上做足功夫在迭代时保持耐心。另一个体会是不要追求一步到位。我见过太多项目想一开始就做一个“全能 Agent”结果复杂度失控最后不了了之。更好的路径是先做一个能解决单一问题的简单 Agent跑通上线流程积累经验再逐步扩展能力。还有一点用户反馈比任何指标都重要。数据能告诉你哪里出了问题但只有用户能告诉你他们真正想要什么。我习惯定期看用户的原始反馈很多优化方向都是从里面来的。最后分享一个实用的小习惯维护一个“坑本”。每次遇到问题、解决问题后把现象、原因、解决方案记下来。时间长了这就是你最宝贵的知识库。我现在的坑本已经记了上百条新项目启动时翻一翻能避开大部分常见的坑。