任务生命周期

任务的生命周期(Life of a Task)

在 Agent2Agent (A2A) 协议中,交互既可以是简单的无状态请求,也可以是复杂、长时间运行的流程。当服务端智能体收到客户端消息时,通常会以两种基本方式响应:

  • 无状态 Message:立即完成、无需跟踪状态的交互。
  • 有状态 Task:需要跟踪进度与状态的工作,可能分多步执行、需要补充输入,并在过程中产生工件(Artifacts)。

使用 contextId 关联一组交互

contextId 是服务端生成的标识,用于把一组相关的 TaskMessage 组织在一起:

  • 首次交互时,服务端会返回一个新的 contextId(如果创建任务,也会同时有 taskId)。
  • 后续请求可携带相同的 contextId 来延续同一会话/目标。
  • 也可以携带 taskId 来继续 某一个具体任务

这为多轮协作提供了基础,也方便客户端与服务端围绕同一目标串联多次调用。

何时用 Message,何时用 Task?

取决于工作性质:

  • Message 适合轻量交互:澄清、协商、一次性问答、无需追踪的简单操作。
  • Task 适合有状态工作:需要状态机、可重连/订阅、需要持续更新、或需要产出工件的场景。

有的智能体总是返回 Message;有的总是返回 Task(即便是简单回答也会建一个已完成任务);也有 混合型:先用 Message 协商范围,再创建 Task 执行。

任务的跟进与改写(Refinement)

客户端经常会在已有结果基础上进行改写/迭代。通常做法是在同一个 contextId 下发起新的交互,并通过 referenceTaskIds 引用之前的任务作为上下文提示。服务端可能返回新的 Task(更常见),也可能在可立即完成时返回 Message

任务不可变性(Immutability)

任务一旦进入终态(例如 completedcanceledrejectedfailed)就不会“重启”。任何与之相关的后续交互都会在同一 contextId 下创建 新任务。这样可以获得:

  • 清晰的工作单元划分
  • 可追溯性更好
  • 客户端编排更可预测

跟进场景示例

1)客户端请求生成一个工件:

{
  "jsonrpc": "2.0",
  "id": "req-001",
  "method": "message.send",
  "params": {
    "message": {
      "role": "user",
      "messageId": "msg-user-001",
      "parts": [
        { "kind": "text", "text": "Generate an image of a sailboat on the ocean." }
      ]
    }
  }
}

2)服务端以“已完成任务 + 图片工件”的形式返回(示意):

{
  "jsonrpc": "2.0",
  "id": "req-001",
  "result": {
    "id": "task-boat-gen-123",
    "contextId": "ctx-conversation-abc",
    "status": { "state": "completed" },
    "artifacts": [
      {
        "artifactId": "artifact-boat-v1-xyz",
        "name": "sailboat_image.png",
        "parts": [
          {
            "kind": "file",
            "file": {
              "name": "sailboat_image.png",
              "mimeType": "image/png",
              "bytes": "base64_encoded_png_data"
            }
          }
        ]
      }
    ],
    "kind": "task"
  }
}

3)客户端在同一 contextId 下请求改写,并引用上一轮任务:

{
  "jsonrpc": "2.0",
  "id": "req-002",
  "method": "message.send",
  "params": {
    "message": {
      "role": "user",
      "messageId": "msg-user-002",
      "contextId": "ctx-conversation-abc",
      "referenceTaskIds": ["task-boat-gen-123"],
      "parts": [
        { "kind": "text", "text": "Please modify the sailboat to be red." }
      ]
    }
  }
}

服务端通常会创建一个新的任务(同一 context,新 taskId),并产生新版本工件。