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.
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
- Start call submittedEvidence: The agent generated an idempotency key and called `catalog.start_partner_sync`.Next: Wait for a structured result or timeout.
- Local timeout creates uncertaintyEvidence: The client has no accepted/failed result after 15 seconds.Next: Record uncertainty instead of retrying the side effect.
- 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.
- 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
- Classify the timeout state before recovery begins: success, failure, or uncertain.
- Choose the next tool call and name the input that prevents duplicate work.
- Write the final user-facing handoff if the status check returns `running`.
Answer key
- The timeout state is uncertain because the client lacks proof that the server did or did not accept the operation.
- Call `catalog.get_sync_status` with the original idempotency key; do not repeat `catalog.start_partner_sync` first.
- 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
- MCP 2026-07-28 tools specification: Tool result handling, self-correction, state handles, timeouts, and audit guidance.
- RFC 9110 HTTP Semantics: Retry-After: The HTTP field that tells a user agent how long to wait before a follow-up request.
- RFC 9110 HTTP Semantics: 503 Service Unavailable: Temporary overload or maintenance response that may include Retry-After.
