代码生成 Agent:你的新"初级开发工程师"?

周五下午的技术讨论会,老李把一沓简历摔在桌上。

“HR 说今年初级开发的 HC 又砍了,让我们‘用 AI 提效’。我就纳闷了,AI 不就是个高级自动补全吗?能写几行代码不假,但让它读懂一个十万行的老项目、找到 Bug、修好、跑通测试、再提个 PR——这中间差着十个实习生的距离。”

小王从笔记本后面探出头:“老李,你说的这个,上个月确实做不到。但现在有个东西叫 SWE-Agent,它已经把从 Issue 到 PR 的整个流程跑通了。”

老李端起保温杯,枸杞晃了晃:“SWE 什么?别又是换个名字炒冷饭。Agent 我见多了,不就是套个壳调 API 吗?写代码这事儿,上下文理解、架构权衡、业务判断——AI 能干哪个?”

“你别急,”小王把屏幕转过来,“我给你看一个真实的案例。就咱们 backlog 里那个躺了三个月的 Bug——用户注册时如果昵称带 emoji,服务端偶尔返回 500。实习生看了两天没定位到,我昨天让 Agent 试了试。”


从 Issue 到 PR:Agent 的完整工作流

老李凑近屏幕。上面是 SWE-Agent 的运行日志,每一步都记录在案。

小王指着第一行:“你看,Agent 收到的是 GitHub Issue 的原文——用户报错信息、复现步骤、期望行为。它没有直接开始改代码,而是先在代码库里搜索相关的文件。”

日志显示 Agent 执行了一个搜索动作:在项目根目录下用正则表达式搜索与“用户注册”相关的 API 路由和处理函数。然后它读取了几个候选文件,逐段理解代码逻辑。

python
# SWE-Agent 的核心循环示意:理解→定位→修改→验证
def solve_issue(issue_text: str, repo_path: str) -> dict:
    # 初始化 Agent,给定可用工具:查看文件、搜索代码、执行测试等
    agent = SWEAgent(repo_path, tools=[
        "view_file", "search_code", "edit_file", "run_test", "submit_pr"
    ])
    
    # Agent 的推理-行动循环
    trajectory = []
    for step in range(max_steps):
        thought = agent.think(issue_text, trajectory)  # 自然语言思考
        action = agent.decide_action(thought)          # 选择工具和参数
        
        if action.name == "submit_pr":
            return action.pr_info
        
        observation = execute(action)                  # 运行工具获取结果
        trajectory.append({"thought": thought, "action": action, "obs": observation})
    
    return {"error": "未能解决,超出步数限制"}

“它找到了 user_service.py 里的 validate_nickname 函数,发现正则表达式 \w+ 只允许字母数字和下划线,emoji 肯定过不了。但它没急着改,而是先查了调用链——这个函数被 API 层捕获异常时,异常处理写得有问题,才导致 500 而不是 400。”

老李眉头微皱:“这逻辑跟人排查差不多啊。它怎么知道查调用链?”

“因为它的系统 Prompt 里写了一条核心原则:‘修改前必须理解上下文,追踪相关函数的所有调用者’。这就像一个强迫症开发者,动手之前一定要把影响范围搞清楚。”

图:SWE-Agent 从 Issue 到 PR 的标准工作流


自己写测试,自己修失败

“最让我惊讶的是这一步。”小王指着日志中间一段。

Agent 第一次修改后,运行测试,有一个边界用例失败了——用户昵称为空字符串时,新的验证逻辑抛了 ValueError。Agent 读到失败日志,自己分析出是空字符串没处理,又回去补了个判断。然后重新跑测试,全绿。

“它还会根据测试失败信息调整代码?”老李的保温杯停在了半空。

“这就是‘测试驱动修复’的能力。你只需要在 Issue 里描述清楚预期行为,Agent 会自己生成测试用例,或者跑已有的测试套件,然后把红灯变绿灯。这个过程跟人类开发者做 TDD 几乎一样。”

老李沉默了几秒,然后问了一个关键问题:“那它改完的代码质量怎么样?不会是能跑就行、毫无可读性的那种吧?”

小王打开了 Agent 提交的 PR。代码改动很小,只改了 validate_nickname 的正则为 [^@#\s]+,并在 API 层加了一行异常转换,把未捕获的异常统一包装成 400。注释清晰,commit message 是“fix: 用户昵称支持 emoji 并修复异常处理导致 500 的问题”。

老李盯着那个 PR,慢慢点了点头:“实习生也写不出这么干净的提交。”


局限性:大修大改、跨语言迁移、安全敏感

“别高兴太早,”小王又泼了盆冷水,“Agent 不是万能的。我把它的能力边界列出来——”

他在白板上画了三个圈。

大范围重构——比如把一个单体服务拆成微服务,涉及几十个文件、改变模块边界。Agent 会迷失在巨大的修改范围里,改到一半逻辑就开始混乱。这种活需要人类先设计好架构,Agent 只能做局部辅助。”

跨语言迁移——把 Python 项目转成 Go,这不只是语法翻译,还涉及语言生态、并发模型、库替代方案。Agent 缺乏全局经验,只能机械翻译,产出的代码多半运行不了。”

安全敏感代码——加密算法、权限校验、支付逻辑。Agent 可能无意中引入漏洞,或者使用了不安全的库版本。这类代码无论 Agent 写得多好看,必须人工审查每一行。”

老李接话:“也就是说,Agent 擅长的是明确、受限、可验证的任务。改 Bug、写单元测试、加个小功能——这些最适合它。”

“对。而且它还需要一个清晰的验收标准——要么有测试用例,要么有明确的 Issue 描述。如果需求模糊,Agent 就容易跑偏。这和实习生的管理一模一样。”


算账:一个 Agent 等于几个实习生?

会议快结束时,老李忽然拿出计算器。

“我们 backlog 里还有多少个类似的 Bug?那种边界条件、单一文件修改、有明确复现步骤的?”

小王翻了翻 Jira:“大概 40 个左右,大部分是异常处理缺失、参数校验不完整、错误码不准确这类问题。”

“如果一个实习生一天能修 2 个,40 个需要 20 人天。Agent 跑了多久修完那个 emoji 的 Bug?”

“从接到 Issue 到提 PR,17 分钟。”

老李按了几下计算器,表情从怀疑变成了深思。然后他拧开保温杯喝了一口,枸杞的香气弥漫在会议室里。

“嗯……还有点意思。下周你把 SWE-Agent 部署到我们的开发环境,先让它清那 40 个 Bug。每个 PR 必须经过 code review,你就当它是你的结对搭档。”

他站起来,走到门口又停下:“那什么,你说 Agent 在改代码之前会搜索文件、读代码,它怎么保证自己读懂了?万一它把一个完全不相关的函数当成了根因,是不是也会改错?它的‘理解’到底靠什么——是语义搜索还是静态分析?你下午给我讲讲它的代码检索策略。”

小王咧嘴笑了:“老李,你这问题问到核心了。它靠的是一套叫‘结构化代码理解’的技术,结合 AST 解析和语义向量——但你要说它真‘理解’了,那倒也未必,更像是一个极端勤奋但缺乏全局视野的新人。”

老李摆摆手走了,保温杯里的枸杞晃晃悠悠,像代码仓库里那些被 Agent 一行一行读懂的源码,静静地等着被修好。

浏览器 Agent:教 AI 学会"点点点"
评估 Agent 表现:比你想象的要难十倍