Compare & Decide Advanced · 7/12
Long-running agent tasks: MCP Tasks vs. A2A tasks vs. durable execution
When agent work takes minutes, hours, or a human approval, three different things called "tasks" compete for the job. What each one guarantees, what it does not, and how they fit together.
Most agent tutorials assume every step finishes in seconds. Real work doesn’t: a CI pipeline runs for twenty minutes, a data export for an hour, a refund waits two days for a manager’s approval. At that point you need something that remembers the work exists while nothing is actively running it.
Three things now offer that, and all three call themselves “tasks”:
- MCP Tasks, an extension to the Model Context Protocol, for a tool call that takes too long to answer in one request.
- A2A tasks, the core unit of the Agent2Agent protocol, for work you delegate to another agent.
- Durable execution, a class of runtimes (Temporal, Restate, DBOS, Inngest, and the persistence layer in frameworks such as LangGraph) that make your own code survive crashes and restarts.
They solve different problems, and the most common mistake is assuming the first two give you the third. They don’t. A protocol tells a caller how to track work across a boundary; it does not keep the worker on the other side alive.
MCP Tasks: a tool call that returns a ticket
In the 2026-07-28 MCP spec revision, Tasks moved out of the core protocol
into an official extension, io.modelcontextprotocol/tasks. Both sides
opt in: the client lists the extension in the capabilities it sends with
each request, and the server advertises it from server/discover.
How it works:
- The client calls a tool as usual. If the server decides the call will
be long-running, it returns a task handle instead of the result
(
resultType: "task", with ataskId, a status, a time-to-livettlMs, and a suggestedpollIntervalMs). The server decides per request; the client just has to handle either shape. - The client polls with
tasks/getuntil the status is terminal. Statuses:working,input_required,completed,failed,cancelled. Servers can also push updates through the newsubscriptions/listenmechanism. - If the task needs something from the user (a confirmation, a missing
value), it moves to
input_requiredwith the requests attached, and the client answers withtasks/update. tasks/cancelasks the server to stop. Cancellation is cooperative: the server may still finish.
What it guarantees: a handle the client can keep and come back to after a disconnect. The spec tells servers to create the task durably before replying, and tells clients to store task IDs durably. What it does not guarantee: that the work behind the handle survives a server crash. That is the server author’s job.
Adoption caveat (October 2026): the extension is new. The official Python SDK had not implemented it yet, and the MCP project’s client support matrix listed no client with Tasks support. Check your client before designing around it.
A2A tasks: delegation with a lifecycle
In A2A, the task is the protocol. When one agent sends another a message, the receiving agent can answer directly or create a task, and from then on both sides talk about that task. The v1.0 spec (released March 2026) defines these states: submitted, working, input-required, auth-required, completed, failed, canceled, and rejected. Results come back as artifacts attached to the task.
The operations, by their v1.0 names: SendMessage and
SendStreamingMessage to start or continue work, GetTask to check on
it, CancelTask, SubscribeToTask to stream updates, and a set of
…TaskPushNotificationConfig operations so the remote agent can call a
webhook when something changes, instead of you polling for hours.
The differences from MCP Tasks come from the peer on the other side. An
A2A peer is an agent: it can reject the task, ask clarifying questions
over several turns, or need its own authorization (auth-required).
It’s usually run by another team or another company. A2A says nothing
about how that agent keeps its work alive either; it only tells you what
state the agent reports.
Durable execution: making the worker itself survive
Durable-execution engines record each step of your code as it runs. If the process dies, a new one replays the record, skips the steps that already completed, and continues from where it stopped. Waiting is cheap: a workflow can sleep for three days, holding no process, and resume when a timer fires or a signal (such as “approved”) arrives.
The main shapes:
- Workflow engines with a server, such as Temporal and Restate. You write workflows in ordinary code; the engine records the history and drives retries, timers and signals. Temporal requires workflow code to be deterministic, with side effects (including LLM and tool calls) placed in separately retried activities.
- Libraries on your own database, such as DBOS, which checkpoints workflow steps in Postgres, so there is no separate orchestrator to run.
- Persistence inside an agent framework, such as LangGraph: compile
the graph with a checkpointer and pass a
thread_id, and the graph’s state is saved as it runs, so it can resume after a failure or a human-in-the-loop interrupt. LangGraph lets you trade speed for safety with its durability modes (exit,async,sync).
The rule they all share: a step that is resumed may run again, so anything with a side effect (sending an email, issuing a refund, writing a record) needs an idempotency key or a check for an existing result. LLM calls are side effects for this purpose too: their output isn’t reproducible, so record it rather than regenerate it on replay.
How they fit together
These are layers, not alternatives. A typical long-running agent action uses a protocol at the boundary and an engine behind it:
%% caption: One refund, three layers: MCP task handle → durable workflow → human approval
sequenceDiagram
autonumber
participant Agent as Agent<br/>(MCP client)
participant Server as MCP server
participant Engine as Workflow<br/>engine
participant Human as Approver
Agent->>Server: tools/call issue_refund<br/>(tasks extension)
Server->>Engine: start workflow<br/>key = request ID
Server-->>Agent: task handle<br/>status: working
loop every pollIntervalMs
Agent->>Server: tasks/get
Server->>Engine: query state
Server-->>Agent: status: working
end
Engine->>Human: approval request
Note over Engine: sleeps, holding<br/>no process
Human-->>Engine: approved (signal)
Engine->>Engine: issue refund<br/>(recorded, retried)
Agent->>Server: tasks/get
Server-->>Agent: completed + resultThe MCP task handle lets the agent stop waiting on an open connection and come back later. The durable workflow lets the refund survive a deploy, a crash, or a two-day approval wait. Swap the MCP server for a remote A2A agent and the picture is the same: A2A at the boundary, whatever durable runtime that team chose behind it.
Decision table
| Your situation | Use | Why |
|---|---|---|
| A tool call takes longer than a client will wait on one request | MCP Tasks (if your client supports it) | Returns a handle instead of blocking; the client polls or subscribes |
| A tool call needs a user’s input partway through | MCP Tasks input_required | Mid-flight input without a second connection |
| You hand long work to an agent owned by another team or vendor | A2A tasks | Lifecycle, multi-turn clarification, push notifications, rejection and auth states |
| Your own agent’s multi-step work must survive restarts and deploys | Durable execution | Records completed steps and resumes; protocols don’t do this |
| A step waits hours or days for a human or an external event | Durable execution (timers and signals) | Sleeps without holding a process, resumes on the signal |
| You’re already on LangGraph and need resume-after-failure | LangGraph checkpointer | Durability without adding an engine; graduate to a dedicated engine if workflows get complex |
| The work finishes in seconds | None of these | A plain tool call with a timeout and retry is simpler |
The verdict
Pick by boundary, then by durability. If the long work sits behind an MCP tool, expose it as an MCP task; if it sits behind another agent, it’s an A2A task. Either way, if losing the work to a crash would cost money or trust, run it on a durable-execution engine and make every side effect idempotent. Starting with the engine and adding the protocol later is easier than the reverse.
Where to go next
For the three protocols side by side, read the agent protocol stack. For deciding which parts of a process should be agent steps at all, see workflow vs. agent. If you maintain an MCP server, migrating to the 2026 spec covers the extension mechanism that Tasks plugs into.
Was this guide useful?
Thanks — noted. It shapes what gets written next.
newsletter
One practical agentic-AI guide in your inbox. No news, no hype.
Tutorials and decision frameworks as they ship. Unsubscribe anytime.