【Harness Agent】源码剖析(二):Core Engine 与 Steering——Agent Loop 的源码级实现
【Harness Agent】 源码剖析二Core Engine 与 Steering——Agent Loop 的源码级实现写在前面第一篇我们俯瞰了 Harness Agent 的五层架构和五阶段 Agent Loop。今天我们深入最核心的子系统——Core Engine 与 Steering。Core Engine 是 Harness 的心脏负责驱动 Agent Loop 的每一次心跳Steering 是 Harness 的方向盘确保长会话中 Agent 不偏离轨道。这两个系统解决的是 Coding Agent 最棘手的两个工程问题如何让 Agent 在长时间运行中保持高效如何让 Agent 在上下文爆炸时保持清醒理解了它们你就理解了 Harness 为什么能在 Harness-Bench 上得分 100%。 文章目录 一、Core Engine四层配置层级 二、三种 WorkflowExecution / Thinking / Compaction 三、Steering事件驱动的行为引导 四、Context 组装条件提示词组合管道️ 五、Compaction渐进式上下文压缩 六、系列预告 一、Core Engine四层配置层级1.1 为什么需要四层Harness 的核心架构是一个Session → Agent → Workflow → LLM的四层配置层级。这不是过度设计——它是解决一个真实工程问题的必要抽象不同的认知任务需要不同的模型能力、延迟和成本。考虑一个 Coding Agent 的典型场景规划任务“这个 bug 怎么修”需要强推理能力适合用 Claude Sonnet执行工具“读取文件内容”需要快速响应适合用 GPT-4o压缩上下文“总结旧对话”只需要便宜模型用 GPT-4o-mini 就够了。如果只用一个模型你要么在规划时用便宜模型质量差要么在压缩时用贵模型浪费钱。四层配置层级让每种 Workflow 独立选择模型各取所长。1.2 四层详解层级职责核心文件配置示例Session一次完整的用户交互会话core/session.pysession_id,project_rootAgent会话中的子 AgentInitializer/Coderagents/manager.pyagent_type,allowed_toolsWorkflowAgent 中的工作流Execution/Thinking/Compactioncore/engine.pyworkflow_type,model_bindingLLM具体的模型调用providers/model_name,api_key1.3 源码映射# core/session.py — 会话层classSession:session_id:stragents:list[Agent]# 包含多个子 Agentcontext:Context# 共享上下文memory:Memory# 跨会话记忆# agents/manager.py — Agent 层classAgentManager:defcreate_agent(self,agent_type:str)-Agent:# 根据 agent_type 创建 Initializer 或 Coder# 每个 Agent 有自己的工具集和提示词# core/engine.py — Workflow 层classEngine:defrun_workflow(self,workflow_type:str,agent:Agent):# 根据 workflow_type 选择 Execution/Thinking/Compaction# 每种 Workflow 独立绑定 LLMmodelself.config.get_model(workflow_type)returnself.execute(model,agent.context)1.4 Compound AI System 的核心价值四层配置层级的核心价值体现在四个方面成本优化——Thinking 用 Claude Sonnet贵但强Compaction 用 GPT-4o-mini便宜但够用延迟优化——Execution 用快速模型Thinking 用慢速但更准确的模型能力优化——规划任务用强模型执行任务用快模型各取所长模型无关——切换模型只需改配置不需要改任何代码。 二、三种 WorkflowExecution / Thinking / Compaction2.1 Execution Workflow——干活模式Execution 是默认的工作流对应标准的 ReAct 循环LLM 接收上下文 → 决定是否调用工具 → 执行工具 → 返回结果。这是 Agent 大部分时间所处的工作模式。关键特征拥有完整的工具访问权限读写文件、执行命令、搜索代码直接与外部环境交互每次工具调用都经过沙箱安全检查结果追加到上下文继续循环。适用场景读取文件、编辑代码、运行测试、执行 Shell 命令——所有动手的操作都在 Execution 中完成。2.2 Thinking Workflow——思考模式当 Agent 遇到复杂任务时会切换到 Thinking Workflow。这个模式的核心思想是先想清楚再动手。在 Thinking 模式下Agent 只有只读工具权限不能修改任何文件或执行任何命令。关键特征只有只读工具权限read_file, search_code, list_dir强制 LLM 先推理再行动可选的自我批评Self-Critique阶段——LLM 审视自己的计划找出漏洞输出一个结构化的执行计划交给 Execution Workflow 执行。适用场景理解复杂代码库、规划多步骤重构、分析 bug 根因——所有动脑的操作都在 Thinking 中完成。2.3 Compaction Workflow——压缩模式当上下文接近 Token 上限时Agent 自动切换到 Compaction Workflow。这个模式用便宜模型总结旧对话历史释放 Token 空间给新的交互。关键特征使用便宜模型如 GPT-4o-mini降低成本渐进式压缩——只压缩旧历史保留最近 N 轮完整对话压缩后注入 Task Context Reminder防止 LLM 丢失当前任务目标压缩结果替换旧历史上下文长度大幅缩减。适用场景长时间运行的会话、上下文超过模型 Token 限制——所有清理的操作都在 Compaction 中完成。2.4 Workflow 切换逻辑三种 Workflow 之间的切换不是随意的而是由 Engine 根据明确的条件触发Execution 遇到复杂任务时切换到 ThinkingThinking 完成规划后切换回 Execution上下文超过阈值时切换到 CompactionCompaction 完成后切换回 Execution。这个切换逻辑定义在core/engine.py中是整个 Agent Loop 的调度中心。 三、Steering事件驱动的行为引导3.1 Instruction Fade-Out 问题长时间运行的 Agent 会遇到一个致命问题Instruction Fade-Out指令遗忘。初始系统提示词在上下文中的位置越来越远LLM 的注意力逐渐衰减开始偏离原始指令。比如你告诉 Agent修复 issue #42但经过 20 轮工具调用后Agent 可能已经忘了自己在修什么 bug开始做无关的事情。3.2 Harness 的解法事件驱动 System ReminderHarness 的 Steering 机制不是简单地把系统提示词写得更长——而是在关键决策点注入针对性提醒。这些提醒是事件驱动的只在特定条件触发时才注入触发事件注入的 Reminder目的工具调用前安全策略提醒“不要删除 .git 目录”上下文压缩后任务上下文提醒“你正在修复 issue #42”迭代超过 N 次停止条件提醒“已尝试 10 次考虑换策略”文件修改后测试提醒“修改后请运行测试”进入 Thinking 模式规划提醒“先理解代码再动手”3.3 为什么事件驱动优于静态提示词静态提示词的问题是它总是存在于上下文中无论是否需要。这浪费了宝贵的 Token 预算而且长提示词本身也会导致注意力稀释。事件驱动 Reminder 的优势在于在需要的时候注入在不需要的时候不占空间。这就像一个好的教练——不是在比赛前把所有战术都喊一遍而是在关键时刻喊出最关键的提醒。 四、Context 组装条件提示词组合管道4.1 提示词不是一坨很多人以为系统提示词就是一大段文本塞给 LLM 就完事了。但 Harness 的提示词是一个条件组合管道——由多个独立的 Section 按优先级组装而成每个 Section 只在满足条件时才加载。4.2 组合管道的四个阶段阶段一Base Prompt——始终加载的基础指令包含 Agent 身份、核心行为准则、工具使用规范。这是宪法不可省略。阶段二Conditional Sections——按需加载的条件指令包含项目特定规则、语言偏好、代码风格要求。这些 Section 有优先级排序高优先级的先加载Token 不够时低优先级的被裁剪。阶段三Event Reminders——事件驱动的动态提醒由 Steering 系统在运行时注入。这些提醒是临时的只在当前决策步骤有效。阶段四Tool Schemas——工具的 JSON Schema 描述告诉 LLM 有哪些工具可用。Harness 使用懒加载工具发现——只加载当前 Agent 需要的工具 Schema不加载全部工具。4.3 懒加载工具发现Harness 定义了大量工具文件读写、Shell 执行、代码搜索、LSP 集成等但不是所有工具都需要同时暴露给 LLM。懒加载工具发现的核心逻辑是Initializer Agent 只加载只读工具 SchemaCoder Agent 加载全部工具 SchemaThinking Workflow 只加载只读工具 SchemaCompaction Workflow 不加载任何工具 Schema。这大大减少了提示词中的 Token 占用让 LLM 的注意力更集中。️ 五、Compaction渐进式上下文压缩5.1 上下文爆炸是不可避免的Coding Agent 的上下文增长速度远超普通聊天一次文件读取可能消耗数千 Token一次工具调用的结果可能更长。一个典型的编程会话10 轮交互后上下文就可能超过 50K Token。如果不压缩模型要么截断旧上下文丢失重要信息要么直接报错超过 Token 限制。5.2 Harness 的渐进式压缩Harness 的 Compaction 不是一刀切的截断而是渐进式压缩——保留最近 N 轮完整对话用便宜模型总结更早的历史。具体步骤如下Step 1检测阈值。Engine 在每次循环后检查上下文长度。如果超过阈值如 100K Token触发 Compaction Workflow。Step 2分割上下文。将上下文分为两部分最近 N 轮保留原样和更早的历史待压缩。Step 3LLM 压缩。用便宜模型如 GPT-4o-mini总结旧历史生成一个压缩摘要。摘要保留关键决策、文件修改记录、错误信息丢弃冗余的工具输出和中间结果。Step 4注入 Reminder。压缩后注入 Task Context Reminder防止 LLM 丢失当前任务目标。回到 Execution Workflow 继续执行。5.3 与 OpenClaw Memory Flush 的对比Harness 的 Compaction 和 OpenClaw 的 Memory Flush 解决的是同一个问题但策略不同OpenClaw 在压缩前让 LLM 将重要信息写入 Markdown 文件文件优先Harness 在压缩时让便宜模型总结旧历史摘要优先。OpenClaw 的优势是记忆可读、可编辑、可 Git 追踪Harness 的优势是压缩更彻底、Token 节省更多、不需要额外的文件系统依赖。 六、系列预告第三篇也是最后一篇我们将拆解 Harness Agent 的沙箱安全与工具生态核心问题沙箱的六阶段 Shell 执行管道是怎么工作的命令白名单和文件系统限制如何防止破坏性操作MCP 协议集成如何扩展 Agent 的工具能力Skills 技能系统如何实现懒加载和自动发现审计日志如何实现全链路追溯关注我不要错过最终篇 总结速查卡Core Engine 核心概念概念一句话解释四层配置Session → Agent → Workflow → LLM每层独立配置Execution干活模式完整工具权限标准 ReAct 循环Thinking思考模式只读权限强制推理可选自我批评Compaction压缩模式便宜模型总结旧历史释放 Token 空间Steering事件驱动 System Reminder对抗 Instruction Fade-Out条件提示词多 Section 按优先级组装按需加载不浪费 Token懒加载工具只加载当前 Agent/Workflow 需要的工具 Schema三种 Workflow 速查Workflow工具权限模型选择触发条件Execution全部读写执行快速模型默认模式Thinking只读强推理模型复杂任务Compaction无便宜模型上下文超阈值一句话总结Harness 的 Core Engine 用四层配置层级实现了 Compound AI System——不同 Workflow 绑定不同模型成本、延迟、能力各取所长。Steering 用事件驱动 System Reminder 对抗遗忘——在关键决策点注入针对性提醒而非依赖初始提示词。Compaction 用渐进式压缩对抗上下文爆炸——便宜模型总结旧历史保留最近 N 轮完整对话。条件提示词组合管道确保提示词按需加载不浪费 Token 预算。这三个系统共同解决了 Coding Agent 最棘手的工程问题如何在长时间运行中既高效又清醒。参考链接Harness Agent GitHub 仓库Building AI Coding Agents for the Terminal (arXiv:2603.05344)The Anatomy of an Agent Harness (LangChain Blog)Context Management in Agent Harnesses (Arize)