← Blog

Engineering · · 4 min read

Why one failed agent call becomes many provider requests

Find overlapping retry loops across the agent, SDK, connector, and job worker, then assign a single retry owner.

Deixic

The task history shows one tool call while the provider logs show several requests. An engineer adds a retry for reliability, and the next outage produces even more traffic. Each layer believes it is repairing one transient failure.

This is retry amplification: the model retries a tool, the framework retries a node, the connector retries an HTTP request, and the provider SDK retries internally.

The AWS Builders' Library discussion of timeouts, retries, and backoff explains why retries need capped policies and why side effects require care. Apply that to the whole agent path, including more than the HTTP client.

Draw the actual attempt tree#

Follow one failed logical operation's identifier from the user task through model call, tool invocation, connector request, and provider response. Annotate every layer that can retry, including queue redelivery and restarts.

In one configuration, a tool wrapper permits two attempts and its SDK three requests per attempt, producing six provider requests for one logical tool action. If the graph restarts the node too, the total grows again. This is arithmetic, not a measurement.

Inspect the installed versions' defaults. A public MCP timeout report shows how assumptions differ across SDKs, and a central configuration file is insufficient if a connector builds another client with its own defaults.

Assign responsibility by failure type#

The lowest layer with enough information handles a narrow transient failure, and the application handles changes to the task, target, or arguments. The model should not invent a different call for every network failure.

  • A read: the connector can retry a transient transport error within a capped deadline.
  • A write: needs documented idempotency or reconciliation.
  • An invalid argument: repeating the request is unproductive; the planner or caller must correct the input.
  • Denied access: retrying does not create authority.
Failure Appropriate owner Required limit
Temporary network error on a read Connector or SDK Attempts and total deadline
Provider throttling Shared provider scheduler Retry-after and quota scope
Invalid tool argument Planner with schema feedback Capped correction attempts
Ambiguous write result Reconciliation routine No blind duplicate submission
Lost worker after accepted job Job recovery logic Stable logical operation identity

The table requires no single retry mechanism, only that no two layers own the same failure unknowingly.

Fix one customer export#

An export agent's SDK retries a slow POST, the connector retries the entire export tool because no file arrived, and the worker restarts and replays the task from its last checkpoint. The fix has three parts:

  1. Preserve the provider's export job identifier as soon as submission succeeds, so recovery polls that job and creates no second export.
  2. Choose which layer owns transport retries on submission and disable overlapping retries.
  3. Store the logical export identity in the task checkpoint before any restart can submit again.

The export can still fail, but as one operation with several capped attempts instead of several independent exports with similar names. The unknown-outcome guide covers the case where submission itself cannot be confirmed.

Budget time across layers#

An outer deadline leaves room for the inner request to return and the application to report a result. If every layer spends its full timeout independently, the user waits far longer than the task's budget.

Pass an absolute deadline or remaining time through the stack, and stop scheduling attempts that lack time to complete. Apply jitter so many agents do not resume together after the same failure.

Do not retry after cancellation because an inner SDK is still alive. Propagate the stop decision to the component that schedules requests, and reconcile any write the provider already accepted.

Retain the attempt tree as a regression#

Test a transient read failure, a throttle response, an invalid input, and an ambiguous write, asserting the maximum provider requests for each logical operation. Include a restart so queue redelivery does not escape the limit.

Publish the retry owner and provider-request cap with the connector configuration, so an operator can state the maximum attempts without inspecting four libraries. Use action evidence to inspect routed calls and the SDK recovery guide for continuation behavior.