AgenticRail SDK — deterministic sequence enforcement for AI agents
Project description
agenticrail
AgenticRail Python SDK — deterministic sequence enforcement for AI agents.
Gate every step of your agent workflow before it executes. Cryptographic receipts. Zero enforcement failures.
pip install agenticrail
What it does
AgenticRail sits beneath your agent and enforces that steps run in the right order, with no skips, no replays, and no re-entry after a sequence is sealed. Every decision — ALLOW, DENY, or HALT — produces a cryptographically signed receipt stored at the edge.
Three verdicts:
- ALLOW — step is clear, your agent code executes
- DENY — enforcement violation (wrong order, replay, sealed), execution blocked
- HALT — hard stop (injection attempt, poison payload detected), execution blocked
Install
# Core client only
pip install agenticrail
# With LangGraph support
pip install "agenticrail[langgraph]"
# With CrewAI support
pip install "agenticrail[crewai]"
# Everything
pip install "agenticrail[all]"
Quick start — any framework
from agenticrail import RailClient
client = RailClient(api_key="DEMO-AGENTICRAIL-PUBLIC-2026")
# RailSequence sends step_order on every call — the gate reads it from each payload
seq = client.sequence(
sequence_id="my-agent-run-001",
step_order=["verify_identity", "assess_risk", "execute_transfer", "audit_ledger"],
)
seq.next("verify_identity") # → ALLOW
seq.next("assess_risk") # → ALLOW
seq.next("execute_transfer") # → ALLOW
seq.next("audit_ledger") # → ALLOW (seals sequence)
# Any out-of-order, replay, or post-seal call raises RailDenied
seq.next("verify_identity") # → raises RailDenied: SEALED_SEQUENCE
Get a production API key at agenticrail.nz.
LangGraph integration
Wrap each node at add_node time. Uses thread_id from LangGraph config as the sequence_id — each graph invocation is isolated.
from langgraph.graph import StateGraph, END
from agenticrail import RailClient
from agenticrail.integrations.langgraph import LangGraphRail
client = RailClient(api_key="YOUR_KEY")
rail = LangGraphRail(
client,
step_order=["research", "analyze", "write_report", "review"],
)
builder = StateGraph(AgentState)
# Wrap each node — gate fires before node execution
builder.add_node("research", rail.wrap("research", research_fn))
builder.add_node("analyze", rail.wrap("analyze", analyze_fn))
builder.add_node("write_report", rail.wrap("write_report", write_report_fn))
builder.add_node("review", rail.wrap("review", review_fn))
builder.set_entry_point("research")
builder.add_edge("research", "analyze")
builder.add_edge("analyze", "write_report")
builder.add_edge("write_report", "review")
builder.add_edge("review", END)
graph = builder.compile()
# thread_id → sequence_id: each invocation is independently tracked and verifiable
result = graph.invoke(
{"query": "EU AI Act compliance checklist"},
config={"configurable": {"thread_id": "run-2026-001"}},
)
What happens on DENY or HALT:
rail.wrap() raises RailDenied inside the node. LangGraph catches unhandled node exceptions and halts graph execution. No subsequent nodes run.
Concurrent runs:
Each thread_id is a separate sequence. Concurrent graph invocations with different thread IDs do not interfere — the gate tracks them independently via Durable Objects.
CrewAI integration
Use guard.kickoff() instead of crew.kickoff(). Step[0] is gated before the crew starts; subsequent steps are gated via a task callback injected between tasks.
from crewai import Crew
from agenticrail import RailClient
from agenticrail.integrations.crewai import CrewRailGuard
client = RailClient(api_key="YOUR_KEY")
guard = CrewRailGuard(
client,
step_order=["research_task", "analysis_task", "write_task"],
)
crew = Crew(
agents=[researcher, analyst, writer],
tasks=[research_task, analysis_task, write_task],
)
# Drop-in replacement for crew.kickoff()
# Each call generates a fresh sequence_id — each run is independently tracked
result = guard.kickoff(crew, inputs={"topic": "AI governance"})
Note on blocking: CrewAI's task_callback fires synchronously between tasks, so the gate can block task N before task N starts. However, if CrewAI swallows exceptions in callbacks, a denied task may still execute. In that case, guard.kickoff() raises RailDenied after the crew finishes, preserving the denial in the audit trail.
For hard blocking (guaranteed pre-execution), use guard.gate() in a custom orchestration loop:
guard.reset()
for step, task_fn in zip(STEP_ORDER, task_functions):
guard.gate(step) # raises RailDenied immediately on DENY
task_fn()
API reference
RailClient
client = RailClient(
api_key="...", # Required. Bearer token for the wrapper API.
model_id="agent", # Optional. Identifies your agent in receipts.
base_url=None, # Optional. Defaults to api.agenticrail.nz/v1/evaluate.
timeout=10, # Optional. Request timeout in seconds.
)
client.evaluate(sequence_id, step, *, ...)
decision = client.evaluate(
sequence_id="my-run-001",
step="verify_identity",
action_type="CHECK_STATE", # Optional. Default: CHECK_STATE.
action="verify user identity", # Optional. Human-readable label.
inputs={"user_id": "u123"}, # Optional. Metadata attached to receipt.
step_order=[...], # Required on every call — gate reads it from each payload.
raise_on_deny=True, # Optional. Default True.
)
# decision.decision → "ALLOW" | "DENY" | "HALT"
# decision.allowed → True if ALLOW
# decision.pack_id → SHA-256 receipt hash
# decision.receipt → full signed receipt dict
# decision.reasons → list of reason codes on DENY/HALT
client.sequence(sequence_id, step_order)
Returns a RailSequence that tracks step_order state — call .next(step) for each step without managing step_order yourself.
RailDenied
try:
seq.next("execute_transfer")
except RailDenied as e:
print(e.decision) # "DENY" or "HALT"
print(e.reasons) # ["SEQUENCE_VIOLATION"]
print(e.pack_id) # receipt hash for audit
print(e.step) # "execute_transfer"
LangGraphRail
rail = LangGraphRail(
client,
step_order=["step_a", "step_b", "step_c"],
fallback_sequence_id=None, # Used when thread_id not in config
)
wrapped_fn = rail.wrap("step_a", original_fn, action_type="CHECK_STATE")
CrewRailGuard
guard = CrewRailGuard(
client,
step_order=["task_1", "task_2", "task_3"],
sequence_id=None, # Optional. Auto-generated per kickoff() call if None.
action_type="CHECK_STATE",
)
result = guard.kickoff(crew, inputs={...})
guard.gate("task_1") # Explicit gate for custom loops
guard.reset() # Reset state for a new run
Compliance reports
Every pack_id in a RailDecision is a verifiable receipt. Paste your sequence ID into the report generator or call it programmatically:
curl -X POST https://api.agenticrail.nz/v1/report \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"sequence_id": "my-run-001", "format": "json"}'
Returns: chain proof, HMAC verification, enforcement log, AI-written compliance narrative (EU AI Act Article 11).
Demo sequences (using DEMO-AGENTICRAIL-PUBLIC-2026) are verifiable at report.agenticrail.nz — no auth needed.
Action types
| Type | Use when |
|---|---|
CHECK_STATE |
Reading or observing state (default) |
VALIDATE_INPUT |
Verifying inputs before acting |
RECORD_RESULT |
Writing or committing an outcome |
CLARIFY_NEXT_STEP |
Asking for clarification |
SELECT_NEXT_STEP |
Choosing a path |
WAIT_FOR_SIGNAL |
Pausing for an external trigger |
PAUSE_CYCLE |
Deliberate suspension |
REDUCE_STIMULUS |
Backing off |
Links
- API docs: agenticrail.nz/docs
- Interactive demo: agenticrail.nz/demo
- Compliance matrix (60+ frameworks): agenticrail.nz/compliance
- Verify a sequence: report.agenticrail.nz
TUARA KURI LIMITED — trading as AgenticRail. Hokianga, New Zealand.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agenticrail-0.1.0.tar.gz.
File metadata
- Download URL: agenticrail-0.1.0.tar.gz
- Upload date:
- Size: 11.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6c76cbe48dd86507700ceaade1076dd3d7633ce8d30ffd63e9f8886b3b4a7f2d
|
|
| MD5 |
0c0fc5a4ca4a7927279305ed36d0fcf4
|
|
| BLAKE2b-256 |
35c8352f3eeca15c518002e246c10506fcb689a2ada7ad1e322deb27749c682d
|
Provenance
The following attestation bundles were made for agenticrail-0.1.0.tar.gz:
Publisher:
publish-python-sdk.yml on MSMD-RUA/AgenticRail
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agenticrail-0.1.0.tar.gz -
Subject digest:
6c76cbe48dd86507700ceaade1076dd3d7633ce8d30ffd63e9f8886b3b4a7f2d - Sigstore transparency entry: 1431254269
- Sigstore integration time:
-
Permalink:
MSMD-RUA/AgenticRail@26ce75d87e0862a32a98391da03f70b860622aad -
Branch / Tag:
refs/tags/python-v0.1.0 - Owner: https://github.com/MSMD-RUA
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-python-sdk.yml@26ce75d87e0862a32a98391da03f70b860622aad -
Trigger Event:
push
-
Statement type:
File details
Details for the file agenticrail-0.1.0-py3-none-any.whl.
File metadata
- Download URL: agenticrail-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7514f84a9448ec9c918558d86ef6205b88261d95e86553261052d55771b85d4b
|
|
| MD5 |
ccf843fe9b86342d83045acd9582ee62
|
|
| BLAKE2b-256 |
a4b46d9e05d00fa7f7d901d9f61f991efae7f4f17152f9e816ba99058dd4022f
|
Provenance
The following attestation bundles were made for agenticrail-0.1.0-py3-none-any.whl:
Publisher:
publish-python-sdk.yml on MSMD-RUA/AgenticRail
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agenticrail-0.1.0-py3-none-any.whl -
Subject digest:
7514f84a9448ec9c918558d86ef6205b88261d95e86553261052d55771b85d4b - Sigstore transparency entry: 1431254366
- Sigstore integration time:
-
Permalink:
MSMD-RUA/AgenticRail@26ce75d87e0862a32a98391da03f70b860622aad -
Branch / Tag:
refs/tags/python-v0.1.0 - Owner: https://github.com/MSMD-RUA
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-python-sdk.yml@26ce75d87e0862a32a98391da03f70b860622aad -
Trigger Event:
push
-
Statement type: