Vinayak Dubey

Timeouts and cancellation in long-running agents

21 October 2026

An agent that can run for a long time needs limits on how long. Without them, one slow tool call can hold a run, and its resources, indefinitely.

Two levels of limits

  • Per step. How long a single model or tool call may take.
  • Per run. How long the whole task may take, no matter how many steps it has.

The step limit catches a hung call. The run limit catches an agent that keeps working but never finishes.

Setting a step timeout

In Python 3.11 and later, asyncio.timeout makes this simple.

import asyncio

async def run_tool(call):
    try:
        async with asyncio.timeout(30):
            return await call()
    except TimeoutError:
        return {"error": "Tool timed out after 30 seconds"}

Returning an error the model can read is often better than raising, because it can choose to retry or try something else.

Cancellation

Sometimes a user closes the page, or a newer request replaces an older one. The run should stop instead of continuing for nobody. In async code this arrives as a cancellation, and you should let it propagate rather than swallow it.

Clean up on the way out

Cancelled or timed-out work may leave things half done. Release locks, close connections and mark the run as cancelled in storage so it is not mistaken for one still in progress.

Cap the steps too

Also set a maximum number of steps per run. A loop where the agent repeats the same action is a common failure, and a step cap turns it into a clear error.