花 3 个月从零写了个 AI Coding Agent,HumanEval 跑出 87.8%,和 GPT-4o 持平

从零构建 AI Agent:6 个让我重新理解"智能体"的工程决策

19K 行 Python,12 家模型商,8 种推理范式,1000+ 测试,HumanEval 87.8%。这不是一篇"我做了个 AI 编程助手"的软文------这是我在构建过程中遇到的 6 个非直觉工程问题,以及为什么标准答案不总是对的。


先看结果

在 HumanEval 基准(164 道 Python 函数补全题)上,OmniAgent 驱动的 deepseek-v4-pro 跑出了 144/164 (87.8%) 的成绩:

对比 HumanEval pass@1
Claude 3.5 Sonnet ~92%
GPT-4o ~90%
OmniAgent + v4-pro 87.8%
GPT-4 ~87%
DeepSeek V3 ~87%
CodeLlama 34B ~56%

但分数只是结果。更值得讲的是:这个 Agent 是怎么设计的。


为什么写这篇文章

2026 年,AI Agent 框架已经多到让人麻木。LangChain、CrewAI、AutoGPT......每个都号称"几行代码搭 Agent"。但当你真正想理解一个 Agent 的内部机制------不是怎么用,而是怎么造------会发现大多数框架把复杂度藏在了抽象层后面。

我花了几个月从零写了一个终端 AI Agent(OmniAgent),不是为了跟 Claude Code 竞争,是为了把 Agent 核心机制做透、看懂。这篇文章分享 6 个关键设计决策。


决策 1:引擎是类,不是 Prompt

直觉做法:切换 Agent 行为 = 换 system prompt。加一句"你要先做计划再执行"就行。

实际问题 :Prompt 只能影响 LLM 输出内容 ,不能改变控制流

ReAct 需要 observe → think → act → observe 循环,Plan-Execute 需要 decompose → topological_sort → parallel_execute → synthesize,Reflection 需要 execute → critic_review → revise → critic_review 双模型多轮。

这三个的代码结构完全不同。把它们压在 prompt 里,等于让 LLM 自己管理控制流------而 LLM 最不擅长的就是保持状态一致性。

bash 复制代码
omniagent/engine/
├── direct_engine.py           # 一条路走到黑
├── react_engine.py            # 循环直到 finish
├── plan_execute_engine.py     # DAG + 拓扑排序
├── reflection_engine.py       # 双模型互审
├── novel_engine.py            # 创意写作专用
├── plan_react_engine.py       # 计划 → ReAct
├── plan_reflection_engine.py  # 计划 → 审查
└── react_reflection_engine.py # ReAct → 审查

每个引擎是独立的类 ,有自己的 run() 方法。切范式不是改 prompt 文本------是 EngineFactory.create(mode) 换一个类。


决策 2:断路器不应该"一次挂、次次挂"

直觉做法:工具调用失败 → 捕获异常 → 返回错误给 LLM → LLM 决定下一步。

实际问题 :LLM 会反复用同样的参数调同一个失败的工具。你见过 LLM 在循环里连续 5 次 read_file("不存在的路径") 吗?我见过。

标准答案是加个重试装饰器。但 Agent 的真正问题是:有些失败是可恢复的(网络抖动),有些是终局性的(文件不存在)。重试机制不分青红皂白统一退避,浪费 token 和时间。

我做的:

ini 复制代码
# 每个工具有独立的断路器实例
breaker = CircuitBreaker(
    failure_threshold=3,      # 3 次连续失败 → 熔断
    cooldown_seconds=30,      # 30s 后进 half_open
    backoff_multiplier=2,     # 再失败冷却翻倍,上限 600s
)

关键不是"熔断"本身------是这个状态跨 LLM 轮次持久化GLOBAL_BREAKERS 字典在 Agent 的整个生命周期存活。


决策 3:上下文压缩不是"取最后 N 条"

直觉做法:对话太长 → 只保留最近 10 条消息。

实际问题 :最近 10 条可能全是工具输出(read_file 返回的 200 行代码),而 15 条之前的 user prompt 才是真正需要的语义信息。

我实现的是 6 步压缩流水线

markdown 复制代码
1. 摘要     → LLM 生成对话摘要
2. 精简     → 工具输出超过 20 行部分用 [N lines truncated] 替换
3. 去重     → 连续相同的工具调用合并为 "[N repeated calls]"
4. 评分     → 按语义密度给每条消息打分
5. 裁剪     → 保留 Top-N 条高分消息
6. 重组     → 摘要 + 裁剪结果拼回 messages 列表

触发条件不是"消息数 > N",而是 Token 窗口达 80%


决策 4:花钱也要分阶段

Agent 在任务尾声还在调 list_filessearch_files------Token 被浪费在无意义的浏览上。

解决:三阶段软预算

阶段 Token 配额 可用工具
EXPLORE 25% 全部 20 个
EXECUTE 50% 全部 20 个
CONVERGE 25% 禁用 7 个纯探索工具

决策 5:MCP 子进程管理不是 subprocess.run

  1. readline() 会无限阻塞
  2. 进程崩溃变僵尸
  3. 守护进程挂了 Agent 不知道

解决:select + 墙钟超时 + terminate() + 兜底 kill()。守护进程崩溃自动重启(最多 3 次)。


决策 6:空输入检测不能只靠 LLM

LLM 有时候会返回:

"我已经完成了任务,文件已更新,代码运行正常。"

------实际什么都没做。HollowDetector 用 15 个正则 + 组合判定来识别空洞回答,靠模式匹配 + 工具调用记录交叉校验。


这些决策的通用性

上面 6 个设计决策不绑定 OmniAgent。无论你用什么框架------LangChain、CrewAI、自研------只要你的 Agent 需要:

  • 多种推理模式 → 把范式差异放在控制流层,不要全压在 prompt 上
  • 可靠执行 → 加断路器,且状态要跨轮次持久化
  • 长对话 → 上下文压缩要按语义密度裁剪,不是简单截断
  • 预算控制 → 分阶段限制可用工具,收束阶段裁掉探索型工具
  • MCP 集成 → 用 select + 超时而不是 readline
  • 输出质量 → 空洞检测基于模式匹配,不要靠 LLM 自检

项目地址

GitHub: github.com/xianyu-shen...

19K 行 Python,MIT 开源,1000+ 测试,HumanEval 87.8%。

如果你也在学习 Agent 架构,欢迎 ⭐Star、读源码、提 issue。

相关推荐
TrisighT2 小时前
Agent 的 JSON 解析崩了三次——拆完 SDK 源码我才搞懂 arguments 为什么是字符串
aigc·agent·ai编程
nopSled2 小时前
AlphaAvatar v0.6.4 架构升级:统一实时感知、RTC 解耦与在线 ENV Memory
人工智能·架构·实时音视频·agent·多模态
chanalbert3 小时前
Agent 工程化指南(二):记忆与规划 — 让 Agent “记得住“且“做得对“
agent·memory·rag·mcp
森叶17 小时前
从 MCP 到扣子:Agent 平台化演化路径
人工智能·大模型·agent·ai agent·mcp
还是转转18 小时前
深入认识 Agent - 构建简单的 Agent 框架
ai·agent·函数调用
Z-D-K1 天前
AI对Anthropic的J-space的分析(1)
ai·aigc·人机交互·agent·agi
沉默王二1 天前
Hy3 + WorkBuddy = 国产顶级 Agent(附完整提示词)。
agent·ai编程·腾讯
不好听6131 天前
MCP Resources:让 AI Agent 拥有"知识库"
agent
浮生望1 天前
MCP 协议:打破工具围墙,让 AI Agent 跨语言跨进程调用任意工具
agent·mcp