Agent Platform · Detail Design

Harness 内核设计

面向企业 Agent Platform 的执行内核设计:把“模型会思考”收敛为“系统可治理、过程可恢复、结果可审计”。

返回文档目录平台首页

Run 管理器

创建 run_id、绑定 session、维护 RunState

工具调用控制器

Skill schema 注入、参数校验、调用执行与重试

审计追踪器

所有终态前必须写 Trace / Audit

Core Flow Diagram
Pipeline
Run 创建→Context→Skill→Plan→Policy→Tool→HITL→Trace

详细设计说明

DESIGN DOCUMENT · HARNESS KERNEL

把 Agent 执行从“调用链”升级为“可治理运行时”

这份文档建议按“为什么要做、系统边界是什么、核心机制怎么保证稳定、工程如何落地”的顺序阅读。现在的重点不只是说明八个步骤,而是让评审者一眼看清:Harness 是企业 Agent Platform 的执行控制面。

设计主张

Harness 不直接追求“更聪明”,而是把模型、工具、审批、审计和状态恢复统一收敛到一个执行内核里,让企业可以安全地把 Agent 接入真实业务系统。

状态机约束双守门员准备/执行分离强制 Trace

评审关注点

  • 每一次运行是否有明确 Run 状态?
  • 工具调用前是否经过 Policy / HITL?
  • 异常、拒绝、超时是否都能进入 Trace?
  • 未来替换模型或 Skill 时,契约是否稳定?
D1 状态机所有运行态显式定义
D2 无副作用准备规划失败可重试
D3 双守门员Policy + HITL
D4 必经 Trace成功失败都留痕
D5 契约隔离步骤可替换可演进

第一章:Harness 定位与概念

SECTION GOAL

一句话回答三件事——Harness 是什么、住在三层架构的哪一层、和普通 LLM 调用链有什么本质差异。本章是全文的入口,后续章节都基于这里建立的认知展开。

1.1 总体架构图

Harness 是 Tier 3 执行内核,承担"一次 Run 的确定性执行"。它不关心用户从哪个产品入口发消息(那是 Tier 1 应用层的事),也不负责把多次 Run 编织成业务流(那是 Tier 2 协同运行时)。

Harness 在三层架构里的位置(Tier 3 · 执行内核)
Tier 1 · App Agent Platform 应用层 PRODUCT Agent 管理 个人 / 项目 / Team 协作工作台 @ 派单 / 群 能力中心 Skill / Tool / 知识 运营控制台 审计 / 成本 开放平台 API / SDK Tier 2 · Runtime 协同运行时 ORCHESTRATION 多 Agent 协作 Coordinator · DelegationTrace 任务调度 父子 Run · Sequential 会话与 Session 跨 Run 上下文 共享记忆 Team / User scope ★ Tier 3 · Kernel Harness 执行内核 本文档主题 单 Run 确定性执行 Run 管理器 RunState 状态机 上下文装配器 memory + history 计划执行器 LLM Plan 工具调用控制器 外部 IO 收口 HITL 控制器 Policy + 审批 审计追踪器 Trace 留痕 PIPELINE ① Run 创建 → ② 上下文装配 → ③ Skill 加载 → ④ Plan 规划 → ⑤ Policy 校验 → ⑥ Tool 调用 → ⑦ HITL 审批 → ⑧ Trace 留痕 CROSS-CUTTING · 横切关注点 治理 / Governance 可观测 / Observability 隔离 / Isolation 三条线贯穿 T1 / T2 / T3,不属于任何一层但每层都受其约束 控制权下沉
Harness 在 Tier 3,由 6 个组件承载下文「八步执行管道」。Tier 1 / Tier 2 在本文档里仅作参照,详细见 三层架构设计 ↗。

1.2 三句话核心哲学

整个设计可以归结为三条强约束。后续所有章节的字段定义、状态转移、契约边界都是这三条的展开。

  1. 状态机 + 双守门员——所有运行态显式定义;Policy(自动规则)和 HITL(人工审批)互补,不能互相替代。
  2. 审计强约束——不经 Trace 的执行等于没有发生。成功、被拒、失败三条路径都必须在 Trace 中留下完整记录。
  3. 准备与执行分离——阶段 B(②③④)是纯计算 + 只读,失败可重试且不污染外部状态;阶段 C(⑤⑥⑦)才产生副作用,由 Policy + HITL 把守入口。

顶部 D1–D5 五大工程决策是这三句哲学的细化,请回顾页面顶部 decision-strip。


第二章:八步执行管道详细设计

SECTION GOAL

把一次 Agent Run 拆成创建、准备、执行、收口四个阶段,明确每一步的输入输出、失败处理和代码位置。

目标读者:后端工程师
使用场景:实现新步骤、替换某步实现、性能调优、调试超时

2.1 总体架构

Harness Pipeline · 八步执行管道
阶段 A · 创建 INGRESS 阶段 B · 准备 无副作用 · 可重试 PREPARE 阶段 C · 执行 双守门员 EXECUTE 阶段 D · 收口 必经 Trace CLOSE ▶ 用户输入 消息 / 邮件 / API 进入系统 ① Run 创建 run_id · session · 初始状态 ② 上下文装配 memory · system · history ③ Skill 加载 schema · 权限 · 版本 ④ Plan 规划 LLM 分解步骤序列 ⑤ Policy 校验 ▼ 权限 · 成本 · 风险 ⑥ Tool 调用 Skill / LLM / Sandbox ⑦ HITL 审批 ▼ 高风险才走 ⑧ Trace 留痕 审计 · 成本 · 状态收口 终态交付 SUCCEEDED REJECTED FAILED PATH LEGEND 主路径 通过 → 收口 异常 / 拒绝路径
主路径:用户输入 → ① → ② → ③ → ④ → ⑤ → ⑥ → ⑦ → ⑧ → 终态。决策节点(⑤ Policy / ⑦ HITL,金色虚线边)和拒绝/失败路径都必须经过 ⑧ Trace 才能进入终态。

2.1.5 内部组件时序图

下图把 Harness 的 6 个内部组件画成 sequence diagram,明确"哪一步由谁负责、跨组件的调用顺序是什么"。左边界是外部 Caller(T2 Coordinator),最右是审计追踪器。实线=必走,虚线=条件触发(HITL 仅在高风险才走)。点击任意 lifeline 头部色块可跳到下面对应组件的详解章节。

Harness Internal · 6 组件 + 外部依赖时序图
Caller / T2 EXT BOUNDARY Run 管理器 RunState 上下文装配器 CTX ASSEMBLER 计划执行器 PLAN EXEC 工具调用控制器 TOOL CTRL HITL 控制器 POLICY + HITL LLM API EXT · CLAUDE/GPT Skill / Sandbox EXT · MCP / OpenClaw 审计追踪器 TRACE 1 create_run · 8步① 2 PREPARING · 装配 3 8步② ctx 就绪 memory + system prompt 4 8步③ Skill schema 5 schema 返回 6 8步④ Plan 推理 → LLM 7 Plan 返回(步骤 + tool 序列) 8 8步⑤ Policy 评估 9 ↻ Policy 自动判断 10 ⤺ 8步⑦ HITL 请求(高风险才走) 11 ↪ 批准 / 拒绝 12 通行 13 8步⑥ Tool 执行 → Skill/Sandbox 14 LLM 推理(LLM 作为 Tool 之一) 15 Skill 结果 + LLM 响应回包 16 结果 → Plan → Run 终态 17 8步⑧ 写 RunTrace / StepTrace / ToolTrace 18 ResultSink
实线=必走 · 虚线=条件触发(HITL 仅高风险) · ↻=组件内自循环 · 数字编号 = 跨组件调用顺序 · 圆点颜色 = 发起方组件
读图要点: 三类 lifeline 用边框区分——实线是 Harness 内部 6 组件,虚线是外部依赖(Caller / LLM / Skill·Sandbox)。一次 Run 会跨 3 次外部边界:⑥⑦ LLM Plan 推理(计划执行器 → LLM API)、⑬⑭⑮ Tool 执行(工具调用控制器 → Skill/Sandbox + LLM as Tool)、⑩⑪ HITL 审批(高风险才走,虚线箭头)。Run 管理器贯穿全程作"主控",计划执行器作"调度中心",工具调用控制器是所有外部 IO 的统一收口——LLM 调用、Skill 执行、沙箱命令都走它。

第三章:6 组件详解 · 沿时序图节点逐个剖析

SECTION GOAL

沿上一章时序图的 6 条内部 lifeline,按顺序逐个剖析:每个组件的职责、它在时序图里收发哪些调用、输入输出契约、关键不变量、失败处理。

3.1 Run 管理器 · 主控(Run Lifecycle Owner)

Role · 主控

维护单次 Run 的状态机,所有终态必须汇回它。它是 Run 生命周期的唯一所有者,激活条贯穿整个时序图。

11 个 RunState激活贯穿全程必经 TRACING

时序图位置

  • 接收 ① create_run(来自 Caller)
  • 发送 ② 装配请求(→ 上下文装配器)
  • 接收 ⑯ 终态汇回(来自 计划执行器)
  • 发送 ⑰ 写 Trace(→ 审计追踪器)
  • 发送 ⑱ ResultSink(→ Caller)

输入输出

方向触发载荷要点状态影响
入Caller create_runuser_input · session_id · caller_identity · chain_remaining(如有)CREATED → PREPARING
出装配请求session 上下文骨架 · 租户 / 用户隔离信息保持 PREPARING
入组件返回(终态)SUCCEEDED 结果 / REJECTED 原因 / FAILED 错误EXECUTING / AWAITING_HITL → TRACING
出写 TraceRunTrace 主记录 · 状态转移序列 · 关闭原因TRACING → CLOSED_*
出ResultSink结构化 answer / artifacts / Trace 索引 · 终态码终态稳定,向 Caller 返回

11 个 RunState 与转移

Run State Machine · 状态流转
阶段 1 · 主路径
正常执行
CREATED消息到达
→
PREPARING上下文装配
→
PLANNING计划生成
→
POLICY_CHECK策略判断
→
EXECUTING执行工具
阶段 2 · 收口
所有终态必经
TRACING审计留痕、成本结算、状态收口
阶段 3 · 中间分支
暂停或异常
AWAITING_HITL人工审批中;通过后回到 EXECUTING
REJECTED / TIMEOUT策略拒绝、人工拒绝或审批超时
FAILED执行异常进入失败态
阶段 4 · 最终关闭态
只能在 TRACING 之后
SUCCEEDED主路径成功
CLOSED_REJECTED被拒结束
CLOSED_FAILED失败结束
约束:REJECTED / FAILED / TIMEOUT 必须先进入 TRACING(阶段 2),再进入最终关闭态(阶段 4)。

关键不变量

失败处理

失败类型触发态处理
装配 / 规划阶段异常PREPARING / PLANNING可重试(无副作用);超过重试上限 → FAILED → TRACING → CLOSED_FAILED
Policy 拒绝POLICY_CHECKREJECTED → TRACING → CLOSED_REJECTED
HITL 超时AWAITING_HITLTIMEOUT → TRACING → CLOSED_REJECTED
工具执行异常EXECUTING按 Skill 重试策略;最终失败 → FAILED → TRACING → CLOSED_FAILED
僵尸 Run任意中间态外部巡检触发强制 → TIMEOUT → TRACING → CLOSED_FAILED

3.2 上下文装配器 · 准备(Context Assembler)

Role · 准备

把 system prompt、对话历史、用户记忆、知识库召回、租户隔离信息组装成一份token 预算可控的 ctx,交给计划执行器。

无副作用可重试token 预检

时序图位置

  • 接收 ② 装配请求(来自 Run 管理器)
  • 发送 ③ ctx 就绪(→ 计划执行器)

输入输出

方向载荷要点
入session_id · user_input · caller_identity · tenant_id · 历史消息上限 / 召回 scope
出 (AssembledContext)system prompt · 对话 history · 召回 memory entries · 知识库片段 · token 预算余量 · 安全过滤标记

子能力(5 件事必须独立测试)

子能力责任失败处理
预检system + history + tools + memory token 总量预估超预算 → 触发压缩
召回按 tenant / user / session / team scope 召回相关 memory召回失败降级到无 memory,记录 trace
压缩保留:用户目标 / 约束 / 工具关键结果 / HITL 决策压缩信息丢失关键项 → 拒绝执行(防错答)
隔离tenant / user / session / team 四层 scope 强制跨 tenant 串记忆 = 一票否决
安全过滤OAuth token / cookie / 临时密钥 / 短期 PII 不进 ctx过滤失败 → 拒绝执行

关键不变量

3.3 计划执行器 · 调度中心(Plan Orchestrator)

Role · 调度中心

拿到 ctx 后驱动整条决策路径:加载 Skill schema → 调 LLM 生成 Plan → 提交 Policy 评估 → 通过后调度 Tool 调用控制器 → 收口结果。

编排者LLM 调用方DAG / Plan

时序图位置

  • 接收 ③ ctx 就绪 / ⑤ schema 返回 / ⑦ Plan 返回 / ⑯ 工具结果回包
  • 发送 ④ 加载 Skill schema / ⑥ LLM Plan 推理 / ⑧ Policy 评估请求
  • 终态时把结果交回 Run 管理器

输入输出

方向对端载荷要点
入上下文装配器AssembledContext
出工具调用控制器Skill 加载请求(按权限过滤)
入工具调用控制器Skill schema 列表(含 manifest_hash)
出LLM APIPlan 推理请求 · prompt + tool schemas
入LLM APIPlan 返回 · 步骤序列 / DAG / 工具调用计划
出HITL 控制器Plan + CallerIdentity,请求 Policy 评估
入工具调用控制器Tool 执行结果汇总
出Run 管理器Run 终态(成功 / 失败 / 拒绝)

Plan 结构

字段含义
steps顺序步骤列表,每步包含目标、输入引用、输出键
tool_calls每个步骤要调的 Skill / LLM 调用请求
dependencies步骤间的有向依赖(DAG)
requires_authorization是否需要 HITL 审批(由 Policy 校验后置标记)
budget_estimate预估 token / 成本

关键不变量

3.4 HITL 控制器 · 双守门员(Policy + HITL)

Role · 双守门员

同时承担自动 Policy 评估(已知规则)和人工 HITL 审批(高风险)。是唯一会跨出 Harness 边界请求 Caller 的内部组件。

Policy 自动判HITL 人工审Break-Glass 不绕审计

时序图位置

  • 接收 ⑧ Policy 评估请求(来自 计划执行器)
  • 自环 ⑨ Policy 自动判断
  • 条件发送 ⑩ HITL 请求(→ Caller,虚线)
  • 条件接收 ⑪ 批准 / 拒绝(来自 Caller,虚线)
  • 发送 ⑫ 通行(→ 工具调用控制器)

Policy 分层

Policy Engine · 规则路由与决议
Plan + CallerIdentity计划与调用人身份
→
规则路由按规则类型分发
结构性规则DAG / Plan 校验
权限规则RBAC 矩阵
成本预算规则Run / User / Workspace 上限
安全护栏敏感操作拦截
统一决议pass / reject / await_hitl
→
pass→ ⑫ 通行
reject→ Run 终态 REJECTED
await_hitl跨边界请求

风险三档(决策树)

HITL Routing · 工具调用风险分流
Tool 调用动作准备执行的外部动作
→
是否不可逆?读写、影响范围、恢复成本
否 · 只读全自动执行
是 · 写操作继续判断资源类型
个人空间低风险自动;中风险本人确认;高风险审批人
项目空间本人确认
生产环境双人复核

四级审批层级

级别触发审批人超时动作
L1 · 自动通过低风险只读 / 个人沙箱写无—
L2 · 本人确认项目空间写 / 中等成本用户本人超时 → REJECTED
L3 · 审批人审批生产环境 / 不可逆 / 高成本指定审批人超时升级 L4 或 REJECTED
L4 · 双人复核金额操作 / 权限变更 / 数据破坏2 名审批人独立批准任一拒绝即终态 REJECTED

关键不变量

3.5 工具调用控制器 · 外部 IO 收口(Tool Controller)

Role · 外部 IO 收口

所有跨出 Harness 进程的执行都由它发起:Skill 调用 / Sandbox 执行 / LLM 推理(作为 Tool 之一)。是 LLM、Skill、沙箱三者的统一调度入口。

Skill 加载manifest 锁定重试 / 熔断沙箱 Provider

时序图位置

  • 接收 ④ Skill schema 请求(来自 计划执行器)
  • 发送 ⑤ schema 返回
  • 接收 ⑫ 通行(来自 HITL 控制器)
  • 发送 ⑬ Tool 执行(→ Skill / Sandbox)
  • 发送 ⑭ LLM 推理(→ LLM API · LLM 作为 Tool)
  • 接收 ⑮ Skill / LLM 结果
  • 发送 ⑯ 整合结果(→ 计划执行器)

Skill 加载契约

步骤动作
权限过滤按 Caller 身份与 RBAC 过滤可见 Skill 列表
版本锁定记录每个 Skill 的 manifest_hash,避免运行中遇到破坏性升级
schema 转换转成 LLM tool schema 格式(OpenAI 风格 / Anthropic 风格自适配)
Trace 标记把 skill_id + version + manifest_hash 写入 Run 上下文,便于 Replay

Tool 调用执行

调用类型路径边界
本地 Skill同进程函数调用不进沙箱(LLM / DB / 外部 API / Memory)
沙箱 SkillSandbox Provider → 容器进沙箱(claude_code / shell_exec / 起服务 / 装依赖)
LLM 调用HTTPS → LLM API不进沙箱(HTTPS 出站)
AgentInvoke 调用Tier 2 · Coordinator → child Run → ResultSink 回填跨 Run 边界(不进沙箱);T3 视角下与一次"慢 Tool 调用"等价,Run 状态保持 EXECUTING,靠 budget.deadline 兜底超时

沙箱边界详见 执行拓扑 · 沙箱边界 ↗。AgentInvoke 协议详见 多 Agent 协作协议 ↗——内核只认它是第 4 类 Tool,不引入 Round / Delegation / Parent 等待态等概念。

失败处理

失败类型处理
网络错误 / 5xx / 429指数退避重试,配额内自动恢复
4xx · auth · billing · context_length立即失败,不重试(避免损失放大)
主模型熔断 / Skill 熔断切备模型 / fallback Skill;fallback 在 manifest 声明
沙箱崩溃该 Run FAILED,不影响其他 Run(per-Run 隔离)

关键不变量

3.6 审计追踪器 · 留痕(Trace Recorder)

Role · 留痕

把 Run 的所有关键事件落盘成不可篡改的 Trace。"不经 Trace 的执行等于没有发生"——成功、被拒、失败三条路径都必须有完整 Trace。

必经路径不可篡改支持 Replay

时序图位置

  • 接收 ⑰ 写 Trace 请求(来自 Run 管理器)
  • 无主动外发;查询接口对外提供(合规审计 / Replay 调试)

TraceSchema · 字段表

字段族关键字段说明
RunTrace(主记录)run_id · session_id · tenant / user · 终态 · 状态转移序列 · 总成本 · trace_hash一次 Run 一条;状态机所有跳转都被记录
StepTracerun_id · step_id · 8 步阶段编号 · 输入 hash · 输出 hash · 耗时 · 状态八步管道每一步一条;输入输出按 hash 引用避免数据冗余
ToolTracerun_id · skill_id · skill_version · manifest_hash · 入参 hash · 结果 hash · 重试次数 · error_code每次 Tool 调用一条;含版本与重试链
PolicyTracerule_id · 决议 · 原因 · 用时每条规则的判定结果都留痕
HITLTrace审批级别 · 审批人 · 等待时长 · 超时动作 · 是否 Break-GlassHITL 路径专用,对接合规审计
CostTracetoken / API 调用 / 沙箱时长 · 单价 · 归属 scope支持按 User / Workspace / Skill 聚合成本看板
ErrorTraceerror_code · stack_hash · 重试历史错误归一化,支持告警与同类聚合

不可篡改写入

设计含义
仅追加所有 Trace 表只允许 INSERT,不允许 UPDATE / DELETE
hash 链每条 Trace 引用前条 trace_hash,篡改一条要重算后续所有 hash
异步批写Redis Stream 缓冲 + 后台批量落盘 MySQL,主流程不阻塞
写入降级批写失败不阻塞 Run 终态,但触发告警;最终一致性保证

关键不变量


第四章:外部边界依赖

SECTION GOAL

说明时序图最左 / 最右 3 条虚线 lifeline(Caller / LLM API / Skill·Sandbox)与 Harness 的边界契约——Harness 不拥有它们,但所有跨边界调用都有明确的入参 / 出参约束。

4.1 Caller / T2 Coordinator · 左边界

方向调用载荷
Caller → Harness① create_runuser_input · session · caller_identity · chain_remaining · 协作群上下文(如有)
Caller → Harness⑪ HITL 批准 / 拒绝(条件)approver_id · 决议 · 备注 · break_glass 标记
Harness → Caller⑩ HITL 请求(条件)action 描述 · 风险等级 · 等待截止时间
Harness → Caller⑱ ResultSinkanswer · artifacts · trace_id · 终态码

Harness 不假设 Caller 是谁——Web API、Celery worker、Coordinator、外部 SDK 都是合法 Caller。Caller 只需遵守上面 4 笔契约。

4.2 LLM API · 右边界

方向调用载荷
Harness → LLM⑥ Plan 推理(计划执行器发起)system + history + tool schemas · 模型 ID · 温度 / top_p · 流式开关
LLM → Harness⑦ Plan 返回步骤序列 / DAG / tool_calls · 完成原因 · token 用量
Harness → LLM⑭ Tool 阶段 LLM 推理(工具调用控制器发起)同上,LLM 作为 Tool 之一调用
LLM → Harness⑮ Tool 阶段响应结构化输出 + 用量统计

LLM 是依赖不是层:通过 Provider 抽象支持 Claude / GPT / 其他模型;切换不影响 Run 结构。

4.3 Skill / Sandbox · 右边界

方向调用载荷
Harness → Skill / Sandbox⑬ Tool 执行(工具调用控制器发起)skill_id · version · manifest_hash · 入参(结构化)· 沙箱配置(按需)
Skill / Sandbox → Harness⑮ 执行结果结构化结果 · stdout / stderr · 工件引用(OSS path)· 用量

Skill 类型与是否进沙箱的判定见 执行拓扑 · 沙箱边界 ↗。沙箱 Provider 通过抽象层支持 OpenClaw / K8s Pod / Hermes Agent,运行时切换。