跳到主要内容

SWE-agent — 架构与原理

核对基准:克隆源 /Users/taiyou/Dev/OpenSource/ai-frontier-reference/aiRef/repos/swe-agent。 下文所有 path:line 引用均针对该克隆源核对。

SWE-agent 是什么 / 解决什么问题

SWE-agent 让你选定的语言模型(如 GPT-4o、Claude Sonnet)自主调用工具去 修复真实 GitHub 仓库里的 issue、查找安全漏洞,或执行自定义任务 (README.md:28-31)。它在 SWE-bench 上是开源项目中的 SOTA,设计哲学是 "把最大自主权留给 LM"、"全部行为由单个 YAML 文件统辖" (README.md:33-36)。

它要解决的核心问题:LM 不是人,直接把人类用的 shell/编辑器丢给它,效果很差。 SWE-agent 的关键贡献是 ACI(Agent-Computer Interface)——一套专为 LM 设计的、反馈紧凑、出错可恢复的命令界面。换句话说,SWE-agent ≈ "一个把 LM 输出解析成命令、在沙箱里执行、再把结果喂回 LM 的循环" + "这套 ACI"。

注:克隆源 README.md:19-25 标注当前主要开发已转向更精简的 mini-swe-agent,SWE-agent 仍是理解 ACI 与 agent 主循环的完整参考实现。

架构总览图

一次 run(env, problem_statement)

┌─────────────────────────▼──────────────────────────┐
│ DefaultAgent │
│ sweagent/agent/agents.py:443 │
│ │
│ run() ──loop──► step() ──► forward_with_handling │
│ :1265 :1235 :1062 (错误→重查) │
│ │ │
│ forward() :1006 │
│ │ │
│ ┌──────────────┐ thought+action ┌───────────┐ │
│ │ AbstractModel│◄──────────────────►│ToolHandler│ │
│ │ models.py:311│ model.query() │ tools.py │ │
│ │ (LM 推理) │ :320 │ :227 │ │
│ └──────┬───────┘ └─────┬─────┘ │
└──────────┼─────────────────────────────────┼────────┘
│ HTTP (LiteLLM) │ parse_actions :378
▼ ▼ 解析出的 shell 命令
┌─────────────────┐ ┌──────────────────────┐
│ LM API 端点 │ │ SWEEnv │
│ (OpenAI/Claude…) │ │ environment/swe_env.py:51│
└─────────────────┘ │ communicate() :197 │
└───────────┬──────────┘
│ run_in_session
▼ (SWE-ReX 运行时)
┌──────────────────────┐
│ 沙箱容器 + 目标 Repo │
│ + 注入的 ACI 工具 │
└──────────────────────┘

数据流一句话:LM 产出文本 → Parser 抽出 action → ToolHandler 转成 shell 命令 → SWEEnv 在沙箱执行 → observation 回灌进 history → 下一轮 LM 推理,直到提交补丁或触发退出条件。

ACI — Agent-Computer Interface 核心理念

ACI 的落地形态是工具 Bundle:每个工具目录(克隆源 tools/ 下,如 search/edit_anthropic/submit/)包含一个 config.yaml 声明命令的 signature / docstring / arguments,外加 bin/ 下的可执行实现与 install.sh(见 tools/search/config.yaml:1-30、目录 tools/search/)。

  • 一个 Bundle 就是"一个带 config.yaml 的工具目录"(sweagent/tools/bundle.py:17), 其 commands 属性把 YAML 里的每条工具读成 Command 对象(sweagent/tools/bundle.py:52)。
  • 这些 bundle 在 agent 启动时被安装进沙箱:ToolHandler.install() (sweagent/tools/tools.py:252)调用 _install_commands()(:292)把命令拷进环境。

设计要点(为 LM 而非人优化):命令签名精简、文档随命令一起暴露给 LM、 执行后由 _get_state() 抽取结构化状态(如当前打开文件、行号)回灌 (sweagent/tools/tools.py:317_get_state,:337get_state)。

主控制循环

主循环全部在 DefaultAgent(sweagent/agent/agents.py:443)中:

方法位置职责
run()agents.py:1265顶层入口;setup 后进入 while not step_output.done 循环,每步存轨迹(:1284-1286)
step()agents.py:1235单步包装:调 forward_with_handling,更新 history、trajectory、info(:1252-1260)
forward_with_handling()agents.py:1062包裹 forward,捕获异常并按需重查模型(bash 语法错等可恢复错误)
forward()agents.py:1006不处理错误的核心:model.query(history)parse_actions 得到 thought/action → handle_action 执行(:1042-1052)
add_step_to_history()agents.py:714把动作与 observation 追加进消息历史
attempt_autosubmission_after_error()agents.py:823出错时尝试自动提交已有改动,避免白跑

循环终止条件:step_output.done 为真(agents.py:1284),由提交命令、退出状态 或执行超时(_TotalExecutionTimeExceeded,agents.py:215、触发点 :1018-1019)决定。

forward() 内的解析委托给工具层:step.thought, step.action = self.tools.parse_actions(output) (agents.py:1045),对应 ToolHandler.parse_actions(sweagent/tools/tools.py:378)。

工具与命令

解析路径(LM 文本 → 可执行命令)由 sweagent/tools/parsing.py 的一族 parser 承担,均实现 AbstractParseFunction.__call__(parsing.py:52,61):

Parser位置适用
ThoughtActionParserparsing.py:109思考+代码块格式(默认家族)
XMLThoughtActionParserparsing.py:168XML 包裹的思考/动作
FunctionCallingParserparsing.py:371原生 tool-calling API
JsonParserparsing.py:455JSON 动作
Identityparsing.py:354直通,不解析

ToolConfig(sweagent/tools/tools.py:75)声明工具集与解析方式,其 use_function_calling(:155)、commands(:168)、tools(:194)等属性 把 bundle 汇总成模型可见的命令清单。ToolHandler(:227)则负责安装、复位 (reset :256)、阻断危险动作(should_block_action :353)、检测提交命令 (check_for_submission_cmd :372)。

模型抽象

所有模型实现统一接口 AbstractModel(sweagent/agent/models.py:311),核心方法 query(history, ...)(:320)。具体实现:

实现位置用途
LiteLLMModelmodels.py:578经 LiteLLM 接 OpenAI/Anthropic 等多家 API(生产路径)
HumanModelmodels.py:344人在回路,手动输入动作
HumanThoughtModelmodels.py:446人类输入思考+动作
ReplayModelmodels.py:464回放已有轨迹
InstantEmptySubmitTestModelmodels.py:551测试用,立即空提交

LiteLLMModel 内部 _single_query(models.py:679)、_query(:783)、 query(:794)负责真正的 API 调用、重试与成本统计(_update_stats :632InstanceStats :292)。工厂函数 get_model(models.py:875)按配置选实现。

配置与运行入口

单个 YAML 统辖全部行为。 克隆源 config/default.yaml 定义了 agent.templates(系统/实例提示词,config/default.yaml:4-25)等。配置目录还含 bash_only.yamlcoding_challenge.yamlbenchmarks/human/ 等多套预设。

运行入口:

入口位置说明
sweagent CLIsweagent/run/run.py:37 (get_cli)、:70 (main)顶层命令分发
单实例运行sweagent/run/run_single.py:125 (RunSingle)、:188 (run)跑一个 problem
批量运行sweagent/run/run_batch.py跑数据集(如 SWE-bench)
入口模块sweagent/__main__.pypython -m sweagent

RunSingle.run()(run_single.py:188)最终调用 agent.run(env, problem_statement, output_dir), 即上文的主循环;run_from_config / run_from_cli(run_single.py:210,214)为薄封装。

环境侧 SWEEnv(sweagent/environment/swe_env.py:51)管理沙箱生命周期: start()(:109)、reset()(:135)、communicate()(:197,经 SWE-ReX 运行时 run_in_session 执行命令)、read_file/write_file(:234,252)、close()(:168)。

代码地图

模块关键符号引用
sweagent/agent/agents.pyDefaultAgentrunstepforwardforward_with_handling:443,1265,1235,1006,1062
sweagent/agent/agents.pyRetryAgentAbstractAgent:257,224
sweagent/agent/models.pyAbstractModelLiteLLMModelget_model:311,578,875
sweagent/tools/tools.pyToolConfigToolHandlerparse_actionsinstall:75,227,378,252
sweagent/tools/parsing.pyAbstractParseFunction 及各 parser:52,109,168,371,455
sweagent/tools/bundle.pyBundlecommands:17,52
sweagent/environment/swe_env.pySWEEnvcommunicateresetstart:51,197,135,109
sweagent/run/run.pyget_climain:37,70
sweagent/run/run_single.pyRunSinglerunrun_from_cli:125,188,214
config/default.yaml默认 agent 模板与配置:4-25
tools/工具 Bundle 目录(search、edit_anthropic、submit…)tools/search/config.yaml:1-30