综合调研

APEX-SWE 深度解剖:50 个真实软件工程任务的评测基准——从源码到设计决策

深入 APEX-SWE 评测框架的源码级分析:25 个多服务集成任务 + 25 个生产故障调试任务,Docker Compose 编排、MCP 工具服务、两套完全不同的 Agent 交互模式、F2P/P2P 评分机制,以及与 APEX-Agents/SWE-bench 的关键差异

Agent APEX-SWE 评测 Benchmark SWE Software Engineering Mercor MCP Docker

引言

APEX-SWE(arXiv 2601.08806)是 Mercor 发布的软件工程 Agent 评测基准,与 APEX-Agents 构成”双子星”体系。如果说 APEX-Agents 评测的是”AI 能不能当投行分析师”,APEX-SWE 评测的是”AI 能不能当软件工程师”。

本报告基于 HuggingFace 数据集(mercor/APEX-SWE,2.08 GB)和 GitHub 评测框架(Mercor-Intelligence/apex-swe)的完整源码分析,逐层拆解其架构。


第一章 · 数据集全景

1.1 基本数据

维度值
总任务数50
集成任务(Integration)25
可观测性任务(Observability)25
数据集大小2.08 GB
许可证CC-BY 4.0(仅限评测,禁止训练)
评测框架github.com/Mercor-Intelligence/apex-swe
Leaderboardmercor.com/apex/apex-swe-leaderboard/

1.2 两大任务类型

APEX-SWE 的核心设计是将软件工程能力分为两个正交维度:

Integration(集成):Agent 面对一个多服务环境(LocalStack、Plane、Zammad、EspoCRM、Medusa、MailHog、Mattermost),需要理解服务间的关系、编写代码实现跨服务数据编排。这考察的是”从零构建”的能力。

Observability(可观测性):Agent 面对一个有 Bug 的真实开源项目(含 Grafana + Loki + Mattermost + Plane 的完整可观测性栈),需要通过日志、团队讨论、Issue 追踪来诊断并修复 Bug。这考察的是”诊断修复”的能力。

对比IntegrationObservability
核心能力多服务 API 编排生产故障诊断 + Bug 修复
环境运行中的真实服务(LocalStack/Zammad/…)有 Bug 的开源代码库 + 可观测性栈
Agent 输出Python 脚本(/app/solution.py)Git patch(代码修改)
评分方式Pytest 三维评分(正确性/功能性/健壮性)F2P/P2P(Fail-to-Pass + Pass-to-Pass)
Agent 框架自研 Harness(multi_step_runner.py)Inspect AI(inspect_eval)
交互方式XML + keystrokes 格式Function Calling(原生工具调用)
任务来源人工设计的集成场景真实开源项目的真实 Bug

1.3 Leaderboard

排名模型总 Pass@1IntegrationObservability
1GPT 5.3 Codex (High)41.5% ± 6.3%—33.3%
2Opus 4.7 (Max)41.3% ± 6.3%52.0%30.7%
3Opus 4.6 (High)40.5% ± 6.3%—31.7%
4Opus 4.5 (High)38.7% ± 6.3%50.7%—
5GPT 5.4 (High)36.5% ± 6.3%50.7%—

关键发现:没有模型能”通吃”两类任务——Integration 榜首和 Observability 榜首是不同的模型,说明这两类能力有本质差异。


第二章 · Integration 任务架构

2.1 任务目录结构

每个 Integration 任务是一个完整的 Docker Compose 项目:

<task-id>/
├── task.yaml                  # 指令、超时、测试脚本引用
├── docker-compose.yaml        # 服务编排(LocalStack + Plane + Zammad + ...)
├── Dockerfile                 # 客户端容器(Agent 运行环境)
├── docker-entrypoint.sh       # 容器初始化(PostgreSQL、环境变量)
├── data/
│   ├── issues.json            # Plane 看板(主任务 + 干扰项)
│   ├── connection-info.md     # 所有服务凭据和连接字符串
│   ├── init-aws.sh            # LocalStack 引导(S3 桶、SQS 队列、DynamoDB 表)
│   └── tool_code_api_docs/    # 每个服务的 API 文档
├── rubric/
│   └── rubric.json            # 评分标准(正确性/功能性/健壮性)
├── tests/
│   ├── test_outputs.py        # Pytest 测试用例
│   └── setup-uv-pytest.sh     # 测试环境安装
└── solution.py                # 参考解决方案(不展示给 Agent)

2.2 服务生态

服务角色Docker 镜像
PostgreSQL关系数据库(容器内运行)—
LocalStackAWS 服务模拟(S3/SQS/DynamoDB/IAM/Step Functions)localstack
Plane项目管理看板(issues、迭代、模块)自建 ECR 镜像
Zammad工单/客服系统(工单、Webhook、SLA)自建 ECR 镜像
EspoCRMCRM 系统(联系人、账户、营销活动)自建 ECR 镜像
Medusa电商后端(产品、订单、购物车)自建 ECR 镜像
MailHogSMTP 邮件捕获mailhog
Mattermost团队消息平台自建 ECR 镜像

所有服务镜像托管在 AWS ECR public.ecr.aws/k4t1e3r5/apex-code 仓库下。

2.3 干扰项设计

data/issues.json 中,Plane 看板会包含一个主任务 issue和多个干扰 issue——模拟真实项目看板上充满无关任务的场景。Agent 必须识别出哪个才是自己需要解决的。

2.4 MCP 服务器(Integration)

Integration 任务的 MCP 服务器全部基于 TypeScript(不是 APEX-Agents 的 Python FastMCP):

MCP Server语言工具数
PlaneTypeScript46+
ZammadPython(FastMCP)20+(含 search/get/create/update/add_article/tags 等)
EspoCRMTypeScript—
MedusaTypeScript—
MattermostTypeScript—

Zammad 是唯一用 Python 写的 MCP Server。从源码看,它基于 zammad_py 库封装了完整的工单 CRUD + 用户/组织查询 + 附件下载 + 标签管理功能。


第三章 · Observability 任务架构

3.1 任务目录结构

<task-name>/
├── task.yaml                   # 任务配置
├── compose.yaml                # Docker Compose(Grafana + Loki + Mattermost + Plane + App)
├── Dockerfile                  # 容器构建
├── problem_statement.md        # Bug 描述(给 Agent 看)
├── prompt_statement.md         # 扩展上下文
├── interface.md                # 接口规格
├── golden.patch                # 参考修复(Agent 看不到)
├── test.patch                  # 需要通过的失败测试
├── test_metadata.json          # 测试元数据(F2P/P2P)
├── requirements.json           # 修复需求清单
├── repo/                       # 含 Bug 的真实开源项目完整克隆
├── data/
│   ├── loki/                   # 预导出的应用日志
│   ├── mattermost/             # 导出的团队聊天记录
│   └── plane/                  # Issue + PR 快照
└── observability/              # Grafana + Loki + Promtail 配置

3.2 任务来源:真实开源项目的真实 Bug

项目语言领域
0xPolygon/borGo区块链
ChainSafe/gossamerGo区块链
containers/podman-composePython容器编排
ethereum-optimism/op-gethGo区块链
git-bug/git-bugGo开发工具
paperless-ngx/paperless-ngxPython文档管理

每个任务对应一个真实的 GitHub Issue + PR,Bug 是真实的,修复是真实的。

3.3 可观测性栈

服务作用
Grafana仪表板可视化(admin/admin)
Loki日志聚合(LogQL 查询)
Promtail日志收集器(将 repo 日志发送到 Loki)
Mattermost团队讨论上下文(关于 Bug 的对话)
PlaneIssue 和 PR 上下文

3.4 MCP 服务器(Observability)

Observability 的 MCP 服务器通过 JSON-RPC over stdin/stdout 交互:

MCP Server核心工具
Grafana-Lokiquery_loki(LogQL)、get_loki_labels、get_loki_label_values、get_datasources
Mattermostmattermost_channels、mattermost_fetch(推荐)、mattermost_search
Planeget_projects、list_issues、search_issues、get_issue_comments

Grafana-Loki MCP Server 基于 Python FastMCP,支持 Grafana 相对时间格式(now-1h)和 LogQL 全部语法。


第四章 · 两套完全不同的 Agent 交互模式

这是 APEX-SWE 最有趣的设计——两种任务使用完全不同的 Agent 框架和交互协议。

4.1 Integration:自研 Harness + XML keystrokes

框架:multi_step_runner.py——自研的多步交互循环。

System Prompt 要求 Agent 输出 XML 结构:

<response>
<analysis>分析当前状态</analysis>
<plan>下一步计划</plan>
<commands>
<keystrokes duration="0.1">ls -la</keystrokes>
<keystrokes duration="0.1">cd /app && find . -name '*.py'</keystrokes>
</commands>
<task_complete>false</task_complete>
</response>

工具:只有 3 个——terminal(tmux 会话内执行命令)、file(8 种文件操作)、todo(可选的任务管理)。

终止条件:<task_complete>true</task_complete> / 超时 / 达到 max_steps / token 接近上限(90%)。

关键约束:严禁 heredoc 语法(cat << EOF)——因为它会导致 tmux 终端挂起。推荐用 python3 -c、printf、echo、tee、sed 替代。

4.2 Observability:Inspect AI + Function Calling

框架:UK AI Safety Institute 的 inspect_ai 库——标准的 react() Agent。

System Prompt(324 行)定义了完整的 Observability 工作流:

  1. 查询 Loki 日志获取错误堆栈
  2. 搜索 Mattermost 获取团队讨论上下文
  3. 查看 Plane issues 获取 PR 信息
  4. 创建计划(update_plan)
  5. 搜索代码(search_files)
  6. 读取代码(read_file)
  7. 应用修复(apply_patch)
  8. 提交(submit)

工具:5 个标准 Function Calling 工具——bash、apply_patch、read_file、search_files、update_plan。

MCP 交互:Agent 通过 bash 工具执行 JSON-RPC 命令与 MCP Server 通信:

# 查询 Loki 日志
{
  echo '{"jsonrpc":"2.0","id":1,"method":"initialize",...}';
  echo '{"jsonrpc":"2.0","method":"notifications/initialized",...}';
  echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"query_loki",...}}';
} | mcp-loki

4.3 为什么用两套不同的框架

维度Integration(自研 Harness)Observability(Inspect AI)
交互粒度终端命令级(keystrokes)工具调用级(Function Calling)
环境持久性有状态的 tmux 会话每次工具调用独立
适合场景需要长时间交互的多服务编排需要精确代码修改的 Bug 修复
评分需求需要检查运行中服务的状态需要对比 git diff
社区兼容性Mercor 自研,不兼容其他框架兼容 SWE-bench 生态

第五章 · 评分机制

5.1 Integration:Pytest 三维评分

评分由 TaskEvaluator 执行(源码 evaluator.py),流程:

  1. 在 Docker 容器内查找测试脚本(run-tests.sh / test.sh / verify.sh)
  2. 将测试文件 base64 编码传入容器
  3. 执行测试并捕获输出
  4. 解析输出——支持三种格式:
    • 结构化格式:results starts here → PASSED/FAILED → results ends here
    • Pytest 原生:N passed in X.XXs
    • 正则匹配:=+ FAILED =+

评分维度由 rubric/rubric.json 定义:正确性(输出是否正确)、功能性(功能是否完整)、健壮性(边界情况处理)。

5.2 Observability:F2P/P2P 评分

F2P(Fail-to-Pass):在基线代码上失败,但在应用 golden patch 后通过的测试——Agent 需要让这些测试通过。

P2P(Pass-to-Pass):在基线和修复后都应通过的测试——Agent 的修复不能引入回归。

生成流程(源码 parser/evaluator.py):

1. 运行 test.patch(基线测试) → 记录每个测试结果
2. 运行 test.patch + golden.patch(参考修复) → 记录每个测试结果
3. F2P = 基线 FAIL + 修复后 PASS 的测试 + 修复后新增且 PASS 的测试
4. P2P = 基线 PASS + 修复后 PASS 的测试

Agent 评分:

1. 应用 Agent 的 git diff
2. 应用 test.patch(重置测试文件到已知状态)
3. 执行测试命令
4. 解析输出,与 F2P/P2P 对比
5. 通过条件:所有 F2P 测试 PASS + 所有 P2P 测试 PASS

F2P 结果缓存到 f2p_cache/<task_id>.json,包含 golden.patch 的 SHA-256 hash 用于缓存失效。


第六章 · 执行流程源码级解剖

6.1 Integration 执行流程

multi_step_runner.py 的 run_single_trial() 分 6 个阶段:

Phase 1 — Docker 启动:

  • 从 docker-compose.yaml 启动所有服务
  • 等待所有 healthcheck 通过(最长 800 秒)
  • 注入默认 healthcheck(LocalStack 用 awslocal s3 ls,EspoCRM 用 wget)

Phase 2 — Git 基线 + MCP 配置:

  • 在 /app 初始化 git,创建基线 commit
  • 如果有 MCP 服务,等待 MCP config 就绪(最长 20 分钟)
  • 写入 /config/mcp-required.txt 声明所需 MCP 依赖

Phase 3 — 工具初始化:

  • 创建 ToolExecutor(file + terminal + todo)
  • 创建 TerminalSessionManager(tmux 会话管理)
  • 构建 initial prompt

Phase 4 — Agent 主循环:

while True:
    # 检查超时
    if elapsed > max_timeout: break
    # 检查步数限制
    if step_num > max_steps: break
    # 检查 token 上限(90%)
    if current_tokens > max_tokens * 0.9: raise ConversationTooLongError
    
    # 调用 LLM
    response = llm.call(current_prompt)
    # 执行工具(解析 keystrokes/tool_use/JSON/bash 格式)
    tool_results = tool_executor.parse_and_execute_tools(response)
    # 构建下一轮 prompt(注入终端当前状态)
    current_prompt = build_episode_prompt(terminal_content)
    # 检查完成标记
    if "<task_complete>true</task_complete>" in response: break

Phase 5 — 构建结果

Phase 6 — 评估:

  • git diff --cached HEAD 捕获 agent.patch
  • 执行 TaskEvaluator 运行测试

6.2 Observability 执行流程

eval_runner/runner.py 的流程更简洁(基于 Inspect AI):

# Phase 1: 构建 Agent
tools = [apply_patch(), bash(), read_file(), search_files(), update_plan()]
agent = react(prompt=AgentPrompt(instructions=system_prompt), tools=tools)

# Phase 2: 创建 Inspect AI Task
task = Task(
    dataset=MemoryDataset([sample]),
    solver=agent,
    scorer=unified_scorer(),
    sandbox=("docker", compose_path),
    time_limit=3600,
    message_limit=250,
)

# Phase 3: 执行(Inspect AI 管理 Docker 沙箱生命周期)
eval_results = inspect_eval(tasks=[task], model=model_name)

# Phase 4: 读取 agent.patch + scoring metadata

Inspect AI 负责 Docker Compose 的启动/停止、Agent 循环、工具执行、沙箱隔离——评测框架只需定义 tools 和 scorer。


第七章 · 关键设计决策分析

7.1 为什么 Integration 不用 Inspect AI

Integration 需要持久的终端会话——Agent 可能先 cd /app,然后 pip install requests,再 python3 solution.py,每个命令的效果要在同一个 shell 中累积。Inspect AI 的 bash 工具每次调用是独立的,不保持状态。

自研 Harness 使用 tmux session 解决了这个问题——所有命令在同一个 tmux 窗口中执行,Agent 下一轮能看到完整的终端状态(包括前几步命令的输出)。

7.2 为什么严禁 heredoc

System prompt 中有大段警告:

⚠️⚠️⚠️ CRITICAL - FILE WRITING ⚠️⚠️⚠️ NEVER use heredoc syntax (cat << EOF, cat <<‘EOF’…) as it WILL cause terminal hangs and timeouts!

原因是 tmux 的 send_keys + 阻塞等待模式无法正确处理 heredoc 的多行输入——send_keys("Enter") 会让 tmux 认为命令已执行完毕,但实际上 heredoc 还在等待 EOF 结束符。这会导致终端永久挂起。

7.3 为什么 Observability 用 apply_patch 而不是直接编辑文件

SWE-bench 生态的标准做法是生成 unified diff patch。好处:

  1. 原子性:一个 patch 可以同时修改多个文件
  2. 可追溯:patch 本身就是 diff,不需要额外的 git diff 步骤
  3. 兼容 F2P/P2P:评分系统只需要 git apply agent.patch → 运行测试
  4. LLM 友好:生成 diff 比生成完整文件更节省 token

7.4 干扰项(Distractor Issues)的设计意义

Integration 任务的 Plane 看板中有干扰 issue。这不是为了增加难度,而是模拟真实工作场景中的信息噪声——真实的项目管理工具上永远有无关的 issue,Agent 需要自己判断哪个才是当前任务。

这是 APEX-SWE 相比 SWE-bench 的一个显著改进——SWE-bench 直接把 issue 内容喂给 Agent,没有噪声。

7.5 为什么支持 20+ 模型

从源码 data_models.py 的 ModelType 枚举可以看到,APEX-SWE 支持:

  • Anthropic:Opus 4/4.1/4.5/4.6、Sonnet 4/4.5
  • OpenAI:GPT-4o、GPT-5 系列(5/5.1/5.2/5.3/5.4 + Codex 变体)
  • Google:Gemini 2.5 Pro/Flash、3 Pro、3.1 Pro
  • xAI:Grok 4
  • Meta:Llama 4 Maverick
  • Qwen:Qwen3 Coder 480B
  • DeepSeek:V3P2
  • Kimi:K2/K2P5

通过 LiteLLM 统一接口 + 按模型自动配置 reasoning effort(Anthropic 用 thinking budget,OpenAI/xAI 用 reasoning_effort,Google 用 thinking budget)。


第八章 · 与 SWE-bench / APEX-Agents 的对比

维度APEX-SWESWE-benchAPEX-Agents
任务数502,294 (SWE-bench Verified: 500)480
领域软件工程开源项目 Bug 修复投行/咨询/法律
环境Docker Compose 多服务单容器Docker + MCP Gateway
任务来源真实开源 Bug + 人工设计集成真实 GitHub Issue/PR真实 Google Takeout + 人工设计任务
Agent 工具tmux 终端 + 文件 / Function Calling + BashBash + 文件编辑MCP 工具(9-18 个)
评分Pytest + F2P/P2PF2P/P2PLLM Rubric
可观测性✅ Grafana + Loki + Mattermost❌❌
干扰项✅ Plane 看板噪声❌❌
多服务编排✅(LocalStack/Zammad/CRM/电商/邮件)❌✅(但是 MCP 模拟层)
完全开源✅(50 个任务全部可复现)✅⚠️(452/480 可复现)
最强 Pass@141.5%~49% (Verified)24%

关键差异

APEX-SWE vs SWE-bench:APEX-SWE 增加了 Integration 任务(SWE-bench 只有 Bug 修复)和可观测性栈(SWE-bench 没有日志/监控),但任务数少得多。SWE-bench 的统计力更强(2,294 vs 50),APEX-SWE 的环境复杂度更高。

APEX-SWE vs APEX-Agents:同一个团队的两套基准,但技术栈完全不同。APEX-Agents 用 Archipelago 框架 + Python MCP Server + S3 数据注入,APEX-SWE 用 Docker Compose + 混合语言 MCP Server + 本地文件。APEX-Agents 的 Leaderboard 分数更低(24% vs 41.5%),说明专业服务任务可能比软件工程任务更难。


第九章 · 100% 可复现性

与 APEX-Agents 不同(有 28 个任务因缺少非公开的 FMP/EDGAR Server 无法执行),APEX-SWE 的全部 50 个任务都可以在开源环境中完整复现。原因:

  1. 没有外部 API 依赖:所有服务都是本地 Docker 容器(LocalStack 模拟 AWS,不需要真实 AWS 账号)
  2. 代码库预置:Observability 任务的 repo/ 目录包含完整的开源项目克隆
  3. 数据预导出:Loki 日志、Mattermost 消息、Plane issues 都是预导出的静态数据
  4. Docker 镜像公开:ECR 镜像 public.ecr.aws/k4t1e3r5/apex-code 可直接拉取

唯一需要的外部依赖是 LLM API Key(用于调用被评测的模型)。


第十章 · 数据合成与环境构建启示

10.1 Integration 任务的构建方法论

  1. 选择服务组合:从 8 个可用服务中选取 2-5 个,设计跨服务的数据流
  2. 编写种子数据:issues.json、connection-info.md、API 文档
  3. 实现参考解决方案:solution.py
  4. 编写 Pytest 测试:三维评分(正确性/功能性/健壮性)
  5. 添加干扰项:在 Plane 看板中放入无关 issue

10.2 Observability 任务的构建方法论

  1. 选择真实 Bug:从 GitHub 找已修复的 Issue/PR
  2. 导出可观测性数据:重放 Bug 场景,导出 Loki 日志、模拟 Mattermost 讨论
  3. 提取 golden.patch:从 PR 中提取修复 diff
  4. 编写 test.patch:确保测试能检测 Bug 的存在和修复
  5. 计算 F2P/P2P:运行基线测试 + golden 测试,自动生成

10.3 MCP 作为工具接口标准

APEX-SWE 的 Integration 和 Observability 都使用 MCP 作为 Agent-Service 交互协议,但方式不同:

  • Integration:MCP Server 在容器内运行,通过 /config/mcp-config.txt 配置
  • Observability:Agent 通过 bash 工具手动构造 JSON-RPC 请求发给 MCP Server

这说明 MCP 协议的灵活性——既可以被框架自动集成,也可以被 Agent 手动调用。


附录 · 支持的模型完整列表

Integration Harness

模型Providercontext window
claude-opus-4-6Anthropic1M
claude-opus-4-5-20251101Anthropic200K
claude-sonnet-4-5-20250929Anthropic1M
claude-sonnet-4-20250514Anthropic1M
gpt-5.4OpenAI272K
gpt-5.3 / gpt-5.3-codexOpenAI400K
gpt-5.2 / gpt-5.2-codexOpenAI400K
gpt-5.1-codexOpenAI272K
gemini-3.1-pro-previewGoogle1M
gemini-3-pro-previewGoogle1M
xai/grok-4xAI256K
qwen3-coder-480bFireworks262K
deepseek-v3p2Fireworks164K
kimi-k2 / kimi-k2p5Fireworks128K

Observability Harness

支持相同的模型列表,通过 eval_runner/config.py 的 MODELS 字典配置。默认模型为 claude-opus-4-5。


参考资源

资源链接
论文arXiv 2601.08806
数据集huggingface.co/datasets/mercor/APEX-SWE
评测框架github.com/Mercor-Intelligence/apex-swe
Leaderboardmercor.com/apex/apex-swe-leaderboard
博客mercor.com/blog/introducing-apex-swe