# AX-SYS-24: Return a task handle for work that outlives one request

> Recovery and reliability · intermediate · AX-SYS-24

When an operation takes longer than a normal request, accept it at once and return a handle the agent can poll, cancel and collect from later, instead of holding the connection open until it times out.

## Why

Exports, builds, batch jobs and anything waiting on a human approval run for minutes or hours. If the only interface is a call that blocks until the work is done, the agent's request times out, it cannot tell whether the work happened, and the obvious recovery (call again) starts a second copy. HTTP has had the answer for decades: RFC 9110's 202 Accepted lets a server take a request for a later process without keeping the connection open, and says the response ought to describe the current status and point to a status monitor. Agent protocols now build on that idea. MCP's Tasks extension lets a server answer a `tools/call` with a task handle instead of a final result, which the client polls with `tasks/get` and can stop with `tasks/cancel`. The handle carries a `pollIntervalMs` that clients should respect and a `ttlMs` after which the server may discard the task. The A2A specification describes itself as async-first for long-running and human-in-the-loop work: when a call returns immediately, the caller polls, subscribes or receives push notifications. A handle is a credential to someone's work, so the MCP extension requires an authentication and authorization check on every task request.

## Do

Return a handle with a status, a suggested poll interval and a retention time, and check the caller's authorization on every lookup.

## Don't

Block a request until a long job finishes, or make the agent resubmit the job to learn whether it ran.

## Artifact

```json
{
  "resultType": "task",
  "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840",
  "status": "working",
  "createdAt": "2025-11-25T10:30:00Z",
  "lastUpdatedAt": "2025-11-25T10:40:00Z",
  "ttlMs": 60000,
  "pollIntervalMs": 5000
}
```

Status values: `working`, `input_required`, `completed`, `cancelled`, `failed`. Over plain HTTP, the same contract is a `202 Accepted` with `Location: /v1/jobs/786512e2` pointing at the status resource.

## Citations

1. [MCP Tasks extension (io.modelcontextprotocol/tasks)](https://tasks.extensions.modelcontextprotocol.io/specification/draft/tasks): The extension allows a server to respond to a tools/call request with an asynchronous task handle instead of a final result, allowing the client to retrieve the eventual result by polling; clients SHOULD respect the pollIntervalMs provided in responses, and servers MUST perform authentication and authorization checks on each task-related request
2. [A2A Protocol Specification](https://github.com/a2aproject/A2A/blob/main/docs/specification.md): Async First: designed for (potentially very) long-running tasks and human-in-the-loop interactions; with return_immediately the operation returns right after creating the task, and it is the caller's responsibility to poll for updates, subscribe, or receive updates via push notifications
3. [RFC 9110: HTTP Semantics (15.3.3, 202 Accepted)](https://www.rfc-editor.org/rfc/rfc9110.html#name-202-accepted): The 202 response allows a server to accept a request for some other process without requiring that the user agent's connection to the server persist until the process is completed; the representation ought to describe the request's current status and point to (or embed) a status monitor

---
Source: Agent Experience Principles (axprinciples.com)