Skip to main content

Zero-dependency Python client for the raxIT runtime governance engine (permit / defer / deny on every tool call)

Project description

raxit — thin Python client for the raxIT governance daemon

Govern every agent tool call with permit / defer / deny, before it executes.

uv add raxit          # zero runtime dependencies (stdlib only)

Not yet published: raxit isn't on PyPI yet (publish is a founder-owned manual step). Until then, install from the monorepo — see docs/quickstart.md.

Platforms: the launcher resolves/downloads engine binaries for darwin/linux only. On Windows, run raxit from WSL — there is no native Windows engine build.

Zero-code governance (raxit run)

The fastest path is no SDK calls at all. raxit run boots the daemon on localhost:8181, sets the child environment, and preloads the auto-patcher (via sitecustomize) so every tool call is governed. raxit init scans your repo and generates the .raxit/ policy workspace first — raxit run fail-closes without it:

raxit init                                     # scan -> generate .raxit/
raxit run --agent-id my-agent -- python agent.py

Under the hood this sets RAXIT_AUTOLOAD=1 and puts the raxit sitecustomize dir on PYTHONPATH, so the auto-patcher fires at Python startup and patches the tool-dispatch choke point of each detected framework:

Framework How it's governed
LangChain Auto-patched (importable)
LangGraph Auto-patched
CrewAI Auto-patched
AutoGen Auto-patched
OpenAI Agents SDK Auto-patched
Pydantic AI Auto-patched
Google ADK Auto-patched
LlamaIndex Auto-patched
Strands Agents Auto-patched
smolagents Auto-patched
Haystack Auto-patched

A blocked call raises RaxitDenied; a MODIFY verdict runs the tool on the engine's transformed arguments; a permit runs it unchanged. raxit.agent also exposes governed / governed_tool as a manual, per-tool escape hatch when auto-patch doesn't fit.

Programmatic client

from raxit import RaxitClient

client = RaxitClient("http://localhost:8181", agent_id="my-agent")
d = client.govern(resource="db.read", args={"query": "select 1"})
if d.deferred:
    d = client.govern.approve_wait(d)      # blocks until a human approves
if d.denied:
    raise RuntimeError(f"{d.reason_code}: {d.hint}")
result = run_tool()                        # only runs on permit
client.output.record(result, car=d.car)    # feeds output governance + taint

LangChain (no langchain import required by this package):

from raxit.langchain import RaxitCallbackHandler
handler = RaxitCallbackHandler(client)    # raises RaxitDenied on deny
agent.run("...", callbacks=[handler])

Fail-closed by default: if the daemon is unreachable, govern() returns deny (deny.daemon_unreachable). Pass fail_open=True for dev only.

RAXIT_GOVERNANCE

Governed by default. RAXIT_GOVERNANCE=off is the kill-switch for contrast/before-after demos — the client then bypasses the daemon entirely and every call synthesizes permit. Only two values are accepted (after strip().lower()): on and off; unset defaults to on. Any other value — 1/true/yes/0/false/no, or a typo — raises ValueError at client construction, before any network call, rather than silently guessing.

Audit — verify the tamper-evident decision log

client.audit.verify() checks the hash-chained Decision Provenance log; pass signatures=True with one or more pinned Ed25519 public keys to also verify record signatures offline against a trusted key (not the daemon's own config):

client = RaxitClient("http://localhost:8181", operator_token="<operator token>")
report = client.audit.verify(
    signatures=True,
    require_signed=True,
    pubkeys=["<base64 raw-32-byte Ed25519 pubkey>"],
)
assert report["signatures_verified"] and report["signed_count"] > 0

Operator-gated (Authorization: Bearer <operator_token>). For fully offline, adversarial-grade verification use the CLI: raxit audit verify --signatures --pubkey <key>.

Budget — read the session/principal budget projection

client.budget.get() is a strictly read-only projection of the engine's budget accountant — never a reservation. It reports used/remaining against each configured cap (call budget, per-session and per-day token/cost caps):

client = RaxitClient("http://localhost:8181", operator_token="<operator token>")
snap = client.budget.get(agent_id="payments-bot", session_id="sess-1")
for b in snap.budgets:
    print(b.name, b.used, "/", b.limit, b.unit, f"({b.window})")

Operator-gated (Authorization: Bearer <operator_token>). Fails closed: an unreachable daemon raises GovernanceError — it is never read as an empty or infinite budget. An empty snap.budgets means genuinely no cap configured.

Warrants — inspect the loaded standing grants

client.warrants.list() / client.warrants.get(id) are a read-only view of the warrants loaded at raxit serve startup. There is no create/revoke — minting stays the operator-controlled load path.

client = RaxitClient("http://localhost:8181", operator_token="<operator token>")
for w in client.warrants.list():
    print(w.id, w.agent_id, w.tool_pattern, w.status, "expires", w.expires_at)

Operator-gated. Fails closed (raises GovernanceError when unreachable, so "none" is never confused with "unreachable"). Warrants carry no credentials and the attested intent-baseline text is never projected.

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

raxit-0.0.1.tar.gz (98.4 kB view details)

Uploaded Source

Built Distribution

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

raxit-0.0.1-py3-none-any.whl (64.5 kB view details)

Uploaded Python 3

File details

Details for the file raxit-0.0.1.tar.gz.

File metadata

  • Download URL: raxit-0.0.1.tar.gz
  • Upload date:
  • Size: 98.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for raxit-0.0.1.tar.gz
Algorithm Hash digest
SHA256 219141a66e49a79563b6aa67f43844f5cf344c4696036980fe30bef9982e842c
MD5 5a0b5574e4d0640928a7d9892f948f6d
BLAKE2b-256 e0ff1916afba6c7f943b48fd4ace68ea71ff89d3e7b2b50bba572667ffdce40f

See more details on using hashes here.

Provenance

The following attestation bundles were made for raxit-0.0.1.tar.gz:

Publisher: publish.yml on raxITlabs/runtime-security-core

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

File details

Details for the file raxit-0.0.1-py3-none-any.whl.

File metadata

  • Download URL: raxit-0.0.1-py3-none-any.whl
  • Upload date:
  • Size: 64.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for raxit-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 4c05f4423c1cad3c85b5aad587930eb7a7774c38dc646c91a3a5956346e64478
MD5 fdb9661e5506e457a467fbcbc834c144
BLAKE2b-256 062783d5c3adde3af9f1ff8a6d9909a74975d3387c6d9ba346e63961680c8ef9

See more details on using hashes here.

Provenance

The following attestation bundles were made for raxit-0.0.1-py3-none-any.whl:

Publisher: publish.yml on raxITlabs/runtime-security-core

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