
Python framework for building LLM workflows as state machines with formal verification via Z3 theorem proving, CTL model checking, and conformal prediction for provably correct data extraction.
Prove your AI agent is injection-safe, in-spec, and won't act out of bounds — before you ship it.
A design-time verifier for LLM agents — not a runtime guardrail. Import your LangGraph / CrewAI / AutoGen / MCP agent and Aura proves five things about the agent you already wrote, then hands you the exact counterexample or a certificate. Z3 · CTL model checking · information-flow/taint · conformal calibration. Runs locally, in CI, no API key.
Verify a design → import a real agent from its code → the lethal trifecta lights up with the exact path → save a baseline and gate regressions. · ▶ watch the full walkthrough
pip install aura-state # or: uv pip install aura-state · uv add aura-state
$ aura-state demo # no keys, no config, no agent of your own needed
aura-state check · support-ticket-agent · 4 nodes
✗ trifecta [send]: lethal trifecta closed — prompt injection at 'fetch' (untrusted)
can reach external sink 'send' unsanitized while 'draft' brings private data into
scope. Path: fetch → lookup → draft → send. Break it with a sanitizer between
'fetch' and 'send', or remove one of the three capabilities.
✗ NOT PROVEN — 1 blocking finding(s) # exit 1 → CI fails
checked: trifecta closed · taint proven · reachability proven · obligations proven · policy 0 flagged
Prompt injection is only one of them.
| Property | In plain words | |
|---|---|---|
| 🔒 | Safe — taint + lethal trifecta | can't be tricked into leaking data |
| ✅ | Correct — Z3/SMT obligations | outputs obey your rules (amount ≤ limit) |
| ♻️ | Live — CTL model checking | terminates, every step reachable, no dead ends |
| 📊 | Calibrated — split-conformal intervals | knows how confident it actually is |
| 🛑 | Governed — risk-controlled abstention | refuses to act when it's unsure |
aura-state check my_agent.json # a studio export
aura-state check your_agent.py # a LangGraph / CrewAI / AutoGen source file — parsed, never executed
aura-state check ./my-agent-repo/ # a whole directory
uvx aura-state check agents/*.json # zero-install via uv — perfect for CI
Beyond the trifecta, check also proves:
"manifest": { "side_effects": ["read"] } to your flow:
✗ least-privilege [Pay]: 'Pay' can external 'payment.charge', outside the declared manifest
~/.cursor/mcp.json and pass it as a parameter"). Static — it never connects to a server.Prove it — then prove the proof. Emit a verifiable certificate and re-check it without trusting whoever issued it:
aura-state certify your_agent.py --out cert.json # design + verdict, content-hashed
aura-state verify-cert cert.json # re-runs the verifier — catches any tamper
Maps to EU AI Act Art. 12 / ISO 42001 (evidence, not just documentation).
Benchmark it. aura-state bench runs a labeled corpus (accuracy on safe/vulnerable pairs — sound, so recall is 100% by construction; the measured number is precision) plus import coverage on real MCP/framework agents ingested unmodified.
Pre-execution agent verifiers exist — but each does one thing and makes you rewrite your agent into their formalism. Aura's edge is being the shipped tool that ingests the agent you already wrote and runs the whole set:
| Static (before it runs)? | Security dataflow? | Imports your real agent? | |
|---|---|---|---|
| AgentProof | ✅ | ❌ topology only | ✅ |
| AgentFlow | ✅ | ✅ | ❌ its own policy DSL |
| FIDES (Microsoft) | ❌ runtime | ✅ | ❌ build-with-it planner |
| Aura-State | ✅ | ✅ | ✅ LangGraph / CrewAI / AutoGen / MCP |
We didn't invent these methods — the research is rich and some of it is more rigorous than ours. We're the one you can pip install and point at your existing agent today. And it's sound / fail-closed: an unknown capability is surfaced as an advisory, never silently passed.
Drop it into CI and every PR is checked:
# .github/workflows/aura.yml
- uses: your-org/aura-state@v0
with: { paths: "agents/*.json" }
The lethal trifecta is the scariest failure mode for a tool-using agent: the moment it can (1) read private data, (2) ingest untrusted content, and (3) communicate externally — all on one reachable path — a prompt injection hidden in that content can read your data and ship it out. Everyone warns about it. Aura proves your agent can't close it, statically, before you ship:
$ aura-state check dev_assistant.tools.json # ← your MCP tools/list export
✗ trifecta [slack_post_message]: lethal trifecta closed — prompt injection at 'fetch'
(untrusted) can reach external sink 'slack_post_message' unsanitized while 'read_file'
brings private data into scope. Path: fetch → Agent → slack_post_message.
Break it with a sanitizer between 'fetch' and 'slack_post_message'.
Point it straight at your MCP setup. Export your agent's tools/list (or hand it your client config) and Aura models the worst case — the LLM can call any tool in any order — then decides whether fetch + filesystem + slack together form an exfiltration channel. It never connects to or runs a server.
Or point it at your agent's code. Aura statically imports the tool surface from a LangGraph / CrewAI / LangChain source file or repo — no install, and it never runs your code:
aura-state check your_agent.py # extracts @tool functions & framework tools
aura-state check ./my-agent-repo/ # a whole directory
✗ trifecta [post_to_slack]: prompt injection at 'fetch_url' (untrusted) can reach
'post_to_slack' unsanitized while 'read_customer_file' brings private data into scope.