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.0.tar.gz (16.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.0-py3-none-any.whl (13.2 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: magicrails-0.1.0.tar.gz
  • Upload date:
  • Size: 16.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.0.tar.gz
Algorithm Hash digest
SHA256 d96c736361584b1c1c2e47fce6d0b67bb5113c1ba4a00b15b2f7b8112f71fa4e
MD5 3f8b0c2da09b285a855aa5432e757c68
BLAKE2b-256 450b98befa81be98f15dadc38691c3390f3ac9718c11a3272dbf29295383e4a9

See more details on using hashes here.

Provenance

The following attestation bundles were made for magicrails-0.1.0.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.0-py3-none-any.whl.

File metadata

  • Download URL: magicrails-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 13.2 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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b78b5b5ccc3f8aecf17a64c39b693c157455eb3b6fc83747fc2eb8def7e9649e
MD5 7e5e47ffff05e6e6dc633df4d4dfd597
BLAKE2b-256 b1b42c266d3433eef323b1e6bd6ef621318319b43eac43db55c1383bb7e7ab80

See more details on using hashes here.

Provenance

The following attestation bundles were made for magicrails-0.1.0-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