Skip to main content

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 as metadata-only 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 (refund > $500 without approval → require_approval) evaluated on a bounded request, fail-open by default. No model participates in the verdict.
  • Metadata-only by construction. The SDK never sends raw arguments or results. It emits a redacted, per-field skeleton — keys kept, values stripped or transformed — built from scratch, never copied.
  • An always-on secrets floor. API keys, tokens, private keys, passwords, connection strings are never emitted, and it can't be turned off.

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.

Optional extras for deeper local scanning:

pip install "actrail[ner]"    # + Presidio / spaCy for names & unstructured PII
pip install "actrail[full]"   # + transformers

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",
    payload={"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 metadata-only telemetry (fire-and-forget).
actrail.capture(
    trail_id="sess_42",
    tool="pay.api",
    action="refund",
    payload={"order": {"amount": 2500}, "customer": {"email": "alice@example.com"}},
)

payload is the structured tool-call args. Actrail walks it into a governed fields[] envelope — it never leaves your machine as raw data.

The telemetry contract

Every field passes through a transform ladder, least → most revealing, and the customer governs it per field (default-deny):

Rung What's emitted Example
drop nothing (skeleton only) unknown fields
type_only just the type customer.email → (type: email)
derived a safe derivation email → domain:example.com
bucket a coarse bucket amount: 2500 → 1000_10000
token a one-way HMAC pseudonym join without revealing
raw the value verbatim only for non-secret, opted-in fields

Three guarantees stack, in order:

  1. Default-deny — an un-contracted field gets a conservative per-type default.
  2. Secrets floor — a secret-typed field, or any value that looks secret, is forced to drop. Non-overridable — a contract can never lift a secret onto the wire.
  3. Outbound validator (fail-closed) — every emitted value is re-scanned and scrubbed if it still looks secret, the last line before anything leaves.

A seeded fuzz test asserts the invariant under the worst case — every field forced to raw: no secret ever appears in an emitted value.

What leaves the machine

{
  "tool": "pay.api", "action": "refund", "destination": "internal",
  "data_classes": ["financial", "pii"],          // derived from the envelope
  "fields": [                                     // the redacted skeleton
    {"path": "order.amount", "semantic_type": "amount", "handling": "bucket", "value": "1000_10000"},
    {"path": "customer.email", "semantic_type": "email", "handling": "type_only"},
    {"path": "auth.api_key", "semantic_type": "api_key", "handling": "drop"}   // floored — no value
  ],
  "amount": 2500,                                 // a first-class grammar fact
  "taint_sources": [{"table": "prod.customers"}], // enables "data from prod.customers" policies
  "taint": ["email:v1:9f3a…"],                    // one-way fingerprints (flow, not values)
  "sdk_version": "1.1.0", "contract_version": "v1"
}

No args. No result. No raw values. Ever.

Architecture

tool call ──► capture()/check() ──► enrich (taint) ──► contract pipeline ──────► backend
              payload · content       HMAC fingerprints  build ▸ govern ▸ validate  /spans · /check
                                                         fields[] · amount · sources
  • Deterministic outside, fail-open at /check, fail-safe at ingest.
  • BYO scanner — the enrichment scanners implement a simple Scanner protocol.
  • Optional NER (pip install actrail[ner]) for richer PII detection; the default path stays lightweight (regex + entropy + detect-secrets).

File and script provenance (v1.1)

Claude Code frequently reads sensitive data, writes a local helper script, and then runs python send.py or uv run python send.py. The final command does not contain the payload, so command scanning alone cannot govern it. v1.1 keeps a small local, metadata-only provenance index:

  1. Read records a one-way resource token, classifications, record count, and taint.
  2. Before a file-upload command, Python script, or Git push runs, Actrail performs bounded local analysis of only the referenced regular files. Python uses a small deterministic data-flow pass, so a local read counts only when its value reaches a supported network call; simple co-occurrence is not treated as a flow.
  3. The /check candidate carries the inherited classifications and the external destination, while earlier source spans are flushed first for ordered evaluation.

Paths, session ids, file contents, and customer values are never persisted in this index. Resource identities and file generations are HMACed, and the state file is written with mode 0600. Script reads are limited to 1 MiB, data classification and record counting to 8 MiB/10,000 records, Git config to 256 KiB, and symlinks, FIFOs, devices, sockets, or files over those limits are never read.

This closes ordinary file-backed curl, supported Python data flows, and Git push paths; it is not an OS network sandbox. Node, Ruby, arbitrary shell scripts, deliberately obfuscated or runtime-downloaded code, native processes that conceal their file/network relationships, and traffic outside a Claude Code tool hook require richer runtime telemetry or host/network controls in addition to Actrail.

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

The metadata-only guarantee is by construction, not detection — see SECURITY.md. Short version: raw payloads never leave the machine, secrets are floored non-overridably, taint is one-way HMAC, and the wire is fail-closed validated.

Development

uv venv && uv pip install -e ".[dev]"
uv run pytest          # tests (+ safety-invariant fuzz)
uv run ruff check .    # lint
uv run mypy            # strict types

License

Apache 2.0

Metadata

Release files for actrail 1.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for actrail 1.2.1
File Size Uploaded
actrail-1.2.1.tar.gz 2.3 MB Details

Built distributions (wheels)

Table of built distributions (wheels) for actrail 1.2.1
File
actrail-1.2.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.17+ x86-64, Linux glibc 2.5+ x86-64 Details
actrail-1.2.1-cp312-cp312-macosx_13_0_arm64.whl CPython 3.12 CPython 3.12 macOS 13.0+ ARM64 Details
actrail-1.2.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.11 CPython 3.11 Linux glibc 2.17+ x86-64, Linux glibc 2.5+ x86-64 Details
actrail-1.2.1-cp311-cp311-macosx_13_0_arm64.whl CPython 3.11 CPython 3.11 macOS 13.0+ ARM64 Details

Total release size: 12.7 MB

Release files / actrail-1.2.1.tar.gz

Download URL actrail-1.2.1.tar.gz
Size 2.3 MB
Tags Source
SHA-256 checksum
How to use checksums
9c079d405c6b635509e6f7d2692998cfcc7f47ffb5d3dac5de4960f81ac93107
BLAKE2b-256 checksum
How to use checksums
e7f6ab62a8fa7960601938e949d7e322b306cba5a1448f747c0f48718be603a8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 28, 2026.

Transparency log

Release files / actrail-1.2.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL actrail-1.2.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 2.3 MB
Tags CPython 3.12 Linux glibc 2.17+ x86-64 Linux glibc 2.5+ x86-64
SHA-256 checksum
How to use checksums
dce3154bdd1754c85d156252e133d787f8bf51cd219a9ec60f87f84f03547ee1
BLAKE2b-256 checksum
How to use checksums
8245087383d55450dcf0d372c0110b11031e23128b85b62a973eefa17ae09eea
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 28, 2026.

Transparency log

Release files / actrail-1.2.1-cp312-cp312-macosx_13_0_arm64.whl

Download URL actrail-1.2.1-cp312-cp312-macosx_13_0_arm64.whl
Size 2.9 MB
Tags CPython 3.12 macOS 13.0+ ARM64
SHA-256 checksum
How to use checksums
67da286a313292189c6f05a503ee07c178884f354e9570f43d6b45bd7c8da015
BLAKE2b-256 checksum
How to use checksums
5bca2bd06be0d02506db7e9c34e12c4c5a29ee8d5566fe69828d633ae026eb9d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 28, 2026.

Transparency log

Release files / actrail-1.2.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL actrail-1.2.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 2.3 MB
Tags CPython 3.11 Linux glibc 2.17+ x86-64 Linux glibc 2.5+ x86-64
SHA-256 checksum
How to use checksums
b2443f5d34e9ac55227a3ce9268ab2af18c5a3f1af7291b8cfc42e15582aa8fb
BLAKE2b-256 checksum
How to use checksums
62244b9437a25a491bfbc5ae5051467b4259f6ca8701c66f210e87edc1ac8353
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 28, 2026.

Transparency log

Release files / actrail-1.2.1-cp311-cp311-macosx_13_0_arm64.whl

Download URL actrail-1.2.1-cp311-cp311-macosx_13_0_arm64.whl
Size 2.9 MB
Tags CPython 3.11 macOS 13.0+ ARM64
SHA-256 checksum
How to use checksums
d40dc02469c2cefd97441eae71b7f7cc94ef48f404395401cc376c86c720646c
BLAKE2b-256 checksum
How to use checksums
1e5ea35e3849089298c4bcdec627b489109274dd621656cb22a43d7af2a97730
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 28, 2026.

Transparency log

Release history Release notifications | RSS feed

2.0.0

5 release files

This release

1.2.1 This release

5 release files

1.2.0

5 release files

1.1.5

5 release files

1.1.4

5 release files

1.1.3

5 release files

1.1.2

5 release files

1.1.1

5 release files

1.1.0

5 release files

1.0.2

5 release files

1.0.1

5 release files

1.0.0

5 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page