Task 不是 Request:从用户目标到可验收任务
用户目标不是 Request:Agent 为什么需要任务契约
前两篇已经把一次 LLM call 的边界讲清:应用发出 Request,模型基于 Context 完成一次 Inference,服务返回 Response。现在看一个看似普通的用户要求:
调研三个主流 Agent Runtime,并给出选型建议。
应用当然可以立刻把它作为 Request 发给模型。模型很可能返回一篇结构完整的比较和推荐,调用状态也会是 completed。但这并不意味着用户的工作已经完成:三个“主流”产品由谁决定?资料截至何时?没有来源的结论能否用于决策?报告面向谁?
这不是模型回答得不够好,而是让一次 Request 承担了它不具备的责任。
本文继续使用本系列的统一案例——“技术调研与报告交付 Agent”。其中第三个实践版本编号为 C03:它不执行调研,而是先把这句模糊需求整理成可确认、可计划、可验收的工作定义。下文的 C03 均指这个案例版本。
Request 成功,为什么任务仍可能失败
先把 C03 的两种处理方式放在一起:
| 直接发起 Request | 先建立任务契约 |
|---|---|
| 模型自行猜测研究对象和比较范围 | 范围、约束与默认值被明确记录 |
| Response 返回文本后,没有统一的完成依据 | 验收条件决定能否完成 |
| 某次调用失败时,只能靠聊天记录恢复上下文 | 任务、进度和失败点可独立保存 |
| 模型可以写“调研已完成” | 只有验收器或授权人可以改变任务状态 |
一次 Request 只回答:“这一次让模型计算什么?”它没有天然的业务授权,也没有跨调用的生命周期,更没有独立的验收机制。要把用户的目标变成可靠工作,系统还需要一份跨 Request 保持有效的承诺;本文将它称为 Task Contract(任务契约)。
用户目标
↓ 澄清或记录可接受默认值
Task Contract:承诺交付什么、受什么约束、怎样算完成
↓
Plan:当前准备怎样完成
↓
Executable Tasks:现在可调度和检查的工作
↓
Request / Tool Call:推进某项工作的具体动作
不同框架的名字不一样。本文用 Spec 表示任务契约,用 Executable Task 表示可调度的工作单元;重要的不是术语,而是不要把这几层职责混成“任务”。
任务契约先固定不该由模型猜的事
任务契约回答的是 What:系统承诺交付什么,在什么边界内交付,又按什么证据验收。对 C03 而言,最小契约至少应明确:
goal:要支持哪项决策;scope:研究对象、比较维度与资料截止日期;constraints:预算、时限、禁止事项;source_requirements:什么可以作为证据;deliverable:交给谁、以什么形式交付;acceptance_criteria:哪些条件通过后才能宣布完成。
例如,经确认后的 ResearchTaskSpec 可以是:
goal: 为需要长任务恢复和人工审批的内部研究系统选择 Agent Runtime
scope:
targets: [OpenAI Agents SDK, LangGraph, Google ADK]
dimensions: [状态管理, 持久化, 人工审批, 可观测性]
as_of: <确认日期>
constraints:
- 不执行付费测试,不使用未公开资料
source_requirements:
- 功能事实优先采用官方文档
- 关键结论保存来源链接和访问日期
deliverable:
format: markdown
audience: 技术负责人和平台工程师
acceptance_criteria:
- 三个对象均覆盖四个比较维度
- 比较矩阵中的功能事实均可追溯到来源
- 推荐结论说明适用前提、取舍和不确定项
这份契约没有告诉系统“先搜什么、后写什么”。这是有意的:路径可以改变,交付基线不能在模型遇到困难时悄悄降低。
并非每个空白都必须打断用户。低风险、可逆的默认值可以由系统采用,但必须显式写入契约;会改变研究范围、成本、外部写入或验收标准的假设,则应请求用户确认。否则系统只是把自己的偏好伪装成用户要求。
结构合法,不等于可以交付
JSON Schema 能检查字段、日期和数量,例如保证研究对象恰好有三个;它无法判断“报告要专业”能否真正验收。前者是结构校验,后者需要业务规则。可检查的条件应更接近“每个对象覆盖四个维度,关键事实带来源”,而不是把主观评价留给模型自行解释。
Task Contract 也不是某次 Prompt。Prompt 可以随步骤变化;契约要跨多次调用保持稳定。模型可以建议修订它,却不应在找不到资料时自行删除“关键结论必须有来源”。
Plan 是路径,不是新的承诺
契约明确后,系统才生成 Plan。Plan 回答 How:当前准备以什么顺序满足承诺。C03 的第一版计划可以很简单:
P1 收集三个对象的官方资料
P2 提取四个维度的事实并保存证据
P3 生成比较矩阵和推荐草稿
P4 检查覆盖度、引用与推荐前提
Plan 的说服力不在于步骤听起来全面,而在于它能覆盖契约。每条验收条件都应能找到负责它的步骤:
| 契约要求 | 负责步骤 |
|---|---|
| 三个对象、四个维度均有覆盖 | P1、P2 |
| 关键事实可追溯 | P2、P4 |
| 交付比较矩阵 | P3 |
| 推荐写明前提和取舍 | P3、P4 |
若“人工审批”这个维度在 P1~P4 中没有任何产出位置,计划再流畅也是不完整的。反过来,一步若不服务任何契约要求,也不为后续步骤提供输出,就应该质疑它是否只是模型习惯性增加的待办。
Plan 可以调整:某份文档迁移了,可以换入口或增加补充步骤;但这不等于用户同意放宽来源要求。契约是基线,Plan 是当前路径。复杂的动态重规划留给后文,C03 只要求第一版 Plan 有可检查的覆盖关系。
Executable Task 让路径可以运行和恢复
“收集三个 Runtime 的资料”仍然太大。Runtime 无法从中判断哪一份已完成、哪一份失败、少了什么,以及应当重试什么。因此 Plan 还要展开为带输入、输出、依赖与完成条件的 Executable Tasks:
| Task | 产出 | 依赖 | 完成条件 |
|---|---|---|---|
| T1 | OpenAI Agents SDK 的证据包 | 契约已确认 | 四个维度均有候选官方来源 |
| T2 | LangGraph 的证据包 | 契约已确认 | 四个维度均有候选官方来源 |
| T3 | Google ADK 的证据包 | 契约已确认 | 四个维度均有候选官方来源 |
| T4 | 带来源的比较矩阵 | T1、T2、T3 | 所有格子均有事实或明确缺口 |
| T5 | 推荐与验证记录 | T4 | 所有验收条件均有检查结果 |
Task 的粒度不必越小越好;只要 Runtime 能安排它、记录状态、定位失败并判断完成,就足够。“完成技术调研”太大,“想一想选型”又没有可观察输出。
Task 仍不等于 Request。T4 可能先读取三份证据包,再发一次 Request 生成矩阵,再发一次 Request 检查缺项。即使两次调用都成功,发现两个格子没有来源时,T4 仍然不应标为 completed。
一个失败,如何证明这些层确实有用
假设 T2 缺少“人工审批”的官方证据。
没有任务契约时,下一次调用只看到一段旧聊天记录。系统难以知道这是“缺一条来源”、还是“可以忽略的维度”;它很容易重新生成整篇报告,或悄悄删掉该维度。
有了契约、Plan 与 Task 后,Runtime 可以保留 T1、T3 的证据,把 T2 标记为 blocked,并沿着完成条件准确报告:LangGraph / 人工审批 / 缺少候选官方来源。随后它可以重试资料收集、请求用户允许补充来源,或在用户修改契约后再重新检查受影响的任务。
spec_revision=2
← plan_version=1
← task_id=T2
← request_id=req_17
← status=blocked
← unmet=human_approval.source
这条追溯链能区分四类问题:用户没有说清范围、Plan 漏掉了要求、某个 Task 的执行失败,或一次 Request 的结果不满足完成条件。它们的处理方式不同,不能都归结为“模型不稳定”。
谁可以改变什么
模型擅长从自然语言提取候选契约、草拟 Plan 与提出下一步;但模型的输出只是建议。Runtime 保存权威版本、执行校验、记录状态;用户确认会影响目标或授权的决定。
| 变化 | 应由谁决定或执行 |
|---|---|
| 提议研究对象、计划或任务拆分 | 模型可以提议 |
| 接受低风险默认值 | Runtime 显式记录 |
| 修改范围、成本、写入权限或验收标准 | 用户确认 |
| 将 Task 标为完成 | Runtime 根据验收结果更新 |
这一边界防止模型既定义“什么算完成”,又生成结果并宣布自己通过。一次 Response 成功,只能说明某次计算成功;Task 是否完成,取决于独立的完成条件。
C03:建立可执行承诺,而不假装完成调研
C03 从那句模糊输入开始。系统先生成候选契约,发现研究对象、截止日期和验收条件缺失,状态为 needs_clarification。获得确认后,它保存 ResearchTaskSpec,生成 ResearchPlan v1、展开 T1~T5,并运行三道检查:
validate_contract → 范围与验收条件完整、可检查
validate_plan → 每条契约要求都有步骤覆盖
validate_tasks → 每个 Task 有输入、输出、依赖和完成条件
最小 Trace 应能还原这个过程:
case=C03 event=contract.validation_failed revision=1
status=needs_clarification
missing=scope.targets,scope.as_of,acceptance_criteria
case=C03 event=contract.confirmed revision=2
case=C03 event=plan.created plan_version=1 steps=4
case=C03 event=tasks.created count=5
case=C03 event=coverage.checked uncovered=0
status=ready
ready 只表示执行承诺已准备好;它不表示已经调研。工具调用、证据收集和执行循环会从下一篇开始进入系统。
小结
Request 管一次模型计算;任务契约管系统对用户的交付承诺。两者之间还需要 Plan 组织当前路径、Executable Task 记录可运行和可恢复的工作。
Task Contract / Spec:我们承诺交付什么,怎样算完成?
Plan:当前准备怎样满足承诺?
Executable Task:现在可以执行、记录和验收哪项工作?
Request:这一次让模型计算什么?
下一篇将继续向执行层走:模型生成的 Tool Call 到底是什么,真正执行工具的又是谁?
案例实践清单
- 保存原始用户目标,并记录缺失的关键条件。
- 生成并确认
ResearchTaskSpec,显式记录默认值与用户确认项。 - 为每条验收条件建立 Plan 覆盖关系。
- 生成
ResearchPlan v1与带完成条件的 T1~T5。 - 模拟一个 Task 缺失证据,记录其状态、缺口与恢复选项。
- 保存 Contract、Plan、Tasks 的版本号和 C03 Trace。
- 确认 C03 只达到
ready,没有宣称完成调研。
参考资料
- GitHub Spec Kit:Documentation:其规格驱动流程采用
Spec → Plan → Tasks → Implement,各阶段产物依次成为下一阶段的输入。 - GitHub Spec Kit:Specification-Driven Development:从模糊想法、澄清与验收条件,到实施计划和任务拆分的完整说明。
- OpenAI:A practical guide to building agents:把 Workflow 描述为为满足用户目标而执行的一系列步骤,并建议让每一步对应具体动作或输出。
- Anthropic:Building effective agents:讨论 Workflow、Agent 以及由编排器动态拆解和分派任务的模式。
- JSON Schema:Required Properties:说明对象属性与必填字段的校验规则。