Skip to main content

An emergency brake for AI agents — budget caps, loop detection, and state-stasis guards in three lines of code.

Project description

MagicRails — the meerkat that halts your runaway AI agent

MagicRails

An emergency brake for AI agents.

CI PyPI Python License: MIT

⚠️ Alpha (v0.1). API may change before v1.0. Not yet recommended for production.

Budget caps, loop detection, and state-stasis guards — in three lines of code.

from magicrails import guard

@guard(budget_usd=10.0, max_repeats=3, stasis_steps=5)
def my_agent(task): ...

That's it. If your agent loops, stalls, or runs past its budget, Magicrails halts it before you get the bill.


Why

Every agent developer has either had — or is one bug away from — a $500 overnight invoice from a runaway agent. The agent retries the same tool forever, the cost graph goes vertical, and you find out at breakfast.

Observability tools show you the disaster. Magicrails stops it.

Install

pip install magicrails

Zero required dependencies. Pure Python. Python 3.10+.

The three guards

1. Budget ceiling — a hard dollar cap

Tokens are counted, priced against a community-maintained table, and summed per session. When the session crosses the limit, the agent is halted.

from magicrails import Magicrails

with Magicrails(budget_usd=10.0) as session:
    resp = client.messages.create(model="claude-opus-4-7", messages=[...])
    session.record_tokens(
        model="claude-opus-4-7",
        input=resp.usage.input_tokens,
        output=resp.usage.output_tokens,
    )

Or use an adapter and let Magicrails instrument your client automatically — no manual record_tokens calls:

from anthropic import Anthropic
from magicrails import Magicrails
from magicrails.adapters import anthropic as magicrails_anthropic

client = magicrails_anthropic.instrument(Anthropic())

with Magicrails(budget_usd=10.0):
    client.messages.create(model="claude-opus-4-7", messages=[...])  # auto-counted

Same shape for OpenAI:

from openai import OpenAI
from magicrails import Magicrails
from magicrails.adapters import openai as magicrails_openai

client = magicrails_openai.instrument(OpenAI())

with Magicrails(budget_usd=10.0):
    client.chat.completions.create(model="gpt-4o", messages=[...])  # auto-counted

2. Repeat-call guard — stop tool loops dead

If the agent calls the same tool with the same arguments N times, it's probably stuck. Magicrails halts it.

with Magicrails(max_repeats=3) as session:
    session.record_call("list_files", {"path": "/tmp"})  # ok
    session.record_call("list_files", {"path": "/tmp"})  # ok
    session.record_call("list_files", {"path": "/tmp"})  # 🛑 TripError

3. State-stasis guard — catch reasoning loops

Hash the agent's state after each step. If it hasn't moved in K steps, the agent is thinking in circles.

with Magicrails(stasis_steps=5) as session:
    for step in agent.run():
        session.record_state(agent.state)

On-trip actions

By default, a trip raises magicrails.TripError. You can override:

from magicrails import guard, actions

# Ask a human in the terminal
@guard(budget_usd=10.0, on_trip=actions.prompt_human)
def my_agent(task): ...

# Send to Slack / PagerDuty / anywhere
@guard(budget_usd=10.0, on_trip=actions.webhook("https://hooks.slack.com/..."))
def my_agent(task): ...

# Custom handler
def alert(reason):
    logger.critical(f"Agent tripped: {reason}")

@guard(budget_usd=10.0, on_trip=alert)
def my_agent(task): ...

Framework adapters

Framework Import Status
OpenAI SDK magicrails.adapters.openai ✅ v0.1
Anthropic SDK magicrails.adapters.anthropic ✅ v0.1
LangChain magicrails.adapters.langchain 🚧 v0.2
LangGraph magicrails.adapters.langgraph 🚧 v0.2
CrewAI magicrails.adapters.crewai 🚧 v0.2
AutoGen magicrails.adapters.autogen 🚧 v0.2
OpenTelemetry magicrails.adapters.otel 🚧 v0.2

Adapters are one-file. PRs welcome.

Pricing table

magicrails/models.json ships with reasonable defaults for the major current models (per 1M tokens, USD). Override or extend:

my_pricing = {
    "my-internal-model": {"input": 0.10, "output": 0.30},
}
with Magicrails(budget_usd=5.0, pricing=my_pricing) as session:
    ...

Unknown models are counted as $0 and emit a WARNING on the magicrails logger (once per model per process). Add the model to your pricing dict to enforce a real budget.

Philosophy

Magicrails is not an observability platform. It is not a tracing tool. It does one thing: stop an agent that is about to cost you money or time you cannot get back.

  • Three lines of code. Anything more is too much friction.
  • In-process. No server, no daemon, no cloud account.
  • Zero required deps. Drop it into any project.
  • Framework agnostic. Adapters, not lock-in.

If you want traces, use Langfuse or Arize Phoenix. If you want routing, use LiteLLM. Magicrails composes with those; it doesn't replace them.

Examples

Run any of them:

pip install -e .
python examples/budget_demo.py

Roadmap

  • v0.1 — three detectors, OpenAI & Anthropic adapters (you are here)
  • v0.2 — LangChain / LangGraph / CrewAI adapters, OpenTelemetry span processor, per-tool sub-budgets
  • v0.3 — adaptive thresholds, multi-session dashboards
  • v1.0 — optional local dashboard (Tauri) for live sessions, Slack/Discord control surface

Contributing

PRs for adapters, pricing updates, and new detectors are very welcome. See CONTRIBUTING.md for the full guide — including the recipe for adding a new framework adapter.

Quick start:

pip install -e '.[dev]'
pytest
ruff check magicrails tests

License

MIT. See LICENSE.


Save your agent from itself. pip install magicrails.

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

magicrails-0.1.1.tar.gz (19.3 kB view details)

Uploaded Source

Built Distribution

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

magicrails-0.1.1-py3-none-any.whl (14.8 kB view details)

Uploaded Python 3

File details

Details for the file magicrails-0.1.1.tar.gz.

File metadata

  • Download URL: magicrails-0.1.1.tar.gz
  • Upload date:
  • Size: 19.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for magicrails-0.1.1.tar.gz
Algorithm Hash digest
SHA256 bb5c549c524120dbbfb8335bc850f78c0d67a655ac70831139ce268c3d564b9c
MD5 fe7466a2c179adf969256ae9094b756c
BLAKE2b-256 4d63df340776382c91a3f35d781a045a0d46998c4d8beb1e4736c970ba17caf5

See more details on using hashes here.

Provenance

The following attestation bundles were made for magicrails-0.1.1.tar.gz:

Publisher: release.yml on magicrails/magicrails

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

File details

Details for the file magicrails-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: magicrails-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 14.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for magicrails-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 ab0597f857239c90db4203a76406076ae02badcca61daf2db2e9d744a208e653
MD5 741835b4f4770884245ed44f776152b6
BLAKE2b-256 d25b6a93de057454a50da8331adc413b5a7018cc5c82621597c48d561e45f3f0

See more details on using hashes here.

Provenance

The following attestation bundles were made for magicrails-0.1.1-py3-none-any.whl:

Publisher: release.yml on magicrails/magicrails

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

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page