Worked example

Timeout recovery: verify before retry

A synthetic sync job shows how an agent should treat an uncertain timeout as product history, verify state, and avoid repeating a side effect blindly.

This is a newly authored synthetic fixture. It is not a production incident report, not a benchmark, and not a measurement of agent or API reliability.

Open Markdown twin

Scenario

An agent starts a partner catalog sync with an idempotency key. The first call returns no usable result before the client timeout. A status tool can check the operation by key, and the server may expose `Retry-After` when it is temporarily unavailable.

Product problem

A timeout is not proof that nothing happened. Retrying a state-changing operation without checking state can duplicate work or make recovery harder to trust.

AX systems touched

  • Orientation and discovery
  • Tools and interfaces
  • Workflows and state
  • Delegated action and trust
  • Evaluation and improvement

State flow

  1. Start call submittedEvidence: The agent generated an idempotency key and called `catalog.start_partner_sync`.Next: Wait for a structured result or timeout.
  2. Local timeout creates uncertaintyEvidence: The client has no accepted/failed result after 15 seconds.Next: Record uncertainty instead of retrying the side effect.
  3. Status lookup resolves duplicate riskEvidence: `catalog.get_sync_status` returns `accepted` for the same idempotency key.Next: Observe operation `sync_7b2` rather than submitting again.
  4. Handoff is verifiableEvidence: Run record contains idempotency key, operation id, status, and next check.Next: Report progress only with the observed state.

Regression case

This input/output pair is produced by the pure decision function used in tests.

{
  "input": {
    "firstAttemptTimedOut": true,
    "idempotencyKey": "sync-key-2026-09-11-a",
    "status": "accepted",
    "operationId": "sync_7b2",
    "retryAfterSeconds": 30
  },
  "output": {
    "state": "in_progress",
    "repeatStartCall": false,
    "next": "poll existing operation after 30 seconds",
    "handoff": "First submit timed out locally; status lookup found accepted operation sync_7b2. I am not resubmitting."
  }
}

Deterministic fixture

User request: “Sync the approved catalog with the partner account and tell me when it is done.”

Starting state

  • `catalog.start_partner_sync` requires `catalog_id`, `partner_account_id`, and `idempotency_key`; its result should include `operation_id` when accepted.
  • `catalog.get_sync_status` accepts either `operation_id` or `idempotency_key` and returns `unknown`, `accepted`, `running`, `complete`, or `failed`.
  • The first start call times out locally after 15 seconds and returns no structured result to the agent.
  • A later status check for the same idempotency key returns `accepted` with `operation_id: sync_7b2`.

Agent should do

  • Record the first attempt as uncertain, not failed or complete.
  • Check status using the idempotency key before repeating the start call.
  • If status is accepted/running/complete, do not call start again; observe or report the existing operation instead.
  • If the service returns temporary unavailability with Retry-After, wait or schedule the follow-up according to that value before polling again.
  • Return a handoff with the idempotency key, observed status, operation id, and next check.

Agent should not do

  • Do not retry the side-effecting start call merely because the client timed out.
  • Do not erase the timed-out attempt from the run history.
  • Do not report success until a status or result proves the terminal state.

Expected decision: Verify by idempotency key first; because the status is accepted with operation `sync_7b2`, continue observing that operation instead of submitting a second start call.

Exercise

  1. Classify the timeout state before recovery begins: success, failure, or uncertain.
  2. Choose the next tool call and name the input that prevents duplicate work.
  3. Write the final user-facing handoff if the status check returns `running`.

Answer key

  1. The timeout state is uncertain because the client lacks proof that the server did or did not accept the operation.
  2. Call `catalog.get_sync_status` with the original idempotency key; do not repeat `catalog.start_partner_sync` first.
  3. Handoff: “The first submit timed out locally, but status lookup found operation sync_7b2 running for the same idempotency key. I am not resubmitting. Next check should poll sync_7b2 after the advised delay or until a complete/failed status appears.”

Limits

  • The fixture assumes status was verified against the original operation by a trusted service; accepting an arbitrary status string is not verification.
  • The fixture does not define a universal retry policy for every API or agent.
  • The fixture assumes the product provides an idempotency key or status lookup; without one, the safer result may be a human handoff.
  • The fixture is not evidence of real-world reliability or benchmark performance.

Public source basis

Back to worked examples