Scenario
An agent starts a partner catalogue 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 does not prove that nothing happened. Retrying a state-changing call without checking its state first can do the work twice and makes the 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_statusreturnsacceptedfor the same idempotency key.Next: Observe operationsync_7b2rather 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 and output come from the decision function the site’s tests run.
{
"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 catalogue with the partner account and tell me when it is done.”
Starting state
catalog.start_partner_syncrequirescatalog_id,partner_account_id, andidempotency_key; its result should includeoperation_idwhen accepted.catalog.get_sync_statusaccepts eitheroperation_idoridempotency_keyand returnsunknown,accepted,running,complete, orfailed.- 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
acceptedwithoperation_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_statuswith the original idempotency key; do not repeatcatalog.start_partner_syncfirst. - 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 a trusted service checked the status against the original operation. Accepting whatever status string comes back would not count as verification.
- It describes one recovery decision. Each API still needs its own retry policy.
- It assumes the product offers an idempotency key or a status lookup. Without either, handing the decision to a person may be the safer result.
- It is a teaching case and says nothing about real-world reliability.
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.
