LeetCode Agent Lab - 项目概述与架构
GitHub: leetcode-coder-agent
项目简介
LeetCode Agent Lab 是一个围绕 LeetCode 算法解题 搭建的工程化 Agent 系统。它不是简单的"调 API 生成代码",而是一套完整的工程链路:从题目拉取、代码生成、本地测试、代码审查、沙箱执行,到在线提交和对比实验,全部打通。
项目提供了两种 Agent 架构:
- 多智能体系统(Multi-Agent):5 个专业化 Agent 协作,Solver 生成代码 → Reviewer 审查 → TestAgent 扩展测试 → ScoreAgent 评分 → NoteWriter 总结沉淀
- 单 ReAct Agent:一个 Agent 通过 ReAct 循环自主调用工具,完成解题全流程
为什么做这个项目
这个项目的出发点不是追求 LeetCode 通过率(说实话,Agent 的通过率和 baseline 持平,甚至预算更高),而是从零搭建一套完整的 Agent 工程链路,深入理解:
- 工具模块怎么设计才能解耦、可扩展
- 沙箱执行怎么做才能安全隔离
- 多 Agent 协作怎么编排、协议怎么定义
- Agent 的可观测性怎么实现(日志、指标、事件追踪)
- Baseline 和 Agent 的对比实验怎么做
开发过程中踩了不少坑,也做了多次迭代:日志模块一开始没考虑,调试时才发现只靠断点效率极低;工具模块最初构想很简单,后来参考了成熟方案逐步完善;Agent 架构也经历了 Planner+ReAct → 六状态机 → 单 ReAct 循环的三版迭代。
技术栈
| 层级 | 技术 |
|---|---|
| 语言 | Python 3.13, Conda 环境 |
| 数据模型 | Pydantic v2(从 dataclass 迁移) |
| 日志 | structlog + JSONL + SQLite 事件存储 |
| Web UI | Streamlit 6 页工作台,遗留 Flask API |
| LLM 集成 | OpenAI Python SDK,兼容 DashScope / Ollama |
| Agent 架构 | 多 Agent 协作 + 单 Agent ReAct 循环 |
| 执行安全 | nsjail 沙箱 / process 降级 / 降级策略 |
| 测试 | Pytest + conftest + parametrize + polyfactory |
| 构建 | setuptools, pyproject.toml |
项目结构
leetcode-coder-agent/
├── src/
│ ├── multi_agent/ # 多 Agent 主业务(5 个 Agent 协作)
│ ├── react_agent/ # 单 ReAct Agent(工具调用循环)
│ ├── tool_executor/ # 统一工具基础设施(6 层架构)
│ ├── execution/ # 代码执行沙箱(nsjail/process)
│ ├── core/ # LeetCode 平台集成(拉题/提交)
│ ├── activity_log/ # 结构化日志(structlog + SQLite)
│ ├── benchmark/ # 对比实验(baseline vs agent)
│ └── webui/ # Streamlit Web 工作台
├── tests/ # 测试(镜像 src 结构)
├── templates/ # 算法模板库(16 类 ~128 个模板)
├── data/test/ # 基准测试题目集
├── examples/problems/ # 示例题目 JSON
├── docs/ # 项目文档
└── pyproject.toml # 项目配置8 大子包职责
| 子包 | 作用 |
|---|---|
multi_agent/ | 多 Agent 编排:Solver / Reviewer / TestAgent / ScoreAgent / NoteWriter |
react_agent/ | 单 ReAct Agent:工具调用、局部自修复、在线提交闭环 |
tool_executor/ | 工具注册、路由、执行编排、@tool_method 装饰器 |
execution/ | 沙箱执行(nsjail / process)、对拍、shell 工具、workspace 工具 |
core/ | LeetCode GraphQL 拉题、HTML 归一化、测试用例提取、在线提交 |
activity_log/ | 结构化日志:EventLogger、span 上下文、SQLite 事件存储 |
benchmark/ | baseline / agent 批量实验、指标聚合、报告生成 |
webui/ | Streamlit 6 页工作台 + Flask API |
快速开始
1. 环境准备
# 创建 Conda 环境
conda create -y -n leetcode-coder-agent python=3.13 pip
conda activate leetcode-coder-agent
# 安装项目
cd leetcode-coder-agent
pip install -e '.[dev]'2. 配置环境变量
cp .env.multi_agent.example .env.multi_agent
cp .env.react_agent.example .env.react_agent常见配置(以 Ollama 本地模型为例):
LLM_API_KEY=ollama
LLM_BASE_URL=http://localhost:11434/v1
LLM_MODEL_ID=qwen3-coder-next:latest3. 运行
# 多 Agent 单题
multi-agent --env-file .env.multi_agent run --problem examples/problems/two_sum.json --backend openai
# 单 ReAct Agent 单题
react-agent --env-file .env.react_agent run --problem examples/problems/two_sum.json --backend openai
# Web 工作台
streamlit run src/webui/streamlit_app.py --server.port 17890
# Baseline 对比实验
benchmark --env-file .env.react_agent run-suite --problems data/test --output-dir output/benchmark题目数据格式
项目使用 JSON 格式定义题目:
{
"slug": "two-sum",
"title": "Two Sum",
"description": "Given an integer array nums and an integer target...",
"function_name": "two_sum",
"signature": "def two_sum(nums: list[int], target: int) -> list[int]:",
"constraints": ["2 <= nums.length <= 10^4", "-10^9 <= nums[i] <= 10^9"],
"tests": [
{"input": {"nums": [2, 7, 11, 15], "target": 9}, "expected": [0, 1]},
{"input": {"nums": [3, 2, 4], "target": 6}, "expected": [1, 2]}
]
}设计原则
项目的几条核心设计原则:
1. 子包自治。 每个 src/ 子包有自己的 __init__.py 公共接口、内部结构、README 和对应测试目录。包之间通过接口通信,不直接访问内部实现。
2. 协议先行。 所有 Agent 输出强制携带 schema_version: "v1",写入时严格校验,读取时宽松兼容。协议层集中管理在 protocols/ 中。
3. 工具与业务分离。 tool_executor 是独立的工具基础设施层,Agent(无论是 multi_agent 还是 react_agent)都通过它调用工具,不直接耦合具体实现。
4. 安全执行。 代码执行走沙箱(nsjail),沙箱不可用时可以降级到 process,但可以通过 fail_on_degrade 策略阻止静默降级。
5. 全链路可观测。 从 LLM 调用、工具执行到沙箱运行,每一步都有结构化日志(structlog + JSONL + SQLite),支持按 run_id 追踪完整执行链路。
写在后面
这个项目做下来,最大的收获不是 Agent 的解题效果,而是对 Agent 工程化的全链路理解。从协议设计到工具路由,从沙箱安全到可观测性,每个环节都有大量工程细节需要处理。
说实话,Agent 解 LeetCode 题目这件事本身还是挺难的。LLM 生成的代码经常在边界条件上翻车,多 Agent 协作的 token 开销也远超预期。但正是这些"不完美",让我对 Agent 的能力边界有了更清醒的认知。
项目源码:leetcode-coder-agent