🧰 工程全景

第16章 目标、计划、技能与定时任务:长程上下文治理

从一次对话走向长期任务:目标状态、计划模式、技能复用与未来触发

16.1 本章导读

一个能调用工具的 Agent 只能解决“眼前这一步”;一个可长期协作的 Agent 还需要知道自己在追什么目标、下一步计划是什么、哪些能力可以复用、未来什么时间该继续工作。本章聚焦四组平台能力:goalplanskillschedule。它们共同回答一个问题:Harness 如何把一次性对话扩展成可持续推进的任务系统

16.2 目标状态机:GoalService

GoalService 同时实现 IGoalQueryServiceIGoalCommandService。它的工作流很直接:读取当前会话目标,规范化命令,交给 GoalAggregate 做状态转移,再通过 IGoalRepository 保存快照。目标是跨回合存在的状态,不是某一条模型消息的临时注释。

状态/动作取值含义
目标状态ACTIVEPAUSEDBLOCKEDCOMPLETEDCLEARED描述长期目标当前是否可继续、暂停、阻塞、完成或清除
目标动作CREATEUPDATEPAUSERESUMECOMPLETEBLOCKCLEAR驱动聚合状态机变更
终态判断COMPLETEDCLEARED只有终态后才允许创建新的目标

目标层还对应一组模型可调用工具:goal_get 读取当前目标,goal_create 创建长期目标,goal_update 推进、暂停、恢复、完成、阻塞或清除目标。这样模型不必直接理解数据库,只需要通过工具协议改变目标状态。

16.3 目标与 HTTP/API 的关系

目标既可以被模型通过工具使用,也可以由外部系统通过 REST API 管理。GoalQueryController 暴露 GET /api/harness/goals/{sessionId}GoalCommandController 暴露 POST /api/harness/goals/{sessionId}。这种双入口设计很重要:模型能自我管理长期任务,控制台或运维系统也能人工介入。

目标命令示例
{
  "action": "CREATE",
  "title": "完成插件开发教程",
  "description": "补齐示例、验证命令和常见错误",
  "maxRounds": 8,
  "continuationEnabled": true
}

边界:目标状态依赖 sessionId。如果未来做多租户或多实例,目标仓储必须与认证身份、会话亲和性和任务锁一起设计,不能只按字符串会话号更新。

16.4 计划模式:PlanModeService 与 exit_plan_mode

计划模式用于让 Agent 先规划、再执行。源码中的 PlanModeService 管理每个会话的 PlanModeStateExitPlanModeTool 则让模型通过工具显式退出计划模式。它的价值不在“生成一段计划文本”,而在把“是否还处于规划阶段”变成可检查的运行状态。

元素职责维护建议
PlanModeState记录计划模式是否开启、计划内容或相关状态作为会话级上下文,不要混入工具返回文本
PlanModeService维护内存中的会话计划状态长期运行前评估持久化和重启恢复
exit_plan_mode让模型声明计划完成并切换执行阶段与 UI 展示和策略树节点保持语义一致

当你新增“强制先计划”或“计划需审批”的能力时,推荐把策略放在用例编排层,而不是把判断写进工具或前端。工具只表达动作,策略树决定什么时候允许动作发生。

16.5 技能工具:SkillTool

SkillTool 是把“可复用能力”塞进工具体系的入口。它实现 ToolDefinition,因此和文件、Shell、Web、插件、MCP 工具一样,会经过工具注册、模型 schema、执行上下文和结果回填。技能的工程价值是把一组稳定做法沉淀成可调用单元,而不是让模型每次都从零推理。

v0.1.3 后技能来源统一由 harness.extensions.skills 管理:rootshomebundled-dir 和项目目录都会被发现;文件可以是 <skill-name>/SKILL.md<skill-name>.md。同名技能按 rank 仲裁,技能名要求 kebab-case,降低多来源注册时的歧义。

维度技能工具关注点
输入应明确任务、上下文和约束,避免无边界自由文本
输出应返回结构化或可审计内容,便于写入会话事件
治理技能内部若会调用高风险工具,仍应经过审批、Hook 和沙箱策略
版本技能更新应考虑兼容旧会话和历史事件回放

16.6 定时任务:ScheduleService

ScheduleService 提供未来触发能力,领域模型包括 ScheduleRecordScheduleKindScheduleStateScheduleView。支持三类计划:AFTER 表示若干秒后触发,AT 表示指定时间触发,EVERY 表示按间隔重复触发。

工具能力说明
schedule_create创建一次性或周期性计划参数可表达 after、at、every 等调度语义
schedule_list列出当前会话计划返回 SCHEDULEDOVERDUE 等视图状态
schedule_delete删除计划按计划 id 删除

drive(sessionId, now) 是调度推进方法:它查找到期记录;对 EVERY 任务会推进到下一个锚点之后;对一次性任务会删除记录,表示已派发。这个设计把“找出该触发什么”和“真正向 Agent 投递任务”分开,方便未来替换调度器。

当前边界:README 已明确指出 ScheduleService 尚无 @Scheduled 或 Quartz 驱动方,且仓储偏内存形态;它是领域能力雏形,不是完整生产级调度系统。上线前必须补驱动、持久化、幂等和失败重试。

16.7 Typert:扩展贡献的注册表

typert 域不是普通业务功能,它更像“扩展贡献目录”。TypertContribution 可以携带多个 InvocationDescriptorTypertService.registerContribution() 会把这些调用描述同时写入 remote 与 local registry。后续调用方可以通过 endpoint 解析 invocation,而不需要知道能力来自插件、远端协议还是本地适配器。

对象职责价值
InvocationDescriptor描述 endpoint、schema、调用方式与元信息让能力可发现、可解析、可治理
TypertContribution把多个 invocation 作为一次贡献注册适合插件或协议加载时批量导入
ITypertRegistryContract聚合 context、lookup、local、remote 四类注册表统一本地与远端能力目录
InMemoryTypertRegistry当前内存实现适合启动期装配和本地演示
TypertProtocolLoader基础设施侧协议加载入口把外部描述导入注册表

如果把第8章的工具系统看成“能执行什么动作”,Typert 更像“动作目录与协议描述”。它给插件、MCP、远端工具和未来 UI 动态表单之间留了一个统一发现层。

16.8 Credentials:密钥引用,而不是明文散落

Agent Harness 需要调用模型、插件、MCP Server、子代理和外部 API,密钥如果散落在脚本、工具参数或日志里,会直接破坏安全边界。项目中的 credentials 域用 CredentialRef 表示引用,用 ResolvedCredentialVO 表示解析后的值,用 CredentialInfoVO 表示可展示但不泄密的摘要。

基础设施层的 CredentialsYamlStoreLocalCredentialProviderPort 提供本地实现;生产环境可以替换为 Vault、KMS、云密钥服务或企业凭据平台。关键是领域层只依赖 ICredentialProviderPort,不会把密钥存储方式扩散到工具系统。

原则落地方式
引用优先工具参数传 CredentialRef,不要直接传明文密钥
最小展示前端只展示 CredentialInfoVO 中的名称、类型和摘要信息
运行期解析真正执行外部调用前才解析成 ResolvedCredentialVO
实现可替换本地 YAML 是开发便利,不应成为生产密钥体系

16.9 六类能力如何组合

目标、计划、技能、定时任务、Typert 和凭据各自独立,但组合后才能支撑长程 Agent。一个典型流程是:用户创建目标;Agent 进入计划模式,拆解步骤;模型调用技能处理可复用动作;插件通过 Typert 贡献可调用端点;需要外部 API 时通过 CredentialRef 解析密钥;遇到需要等待外部条件的步骤时创建定时任务;未来调度触发后,再回到同一个 session 推进目标状态。

16.10 长程上下文的风险

长程能力最怕“看起来能续跑,实际不可审计”。建议重点关注七个风险:目标状态被并发覆盖;计划只在内存中,重启丢失;技能版本变化导致旧会话语义漂移;定时任务重复派发;Typert 注册表重启后丢失;凭据被日志或工具结果泄漏;模型在没有人工确认时长期自动调用高风险工具。解决这些问题,需要把状态、事件、审批、幂等、版本和密钥最小暴露一起设计。

风险建议
目标并发更新使用 revision 或乐观锁,保证状态机转移可追踪
计划丢失把计划模式状态持久化,并写入事件日志
技能漂移记录技能版本,避免历史回放使用新语义解释旧结果
重复调度为派发引入幂等 key 和状态转移日志
注册表漂移Typert contribution 需要版本、来源和健康检查
密钥泄漏日志、事件和工具结果默认脱敏,只保存引用和摘要
长期自动执行周期任务默认低权限,高风险工具仍需运行期审批

16.11 小结

本章要点:目标让 Agent 知道长期追求什么;计划模式让它在执行前先形成结构化路径;技能把稳定能力沉淀成工具;定时任务让系统能在未来继续推进;Typert 负责贡献发现;Credentials 负责密钥引用与解析。它们共同构成“长程上下文治理”的基础,但当前仍有明显生产化缺口:持久化、调度驱动、幂等、版本、密钥托管和审批联动都需要补强。

至此,学习手册完成从基础启动、架构机制、扩展治理,到工程接手、协同执行和长期任务的完整闭环。下一步可以回到第 14 章的协作清单,挑一个真实改动走完整工程流程;也可以沿第 15 章的工作流/子代理方向,把 Harness 从单 Agent 演进成多执行者协作平台。