1. 别急着写Agent:先想明白它要过几道关
现在的AI大模型圈子,最不缺的就是Agent项目。每家都有Demo,你问它"帮我写个登录接口",它唰唰输出一串代码,看起来无所不能。可一旦你真把它放进研发交付流程——让它去改Issue、提PR、跑测试、审代码——大多数项目当场翻车:要么工具调不通,要么模型在循环里出不来,要么回答得一本正经但全是幻觉,要么改一个Prompt导致另一个场景全线崩坏。
我见过太多团队把"调通一个API"当成"做完了Agent",结果上线两周就灰溜溜撤回去。这中间的差距,恰恰就是大厂级Agent项目和玩具Demo的分水岭。一个能进入真实研发交付流程的Agent,不是"模型+提示词"这么简单,它背后至少需要四样东西:
- 运行底座:模型跑在哪、工具怎么接、权限怎么控,也就是标题里说的"底座"。
- Harness控制:Agent不只有大脑,还要有骨架。Harness负责把模型推理和工具调用编排成一个可控的循环。
- Loop与度量:Agent跑起来之后,你得知道它每次循环在干什么、干得好不好、花了多少钱。
- 知识工程:模型不知道你公司的私有代码和文档,RAG知识库是让它"先查资料再开口"的关键。
这篇文章我会按这四个模块逐个拆,最后把它们串进一条真实的研发交付流水线里。无论你是想在公司做智能编码助手,还是准备把Agent接入研发管理平台,这套拆法都适用。先说第一个问题:为什么有些Agent跑不起来。
2. 运行底座:MCP如何让Agent真正摸到研发工具
2.1 MCP到底解决了什么问题
很多人第一次听到MCP(Model Context Protocol,模型上下文协议),第一反应是"又一个新协议"。但你把目光拉回实际开发场景就明白了:Agent要干活,必然要调用外部工具——拉取Git仓库代码、查Jira工单、读日志、跑测试、搜知识库。在没有统一标准之前,每对接一个系统,你都得为Agent写一套专用的工具适配代码。今天接GitLab写一个,明天接飞书写一个,后天接内部运维平台再写一个,全部是重复劳动。
MCP的作用,就是把这些工具接入统一成一套标准协议。打个比方:以前是每个设备配一个专用充电头,现在变成了USB-C,谁支持这个口就能插上去用。MCP Server暴露工具、资源和提示词,MCP Host负责管理和调度,MCP Client建立连接并转发请求。对做Agent的人来说,这意味着你不需要关心对面系统的私有API细节,只要对方提供一个MCP Server,你的Agent就能直接调用它的能力。
大厂为什么热衷这套?因为研发交付流程里的系统太多了,代码仓库、CI流水线、缺陷管理、文档平台、监控系统,如果每个Agent项目各接一遍,工程成本会高到无法接受。标准化之后,一套工具可以被多个Agent复用,也能让不同团队沉淀的能力互相流通。
2.2 一个最小MCP Server长什么样
MCP Server没有想象中那么复杂,它的最小实现就是一个暴露若干工具的服务。以Python为例,用FastMCP库几十行就能写出来:
from mcp.server.fastmcp import FastMCP mcp = FastMCP("dev-tools") @mcp.tool() def search_issue(keyword: str, project: str) -> list[dict]: """在指定项目的缺陷管理系统中搜索Issue""" # 这里调用你的内部系统API issues = call_issue_api(project, keyword) return [ {"id": item["id"], "title": item["title"], "status": item["status"]} for item in issues ] if __name__ == "__main__": mcp.run()从这个例子你可以看到,模型对工具一无所知,它只知道"我有个search_issue工具,传入关键字和项目名,能拿到Issue列表"。而MCP做的事情就是把这个能力以标准方式暴露给模型,包括工具名字、参数结构、返回结果。模型在推理时看到这个工具描述,就会决定要不要调用它。
实际生产环境中,工具描述本身需要下功夫。模型是靠工具名和描述来判断"什么时候用、怎么用"的。描述写得太笼统,模型就会在无关场景误调用;参数定义得不清晰,模型就会传错值。这块需要你像写API文档一样认真打磨。
2.3 底座层的三个坑
MCP只是底座的一部分。把底座真正铺稳,我实际踩过几个坑,值得提前说:
第一个坑是工具调用的超时管理。模型发起工具调用后,如果MCP Server卡住不返回,Agent的循环会一直等在那里。默认超时时间一定要设,而且要区分工具类型:查询类工具可以给短超时,耗时的构建类工具可以给长超时。否则一个Agent实例可能因为一个慢工具而挂掉半天。
第二个坑是幂等性。Agent在循环中可能因为网络重试而重复调用同一个工具。如果一个工具是"创建PR"或"打标签"这类有副作用的操作,重复调用会造成灾难。设计工具时要注意幂等,比如创建PR前先检查是否已存在相同分支和标题的PR。
第三个坑是权限。这是最容易被忽略的。很多团队图省事给Agent一个管理员Token,这等于让一个可能失控的自动程序拿到全仓库权限。正确做法是给Agent单独申请最小权限凭证,只开它完成特定任务所需的范围。后面讲研发交付集成时,我还会详细说这一点。
3. Harness控制层:Agent有想法,但不能让它乱跑
3.1 Harness和Agent的分工
很多人分不清Harness和Agent的区别,觉得它们是同一个东西。我用一个老土的类比说明:Agent是大脑,负责做决策;Harness是骨架加神经,负责把决策变成可控的动作,同时确保大脑不会乱来。
具体到代码层面,Harness要做的事情包括:接收任务、组织上下文、调用模型推理、解析模型输出(判断它到底是想要调用工具还是输出最终答案)、执行工具调用、把结果反馈给模型、处理错误、管理循环终止条件。简单说,Agent负责"想",Harness负责"做"和管理"做"的过程。
为什么不能把这个循环直接写在业务代码里?因为真实的研发流程天然是一个状态机:有串行步骤,有并行分支,有条件跳转,还有需要人工审批的暂停点。如果你用裸的while循环去写,很快会发现代码里全是if-else和全局状态,改一个分支就会引入新问题。最典型的是"模型在多轮工具调用后需要回退一步重新规划",手写循环处理这种场景极其痛苦。
3.2 用LangGraph搭一个研发Agent的Harness
LangGraph是LangChain生态里专门做Agent编排的框架,它的核心概念是状态图和节点。每一个节点是一段逻辑(调用模型、执行工具、判断条件),节点之间用有向边连接,整个图驱动着状态流转。这个思路和研发流程的匹配度非常高。
举个实际的例子:做一个"从Issue到PR"的研发Agent,它的Harness至少需要这几个节点:
from typing import TypedDict from langgraph.graph import StateGraph class AgentState(TypedDict): issue_id: str repo: str plan: list[str] current_step: int code_diff: str test_results: str pr_url: str def planner(state: AgentState) -> dict: # 调用模型,把Issue拆解成实现计划 plan = llm.invoke(f"为Issue {state['issue_id']} 生成实现计划") return {"plan": plan} def executor(state: AgentState) -> dict: # 按计划执行代码修改 diff = implement_plan(state["repo"], state["plan"], state["current_step"]) return {"code_diff": diff} def verifier(state: AgentState) -> dict: # 运行测试,验证修改是否正确 results = run_tests(state["repo"], state["code_diff"]) return {"test_results": results} graph = StateGraph(AgentState) # 定义流转 graph.add_node("planner", planner) graph.add_node("executor", executor) graph.add_node("verifier", verifier) graph.add_edge("planner", "executor") graph.add_edge("executor", "verifier") # 如果测试没通过,回到executor重新修,最多循环3次 graph.add_conditional_edges( "verifier", decide_next_step, # 返回 "pass" 或 "fix" {"pass": "finish", "fix": "executor"} )这个例子展示了Harness的典型形态。你看见的关键点是:模型不在"自由奔跑",它每一步都被限定在图里,该规划就规划,该执行就执行,该验证就验证,出问题只能走预设的回退路径。
3.3 硬性边界设计
再聪明的模型也需要硬性控制。我强烈建议每个Harness都内置这几条规则,不要等出了问题再补:
第一,最大迭代次数。模型在复杂任务中容易陷入"修不好就继续修"的死循环。在Harness里设置一个最大步数上限(比如15步),超过就自动终止并输出当前进展,交给人工判断。这比让模型无限循环省钱得多。
第二,人工审批节点。凡是涉及写操作、合并代码、修改配置的动作,都应在Harness里设置人工确认节点。Harness执行到这一步时暂停,等人在界面或IM里点了"允许"再继续。本质上这就是Human-in-the-loop,它不会拖慢所有任务,但能在关键节点拦住错误。
第三,工具白名单。Harness层面限定每个Agent实例能调用的工具集合。研发Agent可以调代码搜索、可以跑测试,但没有权限调生产环境运维工具。这个白名单是底层能力边界,和模型是否"想"调用无关。
Harness设计的核心思路用一句话总结:让模型有足够的自由度去处理复杂情况,但所有自由度都必须在预设的轨道范围内。
4. Loop与度量:让Agent的每一次循环都可观测、可评估
4.1 看清Agent循环的四个阶段
Agent的运行本质是一个循环。拆开看,每个循环包含四个阶段:
- 观察(Observe):读取当前任务和运行环境的状态,比如拿到的Issue内容、当前的代码分支、上次工具调用的返回结果。
- 推理(Reason):模型根据上下文决定下一步行动,是继续调用工具,还是产生最终输出。
- 行动(Act):实际调用某个工具、执行代码修改、或者写一段文字。
- 反思(Reflect):查看行动结果,判断是否达成目标,决定继续、回退还是终止。
这个循环每走一遍,就是一次"Loop"。Harness的职责之一是记录每个Loop的信息。很多Agent项目出问题,不是模型不够聪明,而是团队根本不知道模型在循环里做了什么。等到线上出Bug,连基本的排查线索都没有。
4.2 建立度量体系
没有度量,就没有改进。Agent的度量不像传统软件那样只看接口成功率,要多维度一起看:
| 度量维度 | 具体指标 | 观测方式 |
|---|---|---|
| 结果质量 | 任务完成率、代码通过率、人工采纳率 | 人工验收+自动校验 |
| 过程效率 | 平均步数、单任务耗时、工具调用成功率 | Trace日志统计 |
| 成本 | 模型调用费用、Token消耗、GPU资源 | 用量账单 |
| 稳定性 | 死循环率、超时率、异常中断率 | 运行监控 |
我个人的经验是:链路指标比单点指标更重要。你单独测模型推理准确率可能很高,但放进Agent循环里,一次小错误会被后续步骤放大。真正要盯的是"端到端任务完成率",而不只是"模型回答正确率"。
4.3 建立回归评估集和追踪系统
想让Agent持续迭代,两个基础设施必须有:评估集和追踪系统。
评估集我建议直接从真实任务里录。从历史Issue中挑20到50个有代表性的任务,人工准备好"期望最终产物",比如一个修复后的PR、一段补全的测试代码、一份正确的变更说明。每次改动Prompt、换模型、调Harness结构,都拿这批任务跑一遍回归,看完成率是否下降。没有这个回归机制,你很可能今天优化了A场景,明天弄坏了B场景还不自知。
追踪系统可以用LangSmith这类现成平台,也可以自建。关键要求是:每个Loop有唯一ID,记录每次模型输入输出、每次工具调用的参数和返回结果、耗时和成本。这样一旦有问题,你就能顺着Trace还原模型当时的决策过程,而不是对着日志猜。
这里有个容易犯的操作错误:一开始就追求评估集规模大。实际上,20条精心标注的任务,比200条随便收集的任务有用得多。先把小评估集的通过率做上去,再逐步扩充覆盖更多场景。
5. 知识工程与RAG:先给Agent配上企业知识库再谈干活
5.1 为什么纯靠模型参数不够
很多做Agent的人容易幻想:大模型训练时见过天量代码,应该什么都知道。现实是,模型对它训练截止之后的代码一无所知,更不熟悉你们公司内部的编码规范、架构设计文档和私有SDK用法。如果让Agent凭记忆回答这些私有知识问题,它大概率会一本正经地编出一个看似合理的错误答案,这就是幻觉。
解决幻觉的主流方案是RAG(Retrieval-Augmented Generation,检索增强生成)。核心逻辑很简单:让模型在生成回答之前,先从企业知识库中检索相关内容,把检索结果作为上下文喂给模型,模型再基于这些材料生成答案。模型不再"背"答案,而是"翻书找答案"。这不仅能减少幻觉,还能让回答带上可追溯的来源,方便人工审计。
5.2 Agentic RAG的实现路径
RAG在Agent场景里有一个重要升级,叫Agentic RAG。传统RAG是"查一次、生成一次",检索结果不好就直接拉胯。Agentic RAG则把检索本身变成了Agent可调用的工具:Agent先判断这个问题是否需要查知识库,查了之后发现结果不够,它可以改写查询词重试,或者换一个向量库再查。
热词里那个"fastapi+langchain+langgraph+rag+pgvector的AI Agentic RAG",就是很典型的落地技术栈。整体链路我拆开说:
第一步是文档解析和清洗。把PDF、Word、Markdown等各种格式的文档转成纯文本,去掉页眉页脚和无关噪音,同时保留文档标题、作者、更新时间这些元数据,后面检索和权限控制都要用。
第二步是分块。文档不能整篇塞给模型,上下文装不下,相关性也会被稀释。通常按固定长度或语义结构切块,一般几百个Token一块。块太大会混入无关内容,块太小会丢失上下文。这里需要根据文档类型多试几次。
第三步是向量化。把每个文本块通过Embedding模型转成向量。中文场景要注意选对模型,比如bge系列、m3e系列在这块的表现都不错。向量化质量直接决定检索效果,这也是很多人忽略的地方。
第四步是存储。向量数据库可以选pgvector(直接复用PostgreSQL,小团队够用)或Milvus(数据量大、高并发时更合适)。热词里的pgvector路线,好处是少维护一个组件,业务数据和向量在一起。
第五步是检索和重排。通常用向量检索加关键词检索的混合模式,再把两者结果合并交给重排模型排序,取最相关的几段作为上下文。重排这一步很关键,很多人光做向量检索就草草上线,效果差再想加就麻烦了。
from langchain_community.vectorstores import PGVector from langchain_community.embeddings import HuggingFaceEmbeddings embeddings = HuggingFaceEmbeddings(model_name="BAAI/bge-large-zh-v1.5") vector_store = PGVector( connection_string="postgresql://user:pass@localhost:5432/ragdb", embedding_function=embeddings, collection_name="company_docs" ) # 检索时配合BM25关键词检索,做混合召回 results = vector_store.similarity_search_with_score("如何部署内部服务", k=10)知识工程落到研发交付场景时,最常用的一个结合点是:Agent在修改代码前,先检索项目的README、架构文档、历史Issue和提交记录,理解代码仓库的设计意图和约定,再动代码。很多Agent"改出来的代码能跑但不符合项目风格",根本原因就是跳过了这一步。
5.3 知识库维护与权限
知识库不是一次性建好就完事的。文档是持续更新的,知识库也要有同步机制:文档变更后触发重新分块和向量化,并保留版本记录。否则Agent会拿三个月前的过期文档给用户当依据。
权限隔离同样要提前设计。不同项目、不同团队的文档放进独立的Collection或带上项目标签,检索时按当前任务的项目ID做过滤。Agent只能检索到它被允许访问的知识,这是底线要求。不然一个Agent同时接两个客户项目,很可能把A的隐私文档检索出来带到B的回答里。
关于RAG的效果,我的切身体会是:项目落地过程中,80%的精力会花在数据治理上,而不是模型调优上。文档解析乱、分块不合理、embedding选错,这些问题都会让检索效果很差。遇到检索不准,先别急着换大模型,把前面这几步重新梳理一遍,往往收益更大。
6. 把Agent嵌入真实研发交付流:PR、Issue、CI
6.1 事件驱动的接入方式
前面讲的底座、Harness、度量、知识库,都是单机能力。Agent要进入真实研发交付流程,必须有合适的接入方式。最常用的是事件驱动:研发平台产生事件(比如有人提了PR、有人评论了Issue、代码推到了主干分支),Webhook把事件推给Agent服务,Agent服务唤醒Harness开始执行。
举一个完整的PR助手场景:
- 开发者在GitHub或GitLab上创建了一个PR。
- Webhook收到pull_request事件,Agent服务被触发。
- Harness启动,先拉取PR的diff内容。
- Agent用RAG检索项目相关文档、历史Issue、团队代码规范。
- 模型基于diff和检索结果进行分析,检查潜在Bug、性能问题、代码风格、缺失的测试用例。
- Agent在PR上提交评论,逐条指出问题并给出修改建议。
- 如果配置了自动修复权限,Agent还可以创建一个修改分支,但必须先经过人工审批才能合并。
这个过程里,Human-in-the-loop体现在"评论"和"审批"环节:Agent给意见,人做最终决定。这个设计不是保守,而是必要。代码合并是研发流程里风险最高的操作之一,Agent现阶段适合当高水平的评审助手,不适合当无人监管的提交者。
6.2 接入研发流程的落地步骤
如果要从零开始做,我建议按这个节奏推进:
第一步,影子模式运行。Agent先只生产分析结果,不执行任何写操作。比如它分析PR后产出"如果是我会这样改"的建议,但不真的改代码。这个阶段用来验证准确率,同时让团队建立对Agent的信任。
第二步,低风险动作自动化。等建议准确率足够高、误报率降下来了,让它做一些低风险操作,比如自动生成PR描述、自动补充单元测试、自动给Issue打标签分优先级。这些动作即使出错,成本也可控。
第三步,逐步开放高权限动作。比如自动修Bug并提交修复PR,但必须保留分支保护和人工审批。观察一段时间的线上表现,再考虑能不能放开更多。
注意Agent token的权限配置。这个我前面提过一次,这里再强调:给Agent的凭证一定是独立申请的,最小权限。比如PR助手只需要读写某个仓库的权限,就不要给它整个组织的权限。很多安全问题不是模型出问题,而是权限配置太宽了。
6.3 上线后的度量与迭代
接入真实流程后,需要用数据回答这几个问题:PR评审时间有没有缩短?Bug逃逸率有没有下降?Agent建议的人工采纳率是多少?误报率呢?这些指标直接决定团队信不信这套系统、愿不愿意继续用。
我见过一个团队把Agent接进PR流程后,只看"推荐了多少条建议"这个数字,一度觉得效果很好,直到研发反馈"建议质量不行,基本看都不看"。后来把指标改成"建议采纳率",才发现实际不到两成。所以度量指标的选择一定要贴近真实业务价值,而不是只盯着"Agent活跃度"这种虚荣指标。
在并行项目多、仓库多的团队里,还可以给Agent加一个"仓库优先级"的配置,让它优先处理核心项目的PR,避免所有仓库一拥而上把算力耗光。
最后,把这篇文章的核心串起来:运行底座负责让Agent接得上工具,Harness负责让Agent跑得稳,Loop与度量负责让Agent成效看得见,知识工程负责让Agent回答有依据,事件驱动把这一切接入真实的研发交付流程。这套体系不是一次搭完就结束的,它是一个持续迭代的工程。我个人的建议是,从最简单的PR助手或文档助手起步,先跑通一条链路,再逐步扩展场景。每一步都要让工程师看到实实在在的效率提升,他们才会愿意配合Agent一起工作。一个真正落地的Agent项目,团队里多了一个"不知疲倦的初级工程师",而不是多了一个"大家都要盯着它别闯祸的实习生"。