Catalog PyPI
Back to packageRELEASE DETAILS

0.1.0

PyPI

agent-fallback-sentinel

Lightweight production middleware for resilient LLM calls: retries, fallback routing, circuit-breaking, and rigid schema validation.

agentscircuit-breakerfallbackllmpydanticresilience
Published3 Oct 2026
Direct dependencies6
Transitive dependenciesNot calculated

README

Version 0.1.0 documentation

agent-fallback-sentinel

CI Python 3.9+ License: MIT

Lightweight, production-grade middleware for resilient LLM calls — retries, automated fallback routing, circuit-breaking, and rigid schema validation.


The problem

LLM APIs rate-limit. They return malformed JSON. They go down at 3am.

When that happens mid-agent-workflow, your entire pipeline dies — and your users see a 500.

agent-fallback-sentinel wraps your LLM calls in a resilience layer that:

  • 🔁 Retries transient failures with configurable backoff.
  • 🛟 Fails over to a secondary provider (OpenAI → Anthropic, etc.) automatically.
  • 🔌 Trips a circuit breaker when all routes are dead, with full error context.
  • ✅ Validates output against a Pydantic schema — no more KeyError: 'action' in prod.
  • 📡 Emits events so you can plug in your own metrics/tracing.

Zero dependencies beyond pydantic.


Install

pip install agent-fallback-sentinel

(Coming to PyPI. For now: pip install git+https://github.com/Jamie643/agent-fallback-sentinel.git)


Quickstart

from pydantic import BaseModel
from agent_fallback_sentinel import AgentSentinel

class Output(BaseModel):
    status: str
    action: str

sentinel = AgentSentinel(max_retries=2, cooldown=1.0)

result = sentinel.execute_with_fallback(
    primary_fn=call_openai,
    fallback_fn=call_anthropic,
    schema=Output,
)
# -> {"status": "success", "action": "retry_job"}

That's it. If call_openai rate-limits or returns garbage, call_anthropic runs automatically. If both fail, you get a SentinelCircuitBreaker with every captured error inside.


Why not just tenacity?

tenacity is great at retries. It doesn't know about:

  • Multi-provider failover (a first-class concept here).
  • Schema validation as a failover trigger — malformed output ≠ retryable; it should fail over immediately.
  • Typed circuit-breaker exceptions carrying every underlying error for observability.

Think of this as tenacity + pydantic + failover, purpose-built for LLM calls.


Configuration

ArgumentDefaultDescription
max_retries2Retry attempts for the primary provider (excludes the first try).
cooldown1.0Seconds between retries on a given provider.
fallback_max_retries1Retry attempts for the fallback provider.
sleep_fntime.sleepInjectable for testing — pass lambda _: None to run instantly.
on_eventNoneCallable[[str, dict], None] for observability hooks.

Events emitted via on_event

EventWhen
attemptBefore each attempt on a provider.
failoverWhen primary is exhausted and we switch to fallback.
successAfter a provider returns a schema-valid result.
tripWhen the circuit breaker opens.

Behavior contract

  1. Primary is retried up to max_retries + 1 times.
  2. Validation errors skip retries — malformed output won't self-heal. Failover is immediate.
  3. Fallback is retried up to fallback_max_retries + 1 times.
  4. If everything fails, SentinelCircuitBreaker.errors contains every captured exception, in order.

Real-world example

See examples/openai_anthropic_failover.py for a complete OpenAI → Anthropic failover with schema validation.


Development

git clone https://github.com/Jamie643/agent-fallback-sentinel.git
cd agent-fallback-sentinel
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pre-commit install
pytest

Roadmap

  • Async support (aexecute_with_fallback)
  • Pluggable backoff strategies (exponential, jittered)
  • Native LangChain / LlamaIndex adapters
  • Prometheus metrics exporter

License

MIT — see LICENSE.

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Declared dependencies 6

Native requirements
6 direct targetsNot calculated transitive count
Package / targetRequirementRelationship
pydantic
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.9",
  "evaluation": "NOT_EVALUATED"
}
pydantic>=2.0runtime
pytest
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.9",
  "evaluation": "NOT_EVALUATED"
}
pytest>=7.4; extra == "dev"runtime
pytest-cov
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.9",
  "evaluation": "NOT_EVALUATED"
}
pytest-cov>=4.1; extra == "dev"runtime
mypy
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.9",
  "evaluation": "NOT_EVALUATED"
}
mypy>=1.8; extra == "dev"runtime
ruff
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.9",
  "evaluation": "NOT_EVALUATED"
}
ruff>=0.4; extra == "dev"runtime
pre-commit
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.9",
  "evaluation": "NOT_EVALUATED"
}
pre-commit>=3.6; extra == "dev"runtime

Distribution files

2 collected
agent_fallback_sentinel-0.1.0-py3-none-any.whl

bdist_wheel · 7.19 KB · Python py3

Source file
agent_fallback_sentinel-0.1.0.tar.gz

sdist · 7.92 KB · Python source

Source file

Repository

PENDING
jamie643/agent-fallback-sentinel

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 21:54 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package_version:570bb3fa537ee4304edfdd0f7e751dc67992ab389c3ba02e1459fff0d14915eb

Other collected versions

View all collected versions →