Every agent tutorial ends the same way: the model calls a tool, the tool returns, the answer appears. Delightful, and entirely unlike the work people actually want automated.

Real tasks take twenty minutes. They involve a build, a large analysis, a batch of documents, a wait on somebody else system. The request-response shape does not fit, and teams usually discover this after they have built everything around it.

The Three Ways Teams Get This Wrong

  • Holding the connection open. Works in development, dies against real timeouts, load balancers and flaky networks.
  • Polling in a loop. The agent sits there asking are we there yet, burning tokens on every check.
  • Fire and forget. The work starts, nobody tracks it, and failures are discovered by a customer.

The Shape That Works

An hourglass measuring time as sand runs through it
Photo: gingertammycat / CC BY 2.0, via Flickr.

Split the work from the waiting. A tool call starts the job and returns a handle immediately. The handle is a plain identifier the model can hold, pass around and check later.

MCP formalised this pattern with the Tasks extension, which moved out of the experimental core into io.modelcontextprotocol/tasks with poll-based retrieval and an update method. Change notifications moved to a single subscription stream clients opt into per notification type, rather than each server inventing its own mechanism.

Even if you are not using that extension, copy the shape. Start, return a handle, check on demand.

Make the State Visible to the Model

The stateless core of the current spec carries a lesson worth generalising. When your server needs state across calls, mint an explicit handle from a tool and have the model pass it back as an argument.

Visible state beats hidden state, because the model can reason about what it is holding. Hidden session state produces the failure where an agent has forgotten it started a job and cheerfully starts it again.

What Every Long-Running Task Needs

PropertyWhy
A stable identifierSo it can be checked, cancelled and logged
A status the model understandsQueued, running, needs input, done, failed
A cancellation pathRunaway jobs must be stoppable by a human
A timeoutEverything must eventually end, including failure
An ownerSomeone gets told when it fails at 4am
A cost ceilingLong-running plus unbounded is an expensive combination

Handling the Mid-Task Question

Long jobs often need something partway through: a confirmation, a missing parameter, an approval.

The current spec handles this with Multi Round-Trip Requests. The server returns an input_required result describing what it needs, the client collects the answer, and the original call is retried with the response attached. No held-open stream, no session to preserve.

Design your own long-running work the same way. A job that can pause and ask beats one that fails because a value was missing at minute one.

Conclusion

Return a handle immediately and let the model check back. Give every job a status the model can act on, a cancellation path, a timeout and a cost ceiling. Let jobs pause and ask rather than failing on a missing input. This is ordinary distributed systems practice, and the main risk is that agent frameworks make it look like something new, so teams reinvent a job queue with worse guarantees.

Frequently Asked Questions

Should we use the Tasks extension or build our own?

Use the extension if your clients support it, because interoperability is the point. If not, copy the shape rather than inventing a different one you will migrate later.

How does the agent know when to check back?

Tell it in the tool response. An estimated duration in the result is enough for the model to behave sensibly instead of polling every two seconds.

What happens if the client disconnects?

With a stateless design, nothing. The job continues and the handle still works when anyone comes back. That is the main reason to prefer this shape.

By Admin

Author at TechzClub & DesignXstream.

Leave a Reply

Your email address will not be published. Required fields are marked *