4.2

Interrupted states: INPUT_REQUIRED and AUTH_REQUIRED

A task can stop and wait for you, and the two kinds of waiting are answered in different places: input on the task itself, authorization outside the protocol.

The planner sends code-reviewer a diff of payments-api and asks for a review. The reviewer cannot start, because it does not know which branch the diff is against. Later the planner asks deployer to deploy build 2026.10.06-1 to staging, and that task stops until an operator approves it.

Neither task has failed. When you finish this section, you can recognize an interrupted task, answer it in the right place, and detect the moment it resumes.

Two states that wait

Interrupted state: a state in which the agent has stopped work and needs something before it can continue. The proto marks exactly two states this way, TASK_STATE_INPUT_REQUIRED and TASK_STATE_AUTH_REQUIRED, and the proto marks each of them as interrupted.

An interrupted task keeps its id, history, and artifacts, and its status message says what the agent needs. A blocking SendMessage returns as soon as the task reaches either state. TASK_STATE_INPUT_REQUIRED needs an answer, sent as a new message on the same task. TASK_STATE_AUTH_REQUIRED needs a credential or an approval, sent outside A2A, and the task can resume without a client message.

Answering on the same task

The reviewer creates task e5c95b09 for the planner's diff, stops, and the blocking call returns the task with its question:

the first reply: a task that asks a questionjsonFull log
    "task": {
      "id": "e5c95b09-6d4b-4b3b-8693-91e81472d12f",
      "contextId": "49c5a238-4158-455d-8d63-b2cb39c0ecac",
      "status": {
        "state": "TASK_STATE_INPUT_REQUIRED",
        "message": {
          …
          "role": "ROLE_AGENT",
          "parts": [
            {
              "text": "Which base branch should I compare this diff against?"
            }
          ]
        },
        "timestamp": "2026-10-06T09:00:00.500Z"
      },
      …
The envelope above the task, the ids inside the status message, and the history are cut. The history holds only the planner's first message.

The answer is an ordinary SendMessage that names the task: the client continues with a new message that has the same taskId and contextId. The planner answers main with both ids. The second reply returns the same task in TASK_STATE_COMPLETED, with the review.json artifact. Figure 4.3 follows the whole exchange.

Fig. 4.3the review question and its answersequence
The review question and its answer A sequence with three lifelines: the planner, the code-reviewer agent, and the stored task e5c95b09. The planner sends a diff with no task id. The reviewer moves the task to TASK_STATE_INPUT_REQUIRED with the question which base branch, and the blocking call returns the task. The planner sends main with the same task and context ids. The reviewer moves the question into history, works, adds the review.json artifact, completes the task, and returns it with four history messages. planner client agent code-reviewer remote agent task e5c95b09 stored task record 1 SendMessage text and refunds.diff, no taskId 2 TASK_STATE_INPUT_REQUIRED asks: which base branch? 3 task, TASK_STATE_INPUT_REQUIRED the blocking call returns here 4 SendMessage: main taskId e5c95b09, contextId 49c5a238 5 history: question, main the question leaves the status 6 TASK_STATE_WORKING Comparing the diff against main 7 artifact review.json a text part and a data part 8 TASK_STATE_COMPLETED status message: 2 findings 9 task, TASK_STATE_COMPLETED review.json, four history messages
The question arrives as the status message of a paused task, and the answer is a new message that carries the same task and context ids. Read top to bottom. Steps 1 to 3 are the first SendMessage and its reply, and steps 4 to 9 answer the question on the same task. Ids are shortened to 8 characters.

Authorization that arrives outside A2A

An agent can need permission partway through a task, for example human approval before a destructive action. Such an agent must move the task to TASK_STATE_AUTH_REQUIRED. The credential takes another road:

The deployer's third stream frame names the place where an operator approves:

frame 3: the deploy asks for approvaljsonFull log
          "statusUpdate": {
            "taskId": "ecf2dcb6-79c8-48f8-8868-24a0541781f4",
            "contextId": "9e8e6bcf-b117-48b9-992a-67971cddcb1b",
            "status": {
              "state": "TASK_STATE_AUTH_REQUIRED",
              "message": {
                …
                "role": "ROLE_AGENT",
                "parts": [
                  {
                    "text": "An operator must approve this deploy at http://localhost:41243/approve/ecf2dcb6-79c8-48f8-8868-24a0541781f4"
                  }
                ]
              },
              "timestamp": "2026-10-06T09:00:00.750Z"
            }
          }
The JSON-RPC envelope and the ids inside the status message are cut.

The approval never enters the protocol. In the kit an operator sends POST /approve/<task id> to the deployer, as the kit README lists. No client message follows. After the agent receives the credential, it is allowed to continue the task at once. The client does not have to send another message.

A client that is itself an agent can pass the request upstream by moving its own task to TASK_STATE_AUTH_REQUIRED. Security schemes and in-task authorization covers what such a chain does to credentials.

Fig. 4.4a deploy that waits for an operatorsequence
A deploy that waits for an operator A sequence with three lifelines: the planner, the deployer agent, and an operator outside A2A. The planner opens a stream with SendStreamingMessage. Frames 1 to 3 carry the task in TASK_STATE_SUBMITTED, TASK_STATE_WORKING, and TASK_STATE_AUTH_REQUIRED with an approval link. The stream stays open with no frames while the operator posts to the approval endpoint over plain HTTP. Then frames 4 to 6 carry TASK_STATE_WORKING, the deploy-report.json artifact, and TASK_STATE_COMPLETED, and the stream closes. planner client agent deployer remote agent operator outside A2A 1 SendStreamingMessage deploy 2026.10.06-1 to staging 2 task, TASK_STATE_SUBMITTED frame 1 3 TASK_STATE_WORKING frame 2: Preparing build 4 TASK_STATE_AUTH_REQUIRED frame 3: link to /approve/ecf2dcb6 the stream stays open, no frames while it waits 5 POST /approve/ecf2dcb6 the approval, outside A2A 6 200, approved: true plain HTTP 7 TASK_STATE_WORKING frame 4: Approved by an operator 8 artifactUpdate frame 5: deploy-report.json 9 TASK_STATE_COMPLETED frame 6, then the stream closes
The deploy waits in TASK_STATE_AUTH_REQUIRED while the stream stays open, and the operator's approval travels outside A2A before the same stream carries the result. Read top to bottom. Steps 2 to 4 and 7 to 9 are the six frames of one stream. Steps 5 and 6 are plain HTTP outside A2A. Ids are shortened to 8 characters.

When the stream closes

In this capture the stream stays open through the wait. Closing is a MUST only at terminal states, and the HTTP+JSON binding closes at a terminal state or at an interrupted state. An agent that waits for a credential outside A2A should keep its open response streams after it moves the task to TASK_STATE_AUTH_REQUIRED. The specification does not settle this (conflict D3).

Upstream, PR #2270 on branch dev-1.1, approved on 2026-09-29 and unreleased, makes both interrupted states non-terminal. It says that entering one does not require closing a stream. On main, §11.7 and the streaming guide still close at both kinds of state.

The kit closes at TASK_STATE_INPUT_REQUIRED and stays open through TASK_STATE_AUTH_REQUIRED, as the kit README lists. The SDKs split the same way:

SDKWhen the server closes a SendStreamingMessage stream
a2a-python 1.2.2when the agent's execute() call returns, so the agent code decides
a2a-goafter a Message, a terminal state, or TASK_STATE_INPUT_REQUIRED, and it stays open through TASK_STATE_AUTH_REQUIRED
a2a-javaafter a terminal state, a Message, or an error, and both interrupted states keep it open after execute() returns
a2a-jsafter a terminal state, TASK_STATE_INPUT_REQUIRED, or a Message, and TASK_STATE_AUTH_REQUIRED keeps it open
a2a-dotnetwhen the handler returns or calls a TaskUpdater method for a terminal or interrupted state
a2a-rsafter a terminal event or when the executor's stream ends, with no rule for interrupted states

A closed stream ends your watching, never the task. Call GetTask, and if the task is not terminal, act on its state and call SubscribeToTask, as SendStreamingMessage and SubscribeToTask shows.

Keep watching while someone else acts

Without an open stream, the client can miss task updates, so subscribe with SubscribeToTask, register a webhook, or poll with GetTask.

The kit's planner subscribes. Its blocking SendMessage returns task a31361b3 in TASK_STATE_AUTH_REQUIRED, and it calls SubscribeToTask at once, in exchanges 7 and 8 of 19-planner.http. It alerts the operator only after the first frame arrives, because the specification defines no replay of earlier events.

A2A protocol 1.0.1 · 3303592 · 2026-05-28 · Edition 2026.10