Agent Wranglers

APP-51Required

Give every request a time limit

Give every request from the screen a time limit, say when a request is slow, and retry only reads and requests with an idempotency key.

How to do it

Abort reads after 10 to 15 seconds and writes after 30, with AbortSignal.timeout. Keep these longer than the server's own limits, as timeouts says. After 3 seconds, show "Still working" in the view. Retry reads with backoff and jitter, at most 3 times. Honour Retry-After. Never repeat a write without an idempotency key. Cancel requests whose answer is no longer needed, such as an old search.

Examples

TypeScript example

const READ_TIMEOUT_MS = 12_000;
const SLOW_AFTER_MS = 3_000;

export async function loadWithTimeLimit<T>(url: string, onSlow: () => void, cancel?: AbortSignal): Promise<T> {
  const slowTimer = setTimeout(onSlow, SLOW_AFTER_MS);
  const signals = [AbortSignal.timeout(READ_TIMEOUT_MS), ...(cancel ? [cancel] : [])];
  try {
    const response = await fetch(url, { signal: AbortSignal.any(signals) });
    if (!response.ok) throw new LoadError(response.status, await response.json().catch(() => null));
    return response.json();
  } finally {
    clearTimeout(slowTimer);
  }
}

Python example

from playwright.sync_api import expect

def test_slow_orders_show_progress_then_error(page):
    held_open = []
    page.route("**/api/orders*", held_open.append)
    page.goto("https://staging.example.com/orders")
    expect(page.get_by_text("Still working")).to_be_visible(timeout=4_000)
    expect(page.get_by_role("button", name="Try again")).to_be_visible(timeout=15_000)

How to check

A browser test holds the orders request open and never answers it. "Still working" appears after 3 seconds, and the error view with a retry button appears at the time limit. A second test holds a write without an idempotency key open, and it is sent once only.

Sources

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/app-ui/resilience/request-timeouts">Agent Wranglers web app interface playbook</a>. In code you write, add a comment next to it with the same link.