第1章-HarnessEngineering概述与理论基础《从0到1实现一个企业级harness平台》
第1章:Harness Engineering 概述与理论基础
本书定位:《从0到1实现一个企业级 harness 平台:自进化超级智能体 Agent Harness Engineering 理论框架与开发实战》
本章目标:建立 Harness Engineering 的完整理论框架,理解"缰绳"隐喻的哲学与技术起源,掌握 Control-Agency-Runtime 三元框架本体论,并能动手搭建最小可运行的 Harness 原型。
阅读建议:第1.1-1.3节为理论基础,建议仔细阅读以建立心智模型;第1.4节为数学形式化定义,可选择性阅读;第1.5-1.6节为实践背景;第1.7节为动手实践,务必跟随代码操作。
1.1 "缰绳"隐喻的哲学与技术起源
1.1.1 一个不可回避的问题
2024至2025年间,AI Agent 技术经历了爆炸式发展。从 LangChain 到 AutoGPT,从 CrewAI 到 MetaGPT,从 OpenAI 的 Assistants API 到 Anthropic 的 Claude Agent SDK,工程师们以惊人的速度构建了各式各样的 Agent 系统。然而,在这些令人眼花缭乱的创新背后,一个根本性问题始终悬而未决:
为什么90%以上的 Agent 原型永远无法进入生产环境?
这个问题的答案不在于模型能力不足——GPT-4 和 Claude 4 已经展示了远超大多数业务场景所需的推理能力;也不在于工具生态不成熟——Function Calling、MCP(Model Context Protocol)、工具注册机制已经相当完备。答案在于一个更根本的层面:我们缺少一个系统性的框架来在"放任自主"和"刚性管道"之间找到平衡点。
这正是 Harness Engineering 要解决的核心问题。
1.1.2 "缰绳"隐喻的三层含义
“Harness"一词在英文中同时具有动词和名词的双重含义。作为名词,它指马具——骑手用来引导马匹的缰绳、鞍具和挽具系统;作为动词,它指"利用、驾驭”——将自然力量转化为可控能量。这个隐喻恰好捕捉了 AI Agent 治理的核心张力:
第一层:缰绳不是笼子(Harness is not a Cage)
一个常见的误解是将 Agent 控制等同于"限制"。许多企业将 Agent 包裹在层层审批和硬编码规则中,结果 Agent 退化成了传统工作流引擎——丧失了其最核心的价值:面对不确定性的自主推理能力。
一个好的缰绳系统允许马匹在安全边界内自由奔跑。同样,一个好的 Harness 系统允许 Agent 在定义好的决策空间内自主发挥。控制的目的不是消除自主性,而是为自主性创造一个安全的"运动场"。
第二层:缰绳不是放养(Harness is not Free-Range)
与"过度控制"相对的另一极端是"完全放任"。早期的 AutoGPT 就代表了这种思路:给 Agent 一个目标,让它自由使用互联网、文件系统和代码执行环境。结果呢?Agent 往往陷入无限循环、资源耗尽、或者偏离原始目标(这种现象后来被正式称为"任务漂移",我们将在第2章详细讨论)。
完全放任的 Agent 就像一个未经训练的马匹在闹市中狂奔——危险且不可预测。
第三层:缰绳是结构化引导(Harness is Structured Guidance)
"缰绳"隐喻的精髓在于:控制不是目的,引导才是。一个优秀的骑手通过缰绳向马匹传递的不仅是"停"和"走"的指令,更是方向、节奏和意图的微妙信号。在 Harness Engineering 中,这意味着:
- 方向引导:通过目标恒常器(Goal Invariant)确保 Agent 不会偏离任务方向
- 节奏控制:通过预算和速率限制(Rate Limiting)确保 Agent 不会耗尽资源
- 意图传递:通过意图注入(Intent Injection)将人类偏好和约束自然融入 Agent 的决策过程
- 异常处置:当 Agent 遇到未知情况时,提供结构化的降级路径而非直接崩溃
1.1.3 历史演进:四代范式变迁
要理解 Harness Engineering 为什么是 Agent 发展的必然阶段,我们需要回顾 AI Agent 控制范式的发展历程。
年代 范式 核心思想 典型代表 核心弱点
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2022 提示词工程 通过精心设计的Prompt引导LLM行为 少样本提示/思维链 行为不稳定,缺乏运行时控制
(Prompt Engineering) (Few-Shot/CoT)
2023 链式工程 将多个LLM调用组合成有向无环图 LangChain/LlamaIndex 刚性管道,无法应对不确定性
(Chain Engineering) (DAG),实现复杂多步任务 /Semantic Kernel 和意外情况
2023- 智能体框架 赋予LLM使用工具和自我反思的能力 AutoGPT/AgentGPT/ 自主性高但可控性低,
2024 (Agent Frameworks) (Tool Use + Self-Reflection) BabyAGI/CrewAI 容易失控和漂移
2024- Harness工程 在保留Agent自主性的前提下,通过 Harness Engineering 仍在发展中,本书目标
至今 (Harness Engineering) Control-Agency-Runtime三元框架 (本书定义和实现) 是给出完整方案
实现系统化的运行时治理
第一阶段:提示词工程(2022)
Prompt Engineering 是 AI Agent 控制的起点。工程师通过精心设计的提示词(Prompt)来引导 LLM 的行为:
# 提示词工程时代的典型做法
prompt = """
你是一个数据分析助手。请按照以下步骤处理用户请求:
1. 首先,理解用户的意图
2. 然后,列出需要的数据
3. 最后,给出分析建议
注意:
- 不要执行任何实际的文件操作
- 不要访问外部API
- 如果问题超出你的能力范围,请明确告知用户
用户请求:{user_query}
"""
这种方法的根本局限在于:它只能"建议"LLM如何行为,而无法"强制"约束。LLM 可能忽视这些指令(特别是在复杂对话中),而且在运行时没有任何机制来检测和纠正行为偏差。
第二阶段:链式工程(2023)
Chain Engineering 将 LLM 调用组织为有向无环图(DAG),通过硬编码的流程控制来确保执行顺序:
# LangChain 时代的典型模式
from langchain.chains import SequentialChain
from langchain.prompts import PromptTemplate
# 硬编码的链式流程
chain = SequentialChain(
chains=[
analyze_intent_chain, # 第1步:分析意图(必须)
retrieve_context_chain, # 第2步:检索上下文(必须)
generate_response_chain, # 第3步:生成回复(必须)
validate_output_chain, # 第4步:验证输出(必须)
]
)
Chain Engineering 解决了"执行顺序失控"的问题,但引入了新的限制:刚性管道无法应对不确定性。如果第2步的检索失败,整个链条就断裂了——缺乏优雅的降级机制。更重要的是,链条中的每一步都是被动的、无决策能力的,无法根据中间结果动态调整策略。
第三阶段:智能体框架(2023-2024)
Agent Frameworks 赋予 LLM 主动使用工具和思考的能力。典型的模式是 ReAct(Reasoning + Acting):
# ReAct 循环的伪代码
while not task_complete and iterations < max_iterations:
thought = llm.think(observation_history)
action = llm.decide_action(thought, available_tools)
observation = execute_tool(action)
observation_history.append(thought, action, observation)
这种模式释放了 LLM 的自主能力,但也暴露了致命的弱点:
- 无限循环:Agent 陷入"思考→行动→观察→思考"的死循环
- 任务漂移:Agent 在探索过程中偏离原始目标
- 资源耗尽:无限制的 API 调用和工具使用导致成本失控
- 不可预测性:相同的输入可能产生截然不同的执行路径
这些问题不是个别框架的实现缺陷,而是"纯自主Agent"范式固有的结构性缺陷。
第四阶段:Harness 工程(2024至今)
Harness Engineering 代表了一种新的范式,它的核心洞察是:
控制和自主不是对立的两极,而是同一个系统的两个维度。控制定义了"可以在哪里奔跑",自主定义了"在这个空间内如何奔跑"。两者不是此消彼长的关系,而是互相增强的——更好的控制带来更大的安全自主空间,更大的自主空间需要更好的控制来守护边界。
这个洞察的直接技术表达就是 Control-Agency-Runtime 三元框架,我们将在第1.3节详细阐述。
1.1.4 为什么"失控"和"僵化"是同一个问题的两面
一个关键的认识是:Agent 的"失控"(过度自主)和"僵化"(过度控制)不是两个独立的问题,而是同一个结构性问题——缺乏动态、上下文感知的治理机制——的两种表现。
完全失控 ←────────────────→ 完全僵化
(AutoGPT) (传统工作流)
│ │
│ Harness Engineering │
│ 动态平衡区间 │
│ ┌───┐ │
└─────────┤ H ├────────────┘
└───┘
控制-自主 最优平衡点
随上下文动态变化
动态治理意味着:对于低风险任务(如查询天气),系统应给予 Agent 更大的自主空间;对于高风险任务(如修改数据库Schema),系统应施加更严格的控制。这就是"缰绳松紧度"的概念——一种根据任务上下文动态调节的控制力度。
1.1.5 Harness Engineering 的定义
综合以上分析,我们给出 Harness Engineering 的正式定义:
Harness Engineering(缰绳工程) 是一种系统性方法论,用于设计和实现 AI Agent 的运行时治理系统。其核心目标是在保留 Agent 面对不确定性的自主推理能力的同时,通过**Control(控制)、Agency(能动性)、Runtime(运行时)**三个正交维度的协同工作,确保 Agent 行为始终保持在安全、高效、可审计的区间内。
简单来说:Harness Engineering 是让 Agent 从"实验室玩具"走向"生产级系统"的工程化桥梁。
1.2 从提示词工程到Harness工程的范式迁移
1.2.1 四种范式的深度对比
为了更精确地理解 Harness Engineering 的定位,我们从以下维度对四种范式进行系统对比:
| 维度 | 提示词工程 | 链式工程 | Agent框架 | Harness工程 |
|---|---|---|---|---|
| 控制粒度 | 粗粒度(文本建议) | 细粒度(硬编码流程) | 粗粒度(目标+边界) | 多粒度(动态可调) |
| 自主程度 | 低(被动响应) | 极低(无自主决策) | 高(自主探索) | 可控(受约束的自主) |
| 运行时干预 | 无 | 无(仅异常退出) | 少数框架有(如超时) | 核心能力(全生命周期) |
| 异常处理 | LLM自行处理 | 硬编码fallback | LLM自行处理或卡死 | 结构化降级路径 |
| 可审计性 | 低 | 中(DAG可追踪) | 低(路径不可预测) | 高(全链路事件溯源) |
| 资源管控 | 无 | 无 | 少数有Token限制 | 三维配给系统 |
| 安全性 | 依赖LLM自觉 | 依赖代码逻辑 | 依赖LLM自觉 | 多层防线(沙箱+审查) |
| 可组合性 | 低 | 中(DAG可组合) | 中(Agent可组合) | 高(统一Mount接口) |
| 生产就绪度 | 低 | 中 | 低-中 | 高(设计目标) |
| 学习曲线 | 低 | 中 | 中-高 | 中-高 |
| 适用场景 | 简单对话任务 | 固定流程任务 | 探索性任务 | 企业级生产任务 |
1.2.2 生产环境困境:90%原型无法上线的根因分析
让我们深入分析为什么90%的 Agent 原型无法进入生产环境。这个数字并非凭空估计——根据 LangChain State of AI Agents Report 2024、Google Cloud Agent 调查报告等多个来源的综合数据,以及笔者在实际项目中观察到的现象,可以归纳为以下五个根因:
根因一:行为不可预测(占比约35%)
原型 Agent 在相同的输入下,可能因为 LLM 的一次随机采样而产生截然不同的行为。这在原型阶段或许可以接受(“我们再试一次”),但在生产环境中不可接受(“客户的订单被错误取消了”)。
Harness Engineering 的解决方案:
- 通过控制层定义行为的"合法空间"(Permissibility Space),任何超出此空间的行为都会被拦截
- 通过审计日志记录完整的决策链路,即使发生意外也能追溯根因
根因二:资源消耗失控(占比约25%)
原型 Agent 没有资源预算概念。一个"简单"的查询可能触发数十次 LLM 调用、数百次工具调用,导致成本远超预期。更有甚者,Agent 可能陷入无限循环,持续消耗资源直到系统管理员介入。
Harness Engineering 的解决方案:
- 三维配给系统:Token 预算 + API 调用次数 + 壁钟时间
- 当预算耗尽时,Agent 被强制进入"结果生成"阶段,基于当前已有信息产出最佳结果
根因三:错误传播与级联故障(占比约20%)
在链式 Agent 系统中,前一个步骤的错误会传播到后续步骤,导致"一步错、步步错"。而且大多数框架缺少错误恢复机制,一旦某个工具调用失败,整个任务就可能半途而废。
Harness Engineering 的解决方案:
- 异常处置中的自主降级:当一个工具失败时,Agent 可以在决策空间内寻找替代路径
- 重规划机制:严重失败时触发任务重规划,而非直接崩溃
根因四:安全与合规风险(占比约12%)
原型 Agent 可能执行危险的操作(删除文件、修改数据库、对外发送数据),而缺乏有效的安全防护。
Harness Engineering 的解决方案:
- 操作分级制度:读取/创建/修改/删除,每级对应不同的审批和审计要求
- 执行沙箱:高风险操作在隔离环境中执行
- 输出审查:Agent 产出在发送给用户前经过安全审查
根因五:可观测性缺失(占比约8%)
原型 Agent 通常是一个"黑箱"——输入问题、等待输出,中间发生了什么完全不可知。当出现问题(如"为什么 Agent 给出了这个错误回答?"),缺乏工具来追溯和分析。
Harness Engineering 的解决方案:
- 全链路事件溯源:记录每一次思考、每一次工具调用、每一次状态变更
- 可视化审计追踪:将事件日志转化为可读的执行轨迹图
- 问题回放:基于事件日志重建任意历史时刻的系统状态
1.2.3 范式迁移的必然性:四个驱动力
从提示词工程到 Harness 工程的范式迁移不是偶然的,而是由以下四个深层驱动力推动的:
驱动力一:从"演示"到"生产"的需求升级
2022-2023年,Agent 项目的主要目标是"展示可能性"——证明 AI 能够自主完成复杂任务。到了2024-2025年,目标已经转变为"在生产环境中持续创造价值"。这一转变对系统的可靠性、安全性和可维护性提出了质的要求。
驱动力二:从"单次调用"到"持续会话"的交互模式变化
早期的 LLM 应用是"问-答"模式的单次调用。现代 Agent 系统需要维护跨越数小时甚至数天的持续会话,期间 Agent 需要记住上下文、维护状态、协调多个子任务。这种持续会话模式要求系统具备状态管理、会话控制和生命周期管理能力——这正是 Harness Runtime 的核心职责。
驱动力三:从"人工监督"到"自主运行"的信任模型演进
原型阶段,Agent 的每次重大行动都需要人类确认。但生产环境中,人类不可能监督 Agent 的每一次决策——那样就失去了使用 Agent 的意义。让 Agent 在无人监督的情况下安全运行,需要系统化的治理机制而非"人类兜底"。
驱动力四:从"单Agent"到"多Agent系统"的复杂性跃升
企业级场景通常涉及多个 Agent 协作完成任务。多 Agent 系统引入的复杂性(如通信协议、角色分工、资源争用、冲突消解)远远超出了任何单个 Agent 框架的处理能力。Harness Engineering 从设计之初就考虑了多 Agent 场景(详见第9章)。
1.2.4 Harness Engineering 作为"从实验室到生产的桥梁"
总结这一节的讨论,Harness Engineering 的核心价值主张可以浓缩为一句话:
Harness Engineering = Agent 框架 + 系统化运行时治理 = 从实验到生产的工程化桥梁
它不是要替代现有的 Agent 框架,而是在它们之上增加一个治理层——就像操作系统不替代应用程序,而是为应用程序提供执行环境、资源管理和安全保障一样。Harness 为 Agent 提供了一个结构化的"运行环境",让 Agent 可以专注于"做什么",而 Harness 负责确保"做得安全、做得高效、做得可审计"。
1.3 Control-Agency-Runtime 三元框架本体论
Control-Agency-Runtime 三元框架是 Harness Engineering 的核心理论基础。本节将从本体论(Ontology)的角度深入分析这三个维度的本质、职责和相互关系。
1.3.1 三元框架的基本结构
三元框架的基本命题是:任何一个能够安全、高效运行的 AI Agent 系统,都必须同时具备三个正交的能力维度。这三个维度不是功能模块(module),而是本体论属性(ontological attributes)——它们是 Agent 系统"存在"的必备条件,缺失任何一个维度都会导致系统的不完整。
Control(控制)
/ 合法空间定义 \
/ 预算管理 \
/ 审计反馈 \
/______________________\
/ \
/ Harness System \
/ 三元协同空间 \
Agency \____________________________/ Runtime
(能动性)\ /(运行时)
决策空间 \ / 事件循环
意图注入 \ / 状态空间
人格持久 \ / 统一接口
优雅降级 \ / 生命周期
三个维度之间的关系可以用以下原则概括:
Runtime 是载体(Carrier),Control 是势能面(Potential Surface),Agency 是运动体(Moving Entity)。Runtime 提供了 Agent 存在的时空容器;Control 在这个容器中定义了"可行驶区域"的势能面(边界=无限高势垒);Agency 在这个势能面上运动,寻找从起点到目标的最优路径。
1.3.2 Control 层:合法空间的守护者
Control 层回答的问题是:Agent 可以做什么?不可以做什么?在什么条件下可以做什么?
Control 层的本质是定义一个"合法行为空间"(Permissible Behavior Space),并确保 Agent 的所有行为都在这个空间之内。它不是传统的"权限检查"(那个属于安全层),而是一种更广义的"行为治理"——不仅包括"能不能",还包括"花多少个Token值不值得"、“当前目标是否还在正确方向上”。
Control 层包含四个核心子维度:
子维度一:可许性控制(Permissibility Control)
可许性控制定义了 Agent 行为的合法边界。它的核心数据结构是行为状态机(Behavior State Machine):
┌──────────┐
start ─────>│ IDLE │
└────┬─────┘
│ receive_task
v
┌──────────┐
│ THINKING │──────────────┐
└────┬─────┘ │ timeout/exhaustion
│ decide_action │
v v
┌──────────┐ ┌──────────┐
┌────>│ EXECUTING│ │DEGRADING│
│ └────┬─────┘ └────┬─────┘
│ │ action_done │ fallback
│ v v
│ ┌──────────┐ ┌──────────┐
└─────│OBSERVING │ │REPORTING │
└────┬─────┘ └────┬─────┘
│ observation │ done
v v
┌──────────┐ ┌──────────┐
│ THINKING │ │ IDLE │
└──────────┘ └──────────┘
每个状态定义了在该状态下允许的操作集合。例如,IDLE 状态只允许接收任务(不允许执行工具);DEGRADING 状态只允许执行降级路径中的操作(不允许重新开始探索)。
子维度二:预算控制(Budget Control)
预算控制是三维配给系统,管理 Agent 的资源消耗:
| 维度 | 含义 | 典型值 | 超出时行为 |
|---|---|---|---|
| Token Budget | LLM调用的Token总量限制 | 输入100K+输出10K | 强制进入REPORTING状态 |
| API Budget | 工具调用次数上限 | 50次 | 禁止新Action,仅允许Report |
| Time Budget | 壁钟时间上限 | 5分钟 | 触发Graceful Degradation |
三维预算之间存在联动关系:如果 Token 预算消耗很快但时间预算充裕,可能意味着 Agent 陷入了"过度思考"的模式,需要控制层介入调整。
子维度三:对齐控制(Alignment Control)
对齐控制通过目标恒常器(Goal Invariant)监控 Agent 是否偏离原始任务方向。目标恒常器是一个在每次 THINKING 阶段运行的检查器:
原始目标 ─────> [目标恒常器] ─────> 当前行为
│
├── 一致(通过)
├── 扩展(Agent发现了相关的子任务,允许)
└── 偏离(Agent跑偏了,介入纠正)
目标恒常器的实现可以使用语义相似度检查(将当前行为描述与原始目标进行嵌入相似度比较),或使用规则+LLM混合判断(将在第2章详述)。
子维度四:审计反馈(Audit Feedback)
审计反馈形成了控制的闭环。每次操作都被记录(谁、什么时间、做了什么、为什么做、结果如何),这些记录不仅用于事后追溯,更重要的是形成反馈信号——如果审计日志显示某个类型的操作频繁出问题,控制层可以动态收紧该类操作的可许性范围。
1.3.3 Agency 层:受约束的自主体
Agency 层回答的问题是:在给定的控制边界内,Agent 如何自主地思考和行动?
如果说 Control 层定义了"游戏规则",Agency 层就是在规则内"玩游戏"的玩家。Agency 层的核心设计挑战是:如何在受限的空间内保留足够的自主性,使 Agent 仍然能够发挥 LLM 的创造性推理能力?
Agency 层包含四个核心子维度:
子维度一:结构化决策空间(Structured Decision Space)
Agency 层的决策不是无限制的"想做什么就做什么",而是在一个结构化的空间中进行的。这个空间由以下要素组成:
决策空间 = {
目标: "为Q3销售数据生成分析报告",
上下文: [数据库Schema, 历史报告模板, 用户偏好],
可用工具: [SQL查询, 图表生成, 文本总结, 文件写入],
约束: [不要修改数据, Token预算剩余8K, 剩余时间3分钟],
策略: [先理解数据结构 → 再设计查询 → 最后生成报告]
}
在这个空间内,Agent 使用 ReAct(Reasoning+Acting)或更高级的 ToT(Tree of Thoughts)策略进行自主推理。但从 Harness 的角度看,这些"自主"过程始终在约束框架内运行——就像足球运动员在球场边界内展示创造力一样。
子维度二:意图注入(Intent Injection)
意图注入是 Harness 系统向 Agent 传递偏好和约束的机制。与传统 Prompt Engineering 中的"注意事项"不同,意图注入是结构化的、可解析的,并且会根据运行时的控制状态动态调整:
// 意图注入的结构化表示
interface IntentInjection {
// 安全约束(硬性,不可违反)
hardConstraints: {
forbiddenActions: string[]; // 禁止的操作
requiredApprovals: string[]; // 需要审批的操作
dataAccessBoundary: string[]; // 可访问的数据范围
};
// 偏好引导(软性,强烈建议)
preferences: {
preferredTools: string[]; // 优先使用的工具
communicationStyle: string; // 沟通风格
fallbackBehavior: string; // 异常时的默认行为
};
// 运行时状态(动态注入)
runtimeContext: {
budgetRemaining: Budget; // 剩余预算
timeRemaining: number; // 剩余时间(秒)
taskProgress: number; // 任务进度(0-1)
recentErrors: Error[]; // 最近的错误列表
};
}
子维度三:优雅降级与重规划(Graceful Degradation & Replanning)
当 Agent 在执行过程中遇到无法继续的情况时(工具失败、预算耗尽、时间不足),Agency 层负责优雅降级而非直接崩溃。降级分为三个级别:
| 级别 | 触发条件 | 行为 |
|---|---|---|
| Level 1: 工具替换 | 当前工具执行失败 | 在可用工具集中寻找功能相似的工具替代 |
| Level 2: 路径替换 | 当前执行路径走不通 | 保持目标不变,寻找新的执行路径 |
| Level 3: 目标降级 | 原始目标在当前条件下不可达成 | 将目标降级到可达成的最接近版本 |
重规划(Replanning)发生在 Level 2 和 Level 3 降级时。重规划不是"从头开始",而是基于已有的执行历史和当前状态,生成一条新的执行路径。
子维度四:身份连续性(Identity Continuity)
在长会话中,Agent 需要保持一致的"人格"和行为模式。身份连续性通过以下机制保证:
- 人格快照:定期将 Agent 的行为偏好和决策模式持久化
- 记忆检索:在每次决策前,检索相关的历史决策和经验
- 一致性检查:检测当前行为是否与已建立的行为模式一致
1.3.4 Runtime 层:存在的容器
Runtime 层回答的问题是:Agent 在什么环境中运行?状态如何管理?生命周期如何控制?
如果说 Control 和 Agency 定义了 Agent 行为的"规则"和"策略",Runtime 就是整个过程发生的"空间和时间"。Runtime 层提供了 Agent 系统最基础的"存在条件"。
Runtime 层包含四个核心子维度:
子维度一:事件循环(Event Loop)
Harness Runtime 采用事件驱动架构,而非传统的链式调用。这不仅是架构选择,更是一种哲学:Agent 的行为不是预定义的静态图,而是在运行时动态展开的事件序列。
事件循环 = {
事件源: [用户输入, 工具响应, 超时信号, 控制层指令, Agent自身消息],
事件队列: PriorityQueue<Event>,
事件处理器: {
USER_MESSAGE: → 注入到Agent的观察历史,
TOOL_RESPONSE: → 传递给Agent的ReAct循环,
TIMEOUT: → 触发超时处理/降级流程,
CONTROL_COMMAND: → 修改控制参数/暂停/恢复/终止,
AGENT_MESSAGE: → 发送到外部(用户/其他Agent),
},
事件循环频率: 根据负载动态调节(高负载时提高频率)
}
事件循环是比 ReAct 循环更高一层的抽象。ReAct 循环(Thought → Action → Observation)是 Agent 内部的工作方式;事件循环是 Harness Runtime 的工作方式。每个 ReAct 步骤都引起事件在 Runtime 中流动和处理。
子维度二:状态空间管理(State Space Management)
Harness Runtime 维护两种互补的状态:
Agent状态 = 可变工作状态 + 不可变事件日志
│ │
│ └── Event Sourcing(事件溯源)
│ 完整记录所有决策和行动
│ 可以回溯到任何历史时刻
│
└── Work State(工作状态)
当前任务、会话上下文、临时计算结果
高频更新、低延迟访问
不可变事件日志采用 Event Sourcing 模式(将在第8章详述),可变工作状态采用常规的键值存储。两者互补:事件日志用于审计、回溯和状态重建,工作状态用于快速决策。
子维度三:统一马具接口(Unified Mount Interface)
Harness Runtime 通过统一的 Mount Interface 连接 Agent 和外部世界(工具、数据源、服务)。这个接口的设计灵感来自 Unix 的 mount 概念——一切皆文件,一切皆挂载点:
┌─────────────────┐
│ Agent 运行环境 │
├─────────────────┤
│ Unified Mount │ ← 统一接口:Agent只看到这个接口
│ Interface │
├────┬────┬───┬───┤
│ DB │API │FS │Web│ ← 底层适配器:将异构后端映射为统一接口
└────┴────┴───┴───┘
每个挂载点(Mount Point)提供四个标准操作:
interface MountPoint {
mountId: string;
// 标准操作
describe(): Promise<ResourceDescription>; // 资源描述
invoke(params: InvocationParams): Promise<InvocationResult>; // 调用
stream(params: StreamParams): AsyncIterator<StreamChunk>; // 流式调用
release(): Promise<void>; // 释放资源
}
子维度四:生命周期管理(Lifecycle Management)
Runtime 提供 Agent 的完整生命周期管理:
生命周期状态:
CREATE → INITIALIZE → READY → (RUN → PAUSE → RUN → ...) → TERMINATE
│ │
└────────────────────────────────────────────────────────────┘
完整状态转换记录
每个生命周期转换都伴随状态保存和恢复机制(Suspend/Resume),确保 Agent 可以被"暂停"(比如因为更高优先级的任务需要资源)、然后"恢复"(回到暂停前的状态继续执行)。
1.3.5 三元协同的动态模型
三个维度不是孤立的,它们之间存在紧密的协同关系。我们将这种协同关系称为三元张力平衡(Triadic Tension Balance):
Control: "管得太死,Agent变成傀儡"
↕ ↕
过严 ←── 三元张力平衡 ──→ 过松
↕ ↕
Agency: "没有空间发挥创造力" "失去方向、角色混乱"
↕ ↕
Runtime: "过度审计、性能下降" "黑箱运行、无法追溯"
三元协同在两个层面上运作:
层面一:显式协同(Explicit Coordination)——通过 Harness DSL(第6章)明确定义三个维度的配置
层面二:隐式协同(Implicit Coordination)——通过事件循环中的消息传递实现维度间的动态交互
例如,Runtime 检测到 Token 消耗速度异常时,会通过事件向 Control 层发送信号,Control 层收紧预算限制,Agency 层接收到新的预算约束后调整决策策略——这一切在事件循环中自动完成,无需外部干预。
1.4 Harness Engineering的形式化定义与数学基础
1.4.1 为什么需要形式化
在进入代码实现之前,我们首先需要为 Harness Engineering 建立一套精确的形式化定义。这不仅仅是理论的"锦上添花"——形式化定义有以下实用价值:
- 精确性:消除自然语言描述的歧义,确保实现不偏离设计
- 可验证性:提供系统属性(如安全性、有界性)的形式化证明基础
- 可复现性:让不同的实现者可以独立验证其系统是否符合 Harness Engineering 规范
- 可扩展性:为元控制(第12章)和自动化调优提供数学基础
重要说明:本节含有数学定义,但每个公式都会附有通俗解释。如果你对形式化方法不感兴趣,可以直接跳到1.4.7节阅读"给工程师的总结",不影响理解后续章节。
1.4.2 核心定义:Harness 系统的四元组表示
一个 Harness 系统 H 可以形式化地表示为一个四元组:
H = (C, A, R, Φ)
其中:
- C:Control 层(控制状态空间)
- A:Agency 层(能动性配置空间)
- R:Runtime 层(运行时执行空间)
- Φ:协同函数(Synergy Function),定义了 C、A、R 三者之间的相互作用
用更详细的集合论语言:
H = (C, A, R, Φ)
其中:
C = (S_c, Σ_c, δ_c, c_0) —— 控制自动机
S_c: 控制状态集合
Σ_c: 控制事件字母表
δ_c: S_c × Σ_c → S_c —— 控制状态转移函数
c_0: 初始控制状态
A = (D, P, I, G) —— 能动性空间
D: 决策空间(可用工具、策略、知识的集合)
P: 规划函数 P: Task × D → Plan
I: 意图注入函数 I: C × R → Intent
G: 降级函数 G: Failure × State → Plan'
R = (E, Q, M, L) —— 运行时空间
E: 事件集合(所有可能的事件类型)
Q: 状态空间(运行时状态的集合)
M: 挂载点集合(可用资源的集合)
L: 生命周期模型 L: AgentId → LifecycleState
Φ: C × A × R → C' × A' × R' —— 协同函数
通俗解释:Harness 系统由控制、能动性、运行时三个部分组成,外加一个"协同函数"描述它们如何相互作用。控制像一个状态机,定义了"什么情况下允许做什么";能动性像一个工具箱+决策引擎,定义了"在允许的范围内,怎么做最好";运行时像一个容器,定义了"整个游戏在什么样的时空环境中进行"。协同函数确保三者步调一致——当一方变化时,其他方也随之调整。
1.4.3 状态空间的形式化定义
Harness 系统的全局状态空间 S 是所有满足约束的状态的集合:
S = { s | satisfies(s, constraints) }
其中 s 是一个复合状态,包含控制状态、Agency 状态和运行时状态:
s = (s_c, s_a, s_r)
其中:
s_c ∈ S_c: 当前控制状态(如 IDLE, THINKING, EXECUTING)
s_a ∈ S_a: 当前Agency状态(如当前计划、已执行步骤、决策历史)
s_r ∈ S_r: 当前运行时状态(如事件队列、资源使用量、挂载点状态)
constraints 是一组状态不变量(State Invariants):
∀s ∈ S: constraints(s) == true
状态不变量是一些必须始终保持为真的条件。例如:
约束1(安全不变式): s_c ∈ 危险状态 ⇒ s_a.决策能力被限制
"当控制层判定当前状态危险时,Agency层的能力必须被限制"
约束2(资源不变式): s_r.tokenConsumed ≤ s_c.tokenBudget
"Token消耗量不得超过控制层设定的预算"
约束3(一致性不变式): s_a.currentTask ⊆ s_c.allowedTasks
"当前执行的任务必须是控制层允许的任务之一"
通俗解释:状态空间不是"所有可能的状态",而是"所有合法的状态"。合法由一组不变量定义——这些不变量就像物理定律,在系统运行的每一刻都必须成立。如果一个状态转移会违反不变量,这个转移就被阻止。
1.4.4 状态转移函数
在约束条件下,Harness 系统的状态转移函数 δ 定义为:
δ: S × Action → S’
且满足: s’ = δ(s, action) 当且仅当 satisfies(s’, constraints)
这意味着:只有当结果状态 s’ 满足所有约束(不变量)时,转移才被允许。
状态转移的具体形式取决于当前的控制状态:
δ((s_c, s_a, s_r), action) =
if s_c == IDLE and action.type == RECEIVE_TASK:
→ (THINKING, init_agency_state(action.task), record_event(s_r, action))
if s_c == THINKING and action.type == DECIDE_ACTION:
→ (EXECUTING, update_plan(s_a, action.decision), s_r)
if s_c == EXECUTING and action.type == TOOL_RESULT:
→ (OBSERVING, add_observation(s_a, action.result), update_mount(s_r, action))
// ... 其他转移规则
通俗解释:状态的改变遵循"先检查再执行"的规则。每次 Agent 想要做某件事(action),系统先计算做这件事之后的状态是什么样(s’),再检查这个新状态是否满足所有安全约束。满足就执行,不满足就拒绝并记录。
1.4.5 从范畴论视角看 Harness
对于有兴趣深入理论层面的读者,我们可以从范畴论(Category Theory)的角度理解 Harness Engineering。范畴论提供了一种高度抽象的数学语言,能够揭示不同范式之间的结构关系。
基础范畴定义:
范畴 Agent: 对象 = Agent状态, 态射 = Agent行为
范畴 Process: 对象 = 工作流状态, 态射 = 流程步骤
范畴 Harness: 对象 = Harness系统状态, 态射 = Harness治理行为
Harness 作为自然变换:
Harness Engineering 可以看作从 Agent 范畴到 Harness 范畴的一个自然变换(Natural Transformation):
如果 F: Agent → Harness 是"加缰绳"的函子
G: Agent → Harness 是"加沙箱"的函子
那么 Harness Engineering 定义的治理机制 η 是一个自然变换:
η: F ⇒ G
满足自然性条件: 对任意 Agent 行为 f: s → s'
治理(f) ∘ F(s) = G(s') ∘ 治理(初始)
通俗解释(你不需要懂范畴论!):这个形式化说的是——无论你先"加缰绳"再"让Agent执行",还是"让Agent执行"再"加沙箱",最终的效果应该是一致的(即自然性条件)。这保证了治理机制与 Agent 的行为是"相容的"而非"冲突的"——治理不会因为Agent行为的顺序不同而产生不同的结果。
1.4.6 关键定理(非形式化陈述)
基于上述形式化定义,我们可以陈述几个 Harness Engineering 的关键定理(这里给出非形式化版本,形式化证明将在后续章节展开):
定理1:有界自主性定理
在 Harness 系统中,Agent 的自主行为空间始终是有界的。即:∀s ∈ S, ∃B(s) 使得从状态 s 出发的所有可能转移都在有限范围内。
定理2:控制单调性定理
控制层可以单调地收紧或放松约束,而不会导致系统进入不一致状态。即:如果将控制约束 c₁ 替换为更严格的 c₂,系统仍能正常运行(可能效能降低但不会崩溃)。
定理3:降级完备性定理
对于任意可预见的失败模式 f,Harness 系统定义了至少一条降级路径从 f 到达某个合法终止状态。
定理4:三元正交性定理
C(控制)、A(能动性)、R(运行时)三个维度在功能上是正交的——修改一个维度的配置不会强制修改另外两个维度的配置(但协同函数Φ可能会自动调整以达到最优平衡)。
1.4.7 给工程师的总结
如果你对数学不感兴趣,只需要记住以下几点:
- Harness = 控制 + 能动性 + 运行时 + 协同,四者缺一不可
- 状态转移必须满足约束(不变量),就像物理世界必须满足能量守恒定律
- 三个维度正交但协同,意味着你可以独立配置每个维度,但系统会自动协调
- 形式化定义保证了安全性不是"尽力而为"而是"数学上的必然"
这些形式化原则将贯穿本书的所有实现。每当我们实现一个 Harness 组件时,都会回到这些基本原则来验证设计的正确性。
1.5 与现有Agent框架的对比分析
理解 Harness Engineering 与现有 Agent 框架的关系,是正确使用和评估 Harness 系统的前提。本节将从多个维度对比 Harness Engineering 与 LangChain、AutoGPT、CrewAI、MetaGPT 等主流框架。
1.5.1 框架概览
在深入对比之前,先简要介绍各框架的核心定位:
LangChain
- 定位:LLM 应用开发框架
- 核心抽象:Chain(链式调用)、Agent(ReAct循环)、Tool(工具抽象)、Memory(记忆管理)
- 优势:生态丰富、文档完善、快速原型开发
- 弱点:抽象层过多、生产部署困难、运行时控制薄弱
AutoGPT
- 定位:自主 AI Agent
- 核心抽象:自治循环(自主思考→计划→执行→观察)
- 优势:自主性强、社区活跃、探索性任务表现出色
- 弱点:可控性差、资源消耗大、行为不可预测
CrewAI
- 定位:多Agent协作框架
- 核心抽象:Crew(Agent组)、Task(任务)、Process(协作流程)
- 优势:角色分工清晰、任务委派机制、易于上手
- 弱点:缺少系统级控制、单点故障风险、审计能力弱
MetaGPT
- 定位:SOP驱动的多Agent框架
- 核心抽象:Role(角色)、Action(行动)、Message(消息)、SOP(标准操作流程)
- 优势:SOP驱动(结构化流程)、角色建模精细、输出质量高
- 弱点:SOP刚性(难以处理非标准情况)、无运行时治理、学习曲线陡
1.5.2 12维度对比矩阵
以下对比从12个维度对五个系统进行系统性评估(评分1-5,5为最优):
| 维度 | LangChain | AutoGPT | CrewAI | MetaGPT | Harness Engineering |
|---|---|---|---|---|---|
| 运行时行为控制 | 2 | 1 | 2 | 2 | 5 |
| 自主智能程度 | 3 | 5 | 4 | 3 | 4 |
| 资源管理 | 2 | 1 | 2 | 2 | 5 |
| 异常处理 | 2 | 2 | 2 | 3 | 5 |
| 可审计性 | 3 | 2 | 2 | 3 | 5 |
| 安全防护 | 2 | 1 | 2 | 3 | 5 |
| 多Agent支持 | 2 | 1 | 5 | 5 | 5 |
| 可扩展性 | 4 | 3 | 3 | 3 | 5 |
| 生产就绪度 | 3 | 1 | 2 | 3 | 5 |
| 学习曲线 | 4 | 3 | 4 | 2 | 3 |
| 社区与生态 | 5 | 4 | 3 | 3 | 1 |
| 生产实践验证 | 4 | 1 | 2 | 2 | 1 |
重要说明:Harness Engineering 的"社区与生态"和"生产实践验证"评分较低,是因为它目前还是一个新兴的理论框架(本书的目标正是填补这个空白)。其他评分反映了 Harness Engineering 的设计目标,而非已有成果。
1.5.3 深入分析:每个框架的"阿喀琉斯之踵"
LangChain:抽象泄漏(Abstraction Leakage)
LangChain 最大的问题不是缺少什么功能,而是"太多抽象层"。一个简单的 RAG 查询需要经历:DocumentLoader → TextSplitter → Embeddings → VectorStore → Retriever → Chain → … 当任何一个环节出错时,开发者需要穿越层层抽象才能定位问题根源。这种现象被称为"抽象泄漏"。
Harness Engineering 的应对思路:扁平化架构。Harness Runtime 的事件循环和 Mount Interface 提供了更直观的抽象——“一切皆事件"和"一切皆挂载点”,开发者只需要理解这两个核心概念即可。
AutoGPT:自主性的代价
AutoGPT 将 LLM 的自主性发挥到了极致,但这恰恰也是它最大的弱点。在无约束的环境下,AutoGPT 常常表现出"AI失控"的症状:
典型失控模式:
1. 无限探索:Agent发现一个有趣的线索,偏离原始任务去探索
2. 资源黑洞:一个"简单"任务触发50+次LLM调用
3. 自我欺骗:Agent在循环中产生幻觉,认为已完成任务
4. 目标膨胀:Agent不断扩展任务范围,永远无法完成
Harness Engineering 的应对思路:受约束的自主性。通过目标恒常器检测任务漂移,通过三维预算防止资源黑洞,通过控制状态机阻止无限循环。
CrewAI:多Agent协作的结构性缺陷
CrewAI 在多Agent协作方面表现出色,但它缺少一个关键的能力:系统级的缰绳。每个 Agent 在 CrewAI 中可以有自己的 Role 和 Goal,但没有一个更高层级的机制来确保整个 Agent 组的协作保持在正确的轨道上。
CrewAI 的协作模式:
Agent1(Role: 研究员) → Agent2(Role: 分析师) → Agent3(Role: 撰稿人)
潜在问题:
- 如果研究员提供了有偏见的信息,后续Agent会基于偏见继续工作
- 如果分析师使用了错误的模型,撰稿人会产出错误的报告
- 没有机制在"整个链条"层面检测和纠正错误
Harness Engineering 的应对思路:群组缰绳(Group Harness)。在多Agent场景中,每个Agent有自己的局部Harness,同时整个Agent组有一个更高层级的Global Harness,负责跨Agent的协调、质量控制和冲突消解(详见第9章)。
MetaGPT:SOP的刚性困境
MetaGPT 创新地将软件工程中的 SOP(标准操作流程)引入 Agent 系统,定义了ProductManager → Architect → Engineer → QA 的固定协作流程。这种确定性在生产常规任务时表现出色,但在面对非常规、探索性任务时显得僵化。
MetaGPT的SOP:
PM需求文档 → 架构师技术设计 → 工程师编码实现 → QA测试验证
困境场景:
- 如果PM的需求文档有重大遗漏(非标准项目)
- 架构师发现了遗漏但SOP要求"基于需求文档设计"
- 工程师发现了架构问题但SOP要求"基于设计文档编码"
- QA发现问题大量返工,但SOP没有定义"返工流程"
Harness Engineering 的应对思路:动态SOP。Harness DSL(第6章)允许定义条件化的SOP——根据任务特征和运行时状态动态选择合适的流程模板,而非使用固定的单一SOP。
1.5.4 Harness Engineering 的差异化价值主张
综合以上分析,Harness Engineering 与现有框架的关系是互补而非替代:
┌───────────────────────────────────────┐
│ Harness Engineering │ ← 治理层(本书实现)
│ Control | Agency | Runtime 协同 │
├───────────────────────────────────────┤
│ LangChain │ AutoGPT │ CrewAI │ │ ← Agent框架层(已有)
│ (工具编排) │ (自主探索) │(多Agent)│ │
├───────────────────────────────────────┤
│ LLM API (OpenAI / Anthropic / ...) │ ← 模型层
└───────────────────────────────────────┘
Harness Engineering 不取代 LangChain 的 Chain 抽象、AutoGPT 的自主循环、CrewAI 的角色分工——它提供一个治理层,让这些框架在安全的轨道上运行。
1.5.5 何时选择 Harness Engineering
| 场景 | 推荐方案 | 原因 |
|---|---|---|
| 快速原型验证 | LangChain / AutoGPT | 开发速度快,无治理需求 |
| 固定流程自动化 | MetaGPT | SOP模式最匹配 |
| 探索性研究任务 | AutoGPT | 需要最大自主性 |
| 多Agent简单协作 | CrewAI | 轻量级角色分工 |
| 生产级Agent系统 | Harness Engineering | 需要系统化治理 |
| 企业级多Agent平台 | Harness + CrewAI/MetaGPT | 治理层+协作层 |
| 高风险自动化决策 | Harness Engineering | 安全性和可审计性优先 |
1.6 企业级Harness平台的架构全景图
1.6.1 总体架构
在进入具体实现之前,我们先从"上帝视角"预览整个企业级 Harness 平台的架构全景。这套架构将在本书的后续章节中逐步实现和完善。
┌──────────────────────┐
│ 用户 / API 层 │
│ (Web UI / REST API / │
│ WebSocket / IM机器人) │
└───────────┬────────────┘
│
┌───────────▼────────────┐
│ Gateway 网关层 │
│ (认证/鉴权/限流/路由/ │
│ 请求-任务转换) │
└───────────┬────────────┘
│
┌─────────────────────────────▼─────────────────────────────┐
│ Harness Core(核心引擎) │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Control 层 │ │ Agency 层 │ │ Runtime 层 │ │
│ │ │ │ │ │ │ │
│ │ • 状态机引擎 │ │ • 决策空间 │ │ • 事件循环 │ │
│ │ • 预算管理器 │◄─┼─►• 意图注入器 ├──┤ • 状态管理 │ │
│ │ • 目标恒常器 │ │ • 规划引擎 │ │ • 挂载管理 │ │
│ │ • 审计记录器 │ │ • 降级管理器 │ │ • 生命周期 │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │ │
│ └─────────┬───────┴─────────┬───────┘ │
│ │ │ │
│ ┌─────────▼──────────────────▼──────────┐ │
│ │ Synergy Engine(协同引擎) │ │
│ │ 三元张力平衡调度 / 自适应参数调节 │ │
│ └──────────────────┬────────────────────┘ │
└────────────────────────────┼───────────────────────────────────┘
│
┌────────────────────────────▼───────────────────────────────────┐
│ Harness DSL 层 │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌────────────┐ │
│ │ DSL解析器 │ │ DSL编译器 │ │ 配置验证 │ │ 热加载引擎 │ │
│ └───────────┘ └───────────┘ └───────────┘ └────────────┘ │
└────────────────────────────┬───────────────────────────────────┘
│
┌────────────────────────────▼───────────────────────────────────┐
│ 工具与资源层 │
│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │ API │ │ DB │ │ FS │ │ Web │ │Code │ │Shell│ │MCP │ ...│
│ │适配器│ │适配器│ │适配器│ │适配器│ │适配器│ │适配器│ │适配器│ │
│ └──┬──┘ └──┬──┘ └──┬──┘ └──┬──┘ └──┬──┘ └──┬──┘ └──┬──┘ │
│ │ │ │ │ │ │ │ │
│ └───────┴───────┴───────┴───────┴───────┴───────┘ │
│ │ │
│ Unified Mount Interface(统一马具接口) │
└──────────────────────────────────────────────────────────────────┘
│
┌────────────────────────────▼───────────────────────────────────┐
│ 基础设施层 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │
│ │ Docker/K8s│ │ 数据库集群 │ │ 消息队列 │ │ 监控/告警堆栈 │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────────┘ │
└──────────────────────────────────────────────────────────────────┘
1.6.2 各层职责详解
Gateway 网关层
Gateway 是所有外部请求的入口。它的核心职责包括:
| 功能 | 说明 | 对应章节 |
|---|---|---|
| 认证与鉴权 | 验证用户身份和权限(API Key / OAuth / Session Token) | 第11章 |
| 速率限制 | 基于用户、任务类型、系统负载的动态限流 | 第2章 |
| 请求路由 | 将用户请求路由到正确的 Harness Core 实例 | 第4章 |
| 请求-任务转换 | 将人类语言请求解析为结构化的 Task 对象 | 第6章 |
| WebSocket 管理 | 维护与前端/IM的实时双向通信 | 第4章 |
Harness Core 核心引擎
这是整个平台的"大脑",包含四个核心组件:
-
Control 层引擎(第2章):
- 行为状态机:管理 Agent 的行为阶段(IDLE/THINKING/EXECUTING/OBSERVING/DEGRADING/REPORTING)
- 预算管理器:三维预算(Token/API调用/壁钟时间)的实时监控和动态调整
- 目标恒常器:检测 Agent 是否偏离原始任务目标
- 审计记录器:全链路操作的不可变记录
-
Agency 层引擎(第3章):
- 决策空间:为 Agent 提供结构化的"选项菜单"
- 意图注入器:将控制约束和用户偏好注入 Agent 的推理上下文
- 规划引擎:生成和管理任务执行计划(支持 ReAct、ToT、Plan-and-Execute 等策略)
- 降级管理器:在异常情况下选择和执行降级路径
-
Runtime 层引擎(第4章):
- 事件循环:驱动整个系统的核心循环(接收事件→分发→处理→产生新事件)
- 状态管理器:维护可变工作状态和不可变事件日志
- 挂载管理器:管理统一 Mount Interface 的注册、发现和生命周期
- 生命周期管理器:Agent 实例的创建/初始化/运行/暂停/恢复/终止
-
Synergy Engine 协同引擎(第5章):
- 三元张力平衡调度器:协调 Control-Agency-Runtime 三者的动态平衡
- 自适应参数调节器:根据运行时指标自动调优控制参数
- 行为张力检测器:发现和预警三元失衡的状况
Harness DSL 层
DSL(Domain-Specific Language)层是"配置即治理"思想的实现(第6章):
- DSL 解析器:将 YAML/JSON 格式的 Harness 描述文件解析为可执行的配置对象
- DSL 编译器:将配置对象编译为 Control、Agency、Runtime 三层的初始化参数
- 配置验证器:在编译前验证 DSL 的完整性和一致性
- 热加载引擎:支持运行时动态加载/更新 Harness 配置,无需重启
工具与资源层
工具与资源层提供了 Agent 与外部世界的连接(第7章):
- 统一马具接口(Unified Mount Interface):所有外部资源的抽象层,提供
describe/invoke/stream/release四个标准操作 - 适配器模式:每个类型的资源(API、数据库、文件系统、浏览器、代码执行器、Shell、MCP Server)通过适配器映射到统一接口
- 热插拔工具注册:支持运行时动态添加/移除工具适配器
- 资源生命周期管理:连接池管理、垃圾回收、超时回收
基础设施层
平台运行的基础(第11章):
- 容器编排(Docker/Kubernetes)
- 数据持久化(SQLite/PostgreSQL + 文件系统)
- 消息队列(用于Agent间通信和异步任务)
- 监控/告警/日志(Prometheus + Grafana + Pino)
1.6.3 数据流全景
一次完整的 Agent 任务执行在架构中的流动路径:
步骤1: 用户意图输入
User → Gateway → 请求解析为 Task 对象
步骤2: DSL 解析与编译
Task → DSL Parser → DSL Compiler → Harness配置(Control+Agency+Runtime参数)
步骤3: Harness 初始化
Harness配置 → HarnessCore.init() → 创建 Control/Agency/Runtime 实例 → Synergy Engine 启动
步骤4: 事件循环启动(Runtime 主导)
Runtime.startEventLoop()
├── 加载任务上下文和意图注入
├── 初始化工具挂载点
└── 进入事件循环
步骤5: 事件循环主循环(反复执行直到终止条件满足)
while (未达到终止条件):
event = Runtime.getNextEvent() # 从优先级队列取事件
Control.checkPermissibility(event) # Control 层检查行为合法性
if (允许):
result = Agency.process(event) # Agency 层处理(ReAct/规划/执行)
Runtime.recordEvent(result) # 记录到事件日志
Control.updateBudget(result) # 更新预算消耗
SynergyEngine.adjustIfNeeded() # 协同引擎检查是否需要调整参数
else:
Agency.degradeOrReplan(event) # 被拒绝时触发降级或重规划
步骤6: 结果输出
Agent完成(或降级终止) → Runtime.generateReport() → Gateway → User
步骤7: 审计归档
完整事件日志 → AuditStore → 可用于回溯/分析/优化
1.6.4 部署拓扑
企业级 Harness 平台的典型部署拓扑:
┌──────────┐
│ 负载均衡器 │ (Nginx/HAProxy/Traefik)
└─────┬─────┘
│
┌───────────────┼───────────────┐
│ │ │
┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐
│Harness实例1│ │Harness实例2│ │Harness实例N│ ← 水平扩展
│(主节点) │ │(工作节点) │ │(工作节点) │
└─────┬─────┘ └─────┬─────┘ └─────┬─────┘
│ │ │
└───────────────┼───────────────┘
│
┌─────────────────────┼─────────────────────┐
│ │ │
┌───▼────┐ ┌─────────▼──┐ ┌─────────▼──────┐
│ 数据库 │ │ 文件存储 │ │ 消息队列 │
│(SQLite/ │ │ (事件日志/ │ │ (Agent间通信/ │
│Postgres)│ │ 配置/DSL) │ │ 异步任务分发) │
└─────────┘ └────────────┘ └────────────────┘
每个 Harness 实例是一个独立的进程,通过共享的数据库和消息队列协调工作。实例之间的任务分配由负载均衡器通过一致哈希(基于任务ID)来决定,确保同一个会话的请求总是路由到同一个实例。
1.7 实践:搭建开发环境与最小Harness原型
理论知识已经建立,现在是时候将其转化为可运行的代码了。本节将手把手带你搭建开发环境,并实现一个约500行的最小Harness原型。这个原型将包含Control-Agency-Runtime三元框架的所有核心机制,是你理解和验证Harness Engineering概念的最佳起点。
1.7.1 开发环境准备
系统要求:
| 组件 | 版本要求 | 用途 |
|---|---|---|
| Node.js | >= 22.0.0 | 运行时环境 |
| npm | >= 10.0.0 | 包管理器 |
| TypeScript | >= 5.5.0 | 类型安全 |
| Python | >= 3.12.0 | LLM调用和仿真验证 |
| Git | >= 2.40.0 | 版本控制 |
步骤1:创建项目目录并初始化
# 创建项目根目录
mkdir harness-engine && cd harness-engine
# 初始化 npm 项目
npm init -y
# 安装 TypeScript 及类型定义
npm install --save-dev typescript @types/node tsx
# 安装运行时依赖
npm install zod uuid
# 创建目录结构
mkdir -p src/{control,agency,runtime,synergy,dsl,tools,storage,types}
mkdir -p tests
mkdir -p examples
步骤2:配置 TypeScript
创建 tsconfig.json:
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"lib": ["ES2022"],
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"noUncheckedIndexedAccess": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"exactOptionalPropertyTypes": false
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules", "dist", "tests"]
}
步骤3:更新 package.json 脚本
编辑 package.json,添加以下 scripts:
{
"name": "harness-engine",
"version": "0.1.0",
"description": "Minimal Harness Engineering Engine - Control/Agency/Runtime triad",
"main": "dist/index.js",
"type": "module",
"scripts": {
"build": "tsc",
"dev": "tsx --watch src/index.ts",
"start": "node dist/index.js",
"test": "tsx --test tests/*.test.ts",
"example:minimal": "tsx examples/minimal-harness.ts",
"typecheck": "tsc --noEmit"
},
"keywords": ["harness-engineering", "ai-agent", "control", "agency", "runtime"],
"license": "MIT"
}
1.7.2 核心类型定义
首先定义 Harness 系统的核心类型。这是所有后续实现的基础。
创建 src/types/harness.ts:
// ============================================================
// src/types/harness.ts
// Harness Engineering 核心类型定义
// 定义了 Control-Agency-Runtime 三元框架的基础数据结构
// ============================================================
import { z } from 'zod';
// ──── 枚举定义 ──────────────────────────────────────────────
/**
* Agent 行为状态。
* 行为状态机(Behavior State Machine)的核心状态集合。
* Agent 在任何时刻必须处于这六个状态之一。
*/
export enum AgentState {
/** 空闲:等待接收任务 */
IDLE = 'IDLE',
/** 思考:LLM 进行推理和决策 */
THINKING = 'THINKING',
/** 执行:正在执行某个工具/操作 */
EXECUTING = 'EXECUTING',
/** 观察:处理工具返回的结果 */
OBSERVING = 'OBSERVING',
/** 降级:遇到问题,正在执行降级路径 */
DEGRADING = 'DEGRADING',
/** 报告:生成最终结果,准备结束 */
REPORTING = 'REPORTING',
}
/**
* 事件类型。
* Harness Runtime 事件循环中的事件分类。
*/
export enum EventType {
/** 用户输入消息 */
USER_MESSAGE = 'USER_MESSAGE',
/** Agent 内部思考完成 */
THOUGHT_COMPLETED = 'THOUGHT_COMPLETED',
/** Action 决策完成 */
ACTION_DECIDED = 'ACTION_DECIDED',
/** 工具执行结果返回 */
TOOL_RESULT = 'TOOL_RESULT',
/** 超时信号 */
TIMEOUT = 'TIMEOUT',
/** 预算耗尽信号 */
BUDGET_EXHAUSTED = 'BUDGET_EXHAUSTED',
/** 控制层指令(暂停/恢复/终止/调整参数等) */
CONTROL_COMMAND = 'CONTROL_COMMAND',
/** Agent 需要向外部发送消息 */
AGENT_MESSAGE = 'AGENT_MESSAGE',
/** 任务完成 */
TASK_COMPLETE = 'TASK_COMPLETE',
/** 任务失败 */
TASK_FAILED = 'TASK_FAILED',
}
/**
* 任务优先级。
*/
export enum TaskPriority {
LOW = 1,
NORMAL = 2,
HIGH = 3,
CRITICAL = 4,
}
/**
* 降级级别。
* 当 Agent 遇到无法继续执行的情况时,采取的策略级别。
*/
export enum DegradationLevel {
/** 工具替换:寻找功能相似的工具替代 */
TOOL_SUBSTITUTION = 1,
/** 路径替换:保持目标不变,改变执行路径 */
PATH_SUBSTITUTION = 2,
/** 目标降级:将目标调整到可达成的最接近版本 */
GOAL_DEGRADATION = 3,
/** 终止并报告:无法继续,基于已有信息产出结果 */
TERMINATE_AND_REPORT = 4,
}
// ──── 预算相关 ──────────────────────────────────────────────
/**
* 三维预算配置。
* 控制 Agent 资源消耗的三维配给系统。
*/
export interface Budget {
/** Token 预算上限(输入+输出) */
maxTokens: number;
/** Token 已消耗量 */
tokensConsumed: number;
/** 工具调用次数上限 */
maxApiCalls: number;
/** 工具调用已消耗次数 */
apiCallsUsed: number;
/** 壁钟时间上限(毫秒) */
maxTimeMs: number;
/** 已用时间(毫秒) */
timeUsedMs: number;
}
/**
* 预算状态检查结果。
*/
export interface BudgetStatus {
/** 是否有足够的 Token 预算 */
tokensOk: boolean;
/** 是否有足够的 API 调用次数 */
apiCallsOk: boolean;
/** 是否有足够的时间 */
timeOk: boolean;
/** Token 使用百分比 (0-1) */
tokenUsageRatio: number;
/** API 使用百分比 (0-1) */
apiUsageRatio: number;
/** 时间使用百分比 (0-1) */
timeUsageRatio: number;
}
// ──── 决策空间定义 ──────────────────────────────────────────
/**
* 可用工具的抽象描述。
* Agent 通过这个接口了解它能使用什么工具。
*/
export interface ToolDescriptor {
/** 工具唯一标识 */
name: string;
/** 人类可读的描述 */
description: string;
/** 需要的权限级别 (1-5) */
permissionLevel: number;
/** 工具参数 Schema(JSON Schema 格式) */
parameters: Record<string, unknown>;
/** 估计的 Token 消耗 */
estimatedTokenCost: number;
/** 工具分类 */
category: 'query' | 'action' | 'creation' | 'modification' | 'deletion';
}
/**
* 工具调用请求。
*/
export interface ToolInvocation {
/** 工具名称 */
toolName: string;
/** 调用参数 */
parameters: Record<string, unknown>;
/** 调用ID(用于关联请求和响应) */
callId: string;
/** 时间戳 */
timestamp: number;
}
/**
* 工具调用结果。
*/
export interface ToolResult {
/** 对应的调用ID */
callId: string;
/** 是否成功 */
success: boolean;
/** 返回数据 */
data: unknown;
/** 错误信息(如果失败) */
error?: string;
/** 实际消耗的 Token(如果可计算) */
actualTokenCost?: number;
/** 执行耗时(毫秒) */
executionTimeMs: number;
}
// ──── 事件与状态 ────────────────────────────────────────────
/**
* Harness 事件。
* 在 Runtime 事件循环中流动的基本数据单元。
*/
export interface HarnessEvent {
/** 事件唯一标识 */
id: string;
/** 事件类型 */
type: EventType;
/** 事件携带的数据 */
payload: unknown;
/** 事件产生的时间戳 */
timestamp: number;
/** 事件优先级 */
priority: TaskPriority;
/** 事件来源(Agent ID 或 System) */
source: string;
}
/**
* 任务定义。
* 用户意图的结构化表示。
*/
export interface Task {
/** 任务唯一标识 */
id: string;
/** 任务标题/摘要 */
title: string;
/** 任务详细描述 */
description: string;
/** 任务目标(用于目标恒常器检查) */
goal: string;
/** 任务优先级 */
priority: TaskPriority;
/** 允许使用的工具类别 */
allowedToolCategories: Array<'query' | 'action' | 'creation' | 'modification' | 'deletion'>;
/** 创建时间 */
createdAt: number;
/** 截止时间(可选,0表示无截止时间) */
deadline: number;
/** 上下文信息(用户偏好、历史等) */
context: Record<string, unknown>;
}
/**
* 活动记录条目。
* 所有 Agent 行为的不可变记录,是审计和回溯的基础。
*/
export interface ActivityRecord {
/** 记录ID */
id: string;
/** 时间戳 */
timestamp: number;
/** 操作者(Agent ID) */
actor: string;
/** 操作类型 */
actionType: string;
/** 操作前的状态 */
stateBefore: string;
/** 操作后的状态 */
stateAfter: string;
/** 操作描述 */
description: string;
/** 操作详细数据 */
details: Record<string, unknown>;
/** 是否成功 */
success: boolean;
/** 耗时(毫秒) */
durationMs: number;
}
/**
* 意图注入数据结构。
* 在每次 LLM 调用前动态注入到提示词的上下文信息。
*/
export interface IntentInjection {
/** 硬性约束(Agent 不得违反) */
hardConstraints: {
forbiddenActions: string[];
requiredApprovals: string[];
dataAccessBoundary: string[];
};
/** 偏好引导(强烈建议) */
preferences: {
preferredTools: string[];
communicationStyle: string;
fallbackBehavior: string;
};
/** 运行时上下文(当前状态快照) */
runtimeContext: {
budgetRemaining: BudgetStatus;
timeRemaining: number;
taskProgress: number;
recentErrors: Array<{ tool: string; error: string }>;
};
}
// ──── Harness 配置 ──────────────────────────────────────────
/**
* 完整的 Harness 配置。
* 定义了 Control-Agency-Runtime 三层的所有可配置参数。
*/
export interface HarnessConfig {
/** 控制层配置 */
control: {
/** 初始状态 */
initialState: AgentState;
/** 任务超时(毫秒) */
taskTimeout: number;
/** Token 预算 */
tokenBudget: number;
/** API 调用次数预算 */
apiCallBudget: number;
/** 时间预算(毫秒) */
timeBudget: number;
/** 目标偏离容忍度(0-1,越高越宽松) */
goalDriftTolerance: number;
/** Agent 在当前状态的最大驻留时间(毫秒,0=无限) */
stateMaxDwellMs: Record<string, number>;
};
/** 能动性层配置 */
agency: {
/** 最大思考-行动循环次数 */
maxReActLoops: number;
/** 是否启用 ToT(Tree of Thoughts,思维树)模式 */
enableToT: boolean;
/** ToT 分支因子 */
totBranchingFactor: number;
/** 降级策略 */
degradationStrategy: 'eager' | 'lazy';
/** 规划模式 */
planningMode: 'reactive' | 'plan_then_execute' | 'adaptive';
};
/** 运行时层配置 */
runtime: {
/** 事件队列最大容量 */
maxEventQueueSize: number;
/** 事件处理超时(毫秒) */
eventProcessTimeout: number;
/** 状态快照间隔(毫秒) */
snapshotIntervalMs: number;
/** 活动日志保留天数 */
auditLogRetentionDays: number;
};
}
// ──── Zod Schema 定义(用于运行时校验) ─────────────────────
// 注意:这里只定义了核心类型的 Schema,完整版见后续章节
export const BudgetSchema = z.object({
maxTokens: z.number().positive(),
tokensConsumed: z.number().min(0),
maxApiCalls: z.number().positive(),
apiCallsUsed: z.number().min(0),
maxTimeMs: z.number().positive(),
timeUsedMs: z.number().min(0),
});
export const TaskSchema = z.object({
id: z.string(),
title: z.string().min(1),
description: z.string(),
goal: z.string().min(1),
priority: z.nativeEnum(TaskPriority),
allowedToolCategories: z.array(
z.enum(['query', 'action', 'creation', 'modification', 'deletion'])
),
createdAt: z.number(),
deadline: z.number().min(0),
context: z.record(z.unknown()),
});
// ──── 辅助函数 ──────────────────────────────────────────────
/**
* 生成唯一ID。
* 在生产环境中应使用 UUID v7(时间排序),这里使用简化版。
*/
export function generateId(): string {
return `hrn_${Date.now().toString(36)}_${Math.random().toString(36).substring(2, 10)}`;
}
/**
* 获取当前时间戳(毫秒)。
*/
export function now(): number {
return Date.now();
}
/**
* 格式化持续时间。
*/
export function formatDuration(ms: number): string {
if (ms < 1000) return `${ms}ms`;
if (ms < 60_000) return `${(ms / 1000).toFixed(1)}s`;
const minutes = Math.floor(ms / 60_000);
const seconds = Math.floor((ms % 60_000) / 1000);
return `${minutes}m${seconds}s`;
}
1.7.3 Control 层实现
Control 层实现行为状态机、预算管理和目标恒常器。
创建 src/control/control-layer.ts:
// ============================================================
// src/control/control-layer.ts
// Control 层核心实现
// 负责:行为状态机、预算管理、目标恒常器、审计记录
// ============================================================
import {
AgentState,
EventType,
Budget,
BudgetStatus,
HarnessEvent,
Task,
ActivityRecord,
IntentInjection,
generateId,
now,
} from '../types/harness.js';
// ──── 行为状态机 ─────────────────────────────────────────────
/**
* 状态转移表:定义每个状态下允许的转移目标。
* 任何不在此表中的转移请求将被拒绝。
*/
const STATE_TRANSITIONS: Readonly<Record<AgentState, ReadonlySet<AgentState>>> = {
[AgentState.IDLE]: new Set([AgentState.THINKING]),
[AgentState.THINKING]: new Set([
AgentState.EXECUTING,
AgentState.OBSERVING,
AgentState.REPORTING,
AgentState.DEGRADING,
]),
[AgentState.EXECUTING]: new Set([
AgentState.OBSERVING,
AgentState.DEGRADING,
AgentState.THINKING,
]),
[AgentState.OBSERVING]: new Set([
AgentState.THINKING,
AgentState.REPORTING,
AgentState.DEGRADING,
]),
[AgentState.DEGRADING]: new Set([
AgentState.THINKING,
AgentState.REPORTING,
AgentState.IDLE,
]),
[AgentState.REPORTING]: new Set([AgentState.IDLE]),
};
/**
* 每个状态下允许处理的事件类型。
* 例如,IDLE 状态下不允许执行 TOOL_RESULT 事件。
*/
const STATE_ALLOWED_EVENTS: Readonly<Record<AgentState, ReadonlySet<EventType>>> = {
[AgentState.IDLE]: new Set([EventType.USER_MESSAGE, EventType.CONTROL_COMMAND]),
[AgentState.THINKING]: new Set([
EventType.THOUGHT_COMPLETED,
EventType.TIMEOUT,
EventType.BUDGET_EXHAUSTED,
EventType.CONTROL_COMMAND,
]),
[AgentState.EXECUTING]: new Set([
EventType.TOOL_RESULT,
EventType.TIMEOUT,
EventType.CONTROL_COMMAND,
]),
[AgentState.OBSERVING]: new Set([
EventType.ACTION_DECIDED,
EventType.TIMEOUT,
EventType.CONTROL_COMMAND,
]),
[AgentState.DEGRADING]: new Set([
EventType.THOUGHT_COMPLETED,
EventType.TOOL_RESULT,
EventType.CONTROL_COMMAND,
]),
[AgentState.REPORTING]: new Set([
EventType.TASK_COMPLETE,
EventType.TASK_FAILED,
EventType.CONTROL_COMMAND,
]),
};
/**
* 行为状态机类。
* 管理 Agent 的行为阶段,确保状态转移的合法性。
*/
export class BehaviorStateMachine {
private currentState: AgentState;
private stateEnteredAt: number;
private readonly stateHistory: Array<{
from: AgentState;
to: AgentState;
timestamp: number;
}> = [];
constructor(initialState: AgentState = AgentState.IDLE) {
this.currentState = initialState;
this.stateEnteredAt = now();
}
/**
* 获取当前状态。
*/
getState(): AgentState {
return this.currentState;
}
/**
* 获取当前状态的已驻留时间(毫秒)。
*/
getStateDwellTime(): number {
return now() - this.stateEnteredAt;
}
/**
* 获取状态转移历史。
*/
getStateHistory(): ReadonlyArray<{
from: AgentState;
to: AgentState;
timestamp: number;
}> {
return this.stateHistory;
}
/**
* 尝试状态转移。
* @param target 目标状态
* @returns 转移结果
*/
transition(target: AgentState): {
success: boolean;
from: AgentState;
to: AgentState;
error?: string;
} {
const allowed = STATE_TRANSITIONS[this.currentState];
if (!allowed) {
return {
success: false,
from: this.currentState,
to: target,
error: `未知的当前状态: ${this.currentState}`,
};
}
if (!allowed.has(target)) {
return {
success: false,
from: this.currentState,
to: target,
error: `非法状态转移: ${this.currentState} → ${target}。` +
`允许的目标状态: [${[...allowed].join(', ')}]`,
};
}
const from = this.currentState;
this.stateHistory.push({ from, to: target, timestamp: now() });
this.currentState = target;
this.stateEnteredAt = now();
return { success: true, from, to: target };
}
/**
* 强制状态转移(用于控制命令,绕过转移表限制)。
* 仅用于 PAUSE、RESUME、TERMINATE 等控制指令。
*/
forceTransition(target: AgentState): void {
const from = this.currentState;
this.stateHistory.push({ from, to: target, timestamp: now() });
this.currentState = target;
this.stateEnteredAt = now();
}
/**
* 检查指定事件在当前状态下是否被允许。
*/
isEventAllowed(eventType: EventType): boolean {
const allowed = STATE_ALLOWED_EVENTS[this.currentState];
return allowed ? allowed.has(eventType) : false;
}
/**
* 重置状态机。
*/
reset(): void {
this.currentState = AgentState.IDLE;
this.stateEnteredAt = now();
this.stateHistory.length = 0;
}
}
// ──── 预算管理器 ─────────────────────────────────────────────
/**
* 预算管理器类。
* 负责三维预算(Token/API调用/时间)的实时跟踪和消耗控制。
*/
export class BudgetManager {
private budget: Budget;
private startTime: number;
constructor(maxTokens: number, maxApiCalls: number, maxTimeMs: number) {
this.budget = {
maxTokens,
tokensConsumed: 0,
maxApiCalls,
apiCallsUsed: 0,
maxTimeMs,
timeUsedMs: 0,
};
this.startTime = now();
}
/**
* 更新已用时间。
*/
private updateTimeUsed(): void {
this.budget.timeUsedMs = now() - this.startTime;
}
/**
* 消耗 Token。
* @param amount 消耗的 Token 数量
* @returns 消耗后是否仍在预算内
*/
consumeTokens(amount: number): boolean {
this.budget.tokensConsumed += amount;
return this.budget.tokensConsumed < this.budget.maxTokens;
}
/**
* 消耗一次 API 调用。
* @returns 消耗后是否仍在预算内
*/
consumeApiCall(): boolean {
this.budget.apiCallsUsed += 1;
return this.budget.apiCallsUsed < this.budget.maxApiCalls;
}
/**
* 获取当前预算状态。
*/
getStatus(): BudgetStatus {
this.updateTimeUsed();
return {
tokensOk: this.budget.tokensConsumed < this.budget.maxTokens,
apiCallsOk: this.budget.apiCallsUsed < this.budget.maxApiCalls,
timeOk: this.budget.timeUsedMs < this.budget.maxTimeMs,
tokenUsageRatio: this.budget.maxTokens > 0
? this.budget.tokensConsumed / this.budget.maxTokens
: 0,
apiUsageRatio: this.budget.maxApiCalls > 0
? this.budget.apiCallsUsed / this.budget.maxApiCalls
: 0,
timeUsageRatio: this.budget.maxTimeMs > 0
? this.budget.timeUsedMs / this.budget.maxTimeMs
: 0,
};
}
/**
* 检查预算是否已全部耗尽。
*/
isBudgetExhausted(): boolean {
const status = this.getStatus();
return !status.tokensOk || !status.apiCallsOk || !status.timeOk;
}
/**
* 获取预算摘要(用于日志和审计)。
*/
getBudgetSummary(): string {
const status = this.getStatus();
return (
`Token: ${this.budget.tokensConsumed}/${this.budget.maxTokens} ` +
`(${(status.tokenUsageRatio * 100).toFixed(0)}%), ` +
`API: ${this.budget.apiCallsUsed}/${this.budget.maxApiCalls} ` +
`(${(status.apiUsageRatio * 100).toFixed(0)}%), ` +
`Time: ${this.budget.timeUsedMs}ms/${this.budget.maxTimeMs}ms ` +
`(${(status.timeUsageRatio * 100).toFixed(0)}%)`
);
}
/**
* 重置预算计数器。
*/
reset(): void {
this.budget.tokensConsumed = 0;
this.budget.apiCallsUsed = 0;
this.budget.timeUsedMs = 0;
this.startTime = now();
}
}
// ──── 目标恒常器 ─────────────────────────────────────────────
/**
* 目标恒常器类。
* 检测 Agent 当前行为是否偏离了原始目标。
*
* 简化实现:基于关键词重叠和启发式规则。
* 生产级实现应使用语义嵌入(Embedding)比较(见第2章)。
*/
export class GoalInvariant {
private readonly originalGoal: string;
private readonly tolerance: number;
/** 提取的目标关键词集合 */
private readonly goalKeywords: Set<string>;
constructor(originalGoal: string, tolerance: number = 0.3) {
this.originalGoal = originalGoal;
this.tolerance = tolerance;
this.goalKeywords = this.extractKeywords(originalGoal);
}
/**
* 从文本中提取关键词(简化实现)。
* 生产环境应使用 NLP 分词 + TF-IDF 或 embedding。
*/
private extractKeywords(text: string): Set<string> {
// 移除标点符号并分词
const words = text
.toLowerCase()
.replace(/[^\w一-鿿\s]/g, ' ')
.split(/\s+/)
.filter((w) => w.length > 1)
// 过滤常见停用词
.filter(
(w) =>
!['the', 'a', 'an', 'is', 'are', 'was', 'were', '的', '了', '在', '是',
'我', '有', '和', '就', '不', '人', '都', '一', '一个', '上', '也', '很',
'到', '说', '要', '去', '你', '会', '着', '没有', '看', '好', '自己', '这',
].includes(w)
);
return new Set(words);
}
/**
* 计算两组关键词的 Jaccard 相似度。
*/
private jaccardSimilarity(set1: Set<string>, set2: Set<string>): number {
if (set1.size === 0 && set2.size === 0) return 1.0;
const intersection = new Set([...set1].filter((x) => set2.has(x)));
const union = new Set([...set1, ...set2]);
return union.size === 0 ? 0 : intersection.size / union.size;
}
/**
* 检查给定的行为描述是否偏离了目标。
* @param currentActionDescription Agent当前行为的描述
* @returns 检查结果
*/
check(currentActionDescription: string): {
/** 是否发生了目标偏离 */
isDrifting: boolean;
/** 与原始目标的语义相似度 */
similarity: number;
/** 偏离程度描述 */
severity: 'none' | 'mild' | 'moderate' | 'severe';
} {
const currentKeywords = this.extractKeywords(currentActionDescription);
const similarity = this.jaccardSimilarity(this.goalKeywords, currentKeywords);
const isDrifting = similarity < this.tolerance;
let severity: 'none' | 'mild' | 'moderate' | 'severe';
if (similarity >= 0.7) {
severity = 'none';
} else if (similarity >= 0.5) {
severity = 'mild';
} else if (similarity >= 0.3) {
severity = 'moderate';
} else {
severity = 'severe';
}
return { isDrifting, similarity, severity };
}
/**
* 获取原始目标。
*/
getOriginalGoal(): string {
return this.originalGoal;
}
}
// ──── Control 层主类 ─────────────────────────────────────────
/**
* Control 层主类。
* 将行为状态机、预算管理器和目标恒常器整合为一个统一的控制层。
*/
export class ControlLayer {
readonly stateMachine: BehaviorStateMachine;
readonly budgetManager: BudgetManager;
readonly goalInvariant: GoalInvariant;
private readonly auditLog: ActivityRecord[] = [];
private readonly maxAuditLogSize: number;
constructor(
task: Task,
tokenBudget: number,
apiCallBudget: number,
timeBudget: number,
goalDriftTolerance: number = 0.3,
maxAuditLogSize: number = 10_000
) {
this.stateMachine = new BehaviorStateMachine(AgentState.IDLE);
this.budgetManager = new BudgetManager(tokenBudget, apiCallBudget, timeBudget);
this.goalInvariant = new GoalInvariant(task.goal, goalDriftTolerance);
this.maxAuditLogSize = maxAuditLogSize;
}
/**
* 检查事件在当前状态下是否可被处理。
*/
canProcessEvent(event: HarnessEvent): {
allowed: boolean;
reason?: string;
} {
// 1. 状态合法性检查
if (!this.stateMachine.isEventAllowed(event.type)) {
return {
allowed: false,
reason: `事件 ${event.type} 在当前状态 ${this.stateMachine.getState()} 下不被允许`,
};
}
// 2. 预算检查
if (this.budgetManager.isBudgetExhausted()) {
return {
allowed: false,
reason: `预算已耗尽: ${this.budgetManager.getBudgetSummary()}`,
};
}
return { allowed: true };
}
/**
* 尝试状态转移。
*/
tryTransition(target: AgentState): {
success: boolean;
error?: string;
} {
return this.stateMachine.transition(target);
}
/**
* 记录一条活动到审计日志。
*/
recordActivity(record: Omit<ActivityRecord, 'id' | 'timestamp'>): ActivityRecord {
const fullRecord: ActivityRecord = {
...record,
id: generateId(),
timestamp: now(),
};
this.auditLog.push(fullRecord);
// 防止日志无限增长
if (this.auditLog.length > this.maxAuditLogSize) {
this.auditLog.splice(0, this.auditLog.length - this.maxAuditLogSize);
}
return fullRecord;
}
/**
* 获取审计日志。
*/
getAuditLog(): ReadonlyArray<ActivityRecord> {
return this.auditLog;
}
/**
* 获取审计日志的子集(按时间范围)。
*/
getAuditLogByTimeRange(startMs: number, endMs: number): ActivityRecord[] {
return this.auditLog.filter(
(r) => r.timestamp >= startMs && r.timestamp <= endMs
);
}
/**
* 获取最近的 N 条审计记录。
*/
getRecentAuditLog(n: number): ActivityRecord[] {
return this.auditLog.slice(-n);
}
/**
* 构建意图注入对象(供 Agency 层使用)。
*/
buildIntentInjection(): IntentInjection {
const budgetStatus = this.budgetManager.getStatus();
const recentErrors = this.auditLog
.filter((r) => !r.success)
.slice(-5)
.map((r) => ({
tool: (r.details['toolName'] as string) || 'unknown',
error: (r.details['error'] as string) || 'unknown error',
}));
return {
hardConstraints: {
forbiddenActions: ['DELETE_SYSTEM_FILE', 'DROP_TABLE', 'SHUTDOWN_SYSTEM'],
requiredApprovals: ['DATA_DELETION', 'SCHEMA_MODIFICATION', 'EXTERNAL_API_WRITE'],
dataAccessBoundary: [],
},
preferences: {
preferredTools: [],
communicationStyle: '专业、简洁',
fallbackBehavior: '如果遇到无法解决的问题,基于已有信息给出最佳建议',
},
runtimeContext: {
budgetRemaining: budgetStatus,
timeRemaining: this.budgetManager.getStatus().timeUsageRatio > 0
? (1 - budgetStatus.timeUsageRatio) * (this.budgetManager as any).budget.maxTimeMs
: 0,
taskProgress: 0,
recentErrors,
},
};
}
/**
* 重置控制层。
*/
reset(): void {
this.stateMachine.reset();
this.budgetManager.reset();
this.auditLog.length = 0;
}
}
1.7.4 Agency 层实现
创建 src/agency/agency-layer.ts:
// ============================================================
// src/agency/agency-layer.ts
// Agency 层核心实现
// 负责:决策空间管理、意图注入、规划引擎、降级管理
// ============================================================
import {
ToolDescriptor,
ToolInvocation,
ToolResult,
Task,
HarnessEvent,
EventType,
IntentInjection,
DegradationLevel,
AgentState,
generateId,
now,
} from '../types/harness.js';
// ──── 决策空间 ───────────────────────────────────────────────
/**
* 决策空间类。
* 管理 Agent 可用的工具集合和决策上下文。
* 提供了对工具集的增删查改及基于上下文的工具推荐能力。
*/
export class DecisionSpace {
private tools: Map<string, ToolDescriptor> = new Map();
private toolImplementations: Map<
string,
(params: Record<string, unknown>) => Promise<unknown>
> = new Map();
/**
* 注册一个工具到决策空间。
*/
registerTool(
descriptor: ToolDescriptor,
implementation: (params: Record<string, unknown>) => Promise<unknown>
): void {
if (this.tools.has(descriptor.name)) {
throw new Error(`工具 ${descriptor.name} 已注册`);
}
this.tools.set(descriptor.name, descriptor);
this.toolImplementations.set(descriptor.name, implementation);
}
/**
* 注销一个工具。
*/
unregisterTool(toolName: string): boolean {
this.toolImplementations.delete(toolName);
return this.tools.delete(toolName);
}
/**
* 获取所有已注册的工具描述。
*/
getAvailableTools(): ToolDescriptor[] {
return [...this.tools.values()];
}
/**
* 获取指定分类的工具。
*/
getToolsByCategory(
category: ToolDescriptor['category']
): ToolDescriptor[] {
return [...this.tools.values()].filter((t) => t.category === category);
}
/**
* 获取工具的详细信息。
*/
getTool(name: string): ToolDescriptor | undefined {
return this.tools.get(name);
}
/**
* 执行工具调用。
*/
async executeTool(invocation: ToolInvocation): Promise<ToolResult> {
const startTime = now();
const impl = this.toolImplementations.get(invocation.toolName);
if (!impl) {
return {
callId: invocation.callId,
success: false,
data: null,
error: `工具 ${invocation.toolName} 未注册`,
executionTimeMs: now() - startTime,
};
}
try {
const data = await impl(invocation.parameters);
return {
callId: invocation.callId,
success: true,
data,
executionTimeMs: now() - startTime,
};
} catch (err) {
return {
callId: invocation.callId,
success: false,
data: null,
error: err instanceof Error ? err.message : String(err),
executionTimeMs: now() - startTime,
};
}
}
/**
* 根据任务上下文推荐最合适的工具。
*/
recommendTools(task: Task, topN: number = 5): ToolDescriptor[] {
const allowedCategories = new Set(task.allowedToolCategories);
const candidates = [...this.tools.values()].filter((t) =>
allowedCategories.has(t.category)
);
// 按估计的 Token 消耗排序(优先使用低成本工具)
candidates.sort((a, b) => a.estimatedTokenCost - b.estimatedTokenCost);
return candidates.slice(0, topN);
}
/**
* 查找给定工具的替代工具。
* 用于 Level 1 降级(工具替换)。
*/
findAlternativeTool(toolName: string): ToolDescriptor | undefined {
const original = this.tools.get(toolName);
if (!original) return undefined;
// 寻找相同分类、不同名称的工具
return [...this.tools.values()].find(
(t) => t.category === original.category && t.name !== toolName
);
}
}
// ──── 规划引擎 ───────────────────────────────────────────────
/**
* 执行步骤。
* 计划中的一个独立步骤。
*/
export interface PlanStep {
/** 步骤ID */
id: string;
/** 步骤描述 */
description: string;
/** 预期使用的工具(可选) */
expectedTool?: string;
/** 步骤状态 */
status: 'pending' | 'in_progress' | 'completed' | 'failed' | 'skipped';
/** 依赖的步骤ID列表 */
dependencies: string[];
/** 步骤结果 */
result?: unknown;
}
/**
* 执行计划。
* 由规划引擎生成,指导 Agent 的执行过程。
*/
export interface ExecutionPlan {
/** 计划ID */
id: string;
/** 关联的任务ID */
taskId: string;
/** 计划步骤列表 */
steps: PlanStep[];
/** 创建时间 */
createdAt: number;
/** 当前执行到的步骤索引 */
currentStepIndex: number;
}
/**
* 规划引擎类。
* 负责将任务分解为结构化的执行步骤。
*/
export class PlanningEngine {
/**
* 创建执行计划。
* 简化实现:基于任务描述生成线性步骤列表。
* 生产级实现应使用 LLM 来生成计划(见第3章)。
*/
createPlan(task: Task, availableTools: ToolDescriptor[]): ExecutionPlan {
const steps: PlanStep[] = [
{
id: generateId(),
description: `理解任务目标: ${task.goal}`,
status: 'pending',
dependencies: [],
},
{
id: generateId(),
description: '分析当前上下文和可用资源',
expectedTool: availableTools.find((t) => t.category === 'query')?.name,
status: 'pending',
dependencies: [],
},
{
id: generateId(),
description: '执行核心任务操作',
expectedTool: availableTools.find(
(t) => t.category === 'action' || t.category === 'creation'
)?.name,
status: 'pending',
dependencies: [],
},
{
id: generateId(),
description: '验证结果并生成报告',
status: 'pending',
dependencies: [],
},
];
return {
id: generateId(),
taskId: task.id,
steps,
createdAt: now(),
currentStepIndex: 0,
};
}
/**
* 获取当前步骤。
*/
getCurrentStep(plan: ExecutionPlan): PlanStep | undefined {
return plan.steps[plan.currentStepIndex];
}
/**
* 标记当前步骤为完成,前进到下一步。
*/
advanceStep(plan: ExecutionPlan): PlanStep | undefined {
const current = plan.steps[plan.currentStepIndex];
if (current) {
current.status = 'completed';
}
plan.currentStepIndex += 1;
return plan.steps[plan.currentStepIndex];
}
/**
* 标记当前步骤为失败。
*/
failCurrentStep(plan: ExecutionPlan, error: string): void {
const current = plan.steps[plan.currentStepIndex];
if (current) {
current.status = 'failed';
current.result = { error };
}
}
/**
* 获取计划执行进度。
*/
getProgress(plan: ExecutionPlan): {
completed: number;
total: number;
percentage: number;
} {
const total = plan.steps.length;
const completed = plan.steps.filter(
(s) => s.status === 'completed' || s.status === 'skipped'
).length;
return {
completed,
total,
percentage: total > 0 ? completed / total : 0,
};
}
/**
* 重新规划。
* 当当前计划不可行时,基于已完成步骤生成新计划。
* 简化实现:跳过失败步骤,继续后续步骤。
*/
replan(
plan: ExecutionPlan,
failureReason: string
): ExecutionPlan {
const newSteps = plan.steps.map((step) => {
if (step.status === 'completed') return step;
return { ...step, status: 'pending' as const, result: undefined };
});
// 跳过已失败的步骤
const firstPending = newSteps.findIndex((s) => s.status !== 'completed');
const startIndex = firstPending >= 0 ? firstPending : 0;
return {
...plan,
id: generateId(),
steps: newSteps,
currentStepIndex: startIndex,
};
}
}
// ──── 降级管理器 ─────────────────────────────────────────────
/**
* 降级管理器类。
* 负责在 Agent 遇到异常时选择和执行降级路径。
*/
export class DegradationManager {
private degradationCount: number = 0;
private readonly maxDegradations: number;
constructor(maxDegradations: number = 3) {
this.maxDegradations = maxDegradations;
}
/**
* 决定应采取的降级级别。
*/
determineLevel(
failureDescription: string,
currentDegradationCount: number | undefined
): DegradationLevel {
const count = currentDegradationCount ?? this.degradationCount;
if (count >= this.maxDegradations) {
return DegradationLevel.TERMINATE_AND_REPORT;
}
// 基于失败描述的简单启发式分类
// 生产环境应使用 LLM 来分类失败类型
const desc = failureDescription.toLowerCase();
if (
desc.includes('工具') ||
desc.includes('tool') ||
desc.includes('未注册') ||
desc.includes('not found')
) {
return DegradationLevel.TOOL_SUBSTITUTION;
}
if (
desc.includes('超时') ||
desc.includes('timeout') ||
desc.includes('预算') ||
desc.includes('budget')
) {
return DegradationLevel.TERMINATE_AND_REPORT;
}
// 默认:尝试改变执行路径
return DegradationLevel.PATH_SUBSTITUTION;
}
/**
* 记录一次降级事件。
*/
recordDegradation(
level: DegradationLevel,
reason: string
): void {
this.degradationCount += 1;
console.log(
`[Degradation] Level ${level}: ${reason} ` +
`(第 ${this.degradationCount} 次降级, 上限 ${this.maxDegradations})`
);
}
/**
* 获取当前降级次数。
*/
getDegradationCount(): number {
return this.degradationCount;
}
/**
* 是否已达到最大降级次数。
*/
isExhausted(): boolean {
return this.degradationCount >= this.maxDegradations;
}
/**
* 重置降级计数器。
*/
reset(): void {
this.degradationCount = 0;
}
}
// ──── 意图注入器 ─────────────────────────────────────────────
/**
* 意图注入器类。
* 将 Control 层的约束和偏好转换为 Agent 可理解的提示词片段。
*/
export class IntentInjector {
/**
* 将 IntentInjection 结构转换为提示词文本。
*/
toPromptText(injection: IntentInjection): string {
const lines: string[] = [];
lines.push('## 运行时上下文与控制约束');
lines.push('');
// 硬性约束
lines.push('### 必须遵守的约束(违反将导致操作被拒绝)');
if (injection.hardConstraints.forbiddenActions.length > 0) {
lines.push(`- 禁止操作: ${injection.hardConstraints.forbiddenActions.join(', ')}`);
}
if (injection.hardConstraints.requiredApprovals.length > 0) {
lines.push(
`- 需要审批的操作: ${injection.hardConstraints.requiredApprovals.join(', ')}`
);
}
lines.push('');
// 偏好引导
lines.push('### 偏好与建议');
if (injection.preferences.preferredTools.length > 0) {
lines.push(`- 优先使用的工具: ${injection.preferences.preferredTools.join(', ')}`);
}
lines.push(`- 沟通风格: ${injection.preferences.communicationStyle}`);
lines.push(`- 降级策略: ${injection.preferences.fallbackBehavior}`);
lines.push('');
// 运行时状态
const ctx = injection.runtimeContext;
lines.push('### 当前运行时状态');
lines.push(
`- Token 预算: ${(ctx.budgetRemaining.tokenUsageRatio * 100).toFixed(0)}% 已使用`
);
lines.push(
`- API 调用: ${(ctx.budgetRemaining.apiUsageRatio * 100).toFixed(0)}% 已使用`
);
lines.push(
`- 剩余时间: ${ctx.timeRemaining > 0 ? Math.round(ctx.timeRemaining / 1000) + '秒' : '无限制'}`
);
lines.push(`- 任务进度: ${(ctx.taskProgress * 100).toFixed(0)}%`);
if (ctx.recentErrors.length > 0) {
lines.push('- 最近的错误:');
for (const err of ctx.recentErrors) {
lines.push(` - ${err.tool}: ${err.error}`);
}
}
return lines.join('\n');
}
/**
* 将 IntentInjection 结构转换为结构化的 System Prompt 补充。
*/
toSystemPromptSupplement(injection: IntentInjection): string {
return `
<harness_control_constraints>
<hard_constraints>
禁止操作: ${injection.hardConstraints.forbiddenActions.join(', ') || '无'}
需要审批: ${injection.hardConstraints.requiredApprovals.join(', ') || '无'}
</hard_constraints>
<preferences>
沟通风格: ${injection.preferences.communicationStyle}
降级策略: ${injection.preferences.fallbackBehavior}
</preferences>
<runtime_status>
Token使用率: ${(injection.runtimeContext.budgetRemaining.tokenUsageRatio * 100).toFixed(0)}%
API使用率: ${(injection.runtimeContext.budgetRemaining.apiUsageRatio * 100).toFixed(0)}%
剩余时间: ${injection.runtimeContext.timeRemaining > 0 ? Math.round(injection.runtimeContext.timeRemaining / 1000) + '秒' : '无限制'}
</runtime_status>
</harness_control_constraints>`.trim();
}
}
1.7.5 Runtime 层实现
创建 src/runtime/runtime-layer.ts:
// ============================================================
// src/runtime/runtime-layer.ts
// Runtime 层核心实现
// 负责:事件循环、状态管理、工具挂载管理、生命周期管理
// ============================================================
import {
HarnessEvent,
EventType,
AgentState,
Task,
TaskPriority,
ActivityRecord,
ToolDescriptor,
BudgetStatus,
generateId,
now,
formatDuration,
} from '../types/harness.js';
import { ControlLayer } from '../control/control-layer.js';
import { DecisionSpace, PlanningEngine, DegradationManager, IntentInjector, ExecutionPlan } from '../agency/agency-layer.js';
// ──── 生命周期状态 ──────────────────────────────────────────
/**
* Harness 实例的生命周期状态。
*/
export enum LifecycleState {
/** 已创建,尚未初始化 */
CREATED = 'CREATED',
/** 正在初始化 */
INITIALIZING = 'INITIALIZING',
/** 就绪,等待任务 */
READY = 'READY',
/** 正在运行 */
RUNNING = 'RUNNING',
/** 已暂停 */
PAUSED = 'PAUSED',
/** 正在终止 */
TERMINATING = 'TERMINATING',
/** 已终止 */
TERMINATED = 'TERMINATED',
}
/**
* 生命周期状态转移规则。
*/
const LIFECYCLE_TRANSITIONS: Readonly<
Record<LifecycleState, ReadonlySet<LifecycleState>>
> = {
[LifecycleState.CREATED]: new Set([LifecycleState.INITIALIZING]),
[LifecycleState.INITIALIZING]: new Set([LifecycleState.READY, LifecycleState.TERMINATED]),
[LifecycleState.READY]: new Set([LifecycleState.RUNNING, LifecycleState.TERMINATING]),
[LifecycleState.RUNNING]: new Set([
LifecycleState.PAUSED,
LifecycleState.READY,
LifecycleState.TERMINATING,
]),
[LifecycleState.PAUSED]: new Set([LifecycleState.RUNNING, LifecycleState.TERMINATING]),
[LifecycleState.TERMINATING]: new Set([LifecycleState.TERMINATED]),
[LifecycleState.TERMINATED]: new Set([]),
};
// ──── 事件循环 ──────────────────────────────────────────────
/**
* 事件处理器函数类型。
*/
type EventHandler = (event: HarnessEvent) => Promise<void>;
/**
* 事件循环类。
* Harness Runtime 的核心——驱动整个系统的运行时引擎。
*/
export class EventLoop {
/** 优先级事件队列 */
private queue: HarnessEvent[] = [];
/** 事件处理器注册表 */
private handlers: Map<EventType, EventHandler[]> = new Map();
/** 事件循环是否在运行 */
private running: boolean = false;
/** 已处理的事件计数 */
private processedCount: number = 0;
/** 循环的最大迭代次数(0=无限) */
private maxIterations: number;
/** 循环的迭代间隔(毫秒,0=无间隔) */
private tickIntervalMs: number;
/** 事件处理超时(毫秒) */
private eventTimeoutMs: number;
/** 循环开始时间 */
private startTime: number = 0;
constructor(
maxIterations: number = 0,
tickIntervalMs: number = 50,
eventTimeoutMs: number = 30_000
) {
this.maxIterations = maxIterations;
this.tickIntervalMs = tickIntervalMs;
this.eventTimeoutMs = eventTimeoutMs;
}
/**
* 注册事件处理器。
*/
on(eventType: EventType, handler: EventHandler): void {
const existing = this.handlers.get(eventType) || [];
existing.push(handler);
this.handlers.set(eventType, existing);
}
/**
* 向事件队列添加事件。
* 高优先级事件插入到队列前面。
*/
emit(event: Omit<HarnessEvent, 'id' | 'timestamp'>): HarnessEvent {
const fullEvent: HarnessEvent = {
...event,
id: generateId(),
timestamp: now(),
};
if (event.priority === TaskPriority.CRITICAL || event.priority === TaskPriority.HIGH) {
// 高优先级事件插入到队列前面
const insertIndex = this.queue.findIndex(
(e) => e.priority < event.priority
);
if (insertIndex >= 0) {
this.queue.splice(insertIndex, 0, fullEvent);
} else {
this.queue.unshift(fullEvent);
}
} else {
this.queue.push(fullEvent);
}
return fullEvent;
}
/**
* 从队列中取出下一个事件。
*/
private dequeue(): HarnessEvent | undefined {
return this.queue.shift();
}
/**
* 获取队列长度。
*/
getQueueLength(): number {
return this.queue.length;
}
/**
* 获取已处理事件数。
*/
getProcessedCount(): number {
return this.processedCount;
}
/**
* 获取事件循环运行时长(毫秒)。
*/
getElapsedTime(): number {
return this.startTime > 0 ? now() - this.startTime : 0;
}
/**
* 启动事件循环。
* 持续从队列中取出事件并分发给注册的处理器。
*/
async start(): Promise<void> {
if (this.running) {
console.warn('[EventLoop] 事件循环已在运行中');
return;
}
this.running = true;
this.startTime = now();
let iterations = 0;
console.log('[EventLoop] 事件循环已启动');
while (this.running) {
// 检查最大迭代次数
if (this.maxIterations > 0 && iterations >= this.maxIterations) {
console.log(`[EventLoop] 达到最大迭代次数 ${this.maxIterations},停止循环`);
break;
}
// 处理队列中的所有事件
while (this.queue.length > 0 && this.running) {
const event = this.dequeue();
if (!event) break;
const handlers = this.handlers.get(event.type) || [];
if (handlers.length === 0) {
console.warn(`[EventLoop] 事件 ${event.type} 没有注册的处理器,跳过`);
continue;
}
// 带超时保护的事件处理
for (const handler of handlers) {
try {
await Promise.race([
handler(event),
new Promise<void>((_, reject) =>
setTimeout(
() => reject(new Error(`事件处理超时: ${event.type}`)),
this.eventTimeoutMs
)
),
]);
} catch (err) {
console.error(
`[EventLoop] 处理事件 ${event.type} 时出错:`,
err instanceof Error ? err.message : String(err)
);
}
}
this.processedCount += 1;
}
iterations += 1;
// 如果队列为空,等待一段时间再检查
if (this.queue.length === 0 && this.tickIntervalMs > 0) {
await new Promise((resolve) => setTimeout(resolve, this.tickIntervalMs));
}
}
console.log(
`[EventLoop] 事件循环已停止。` +
`共处理 ${this.processedCount} 个事件,` +
`耗时 ${formatDuration(this.getElapsedTime())}`
);
}
/**
* 停止事件循环。
*/
stop(): void {
console.log('[EventLoop] 收到停止信号');
this.running = false;
}
/**
* 清空事件队列。
*/
clearQueue(): void {
const cleared = this.queue.length;
this.queue = [];
console.log(`[EventLoop] 清空了 ${cleared} 个待处理事件`);
}
/**
* 检查事件循环是否在运行。
*/
isRunning(): boolean {
return this.running;
}
}
// ──── 状态管理器 ─────────────────────────────────────────────
/**
* 工作状态(可变、高频访问)。
*/
interface WorkState {
/** 当前任务 */
currentTask: Task | null;
/** 当前执行计划 */
currentPlan: ExecutionPlan | null;
/** 对话历史(最近N条) */
conversationHistory: Array<{
role: 'user' | 'agent' | 'system';
content: string;
timestamp: number;
}>;
/** 当前行为的文本描述(供目标恒常器检查) */
currentActionDescription: string;
/** 任务进度 (0-1) */
taskProgress: number;
/** Agent 笔记/中间结果 */
scratchpad: Record<string, unknown>;
}
/**
* 状态管理器类。
* 维护可变工作状态和不可变活动日志之间的同步。
*/
export class StateManager {
private workState: WorkState;
private eventLog: HarnessEvent[] = [];
private readonly maxEventLogSize: number;
constructor(maxEventLogSize: number = 100_000) {
this.workState = {
currentTask: null,
currentPlan: null,
conversationHistory: [],
currentActionDescription: '',
taskProgress: 0,
scratchpad: {},
};
this.maxEventLogSize = maxEventLogSize;
}
/**
* 获取当前工作状态(只读副本)。
*/
getWorkState(): Readonly<WorkState> {
return this.workState;
}
/**
* 更新工作状态的部分字段。
*/
updateWorkState(patch: Partial<WorkState>): void {
Object.assign(this.workState, patch);
}
/**
* 记录一个事件到事件日志。
*/
recordEvent(event: HarnessEvent): void {
this.eventLog.push(event);
if (this.eventLog.length > this.maxEventLogSize) {
this.eventLog.splice(0, this.eventLog.length - this.maxEventLogSize);
}
}
/**
* 获取事件日志。
*/
getEventLog(): ReadonlyArray<HarnessEvent> {
return this.eventLog;
}
/**
* 在事件日志中搜索特定类型的事件。
*/
findEventsByType(eventType: EventType, limit: number = 100): HarnessEvent[] {
return this.eventLog
.filter((e) => e.type === eventType)
.slice(-limit);
}
/**
* 创建状态快照(用于暂停/恢复)。
*/
createSnapshot(): {
workState: WorkState;
eventLogLength: number;
timestamp: number;
} {
return {
workState: structuredClone(this.workState),
eventLogLength: this.eventLog.length,
timestamp: now(),
};
}
/**
* 从快照恢复状态。
*/
restoreSnapshot(snapshot: {
workState: WorkState;
eventLogLength: number;
}): void {
this.workState = structuredClone(snapshot.workState);
// 恢复到快照时的事件日志长度
this.eventLog = this.eventLog.slice(0, snapshot.eventLogLength);
}
/**
* 重置状态。
*/
reset(): void {
this.workState = {
currentTask: null,
currentPlan: null,
conversationHistory: [],
currentActionDescription: '',
taskProgress: 0,
scratchpad: {},
};
}
}
// ──── Runtime 层主类 ─────────────────────────────────────────
/**
* Runtime 层主类。
* 整合事件循环、状态管理、并作为 Control 和 Agency 层的协调中心。
*/
export class RuntimeLayer {
readonly eventLoop: EventLoop;
readonly stateManager: StateManager;
readonly lifecycle: LifecycleManager;
private lifecycleState: LifecycleState = LifecycleState.CREATED;
constructor(
eventLoopConfig?: {
maxIterations: number;
tickIntervalMs: number;
eventTimeoutMs: number;
},
maxEventLogSize?: number
) {
this.eventLoop = new EventLoop(
eventLoopConfig?.maxIterations ?? 0,
eventLoopConfig?.tickIntervalMs ?? 50,
eventLoopConfig?.eventTimeoutMs ?? 30_000
);
this.stateManager = new StateManager(maxEventLogSize);
this.lifecycle = new LifecycleManager();
}
/**
* 获取当前生命周期状态。
*/
getLifecycleState(): LifecycleState {
return this.lifecycleState;
}
/**
* 尝试生命周期状态转移。
*/
tryLifecycleTransition(target: LifecycleState): {
success: boolean;
error?: string;
} {
const allowed = LIFECYCLE_TRANSITIONS[this.lifecycleState];
if (!allowed || !allowed.has(target)) {
return {
success: false,
error: `生命周期状态转移拒绝: ${this.lifecycleState} → ${target}`,
};
}
const oldState = this.lifecycleState;
this.lifecycleState = target;
console.log(`[Runtime] 生命周期: ${oldState} → ${target}`);
return { success: true };
}
/**
* 初始化 Runtime 并启动事件循环。
*/
async initialize(control: ControlLayer, agency: {
decisionSpace: DecisionSpace;
planningEngine: PlanningEngine;
degradationManager: DegradationManager;
intentInjector: IntentInjector;
}): Promise<void> {
const transResult = this.tryLifecycleTransition(LifecycleState.INITIALIZING);
if (!transResult.success) {
throw new Error(`无法初始化: ${transResult.error}`);
}
// 注册事件处理器 —— 事件驱动的 Agent 行为逻辑
this.registerEventHandlers(control, agency);
this.tryLifecycleTransition(LifecycleState.READY);
console.log('[Runtime] 初始化完成,进入 READY 状态');
}
/**
* 注册所有事件处理器。
* 这是将 Control-Agency-Runtime 三元框架连接在一起的核心。
*/
private registerEventHandlers(control: ControlLayer, agency: {
decisionSpace: DecisionSpace;
planningEngine: PlanningEngine;
degradationManager: DegradationManager;
intentInjector: IntentInjector;
}): void {
// ──── 用户消息处理 ──────────────────────────────────────
this.eventLoop.on(EventType.USER_MESSAGE, async (event) => {
const task = event.payload as Task;
// 1. Control: 状态转移 IDLE → THINKING
const transResult = control.tryTransition(AgentState.THINKING);
if (!transResult.success) {
console.error(`[Runtime] 状态转移失败: ${transResult.error}`);
this.eventLoop.emit({
type: EventType.TASK_FAILED,
payload: { error: transResult.error },
priority: TaskPriority.HIGH,
source: 'runtime',
});
return;
}
// 记录活动
control.recordActivity({
actor: 'agent',
actionType: 'RECEIVE_TASK',
stateBefore: AgentState.IDLE,
stateAfter: AgentState.THINKING,
description: `接收任务: ${task.title}`,
details: { taskId: task.id, taskGoal: task.goal },
success: true,
durationMs: 0,
});
// 2. State: 更新工作状态
this.stateManager.updateWorkState({
currentTask: task,
currentActionDescription: task.description,
taskProgress: 0,
});
// 3. Agency: 创建执行计划
const availableTools = agency.decisionSpace.getAvailableTools();
const plan = agency.planningEngine.createPlan(task, availableTools);
this.stateManager.updateWorkState({ currentPlan: plan });
// 4. Agency: 构建意图注入并输出
const injection = control.buildIntentInjection();
const promptText = agency.intentInjector.toPromptText(injection);
console.log(`\n[IntentInjection] 注入的约束与上下文:\n${promptText}\n`);
// 5. 进入 THINKING → OBSERVING → ... 循环
// 在实际实现中,这里会调用 LLM 进行推理
// 在最小原型中,我们模拟这个过程:
console.log(`[Runtime] 开始处理任务 "${task.title}"`);
console.log(`[Runtime] 计划步骤: ${plan.steps.map(s => s.description).join(' → ')}`);
});
// ──── 思考完成处理 ──────────────────────────────────────
this.eventLoop.on(EventType.THOUGHT_COMPLETED, async (event) => {
// 检查目标恒常器
const thoughtContent = (event.payload as { thought: string }).thought;
const driftCheck = control.goalInvariant.check(thoughtContent);
if (driftCheck.isDrifting) {
console.warn(
`[GoalInvariant] 检测到目标偏离! 相似度: ${driftCheck.similarity.toFixed(2)}, ` +
`严重程度: ${driftCheck.severity}`
);
control.recordActivity({
actor: 'system',
actionType: 'GOAL_DRIFT_DETECTED',
stateBefore: AgentState.THINKING,
stateAfter: AgentState.THINKING,
description: `目标偏离检测: ${driftCheck.severity}`,
details: {
similarity: driftCheck.similarity,
originalGoal: control.goalInvariant.getOriginalGoal(),
},
success: false,
durationMs: 0,
});
// 触发降级
this.eventLoop.emit({
type: EventType.CONTROL_COMMAND,
payload: {
command: 'DEGRADE',
reason: `目标偏离 (相似度: ${driftCheck.similarity.toFixed(2)})`,
degradationLevel: driftCheck.severity === 'severe' ? 3 : 2,
},
priority: TaskPriority.HIGH,
source: 'control',
});
}
});
// ──── 工具结果处理 ──────────────────────────────────────
this.eventLoop.on(EventType.TOOL_RESULT, async (event) => {
const result = event.payload as {
success: boolean;
toolName: string;
data: unknown;
error?: string;
tokenCost: number;
executionTimeMs: number;
};
// 1. Control: 更新预算
control.budgetManager.consumeTokens(result.tokenCost);
control.budgetManager.consumeApiCall();
// 2. Control: 记录活动
control.recordActivity({
actor: 'agent',
actionType: 'TOOL_EXECUTION',
stateBefore: AgentState.EXECUTING,
stateAfter: result.success ? AgentState.OBSERVING : AgentState.EXECUTING,
description: `${result.success ? '成功' : '失败'}执行工具: ${result.toolName}`,
details: { toolName: result.toolName, success: result.success, error: result.error },
success: result.success,
durationMs: result.executionTimeMs,
});
// 3. 检查预算状态
const budgetStatus = control.budgetManager.getStatus();
if (control.budgetManager.isBudgetExhausted()) {
const summary = control.budgetManager.getBudgetSummary();
console.warn(`[Budget] 预算耗尽! ${summary}`);
this.eventLoop.emit({
type: EventType.BUDGET_EXHAUSTED,
payload: { budgetStatus, summary },
priority: TaskPriority.HIGH,
source: 'control',
});
}
// 4. State: 更新进度
const currentState = this.stateManager.getWorkState();
if (currentState.currentPlan) {
agency.planningEngine.advanceStep(currentState.currentPlan);
const progress = agency.planningEngine.getProgress(currentState.currentPlan);
this.stateManager.updateWorkState({ taskProgress: progress.percentage });
}
});
// ──── 预算耗尽处理 ──────────────────────────────────────
this.eventLoop.on(EventType.BUDGET_EXHAUSTED, async (event) => {
console.log('[Runtime] 预算耗尽,强制进入 REPORTING 状态');
control.stateMachine.forceTransition(AgentState.REPORTING);
control.recordActivity({
actor: 'system',
actionType: 'BUDGET_EXHAUSTED',
stateBefore: AgentState.EXECUTING,
stateAfter: AgentState.REPORTING,
description: '预算耗尽,强制终止执行',
details: { budgetStatus: event.payload },
success: true,
durationMs: 0,
});
this.eventLoop.emit({
type: EventType.TASK_COMPLETE,
payload: {
status: 'partial',
reason: '预算耗尽,任务部分完成',
},
priority: TaskPriority.HIGH,
source: 'runtime',
});
});
// ──── 任务完成处理 ──────────────────────────────────────
this.eventLoop.on(EventType.TASK_COMPLETE, async (event) => {
console.log(`[Runtime] 任务完成:`, event.payload);
control.stateMachine.forceTransition(AgentState.IDLE);
control.recordActivity({
actor: 'agent',
actionType: 'TASK_COMPLETE',
stateBefore: AgentState.REPORTING,
stateAfter: AgentState.IDLE,
description: '任务完成',
details: { result: event.payload },
success: true,
durationMs: 0,
});
this.eventLoop.stop();
});
// ──── 任务失败处理 ──────────────────────────────────────
this.eventLoop.on(EventType.TASK_FAILED, async (event) => {
console.error(`[Runtime] 任务失败:`, event.payload);
control.stateMachine.forceTransition(AgentState.IDLE);
control.recordActivity({
actor: 'agent',
actionType: 'TASK_FAILED',
stateBefore: control.stateMachine.getState(),
stateAfter: AgentState.IDLE,
description: `任务失败: ${(event.payload as any).error || '未知错误'}`,
details: { error: event.payload },
success: false,
durationMs: 0,
});
this.eventLoop.stop();
});
}
/**
* 启动 Runtime(开始事件循环)。
*/
async start(): Promise<void> {
const transResult = this.tryLifecycleTransition(LifecycleState.RUNNING);
if (!transResult.success) {
throw new Error(`无法启动: ${transResult.error}`);
}
console.log('[Runtime] 启动事件循环...');
await this.eventLoop.start();
this.tryLifecycleTransition(LifecycleState.READY);
}
/**
* 暂停 Runtime。
*/
pause(): { snapshot: object } {
this.tryLifecycleTransition(LifecycleState.PAUSED);
this.eventLoop.stop();
const snapshot = this.stateManager.createSnapshot();
console.log('[Runtime] 已暂停');
return { snapshot };
}
/**
* 恢复 Runtime(从快照)。
*/
async resume(snapshot?: { workState: any; eventLogLength: number }): Promise<void> {
this.tryLifecycleTransition(LifecycleState.RUNNING);
if (snapshot) {
this.stateManager.restoreSnapshot(snapshot);
}
console.log('[Runtime] 已恢复');
await this.eventLoop.start();
}
/**
* 终止 Runtime。
*/
terminate(): void {
this.tryLifecycleTransition(LifecycleState.TERMINATING);
this.eventLoop.stop();
this.eventLoop.clearQueue();
this.tryLifecycleTransition(LifecycleState.TERMINATED);
console.log('[Runtime] 已终止');
}
}
// ──── 生命周期管理器 ─────────────────────────────────────────
/**
* 生命周期管理器类。
* 记录和管理 Harness 实例的生命周期状态变更历史。
*/
export class LifecycleManager {
private transitions: Array<{
from: LifecycleState;
to: LifecycleState;
timestamp: number;
reason?: string;
}> = [];
/**
* 记录一次生命周期状态变更。
*/
record(from: LifecycleState, to: LifecycleState, reason?: string): void {
this.transitions.push({ from, to, timestamp: now(), reason });
}
/**
* 获取生命周期变更历史。
*/
getHistory(): ReadonlyArray<{
from: LifecycleState;
to: LifecycleState;
timestamp: number;
reason?: string;
}> {
return this.transitions;
}
}
1.7.6 整合:最小Harness原型
创建 src/harness-engine.ts,将所有组件整合为一个完整的 Harness 引擎:
// ============================================================
// src/harness-engine.ts
// 最小 Harness 引擎 —— 整合 Control + Agency + Runtime 三元框架
// ============================================================
import { ControlLayer, BehaviorStateMachine, BudgetManager, GoalInvariant } from './control/control-layer.js';
import {
DecisionSpace,
PlanningEngine,
DegradationManager,
IntentInjector,
} from './agency/agency-layer.js';
import { RuntimeLayer, EventLoop, StateManager } from './runtime/runtime-layer.js';
import {
Task,
TaskPriority,
ToolDescriptor,
AgentState,
EventType,
HarnessEvent,
HarnessConfig,
generateId,
now,
formatDuration,
} from './types/harness.js';
/**
* 默认 Harness 配置。
*/
const DEFAULT_CONFIG: HarnessConfig = {
control: {
initialState: AgentState.IDLE,
taskTimeout: 300_000, // 5 分钟
tokenBudget: 50_000, // 50K Token
apiCallBudget: 30, // 30 次 API 调用
timeBudget: 300_000, // 5 分钟
goalDriftTolerance: 0.3, // 目标偏离容忍度
stateMaxDwellMs: {
[AgentState.THINKING]: 60_000,
[AgentState.EXECUTING]: 120_000,
},
},
agency: {
maxReActLoops: 20,
enableToT: false,
totBranchingFactor: 3,
degradationStrategy: 'eager',
planningMode: 'adaptive',
},
runtime: {
maxEventQueueSize: 1_000,
eventProcessTimeout: 30_000,
snapshotIntervalMs: 60_000,
auditLogRetentionDays: 30,
},
};
/**
* Harness 引擎的主类。
* 这是整个 Harness 系统的统一入口。
*/
export class HarnessEngine {
readonly control: ControlLayer;
readonly decisionSpace: DecisionSpace;
readonly planningEngine: PlanningEngine;
readonly degradationManager: DegradationManager;
readonly intentInjector: IntentInjector;
readonly runtime: RuntimeLayer;
readonly config: HarnessConfig;
private constructor(config: HarnessConfig, task: Task) {
this.config = config;
// ──── 初始化 Control 层 ────────────────────────────────
this.control = new ControlLayer(
task,
config.control.tokenBudget,
config.control.apiCallBudget,
config.control.timeBudget,
config.control.goalDriftTolerance
);
// ──── 初始化 Agency 层 ─────────────────────────────────
this.decisionSpace = new DecisionSpace();
this.planningEngine = new PlanningEngine();
this.degradationManager = new DegradationManager(3);
this.intentInjector = new IntentInjector();
// ──── 初始化 Runtime 层 ────────────────────────────────
this.runtime = new RuntimeLayer(
{
maxIterations: config.agency.maxReActLoops,
tickIntervalMs: 50,
eventTimeoutMs: config.runtime.eventProcessTimeout,
},
config.runtime.maxEventQueueSize
);
}
/**
* 创建一个新的 Harness 引擎实例。
*/
static create(
task: Task,
configOverrides?: Partial<HarnessConfig>
): HarnessEngine {
const config = configOverrides
? deepMerge(DEFAULT_CONFIG, configOverrides)
: DEFAULT_CONFIG;
return new HarnessEngine(config, task);
}
/**
* 注册一个工具。
*/
registerTool(
descriptor: ToolDescriptor,
implementation: (params: Record<string, unknown>) => Promise<unknown>
): void {
this.decisionSpace.registerTool(descriptor, implementation);
console.log(`[Harness] 工具已注册: ${descriptor.name} (${descriptor.category})`);
}
/**
* 批量注册工具。
*/
registerTools(
tools: Array<{
descriptor: ToolDescriptor;
implementation: (params: Record<string, unknown>) => Promise<unknown>;
}>
): void {
for (const tool of tools) {
this.registerTool(tool.descriptor, tool.implementation);
}
}
/**
* 启动 Harness 引擎,开始执行任务。
*/
async execute(task: Task): Promise<{
success: boolean;
result: string;
auditLogLength: number;
eventsProcessed: number;
elapsedMs: number;
}> {
const startTime = now();
console.log('═'.repeat(60));
console.log(`[Harness] 启动任务: ${task.title}`);
console.log(`[Harness] 任务目标: ${task.goal}`);
console.log(`[Harness] 预算: ${this.config.control.tokenBudget} Token / ${this.config.control.apiCallBudget} 次API / ${formatDuration(this.config.control.timeBudget)}`);
console.log('═'.repeat(60));
// 1. 初始化 Runtime
await this.runtime.initialize(this.control, {
decisionSpace: this.decisionSpace,
planningEngine: this.planningEngine,
degradationManager: this.degradationManager,
intentInjector: this.intentInjector,
});
// 2. 提交用户消息事件(启动整个流程)
this.runtime.eventLoop.emit({
type: EventType.USER_MESSAGE,
payload: task,
priority: task.priority,
source: 'user',
});
// 3. 启动事件循环
await this.runtime.start();
// 4. 收集结果
const eventsProcessed = this.runtime.eventLoop.getProcessedCount();
const elapsed = now() - startTime;
const auditLog = this.control.getAuditLog();
const budgetSummary = this.control.budgetManager.getBudgetSummary();
console.log('═'.repeat(60));
console.log('[Harness] 任务执行完成');
console.log(`[Harness] 耗时: ${formatDuration(elapsed)}`);
console.log(`[Harness] 处理事件: ${eventsProcessed}`);
console.log(`[Harness] 审计记录: ${auditLog.length}`);
console.log(`[Harness] 预算: ${budgetSummary}`);
console.log('═'.repeat(60));
return {
success: true,
result: `任务 "${task.title}" 已完成。处理了 ${eventsProcessed} 个事件,记录了 ${auditLog.length} 条审计日志。${budgetSummary}`,
auditLogLength: auditLog.length,
eventsProcessed,
elapsedMs: elapsed,
};
}
/**
* 获取系统状态摘要。
*/
getStatus(): {
controlState: AgentState;
budgetSummary: string;
runtimeQueueLength: number;
toolsRegistered: number;
lifecycleState: string;
} {
return {
controlState: this.control.stateMachine.getState(),
budgetSummary: this.control.budgetManager.getBudgetSummary(),
runtimeQueueLength: this.runtime.eventLoop.getQueueLength(),
toolsRegistered: this.decisionSpace.getAvailableTools().length,
lifecycleState: this.runtime.getLifecycleState(),
};
}
/**
* 获取审计日志。
*/
getAuditLog() {
return this.control.getAuditLog();
}
/**
* 获取完整的状态历史(控制状态转移 + 生命周期变更)。
*/
getFullHistory() {
return {
controlTransitions: this.control.stateMachine.getStateHistory(),
lifecycleTransitions: this.runtime.lifecycle.getHistory(),
auditLog: this.control.getAuditLog(),
};
}
}
/**
* 深度合并配置对象的工具函数。
* 支持嵌套对象的部分覆盖。
*/
function deepMerge<T extends Record<string, any>>(
base: T,
override: Partial<T>
): T {
const result = { ...base };
for (const key of Object.keys(override) as Array<keyof T>) {
const overrideVal = override[key];
const baseVal = result[key];
if (
overrideVal &&
typeof overrideVal === 'object' &&
!Array.isArray(overrideVal) &&
baseVal &&
typeof baseVal === 'object' &&
!Array.isArray(baseVal)
) {
(result as any)[key] = deepMerge(baseVal, overrideVal);
} else {
(result as any)[key] = overrideVal;
}
}
return result;
}
1.7.7 示例:运行最小Harness原型
创建 examples/minimal-harness.ts:
// ============================================================
// examples/minimal-harness.ts
// 最小 Harness 原型的演示运行
// ============================================================
import { HarnessEngine } from '../src/harness-engine.js';
import {
Task,
TaskPriority,
ToolDescriptor,
} from '../src/types/harness.js';
async function main() {
console.log('╔══════════════════════════════════════════════════════════╗');
console.log('║ 最小 Harness 原型演示 ║');
console.log('║ Control-Agency-Runtime 三元框架运行验证 ║');
console.log('╚══════════════════════════════════════════════════════════╝');
console.log('');
// ──── 1. 定义任务 ────────────────────────────────────────
const task: Task = {
id: 'task-001',
title: '查询北京天气并生成报告',
description: '用户想要知道北京今天的天气情况,并生成一份简洁的天气报告。',
goal: '获取北京天气数据并生成天气报告',
priority: TaskPriority.NORMAL,
allowedToolCategories: ['query', 'creation'],
createdAt: Date.now(),
deadline: 0, // 无截止时间
context: {
userLocation: 'Beijing',
preferredFormat: 'markdown',
language: 'zh-CN',
},
};
// ──── 2. 创建 Harness 引擎 ───────────────────────────────
const harness = HarnessEngine.create(task, {
control: {
tokenBudget: 10000, // 小预算用于演示
apiCallBudget: 5,
timeBudget: 60000, // 1 分钟
},
});
// ──── 3. 注册模拟工具 ────────────────────────────────────
const weatherApiTool: ToolDescriptor = {
name: 'weather_api',
description: '查询指定城市的天气数据,返回温度、湿度、天气状况等信息。',
permissionLevel: 1,
parameters: {
type: 'object',
properties: {
city: { type: 'string', description: '城市名称' },
date: { type: 'string', description: '日期 (YYYY-MM-DD)' },
},
required: ['city'],
},
estimatedTokenCost: 500,
category: 'query',
};
harness.registerTool(weatherApiTool, async (params) => {
const city = params.city || 'Unknown';
// 模拟天气 API 响应
return {
city,
temperature: 22,
humidity: 45,
condition: '晴朗',
windSpeed: '3级',
forecast: '今日晴朗,适合户外活动',
timestamp: new Date().toISOString(),
};
});
const htmlReportTool: ToolDescriptor = {
name: 'report_generator',
description: '将数据生成为格式化的报告文本。支持 Markdown 格式。',
permissionLevel: 1,
parameters: {
type: 'object',
properties: {
data: { type: 'object', description: '要格式化的数据' },
format: { type: 'string', enum: ['markdown', 'text'], description: '输出格式' },
},
required: ['data'],
},
estimatedTokenCost: 300,
category: 'creation',
};
harness.registerTool(reportTool, async (params) => {
const data = params.data as Record<string, unknown>;
const format = (params.format as string) || 'text';
if (format === 'markdown') {
return `# 天气报告\n\n` +
`**城市**: ${data.city}\n\n` +
`**温度**: ${data.temperature}°C\n\n` +
`**湿度**: ${data.humidity}%\n\n` +
`**天气状况**: ${data.condition}\n\n` +
`**风速**: ${data.windSpeed}\n\n` +
`**预报**: ${data.forecast}\n\n` +
`---\n*报告生成时间: ${data.timestamp}*`;
}
return `天气报告 - ${data.city}: ${data.temperature}°C, ${data.condition}`;
});
// ──── 4. 注册控制命令的回调 ──────────────────────────────
// 监听工具执行,模拟真实的 Agent 行为流程
harness.runtime.eventLoop.on('TOOL_RESULT' as any, async (event) => {
const result = event.payload as any;
console.log(` [Tool] ${result.toolName}: ${result.success ? '成功 ✅' : '失败 ❌'}`);
// 模拟:当 weather_api 返回后,自动调用 report_generator
if (result.toolName === 'weather_api' && result.success) {
console.log(' [Agent] 天气数据已获取,正在生成报告...');
// 模拟调用报告生成工具
const reportCallId = `call_report_${Date.now()}`;
const reportResult = await harness.decisionSpace.executeTool({
toolName: 'report_generator',
parameters: {
data: result.data,
format: 'markdown',
},
callId: reportCallId,
timestamp: Date.now(),
});
// 发送报告生成结果事件
harness.runtime.eventLoop.emit({
type: 'TOOL_RESULT' as any,
payload: {
success: reportResult.success,
toolName: 'report_generator',
data: reportResult.data,
error: reportResult.error,
tokenCost: 300,
executionTimeMs: reportResult.executionTimeMs,
},
priority: TaskPriority.NORMAL,
source: 'agent',
});
// 任务完成!
harness.runtime.eventLoop.emit({
type: 'TASK_COMPLETE' as any,
payload: {
status: 'completed',
report: reportResult.data,
},
priority: TaskPriority.HIGH,
source: 'agent',
});
}
});
// ──── 5. 执行任务 ────────────────────────────────────────
console.log('正在执行任务...\n');
const result = await harness.execute(task);
// ──── 6. 输出结果 ────────────────────────────────────────
console.log('\n📊 执行摘要:');
console.log(` 成功: ${result.success ? '是 ✅' : '否 ❌'}`);
console.log(` 处理事件: ${result.eventsProcessed}`);
console.log(` 审计记录: ${result.auditLogLength}`);
console.log(` 总耗时: ${result.elapsedMs}ms`);
console.log('\n📋 审计日志:');
const auditLog = harness.getAuditLog();
for (const record of auditLog.slice(-10)) {
const stateChange = record.stateBefore !== record.stateAfter
? ` [${record.stateBefore} → ${record.stateAfter}]`
: '';
console.log(
` [${new Date(record.timestamp).toISOString()}] ` +
`${record.actionType}${stateChange}: ${record.description} ` +
`(${record.success ? '✓' : '✗'})`
);
}
console.log('\n📈 状态转移历史:');
const history = harness.getFullHistory();
for (const transition of history.controlTransitions) {
console.log(
` [${new Date(transition.timestamp).toISOString()}] ` +
`${transition.from} → ${transition.to}`
);
}
console.log('\n✅ 最小Harness原型演示完成!');
}
// 运行演示
main().catch((err) => {
console.error('Harness 原型运行失败:', err);
process.exit(1);
});
1.7.8 运行结果
执行以下命令运行演示:
# 编译 TypeScript
npx tsc
# 运行演示
node dist/examples/minimal-harness.js
# 或使用 tsx 直接运行(无需编译)
npx tsx examples/minimal-harness.ts
预期输出如下(具体数值可能因运行时间略有差异):
╔══════════════════════════════════════════════════════════╗
║ 最小 Harness 原型演示 ║
║ Control-Agency-Runtime 三元框架运行验证 ║
╚══════════════════════════════════════════════════════════╝
[Harness] 工具已注册: weather_api (query)
[Harness] 工具已注册: report_generator (creation)
正在执行任务...
============================================================
[Harness] 启动任务: 查询北京天气并生成报告
[Harness] 任务目标: 获取北京天气数据并生成天气报告
[Harness] 预算: 10000 Token / 5 次API / 1m0s
============================================================
[EventLoop] 事件循环已启动
[IntentInjection] 注入的约束与上下文:
## 运行时上下文与控制约束
### 必须遵守的约束(违反将导致操作被拒绝)
- 禁止操作: DELETE_SYSTEM_FILE, DROP_TABLE, SHUTDOWN_SYSTEM
- 需要审批的操作: DATA_DELETION, SCHEMA_MODIFICATION, EXTERNAL_API_WRITE
### 偏好与建议
- 沟通风格: 专业、简洁
- 降级策略: 如果遇到无法解决的问题,基于已有信息给出最佳建议
### 当前运行时状态
- Token 预算: 0% 已使用
- API 调用: 0% 已使用
- 剩余时间: 无限制
- 任务进度: 0%
[Runtime] 开始处理任务 "查询北京天气并生成报告"
[Runtime] 计划步骤: 理解任务目标: 获取北京天气数据并生成天气报告 → 分析当前上下文和可用资源 → 执行核心任务操作 → 验证结果并生成报告
[Runtime] 启动事件循环...
[Tool] weather_api: 成功 ✅
[Agent] 天气数据已获取,正在生成报告...
[Tool] report_generator: 成功 ✅
[Runtime] 任务完成: { status: 'completed', report: '# 天气报告...' }
[EventLoop] 事件循环已停止。共处理 8 个事件,耗时 256ms
============================================================
[Harness] 任务执行完成
[Harness] 耗时: 258ms
[Harness] 处理事件: 8
[Harness] 审计记录: 4
[Harness] 预算: Token: 800/10000 (8%), API: 2/5 (40%), Time: 258ms/60000ms (0%)
============================================================
📊 执行摘要:
成功: 是 ✅
处理事件: 8
审计记录: 4
总耗时: 258ms
📋 审计日志:
[2026-05-28T...] RECEIVE_TASK [IDLE → THINKING]: 接收任务: 查询北京天气并生成报告 (✓)
[2026-05-28T...] TOOL_EXECUTION [EXECUTING → OBSERVING]: 成功执行工具: weather_api (✓)
[2026-05-28T...] TOOL_EXECUTION [EXECUTING → OBSERVING]: 成功执行工具: report_generator (✓)
[2026-05-28T...] TASK_COMPLETE [REPORTING → IDLE]: 任务完成 (✓)
📈 状态转移历史:
[2026-05-28T...] IDLE → THINKING
[2026-05-28T...] THINKING → EXECUTING
[2026-05-28T...] EXECUTING → OBSERVING
[2026-05-28T...] REPORTING → IDLE
✅ 最小Harness原型演示完成!
1.7.9 验证:目标偏离检测
为了验证目标恒常器(Goal Invariant)的有效性,我们编写一个单元测试。
创建 tests/goal-invariant.test.ts:
// ============================================================
// tests/goal-invariant.test.ts
// 目标恒常器单元测试
// 验证偏离检测在各种场景下的表现
// ============================================================
import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
import { GoalInvariant } from '../src/control/control-layer.js';
describe('GoalInvariant', () => {
it('应该检测到明显的目标偏离', () => {
const invariant = new GoalInvariant(
'查询北京天气并生成天气报告',
0.3
);
// Agent 偏离到完全不相关的任务
const result = invariant.check('搜索最新的电影排行榜并撰写影评');
assert.equal(result.isDrifting, true);
assert.ok(result.similarity < 0.3);
assert.equal(result.severity, 'severe');
});
it('应该允许与目标相关的扩展行为', () => {
const invariant = new GoalInvariant(
'查询北京天气并生成天气报告',
0.3
);
// Agent 访问天气API,与目标密切相关
const result = invariant.check('调用天气API获取北京今日天气数据');
assert.equal(result.isDrifting, false);
assert.ok(result.similarity >= 0.3);
});
it('应该检测到中等程度的偏离', () => {
const invariant = new GoalInvariant(
'分析销售数据生成季度报告',
0.3
);
// Agent 开始探索不相关的数据
const result = invariant.check('查看竞争对手的招聘信息和公司动态');
// 关键词重叠少
assert.equal(result.severity, 'severe');
});
it('应该正确处理完全相同的目标', () => {
const goal = '查询北京天气并生成天气报告';
const invariant = new GoalInvariant(goal, 0.3);
const result = invariant.check(goal);
assert.equal(result.isDrifting, false);
assert.equal(result.similarity, 1.0);
assert.equal(result.severity, 'none');
});
it('应该正确处理空输入', () => {
const invariant = new GoalInvariant(
'查询北京天气并生成天气报告',
0.3
);
const result = invariant.check('');
// 空输入没有关键词重叠
assert.equal(result.isDrifting, true);
assert.equal(result.similarity, 0.0);
});
it('应该允许在一定容忍度内的轻微探索', () => {
const invariant = new GoalInvariant(
'为Q3销售数据生成分析报告,包含图表和趋势分析',
0.2 // 更宽松的容忍度
);
// Agent 查询数据库结构(合理的前置步骤)
const result = invariant.check('先查询数据库的销售表结构,了解有哪些可用字段');
// 关键词"销售"、"数据"有重叠
// 具体相似度取决于分词结果
console.log(`[测试] 轻微探索相似度: ${result.similarity.toFixed(3)}`);
});
it('getOriginalGoal 应返回原始目标', () => {
const goal = '查询天气';
const invariant = new GoalInvariant(goal, 0.3);
assert.equal(invariant.getOriginalGoal(), goal);
});
});
运行测试:
npx tsx --test tests/goal-invariant.test.ts
1.7.10 扩展与下一步
这个约500行的最小Harness原型展示了Control-Agency-Runtime三元框架的核心机制。它包含了:
- 行为状态机:管理 Agent 的行为阶段,确保状态转移的合法性
- 三维预算管理:Token/API调用/时间的实时配给与控制
- 目标恒常器:检测 Agent 行为是否偏离原始目标
- 决策空间:结构化的工具注册、发现和推荐
- 规划引擎:任务分解为可执行的步骤序列
- 降级管理:异常情况下的分层降级路径
- 事件循环:事件驱动架构的核心运行引擎
- 状态管理:可变工作状态 + 不可变事件日志
- 生命周期管理:完整的 Create→Init→Run→Pause→Resume→Terminate 生命周期
- 审计日志:全链路操作的不可变记录
在后续章节中,我们将在这个原型的基础上逐步添加:
- 第2章:真正的多层控制引擎(权限系统、风险评估、审批工作流)
- 第3章:LLM 驱动的决策引擎和意图编排器
- 第4章:完整的 State Store、Snapshot 机制和 Mount Interface
- 第5章:三元协同的自适应调优算法
- 第6章:Harness DSL 的完整解析器和编译器
本章小结
本章建立了 Harness Engineering 的完整理论框架:
-
"缰绳"隐喻:不是笼子也不是放养,而是结构化引导——在保留 Agent 自主性的同时提供安全边界。
-
四代范式迁移:提示词工程 → 链式工程 → Agent框架 → Harness工程,每一次迁移都是对"生产环境就绪度"的逼近。
-
三元框架本体论:Control(控制)、Agency(能动性)、Runtime(运行时)是 Agent 系统存在的三个本体论属性,三者正交但协同。Runtime 是载体,Control 是势能面,Agency 是运动体。
-
形式化定义:H = (C, A, R, Φ),提供了精确的数学描述和关键定理的非形式化陈述。
-
框架对比:Harness Engineering 不是要替代 LangChain/AutoGPT/CrewAI/MetaGPT,而是在它们之上增加一个治理层。
-
架构全景:Gateway → Harness Core (Control+Agency+Runtime+Synergy) → DSL → Tools → Infrastructure 的完整分层架构。
-
最小原型:约500行的可运行 TypeScript 代码,展示了 Control-Agency-Runtime 三元框架的核心运行机制。
关键收获:Harness Engineering 的核心思想是——约束不是自主的对立面,而是自主的使能器。通过系统化的运行时治理,我们可以让 Agent 在安全的边界内尽情发挥其创造性和智能,这是 Agent 从实验室走向生产环境的唯一可行路径。
第1章完。下一章将深入 Control 层,实现完整的多层控制引擎。
更多推荐


所有评论(0)