Catalog PyPI
PACKAGE EXPLORERView in registry

actrail

PyPI

Runtime policies for agents — the open-source edge SDK (capture + check).

agentsaigovernanceguardrailsllmsecurity
Versions collected1
Direct dependencies13From release 2.0.0
Last observed20 Oct, 18:40 UTC

README

Version 2.0.0 documentation

Actrail

Runtime policies for AI agents — the open-source edge SDK

Govern what your agents do, not just what they say. Actrail captures every agent action's full tool-call arguments as telemetry and enforces deterministic policies before a risky action runs — a human-readable rule, never an LLM, in the binding decision.

PyPI Python License Ruff mypy: strict


Why Actrail

AI agents don't just generate text — they take actions: refund a customer, delete a row, deploy to prod, send data to an external LLM. Content guardrails don't see any of that. Actrail governs the actions:

  • Deterministic enforcement. Policies are plain rules (`payment.transaction_amount

    5000 → deny`) evaluated on a bounded request, fail-open by default. No model participates in the verdict.

  • Value-aware policies. The SDK sends the tool call's full argument JSON — not a value-stripped skeleton — so a policy can be written against an actual argument value (an amount, a currency, a destination path), not just which fields exist.
  • A thin edge. The SDK is a hook → span/check relay: it classifies a call's action and destination locally, then hands the backend the full picture. Redaction of credential-shaped values and PII classification are the backend's job now, not an edge heuristic — see Security & privacy.

Install

pip install actrail

Requirements

  • Python 3.11+. The system Python on macOS is 3.9 and will not work — use a 3.11/3.12 environment.
  • macOS 12+ (Apple Silicon or Intel) or Linux x86_64. Prebuilt wheels bundle the native shim — no toolchain needed.

Verify:

actrail --help                                        # bundled CLI on PATH
python -c "import actrail; print(actrail.__version__)"

not a supported wheel on this platform? Almost always your Python isn't 3.11/3.12 (macOS ships 3.9). Create a 3.11/3.12 env — e.g. uv venv --python 3.12 — and reinstall.

Quickstart

Claude Code (zero-code onboarding)

actrail init --key ak_live_...     # registers the SDK, wires hooks, starts the daemon (shadow)
actrail doctor                     # verify config · hooks · daemon

init also registers this SDK release with the backend (metadata only — integration/version/contract, no customer data), so Actrail can install the managed policies this release is certified to enforce before the first trail arrives.

init wires the pre-tool policy check immediately. Policies still begin in shadow, so nothing blocks until an administrator graduates one to enforce in the Actrail console. actrail enforce off is an explicit local emergency opt-out; enforce on restores the hook if it was removed.

Two managed catalog rules intentionally need organization-specific named sets before they can govern: production_destructive_action needs prod_hosts, and customer_data_unapproved_destination needs approved_destinations. Configure those in the console during onboarding; the SDK never guesses tenant trust boundaries.

Any agent (the library)

import actrail

actrail.init(key="ak_live_...", agent="support-bot")

# Before a risky action — get a deterministic, bounded verdict.
verdict = actrail.check(
    trail_id="sess_42",
    tool="pay.api",
    action="refund",
    tool_input={"order": {"amount": 2500, "currency": "USD"}, "table": "prod.customers"},
)
if not verdict.allow:
    raise PermissionError(verdict.reason)   # require_approval / deny

# After it runs — capture the action as telemetry (fire-and-forget).
actrail.capture(
    trail_id="sess_42",
    tool="pay.api",
    action="refund",
    tool_input={"order": {"amount": 2500}, "customer": {"email": "alice@example.com"}},
)

tool_input is the full tool-call argument JSON, exactly as your integration (or Claude Code) produced it. Actrail sends it on the wire, bounded only by size (see What leaves the machine) — the backend is where it's governed: bounded and redacted server-side, and turned into the policy-queryable fields a custom rule like "deny refund_payment when payment.transaction_amount > 5000" is written against.

What leaves the machine

{
  "tool": "mcp__razorpay__refund_payment", "action": "call", "destination": "razorpay",
  "tool_use_id": "toolu_01AbC…",
  "tool_input": {                                 // the FULL argument JSON, as produced
    "payment": {"transaction_amount": 6000, "currency": "INR"}
  },
  "signals": {},
  "sdk_version": "2.0.0", "contract_version": "v3"
}

No SDK-side redaction, bucketing, or type-only reduction — that governance moved to the backend (Ingest::ToolInput): it bounds an oversized payload, redacts a credential-shaped value or a value under a secret-named key (api_key, password, token, …) in place, and derives the field.<path> facts a policy can match on. A credential passed as an ordinary tool argument (e.g. a curl command with an Authorization header, or an MCP tool whose input includes an API key) is redacted there, not on the SDK side — the SDK does no content scanning at all.

Architecture

tool call ──► capture()/check() ──► classify (action/destination) ──► bound (size only) ──► backend
                                     structural parsers only            src/actrail/bound.py    /spans · /check
  • Deterministic outside, fail-open at /check, fail-safe at ingest.
  • The SDK does no content scanning — no secret/PII detection, no taint tracking, no file/script provenance. It classifies a call's action and destination from the tool name (and, for Bash, the command text) and bounds tool_input for size; everything else is the backend's job.

After upgrading, run:

actrail init --key ak_live_...     # idempotently upgrades owned hook matchers
actrail restart                    # loads the new SDK into the warm daemon
actrail doctor

Security & privacy

See SECURITY.md for the full picture. Short version: the SDK sends the full tool_input — bounded for size, nothing more — and the backend is the boundary that bounds, redacts, and validates it before anything is persisted or evaluated.

Development

uv venv && uv pip install -e ".[dev]"
uv run pytest          # tests
uv run ruff check .    # lint
uv run mypy            # strict types

License

Apache 2.0

Downloads & popularity

Awaiting observations

No metric observations yet

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

Versions 1

Collected releases
VersionPublishedDirect dependenciesOpen version
2.0.023 Sept 202613

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 18:40 UTC

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

Record identity

package:bd8fb7ab538829f4519402c0bf172b492e1419ec4c8b8452690562e8e99cb74b