Skip to content

ArticlesAnalysis

What Happens When an AI Agent Job Runs for Hours in the Background?

MCP Tasks replaced the long-held connection with a durable task handle. Here is the lifecycle, the support gap, and how to design a job that survives a crash.

What Happens When an AI Agent Job Runs for Hours in the Background?
On this page
  1. What does "hours" mean for an agent job?
  2. How MCP Tasks actually work
  3. Why a task handle beats a long connection
  4. What support looks like today, honestly
  5. Claude Code's background jobs are not MCP Tasks
  6. Events: the other half of the problem
  7. Designing a long job that survives failure
  8. What we learned running long jobs on our own stack
  9. Frequently asked questions
  10. What are MCP Tasks?
  11. Does Claude Code support MCP Tasks?
  12. How long can an agent job run?
  13. What happens if the client disconnects mid-job?
  14. Should I build my own job polling instead of waiting for Tasks support?

Last Updated: 24 October 2026

Key takeaways

  • MCP Tasks shipped with the 2026-07-28 specification as an official extension, so a server can return a durable task handle instead of holding a connection open for hours.
  • A task carries a taskId, a TTL, a polling interval and one of five states: working, input_required, completed, failed or cancelled.
  • The client polls, not the model. Polling stays outside the model context, so a long job does not burn extra turns.
  • Support is uneven as of October 2026: the C# and Rust SDKs implement tasks, TypeScript and Python do not, and Claude Code, Codex and Cursor do not yet declare the extension.
  • Claude Code does run background jobs natively through its own task panel. That is a different mechanism from MCP Tasks, and conflating the two leads to bad architecture decisions.

What does "hours" mean for an agent job?

A normal tool call is a request that waits for a response. That model breaks the moment work takes minutes rather than milliseconds. CI pipelines, batch document processing, model training runs, large migrations and human approval steps all exceed the timeout of the client, the serverless function or the user's patience, whichever gives up first.

Until recently, teams worked around this with polling endpoints they built themselves, or by keeping a connection open and hoping nothing restarted. Both are fragile. The 2026-07-28 MCP specification added Tasks as an official extension, io.modelcontextprotocol/tasks, to make long-running work a first-class part of the protocol rather than a per-vendor workaround.

How MCP Tasks actually work

The client opts in once by declaring the tasks extension in its capabilities. From then on, the server decides per request whether to answer normally or return a task handle. If it returns a task, the response is a CreateTaskResult with resultType "task", containing a taskId, an initial status, a TTL and a suggested pollIntervalMs. The task is durably created before the response is sent, which is what makes it survivable.

The client then calls tasks/get with the taskId. While the job runs, the status is working. If the job needs input, for example a human confirmation, it moves to input_required and returns an inputRequests map. The client answers through tasks/update, so there is no second connection and no unsolicited server-to-client message. When the job finishes, completed carries the result the synchronous call would have returned. Failure carries a JSON-RPC error. Cancellation is cooperative: the client sends tasks/cancel, the server acknowledges the intent, but it is not obligated to stop mid-step.

Diagram of the MCP task lifecycle from creation through working to completed, failed or cancelled
How it works: the task moves through five states, and input_required lets the job pause for a human without dropping the connection.

Why a task handle beats a long connection

Four problems disappear when the server returns a handle instead of blocking. Long-lived connections stop tying up transport. Crash resilience improves because the taskId is a durable handle the client can resume with after a restart. Progress becomes visible through status messages rather than silence. And mid-flight interaction becomes a protocol feature instead of a custom webhook.

There is a subtler benefit that matters for cost. Because the host polls outside the model context, a two-hour job does not accumulate two hours of conversation turns. The model is invoked when there is something to decide, not on every poll. That keeps token spend proportional to decisions rather than to wall-clock time.

Diagram of a durable task handle stored server-side and polled by the client until completion
How it works: the task is persisted before the response is sent, so polling survives restarts and the model is not invoked on every check.

What support looks like today, honestly

This is the part most vendor announcements gloss over. According to Upstash's support review on 7 October 2026, ChatGPT does not declare the tasks extension but does support webhooks in Work chats. Codex does not support tasks and only supports events for OpenAI's own connectors. Claude Code does not declare tasks and has an open feature request. Cursor and OpenCode support neither. On the SDK side, C# and Rust ship task support, while TypeScript and Python do not yet.

ClientMCP TasksMCP EventsPractical workaround
ChatGPTNoWebhooks in Work chatsEvents for wake-ups, custom job tools for long work
Claude CodeNoNoNative background tasks plus a job-status tool
CodexNoOpenAI connectors onlyCustom job tools with polling
Cursor and OpenCodeNoNoCustom job tools with polling
C# and Rust SDKsYesNoNative task support

The practical conclusion is that you should not design your architecture around a client feature that most clients do not implement yet. Build the job pattern yourself as ordinary MCP tools, then adopt native Tasks when your client declares support. Upstash's toolkit does exactly this: a task tool returns an ID immediately, and shared task_status and task_cancel tools check or stop it, with state in Redis and work on QStash or Upstash Workflow.

Claude Code's background jobs are not MCP Tasks

Claude Code does run long work in the background. Its task panel covers background bash commands, cloud sessions, ultrareview runs and memory jobs, according to W Media's October 2026 walkthrough. That is a native harness feature, not the MCP Tasks extension. The distinction matters because a native background job is tied to that harness and its session model, while an MCP task is a portable handle any compliant client can resume.

If you are building on Claude Code today, use its background tasks for developer-side work and build a portable job tool for anything that must survive a client change. Do not assume a migration path that does not exist yet.

Diagram of resuming an interrupted agent job by reconnecting with the stored task ID
How it works: after a crash or disconnect, the client resumes with the same taskId instead of restarting the work.

Events: the other half of the problem

Tasks solve "tell me when it is done". Events solve "wake me when something happens". Events are newer and not yet a specification. The design lives as a sketch in the MCP Triggers and Events Working Group incubation repo, with no formal proposal yet. OpenAI shipped the webhook part of that sketch in ChatGPT on 29 September 2026.

The shape is straightforward. The user tells the agent what to watch and what to do about it. The host subscribes through the MCP server and hands over a callback URL and a signing secret. When a matching event occurs, the server POSTs a signed delivery, and the agent wakes up and acts. The server has to implement events/list, events/subscribe and events/unsubscribe on the same endpoint as its tools, verify the callback with a signed challenge, sign deliveries with Standard Webhooks, retry with backoff, and store subscriptions across restarts with a refreshable expiry.

Tasks and events compose well. A nightly research job is a task. "Wake me when a new review comment appears" is an event. Together they cover work that takes time and work that starts in the world rather than in a chat window.

Designing a long job that survives failure

Whether you use native Tasks or your own job tools, five properties decide whether the job is production-grade: a durable task ID, checkpoints that survive a restart, idempotency keys on every side effect, a cost ceiling checked outside the model, and a path for the job to ask a human for input. Miss any one of them and a two-hour job becomes a two-hour outage.

  1. A durable job ID, created before any work starts, that survives client restarts and server deploys.
  2. Checkpoints at step boundaries, so a resume repeats one step rather than the whole run.
  3. Idempotency keys on every external write, so a retry cannot double-charge or double-send.
  4. A cost ceiling per job, enforced outside the model, that pauses rather than overspends.
  5. A human input path that parks the job in a waiting state instead of holding a connection open.
Diagram of a cost ceiling control loop that pauses a long-running agent job before it overspends
How it works: a meter checks spend at every step boundary and pauses the job before it crosses the ceiling.

What we learned running long jobs on our own stack

Our Hermes and OpenClaw agents run long research and content jobs on dual DGX Sparks. The failure mode was never the model. It was session state. A long-running gateway accumulated conversation history until it approached the context budget, then compaction kicked in on every turn, and memory pressure grew until the host started swapping.

The fixes were unglamorous: cap history, checkpoint work to disk at step boundaries, keep polling outside the model context, and restart the gateway on a schedule before it swaps. That is the same set of concerns MCP Tasks formalises, which is a useful sanity check. The protocol is catching up to what anyone running agents in production has already had to build.

Infographic checklist of five properties every long-running AI agent job needs
At a glance: the five properties that separate a resilient long job from a hopeful one.

Frequently asked questions

What are MCP Tasks?

MCP Tasks are an official extension to the Model Context Protocol, shipped with the 2026-07-28 specification. They let a server return a durable task handle for long-running work instead of blocking the connection, and the client polls for status and results.

Does Claude Code support MCP Tasks?

Not as of October 2026. Claude Code has an open feature request for the tasks extension. It does run background jobs natively through its own task panel, but that is a harness feature rather than a portable MCP task.

How long can an agent job run?

As long as the task TTL allows and the server keeps state durable. In practice the limit is your cost ceiling and checkpoint discipline, not the protocol. Jobs measured in hours are routine. Jobs measured in days need explicit budget and progress controls.

What happens if the client disconnects mid-job?

With Tasks, nothing is lost. The task was durably created before the response, so the client reconnects and resumes polling with the same taskId. Without a durable handle, the work is usually orphaned or repeated.

Should I build my own job polling instead of waiting for Tasks support?

Yes, for now. Most clients do not declare the extension, so build job tools with a task ID, a status tool and a cancel tool, then adopt native Tasks when your client supports them.

  • MCP
  • AI agents
  • long running jobs
  • claude code
  • agent infrastructure

One email a week, no noise

A Friday digest of the week's analysis, guides and comparisons. Unsubscribe anytime.

One good place to start

What would you like to take off your plate?

Bring a process that feels repetitive or harder than it needs to be. We’ll help you find a practical first step.

Book a free consult

A free 1-hour conversation with AJ. No pressure, no pitch.