Skip to content

API requests don’t always succeed on the first attempt.

A provider might be temporarily unavailable, your network connection could timeout, or the service may return a temporary rate limit response.

These failures are often short-lived and succeed if attempted again a few moments later.

Swytchcode automatically retries these transient failures - so your applications remain reliable without requiring custom retry logic for every provider.


Why Retries Matter

Imagine an AI agent creating a GitHub issue.

Create Issue
│
▼
GitHub API
│
▼
503 Service Unavailable

Without retries, the request immediately fails.

With Swytchcode, the runtime detects that the error is temporary, waits briefly, and retries automatically.

Attempt 1
│
▼
503 Service Unavailable
│
▼
Retry
│
▼
Attempt 2
│
▼
200 OK

Your application receives the successful response without writing any retry logic.


How Retries Work

Every execution follows the same retry lifecycle.

Execute Tool
│
▼
Send Request
│
▼
Receive Response
│
▼
Is the error retryable?
│
┌────┴────┐
│ │
No Yes
│ │
▼ ▼
Return Wait
Error │
▼
Retry Request
│
▼
Retry Budget Remaining?
│
┌─────┴─────┐
│ │
Yes No
│ │
▼ ▼
Retry Again Return Error

The runtime continues retrying until the request succeeds or the configured retry limit is reached.


Configuring Retries

Retry behavior is configured per integration in manifest.json.

{
"execution_policy": {
"max_retries": 5,
"base_delay_ms": 500,
"max_delay_ms": 30000,
"http_timeout_ms": 30000,
"connect_timeout_ms": 5000,
"total_timeout_ms": 90000,
"retry_on": [429, 503, 504],
"non_retryable": [400, 401, 403, 404, 422],
"on_401": "refresh_and_retry"
}
}

Every field is optional.

If a value is not specified, Swytchcode automatically uses the default execution policy.


Default Retry Policy

FieldDefault
max_retries3
base_delay_ms500 ms
max_delay_ms30000 ms
http_timeout_ms30000 ms
connect_timeout_ms5000 ms
total_timeout_ms90000 ms
retry_on[429, 503, 504]
non_retryable[400, 401, 403, 404, 422]
on_401"fail"

Retryable Failures

By default, Swytchcode retries failures that are likely to succeed on another attempt.

HTTP Status Codes

Status CodeMeaning
429Too Many Requests
503Service Unavailable
504Gateway Timeout

Network Errors

The runtime also retries temporary network failures such as:

  • Connection timeouts
  • Connection resets
  • Temporary network interruptions
  • DNS resolution failures

These failures are usually caused by infrastructure issues rather than invalid requests.


Non-Retryable Failures

Some failures should never be retried because the request itself is invalid.

Status CodeMeaning
400Bad Request
401Unauthorized
403Forbidden
404Not Found
422Validation Failed

Retrying these requests would only repeat the same failure, so Swytchcode immediately returns the error to your application.


Exponential Backoff

Retries are not performed immediately.

Instead, Swytchcode waits progressively longer between each attempt.

Attempt 1
↓
Wait 500 ms
↓
Attempt 2
↓
Wait 1 second
↓
Attempt 3
↓
Wait 2 seconds
↓
Success

This exponential backoff helps prevent overwhelming providers during temporary outages.

If the provider returns a Retry-After header, Swytchcode waits that long instead of calculating its own delay. Both forms of the header work: a number of seconds, or a date. If the provider asks you to wait longer than the call has left (see total_timeout_ms), Swytchcode stops straight away and the error says how long the provider asked to wait, instead of waiting until the call times out.

Which requests are retried

  • GET, HEAD, PUT, DELETE, OPTIONS and TRACE are retried, because sending them twice has the same effect as sending them once.
  • POST and PATCH are retried only when the request carries an idempotency key, so a payment or an email is never sent twice by a retry. Turn keys on with idempotency.mode.
  • 500 and 502 are not retried by default; add them to retry_on if your provider recovers from them.
  • If you run a POST again yourself after it timed out, it is a new call with a new key, so the provider can’t tell it is a repeat. Check whether the first one went through before running it again.

Retry Budget

Retries are intentionally limited.

Each integration has a configurable retry budget.

Attempt 1
↓
Retry 1
↓
Retry 2
↓
Retry 3
↓
Return Error

Once the retry budget is exhausted, the runtime returns the final error instead of retrying indefinitely, and swy exec exits with code 1.


Inspecting Retries

Every attempt - including retried ones - is logged as a separate outbound network call. If you need to confirm retries actually happened (and how long each attempt took), check the local audit log rather than guessing from the final response:

Terminal window
swy audit network # recent outbound calls: host, method, status, duration
swy audit network -n 20 # last 20 calls
swy audit network --info <id> # full detail for one call (id looks like nw_...)

This is often the fastest way to tell “the provider was slow and we retried three times” apart from “the provider failed once and we gave up,” especially when debugging a workflow that ran inside an AI agent rather than a terminal you were watching. See the Command Reference for the full swy audit surface.


Timeout Management

Retries are governed by multiple timeout settings to prevent requests from hanging forever.

TimeoutPurpose
Connect TimeoutMaximum time allowed to establish a network connection.
HTTP TimeoutMaximum duration for a single request.
Total TimeoutMaximum duration across the entire retry chain.

This ensures requests either complete successfully or fail within a predictable amount of time.


OAuth Token Refresh

For OAuth-based providers, Swytchcode can automatically recover from expired access tokens.

When enabled, the runtime performs the following steps:

Execute Request
│
▼
401 Unauthorized
│
▼
Refresh OAuth Token
│
▼
Retry Request

This allows requests to continue without requiring the user to manually reconnect their account.

The behavior is controlled by the on_401 option in the integration’s execution policy.


Best Practices

  • Retry only transient failures.
  • Do not retry validation or authorization errors.
  • Respect provider rate limits and Retry-After headers.
  • Configure retry policies for each integration independently.
  • Keep retry budgets reasonable to avoid long-running requests.
  • Combine retries with idempotency for safe execution of mutating APIs.
  • Test retry behavior in sandbox environments before deploying to production.