仓库: princeton-nlp/SWE-agent (现迁移至 SWE-agent org)
论文: *SWE-agent: Agent-Computer Interfaces Enable Automated Software Engineering* (NeurIPS 2024)
团队: Princeton University & Stanford University
成就: SWE-bench 开源项目 SOTA,已发布 1.0 版本
一、系统总览与设计哲学
SWE-agent 是一个让大语言模型(LLM)自主修复 GitHub Issue 的自动化软件工程代理。其核心设计哲学是 “最大化代理自由度”(Maximal Agency)——尽可能少地约束 LLM 的行为,通过精心设计的 Agent-Computer Interface(ACI)让模型自由探索代码仓库、执行命令、生成补丁。
整体架构遵循经典的 Agent-Environment Loop 模式:Agent 接收问题描述,在隔离环境中执行动作,观察环境反馈,循环直至问题解决。系统由 YAML 配置文件统一驱动,支持 GPT-4o、Claude Sonnet 等多种模型后端。
┌─────────────┐ ┌──────────────┐ ┌─────────────────┐
│ Problem │────▶│ Agent │────▶│ SWEEnv │
│ Statement │ │ (LLM Loop) │◀────│ (Docker/Modal) │
└─────────────┘ └──────────────┘ └─────────────────┘
│
┌──────┴──────┐
│ Tool System │
│ (Commands) │
└─────────────┘
二、Agent 核心架构(agents.py)
Agent 层是 SWE-agent 的大脑,采用 多态 Agent 设计,通过 Pydantic 配置区分三种 Agent 类型:
| Agent 类型 | 配置类 | 用途 |
|---|
|———–|——–|——|
DefaultAgent |
DefaultAgentConfig |
标准单次 Agent,核心循环 |
|---|---|---|
RetryAgent |
RetryAgentConfig |
多次尝试 + 评审机制 |
ShellAgent |
ShellAgentConfig |
Shell 交互模式 |
DefaultAgent 是核心实现,其 step() 方法包含完整的 Forward → Parse → Execute 循环:
- 构建 History:通过
HistoryProcessor链处理历史消息(裁剪、压缩、缓存控制) - 模型查询:调用
model.query(history)获取 LLM 输出 - 动作解析:通过
ToolHandler.parse_actions()将文本输出解析为 thought + action - 动作执行:调用
handle_action()在环境中执行命令 - 结果反馈:将执行结果添加到 trajectory
RetryAgent 在此基础上引入了 多次尝试 + 评审 机制:Agent 执行完毕后,由 Reviewer 模型对结果评分,若不满意则重置环境重新尝试。支持 ScoreRetryLoop(评分循环)和 ChooserRetryLoop(选择器循环)两种策略。每次尝试的配置可以不同(轮询 agent_configs 列表),实现策略多样性。
错误处理采用 分层异常机制:FormatError、_BlockedActionError、BashIncorrectSyntaxError 等触发重新查询(最多 max_requeries=3 次),CostLimitExceededError、ContextWindowExceededError 则触发自动提交或退出。
三、模型抽象层(models.py)
模型层通过 AbstractModel 抽象基类 统一接口,支持多种后端:
- LiteLLMModel:核心实现,通过
litellm库统一调用 OpenAI、Anthropic、Google 等 API。支持重试(指数退避,最多 20 次)、多 API Key 轮询(按线程分配以利用 prompt caching)、fallback 模型。 - HumanModel / HumanThoughtModel:人机交互模式,用于调试和演示。
- ReplayModel:轨迹回放模式,用于复现历史执行。
- InstantEmptySubmitTestModel:测试用,立即提交空补丁。
成本控制 是模型层的关键特性:
per_instance_cost_limit:单任务成本上限(默认 $3)total_cost_limit:总成本上限per_instance_call_limit:单任务 API 调用次数上限- 通过
GlobalStats+InstanceStats双层统计实现精确成本追踪
API Key 管理支持 ::: 分隔的多 Key 配置,按线程名哈希分配,确保同一任务始终使用同一 Key(利用 Anthropic 的 prompt caching)。
四、环境层架构(swe_env.py)
SWEEnv 是代理执行动作的沙箱环境,基于 SWE-ReX 运行时抽象层:
class SWEEnv:
deployment: AbstractDeployment # Docker / Modal / Local
repo: Repo | RepoConfig # 仓库配置
生命周期:start() → _init_deployment() → reset() → Agent Loop → close()
- 部署抽象:通过
swerex.deployment支持 Docker 容器(默认python:3.11)、Modal 无服务器、本地执行等多种后端 - 仓库管理:支持 GitHub 远程仓库克隆、本地路径拷贝、预存在仓库三种模式
- 命令执行:
communicate()方法封装了命令发送、超时控制(默认 25s)、错误检查(warn/ignore/raise 三级) - 环境重置:
hard_reset()完全重启部署;reset()仅重置仓库状态(git restore + git checkout base_commit)
环境 Hook 机制允许在关键节点注入自定义逻辑(on_start_deployment、on_copy_repo_started、on_environment_startup 等)。
五、工具系统与命令解析(tools/)
工具系统是 SWE-agent 的 ACI 核心,分为三层:
5.1 命令定义(Command)
每个命令是一个结构化对象,包含 name、arguments(带类型和必填标记)、invoke_format(shell 模板)、end_name(多行命令终止符)。内置 BASH_COMMAND 作为默认 shell 命令。
5.2 解析器(Parser)
解析器将 LLM 文本输出转换为 (thought, action) 元组,支持 11 种格式:
| 解析器 | 适用场景 |
|---|
|——–|———|
ThoughtActionParser |
最经典,讨论 + 代码块 格式 |
|---|---|
FunctionCallingParser |
原生 function calling 模型 |
XMLFunctionCallingParser |
XML 标签格式的函数调用 |
JsonParser |
JSON 格式的结构化输出 |
BashCodeBlockParser |
执行 `bash 代码块 |
EditFormat |
编辑窗口内容格式 |
解析失败时抛出 FormatError,触发 Agent 的重新查询机制。
5.3 工具过滤(ToolFilter)
通过黑名单机制过滤危险命令(如 vim、nano 等交互式命令),防止 Agent 陷入交互式程序。
5.4 Bundle 机制
工具通过 Bundle 加载,支持外部工具包扩展,实现命令的模块化管理。
六、问题陈述与输入(problem_statement.py)
SWE-agent 支持多种问题输入格式:
- TextProblemStatement:纯文本描述
- FileProblemStatement:从文件读取问题描述
- GithubIssue:直接从 GitHub Issue URL 自动获取标题、描述、评论
- SWEBenchMultimodalProblemStatement:支持图文混合输入(图片 base64 编码)
- EmptyProblemStatement:空问题(用于自由探索)
每种类型都实现统一的 ProblemStatement 接口,提供 id、get_problem_statement() 方法。GithubIssue 通过 GitHub API 自动解析 issue 内容,支持 GITHUB_TOKEN 认证。
七、历史管理与上下文工程(history_processors.py)
历史处理器是 SWE-agent 处理长上下文的关键机制,采用 Pipeline 模式 链式处理:
- LastNObservations:只保留最近 N 条观察结果(经典论文方案,N=5),旧观察替换为
"Old environment output: (n lines omitted)" - CacheControl:在指定位置添加 Anthropic 缓存标记,利用 prompt caching 降低延迟和成本
- RemoveRegex:正则表达式匹配移除特定内容(如行号前缀)
- WindowedObservation:窗口化处理,避免重复文件内容膨胀上下文
- ImageParser:将 markdown 图片语法转换为多模态 API 格式
这种设计使得 Agent 在长时间交互中能有效控制上下文窗口大小,避免超出模型限制。
八、动作采样与多代理协作(action_sampler.py)
SWE-agent 1.0 引入了创新的 动作采样 机制,实现类似”多代理讨论”的效果:
- AskColleagues:让多个 Agent(或同一 Agent 多次采样)独立思考,然后将所有同事的思路汇总给主 Agent 做最终决策。流程:采样 N 个 completions → 拼接为 “colleague discussion” → 主 Agent 综合决策。
- BestOfN:采样 N 个候选动作,通过比较模型选择最优方案。支持去重过滤。
这种设计避免了传统 Multi-Agent 系统的复杂通信开销,通过 单 Agent 多采样 + 选择器 实现了类似效果,同时保持了架构简洁性。
九、评审与重试机制(reviewer.py)
Reviewer 是 SWE-agent 1.0 的重要新增组件,实现 自我评审 能力:
- Reviewer:对 Agent 提交的 patch 进行评分(float 或 bool),使用独立的 LLM 实例,配有专用的 system_template 和 instance_template。
- Preselector:在多个提交中预筛选,减少评审开销。
- Chooser:在多个候选中选择最佳方案。
- TrajectoryFormatter:将 Agent 轨迹格式化为评审输入,支持过滤特定动作和输出。
与 RetryAgent 配合,形成 执行 → 评审 → 重试 的闭环:Agent 完成一轮后,Reviewer 评分,若分数不达标则重置环境、切换策略重新尝试(受 cost_limit 约束)。
十、运行编排与配置驱动(run/)
10.1 RunSingle:单任务执行器
RunSingle 是顶层编排器,负责组装 Environment、Agent、ProblemStatement 并驱动执行:
RunSingle.from_config(config).run()
# 1. 加载环境变量
# 2. 创建 SWEEnv(Docker/Modal)
# 3. 创建 Agent(Default/Retry/Shell)
# 4. agent.run(env, problem_statement, output_dir)
# 5. 保存预测结果
10.2 配置驱动架构
整个系统由 YAML 配置文件驱动,通过 Pydantic 模型验证:
agent:
model:
name: "gpt-4o"
per_instance_cost_limit: 3.0
tools:
parse_function:
type: "thought_action"
filter:
blocklist: ["vim", "nano"]
history_processors:
- type: last_n_observations
n: 5
env:
deployment:
type: docker
image: "python:3.11"
repo:
github_url: "https://github.com/owner/repo"
problem_statement:
github_url: "https://github.com/owner/repo/issues/1"
10.3 Hook 系统
贯穿全流程的 Hook 机制支持在各阶段注入自定义逻辑:
- RunHook:
on_start、on_instance_start、on_instance_completed、on_end - AgentHook:
on_model_query、on_actions_generated - EnvHook:
on_start_deployment、on_copy_repo_started
内置 Hook 包括 SaveApplyPatchHook(本地应用补丁)和 OpenPRHook(自动创建 Pull Request)。
架构总结与启示
| 维度 | 设计选择 | 评价 |
|---|
|——|———|——|
| 代理模式 | 单 Agent + 多采样/评审 | 简洁高效,避免 Multi-Agent 通信开销 |
|---|---|---|
| 环境隔离 | Docker/Modal 沙箱 | 安全可靠,支持多后端切换 |
| 工具接口 | 可配置命令 + 多解析器 | 灵活适配不同模型输出格式 |
| 上下文管理 | Pipeline 式历史处理器 | 有效控制 token 消耗 |
| 成本控制 | 多层成本限制 + 统计追踪 | 防止意外高额 API 调用 |
| 错误恢复 | 分层异常 + 自动重查询 | 提高单次交互成功率 |
| 配置驱动 | Pydantic + YAML | 类型安全,支持 CLI 覆盖 |
| 可扩展性 | Hook + Bundle + 多态 Agent | 易于添加新功能和工具 |
SWE-agent 的核心创新在于 ACI(Agent-Computer Interface) 的设计理念——不是让 Agent 直接操作文件系统,而是通过精心设计的命令接口(如结构化的 edit、search、view 命令)降低 LLM 的操作难度。这一思想对后续的 Coding Agent 系统(如 OpenHands、Devin 等)产生了深远影响。
值得注意的是,团队已发布 mini-SWE-agent,用仅 100 行 Python 代码实现了相当的性能(SWE-bench verified 65%),证明了核心架构的精简性——真正的复杂性在于环境封装和工具接口设计,而非 Agent 循环本身。