The problem
An agent loop that calls an API, a tool, or a browser action has no built-in guarantee that call ever finishes. A hung connection or an unresponsive tool can freeze the entire loop indefinitely, with no error and no way for your code to notice and recover.
Expected outcome
By the end of this guide you will have a small wrapper that caps any async call to a maximum duration, throwing a clear error if it’s exceeded, so your agent can detect and handle a stuck call instead of hanging forever.
Requirements and costs
- Node.js (version 18 or newer).
- Cost: free. No dependencies.
Step-by-step implementation
- Download the starter from the link below.
- Wrap any async call with a maximum duration in milliseconds:
const { withTimeout } = require("./with-timeout"); const result = await withTimeout(() => callSomethingSlow(), 5000); - Catch the timeout like any other error, and decide what your agent should do — retry, skip this step, or tell the user it couldn’t complete this action in time.
A real example
// A call that finishes well within its 200ms limit
{ "ok": true, "value": "done in time" }
// A call that takes 300ms, given only a 50ms limit
{ "ok": false, "error": "Timed out after 50ms" }
Verification and troubleshooting
What we tested, on 5 October 2026 (record TNT-TEST-2026-10-05-011): a call finishing in 20ms against a 200ms limit — correctly resolved with its real value. A call taking 300ms against a 50ms limit — correctly rejected with “Timed out after 50ms” rather than hanging or silently returning nothing.
Troubleshooting:
- The wrapped call keeps running in the background after it “times out.”
withTimeoutstops WAITING for the call, but it can’t forcibly cancel work already in progress (e.g. a network request already sent) — for that, pass anAbortController‘s signal into your own function if the underlying call supports cancellation. - You’re not sure what timeout to pick. Start generous (several seconds for a network call) and tighten it once you’ve seen real response times — too short, and you’ll time out calls that were about to succeed.
- Every call seems to time out immediately. Double-check the timeout value is in milliseconds, not seconds —
5000is 5 seconds, not 5000 seconds.
Limitations and alternatives
This stops your code from waiting, not the underlying operation from running — genuine cancellation needs cooperation from whatever you’re calling (most fetch-based APIs support an AbortSignal for this). Combine this with the retry/backoff wrapper from our other agent guide for calls that are both slow sometimes and worth retrying when they fail.
Free resources
The download contains the timeout wrapper and a runnable demo showing both outcomes.
Download the timeout starter (ZIP, 1 KB)
Is there a paid version?
Not yet. This is the complete method. TNT Review has sold nothing to date and has no checkout, so any price we discuss in future should be read as a hypothesis, not an offer.