A production runtime guardrail for AI agents: budget caps, timeouts, tool limits, and OpenTelemetry traces.
Project description
GuardLoop
GuardLoop is a production runtime guardrail for AI agents. It wraps model clients and tools with hard budget caps, timeout control, tool-call limits, and per-tool circuit breakers, with OpenTelemetry traces for every protected call. Runaway agent loops can be stopped before they burn through money, and flaky tools can be cut off before an agent retries them into a bigger incident.
The v0.2 focus is intentionally sharp: runtime guardrails for async Python agents using direct OpenAI and Anthropic wrappers plus protected tool calls.
from guardloop import (
GuardLoop,
BudgetConfig,
CircuitBreakerConfig,
CircuitBreakerPolicy,
RunContext,
)
runtime = GuardLoop(
budget=BudgetConfig(
cost_limit_usd="0.10",
token_limit=10_000,
time_limit_seconds=60,
tool_call_limit=20,
),
circuit_breakers=CircuitBreakerConfig(
default=CircuitBreakerPolicy(
failure_threshold=3,
recovery_timeout_seconds=30,
)
),
)
async def agent(ctx: RunContext, prompt: str) -> str:
response = await ctx.openai.responses.create(
model="gpt-5.2",
input=prompt,
max_output_tokens=300,
)
return str(response.output_text)
result = await runtime.run(agent, "research agent runtime safety")
print(result.model_dump_json(indent=2))
Why This Exists
Agents are loops around probabilistic systems. When they go wrong, they can call the same model or tool repeatedly, spend unexpected money, and fail without a clear trace. GuardLoop puts an explicit execution layer around that loop:
flowchart LR
U["User code"] --> R["GuardLoop"]
R --> B["BudgetController"]
R --> CB["CircuitBreakerRegistry"]
R --> T["OpenTelemetry spans"]
R --> C["RunContext"]
C --> O["Wrapped OpenAI client"]
C --> A["Wrapped Anthropic client"]
C --> W["Wrapped tools"]
Install
After the first PyPI release is published:
pip install guardloop
For local development:
uv sync
Optional OpenTelemetry exporters are available through the otel extra:
pip install "guardloop[otel]"
For local development with the extra:
uv sync --extra otel
Try the No-Key Demo
uv run python examples/runaway_cost_prevention.py
The demo uses a fake OpenAI-compatible client and intentionally loops forever. GuardLoop stops it when the next model request would exceed the cost cap.
uv run python examples/tool_circuit_breaker.py
This demo uses a failing fake tool. GuardLoop allows the first failures, opens the circuit breaker, then rejects the next call without invoking the tool.
Live Provider Smoke Tests
export OPENAI_API_KEY="..."
export ANTHROPIC_API_KEY="..."
uv run python examples/live_openai_basic.py
uv run python examples/live_anthropic_basic.py
Both live examples can be customized with OPENAI_MODEL or ANTHROPIC_MODEL.
Quality Gates
uv run pytest
uv run pytest --cov=guardloop
uv run ruff check .
uv run ruff format --check .
uv run pyright
v0.2 Scope
- Async Python runtime with
src/package layout. - Hard caps for cost, tokens, time, and tool calls.
- Per-tool circuit breakers with closed, open, and half-open states.
- Global default breaker policy plus per-tool overrides.
- Direct wrappers for
AsyncOpenAI.responses.create. - Direct wrappers for
AsyncAnthropic.messages.create. - OpenTelemetry spans for agent runs, LLM calls, and tools.
- Fake-client tests and demos that do not require API keys.
Roadmap
- v0.2: per-tool circuit breakers.
- v0.3: verifier/self-healing retry loop.
- v0.4: LangGraph and OpenAI Agents SDK adapters.
- v0.5: Jaeger/Phoenix trace screenshots, blog post, and GitHub release.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file guardloop-0.2.0.tar.gz.
File metadata
- Download URL: guardloop-0.2.0.tar.gz
- Upload date:
- Size: 94.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a7ac99b6663f50b960e07db6b660bde96fe9d1171095706971c33317a9ba092e
|
|
| MD5 |
f14467f306fe18de7e0bcd10a4a098e2
|
|
| BLAKE2b-256 |
034a723701d18f0b869af19dc18e4095d518517d1ca4ec575ca5b941751292e2
|
Provenance
The following attestation bundles were made for guardloop-0.2.0.tar.gz:
Publisher:
publish-pypi.yml on awesome-pro/guardloop
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
guardloop-0.2.0.tar.gz -
Subject digest:
a7ac99b6663f50b960e07db6b660bde96fe9d1171095706971c33317a9ba092e - Sigstore transparency entry: 1491566464
- Sigstore integration time:
-
Permalink:
awesome-pro/guardloop@cbeb22abf887c280941c499896d61e955913ba02 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/awesome-pro
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@cbeb22abf887c280941c499896d61e955913ba02 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file guardloop-0.2.0-py3-none-any.whl.
File metadata
- Download URL: guardloop-0.2.0-py3-none-any.whl
- Upload date:
- Size: 22.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a91d9a4dfff171457d31bda0a7f0b395ade5414fe813e62a9f9f0e866c63a6d5
|
|
| MD5 |
a7fc5526cb2a3849e834e457d0f4f827
|
|
| BLAKE2b-256 |
2ec9a0c173010f087f8777542f14c1a4d065743073e40a343e6a85689daf9eeb
|
Provenance
The following attestation bundles were made for guardloop-0.2.0-py3-none-any.whl:
Publisher:
publish-pypi.yml on awesome-pro/guardloop
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
guardloop-0.2.0-py3-none-any.whl -
Subject digest:
a91d9a4dfff171457d31bda0a7f0b395ade5414fe813e62a9f9f0e866c63a6d5 - Sigstore transparency entry: 1491566918
- Sigstore integration time:
-
Permalink:
awesome-pro/guardloop@cbeb22abf887c280941c499896d61e955913ba02 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/awesome-pro
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@cbeb22abf887c280941c499896d61e955913ba02 -
Trigger Event:
workflow_dispatch
-
Statement type: