Skip to main content

Retry With Backoff (Rust)

High-performance retry and backoff policy engine for ContextForge and MCP Gateway.

Features

  • Rust-backed retry state tracking for tool invocations
  • Exponential backoff with optional jitter
  • Per-tool policy overrides without duplicating whole plugin configs
  • Retry decisions based on isError, structured status_code, or optional parsed text payloads
  • Automatic state eviction for stale request entries
  • Gateway ceiling enforcement for max_retries
  • Retry policy metadata returned on tool and resource hooks

Build

make install

Runtime Requirements

This plugin depends on cpex>=0.1.0,<0.2 and imports hook models from cpex.framework. The compiled Rust extension is mandatory; there is no Python fallback implementation.

Usage

The plugin runs on tool_post_invoke and resource_post_fetch.

Typical uses:

  • Retry transient upstream failures such as 429, 500, 502, 503, and 504
  • Clamp aggressive plugin settings to the gateway-wide retry ceiling
  • Apply stricter retry budgets to fragile or expensive tools

Configuration

Core settings

  • max_retries: maximum retry attempts before giving up
  • backoff_base_ms: base delay for exponential backoff
  • max_backoff_ms: upper bound for computed retry delays
  • retry_on_status: HTTP or structured status codes treated as retriable
  • jitter: randomize delay within the current exponential ceiling
  • check_text_content: inspect text content for JSON-encoded error payloads when structured content is absent

Per-tool overrides

Use tool_overrides to change retry behavior for a specific tool:

  • max_retries
  • backoff_base_ms
  • max_backoff_ms
  • retry_on_status
  • jitter

Behavior Notes

  • Successful responses clear retry state for the (tool, request_id) pair.
  • Retry state expires after a short TTL so abandoned request state does not accumulate indefinitely.
  • If check_text_content is disabled, the hot path uses the Rust state manager directly.
  • If check_text_content is enabled, Python-side payload inspection supplements the Rust state manager before applying retry policy.

Returned Metadata

tool_post_invoke — OpenTelemetry metrics

tool_post_invoke accepts an optional extensions parameter carrying OpenTelemetry trace context. When a trace context is present (via extensions.request.trace_id), the plugin emits operational metrics on result.metadata["retry_with_backoff"] with the following schema:

result.metadata["retry_with_backoff"] = {
    "retry_count": 1,      # int — consecutive_failures after this call's outcome is recorded; 0 on success
    "retry_delay_ms": 100, # int — the per-attempt delay computed for this call; 0 on success or once exhausted
}

Every call (success, within-budget retry, or exhausted) has a meaningful outcome to report, including the all-zero success case — there is deliberately no total_backoff_ms cumulative counter, only these two per-call fields.

Gating: Metrics are only emitted when a valid trace_id is present in the trace context (extensions.request.trace_id). No trace context means no result.metadata write at all, regardless of any config flag.

resource_post_fetch — unchanged config echo

resource_post_fetch is out of scope for the OTel metrics contract above — it never receives extensions and continues to unconditionally emit the plugin's active retry policy configuration (not per-call outcome data) on result.metadata:

  • max_retries
  • backoff_base_ms
  • max_backoff_ms
  • retry_on_status

Migration Note

Version 0.3.6 is a breaking change for tool_post_invoke consumers only (resource_post_fetch is unaffected):

  • tool_post_invoke no longer emits the flat, unconditional retry_policy config echo (max_retries, backoff_base_ms, max_backoff_ms, retry_on_status). That echo is replaced by the namespaced, trace-gated result.metadata["retry_with_backoff"] schema above (retry_count, retry_delay_ms).
  • tool_post_invoke now accepts a new optional extensions parameter carrying OpenTelemetry trace context. Emission is gated solely on extensions.request.trace_id being present and valid — if no trace context is supplied, no metrics are written at all.
  • Consumers that previously read the config echo from tool_post_invoke unconditionally must migrate to reading result.metadata["retry_with_backoff"] and must pass a trace_id via extensions to receive metrics.
  • resource_post_fetch keeps its pre-existing, un-namespaced config echo byte-for-byte unchanged — it is a different contract, not covered by this migration.

Testing

# Full plugin CI
make ci

Performance

The retry state manager is implemented in Rust so the common retry decision path avoids Python bookkeeping overhead for normal structured tool results.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cpex_retry_with_backoff-0.3.8.tar.gz (42.8 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

cpex_retry_with_backoff-0.3.8-cp311-abi3-win_amd64.whl (206.4 kB view details)

Uploaded CPython 3.11+Windows x86-64

cpex_retry_with_backoff-0.3.8-cp311-abi3-manylinux_2_34_x86_64.whl (289.2 kB view details)

Uploaded CPython 3.11+manylinux: glibc 2.34+ x86-64

cpex_retry_with_backoff-0.3.8-cp311-abi3-manylinux_2_34_s390x.whl (316.6 kB view details)

Uploaded CPython 3.11+manylinux: glibc 2.34+ s390x

cpex_retry_with_backoff-0.3.8-cp311-abi3-manylinux_2_34_ppc64le.whl (315.1 kB view details)

Uploaded CPython 3.11+manylinux: glibc 2.34+ ppc64le

cpex_retry_with_backoff-0.3.8-cp311-abi3-manylinux_2_34_aarch64.whl (274.0 kB view details)

Uploaded CPython 3.11+manylinux: glibc 2.34+ ARM64

cpex_retry_with_backoff-0.3.8-cp311-abi3-macosx_11_0_arm64.whl (261.3 kB view details)

Uploaded CPython 3.11+macOS 11.0+ ARM64

File details

Details for the file cpex_retry_with_backoff-0.3.8.tar.gz.

File metadata

  • Download URL: cpex_retry_with_backoff-0.3.8.tar.gz
  • Upload date:
  • Size: 42.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for cpex_retry_with_backoff-0.3.8.tar.gz
Algorithm Hash digest
SHA256 66182013289ad2a170a5fbcdf6ac9a45f5db65bc92e95a3bca415c5bb6e6d414
MD5 7ccfc0ef4617a313eadf07d222872ee9
BLAKE2b-256 1feca9d60ae66fff755a8d8a2dda45222df57689f56ec2068f38e5765d5855ea

See more details on using hashes here.

Provenance

The following attestation bundles were made for cpex_retry_with_backoff-0.3.8.tar.gz:

Publisher: release-rust-python-package.yaml on IBM/cpex-plugins

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cpex_retry_with_backoff-0.3.8-cp311-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for cpex_retry_with_backoff-0.3.8-cp311-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 79040dcbbc9338718cc59b8aee5b6cda254cb533c4325990d5bfd7c0287cf5a4
MD5 5dde87f961d820d81eef7a0ba508fe23
BLAKE2b-256 1fb9f2759729f701feb529224e018392e543d2044b9b4906c78a143d04406f02

See more details on using hashes here.

Provenance

The following attestation bundles were made for cpex_retry_with_backoff-0.3.8-cp311-abi3-win_amd64.whl:

Publisher: release-rust-python-package.yaml on IBM/cpex-plugins

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cpex_retry_with_backoff-0.3.8-cp311-abi3-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for cpex_retry_with_backoff-0.3.8-cp311-abi3-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 32eee2e333cfcbf796de62e5fd4e82f68eb340859f1e0ab4d31936752ca5f4fd
MD5 531959db05327e00bf318fd2b942bf08
BLAKE2b-256 d4179ae5cfed7e0f0bc717813c2d57073e724f605c88fe7d40ac244de4da7bc5

See more details on using hashes here.

Provenance

The following attestation bundles were made for cpex_retry_with_backoff-0.3.8-cp311-abi3-manylinux_2_34_x86_64.whl:

Publisher: release-rust-python-package.yaml on IBM/cpex-plugins

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cpex_retry_with_backoff-0.3.8-cp311-abi3-manylinux_2_34_s390x.whl.

File metadata

File hashes

Hashes for cpex_retry_with_backoff-0.3.8-cp311-abi3-manylinux_2_34_s390x.whl
Algorithm Hash digest
SHA256 cf3bbd0f196e400c2a88d36689affc9a274b6b8a388652b5da8c30235041f14c
MD5 df0c09426f49e81565e94c4ab3acd999
BLAKE2b-256 434be47edaf102bb1939e84692804d1c70fabb71faf481e41c492670b8e8b3e9

See more details on using hashes here.

Provenance

The following attestation bundles were made for cpex_retry_with_backoff-0.3.8-cp311-abi3-manylinux_2_34_s390x.whl:

Publisher: release-rust-python-package.yaml on IBM/cpex-plugins

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cpex_retry_with_backoff-0.3.8-cp311-abi3-manylinux_2_34_ppc64le.whl.

File metadata

File hashes

Hashes for cpex_retry_with_backoff-0.3.8-cp311-abi3-manylinux_2_34_ppc64le.whl
Algorithm Hash digest
SHA256 5e1b4bc680b5ddee80cea15842a3e7c4d9bc134da9b5fe671a7852a1b0d1ac36
MD5 9749f64d450194d421e0280d09e4930c
BLAKE2b-256 8fb9d16faab069bddd79608f70397015b2ccc979951b4ece714c7087c089c8fe

See more details on using hashes here.

Provenance

The following attestation bundles were made for cpex_retry_with_backoff-0.3.8-cp311-abi3-manylinux_2_34_ppc64le.whl:

Publisher: release-rust-python-package.yaml on IBM/cpex-plugins

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cpex_retry_with_backoff-0.3.8-cp311-abi3-manylinux_2_34_aarch64.whl.

File metadata

File hashes

Hashes for cpex_retry_with_backoff-0.3.8-cp311-abi3-manylinux_2_34_aarch64.whl
Algorithm Hash digest
SHA256 f73831e706b008becefa9a8d097f3eafcac9bfbbc6bfa89d31782e7c3a47d35f
MD5 996f1491506f065e65880e5b5131b64d
BLAKE2b-256 669ee33511ff9f45cadb72c4676b4b645e19bfde4008e3b74d5c01888b335964

See more details on using hashes here.

Provenance

The following attestation bundles were made for cpex_retry_with_backoff-0.3.8-cp311-abi3-manylinux_2_34_aarch64.whl:

Publisher: release-rust-python-package.yaml on IBM/cpex-plugins

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cpex_retry_with_backoff-0.3.8-cp311-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for cpex_retry_with_backoff-0.3.8-cp311-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 8bf9227562787db4d597f69d8c4b7809c80dce75735af13d8f1daa686120edbf
MD5 b3c309b0ac1e51f21759198aefa2e5a5
BLAKE2b-256 44ec0ae24e3d0a43a0aadb09b2c9beaf40a921b59666952fe13a3305d8fc8078

See more details on using hashes here.

Provenance

The following attestation bundles were made for cpex_retry_with_backoff-0.3.8-cp311-abi3-macosx_11_0_arm64.whl:

Publisher: release-rust-python-package.yaml on IBM/cpex-plugins

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.3.8 This release

7 files

0.3.7

7 files

0.3.6

7 files

0.3.5

7 files

0.3.4

7 files

0.3.3

7 files

0.3.1

7 files

0.3.0

7 files

0.2.1

7 files

0.2.0

7 files

0.1.0

7 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page