第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 的自主能力,但也暴露了致命的弱点:

  1. 无限循环:Agent 陷入"思考→行动→观察→思考"的死循环
  2. 任务漂移:Agent 在探索过程中偏离原始目标
  3. 资源耗尽:无限制的 API 调用和工具使用导致成本失控
  4. 不可预测性:相同的输入可能产生截然不同的执行路径

这些问题不是个别框架的实现缺陷,而是"纯自主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 需要保持一致的"人格"和行为模式。身份连续性通过以下机制保证:

  1. 人格快照:定期将 Agent 的行为偏好和决策模式持久化
  2. 记忆检索:在每次决策前,检索相关的历史决策和经验
  3. 一致性检查:检测当前行为是否与已建立的行为模式一致

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 建立一套精确的形式化定义。这不仅仅是理论的"锦上添花"——形式化定义有以下实用价值:

  1. 精确性:消除自然语言描述的歧义,确保实现不偏离设计
  2. 可验证性:提供系统属性(如安全性、有界性)的形式化证明基础
  3. 可复现性:让不同的实现者可以独立验证其系统是否符合 Harness Engineering 规范
  4. 可扩展性:为元控制(第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 给工程师的总结

如果你对数学不感兴趣,只需要记住以下几点:

  1. Harness = 控制 + 能动性 + 运行时 + 协同,四者缺一不可
  2. 状态转移必须满足约束(不变量),就像物理世界必须满足能量守恒定律
  3. 三个维度正交但协同,意味着你可以独立配置每个维度,但系统会自动协调
  4. 形式化定义保证了安全性不是"尽力而为"而是"数学上的必然"

这些形式化原则将贯穿本书的所有实现。每当我们实现一个 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 核心引擎

这是整个平台的"大脑",包含四个核心组件:

  1. Control 层引擎(第2章):

    • 行为状态机:管理 Agent 的行为阶段(IDLE/THINKING/EXECUTING/OBSERVING/DEGRADING/REPORTING)
    • 预算管理器:三维预算(Token/API调用/壁钟时间)的实时监控和动态调整
    • 目标恒常器:检测 Agent 是否偏离原始任务目标
    • 审计记录器:全链路操作的不可变记录
  2. Agency 层引擎(第3章):

    • 决策空间:为 Agent 提供结构化的"选项菜单"
    • 意图注入器:将控制约束和用户偏好注入 Agent 的推理上下文
    • 规划引擎:生成和管理任务执行计划(支持 ReAct、ToT、Plan-and-Execute 等策略)
    • 降级管理器:在异常情况下选择和执行降级路径
  3. Runtime 层引擎(第4章):

    • 事件循环:驱动整个系统的核心循环(接收事件→分发→处理→产生新事件)
    • 状态管理器:维护可变工作状态和不可变事件日志
    • 挂载管理器:管理统一 Mount Interface 的注册、发现和生命周期
    • 生命周期管理器:Agent 实例的创建/初始化/运行/暂停/恢复/终止
  4. 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三元框架的核心机制。它包含了:

  1. 行为状态机:管理 Agent 的行为阶段,确保状态转移的合法性
  2. 三维预算管理:Token/API调用/时间的实时配给与控制
  3. 目标恒常器:检测 Agent 行为是否偏离原始目标
  4. 决策空间:结构化的工具注册、发现和推荐
  5. 规划引擎:任务分解为可执行的步骤序列
  6. 降级管理:异常情况下的分层降级路径
  7. 事件循环:事件驱动架构的核心运行引擎
  8. 状态管理:可变工作状态 + 不可变事件日志
  9. 生命周期管理:完整的 Create→Init→Run→Pause→Resume→Terminate 生命周期
  10. 审计日志:全链路操作的不可变记录

在后续章节中,我们将在这个原型的基础上逐步添加:

  • 第2章:真正的多层控制引擎(权限系统、风险评估、审批工作流)
  • 第3章:LLM 驱动的决策引擎和意图编排器
  • 第4章:完整的 State Store、Snapshot 机制和 Mount Interface
  • 第5章:三元协同的自适应调优算法
  • 第6章:Harness DSL 的完整解析器和编译器

本章小结

本章建立了 Harness Engineering 的完整理论框架:

  1. "缰绳"隐喻:不是笼子也不是放养,而是结构化引导——在保留 Agent 自主性的同时提供安全边界。

  2. 四代范式迁移:提示词工程 → 链式工程 → Agent框架 → Harness工程,每一次迁移都是对"生产环境就绪度"的逼近。

  3. 三元框架本体论:Control(控制)、Agency(能动性)、Runtime(运行时)是 Agent 系统存在的三个本体论属性,三者正交但协同。Runtime 是载体,Control 是势能面,Agency 是运动体。

  4. 形式化定义:H = (C, A, R, Φ),提供了精确的数学描述和关键定理的非形式化陈述。

  5. 框架对比:Harness Engineering 不是要替代 LangChain/AutoGPT/CrewAI/MetaGPT,而是在它们之上增加一个治理层。

  6. 架构全景:Gateway → Harness Core (Control+Agency+Runtime+Synergy) → DSL → Tools → Infrastructure 的完整分层架构。

  7. 最小原型:约500行的可运行 TypeScript 代码,展示了 Control-Agency-Runtime 三元框架的核心运行机制。

关键收获:Harness Engineering 的核心思想是——约束不是自主的对立面,而是自主的使能器。通过系统化的运行时治理,我们可以让 Agent 在安全的边界内尽情发挥其创造性和智能,这是 Agent 从实验室走向生产环境的唯一可行路径。


第1章完。下一章将深入 Control 层,实现完整的多层控制引擎。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐