AORTA: Adding Organizational Reasoning to Agents
Deterministic governance for Claude Code
You tell Claude Code "don't touch .env" in a system prompt.
It works, until context compaction drops that instruction
or the agent reasons itself into an exception.
System prompts are suggestions. Tool calls are actions.
aorta watchA real Claude Code session with aorta governance active. Every block is deterministic. The engine decides, not the LLM.
Enforcement happens at the tool call layer, outside the context window. The LLM never decides whether a rule applies.
Declare paths as read-write, read-only, or no-access. Writes outside scope are blocked before execution. Not suggested against. Blocked.
The agent cannot edit its governance config, cannot delete the hooks, and cannot run aorta reset. The guardrails guard themselves.
Shell commands are analyzed for hidden file writes. cp src/app.py /tmp/leak.py is caught even though the Bash tool itself is allowed.
"Commit only after tests pass" with automatic achievement tracking. Tests pass → commit unlocked → file change → achievement reset.
Git commit/push require user confirmation. Guards against post-compaction hallucinated commits where the agent acts on stale context.
When the agent reads a read-only file, a governance notice tells it not to hardcode values. In testing, Claude refused to embed a database password.
One command to set up. YAML to configure. Works with Claude Code hooks today.
Requires Python ≥ 3.10. No dependencies beyond PyYAML.
Creates the org spec, hooks config, state file, and registers the agent. One command.
The access map in the YAML spec is the primary interface. Three levels: read-write, read-only, no-access.
Every Write, Edit, Read, and Bash call goes through governance automatically. Open aorta watch in a second terminal to see decisions in real-time.
The governance engine sits between Claude Code and your filesystem via hooks. No modifications to Claude Code itself.
Claude Code calls a tool (Write, Edit, Bash, Read). The hook in .claude/settings.local.json fires aorta hook pre-tool-use before execution.
The pure-Python governance engine checks the action against compiled norms. Path-based rules use structural unification: variables bind at check time and propagate through conditions. No LLM involved in the decision.
Hard blocks deny outright. Soft blocks prompt the user to confirm. Approvals pass through. Every decision is logged to the event stream.
Manage governance from the command line. The agent can run read-only commands; mutating commands are blocked.
This is a meaningful layer of defense, not a security boundary. Here's what it can and can't do.
aorta blocks writing to .env but can't prevent the agent from reading a file (via allow-once) and pasting its contents elsewhere. The sensitive content warning is a prompt-level nudge, not enforcement.
An agent can construct commands that evade heuristic detection (e.g., python -c "open('x','w')..."). LLM analysis catches most but isn't bulletproof.
Governance only sees tool calls, not side effects. If a command creates files indirectly, the engine doesn't know.
The governance engine is generic, but the hook integration is specific to Claude Code. The architecture could adapt to other agent runtimes.
aorta4llm applies the AORTA organizational reasoning framework (Jensen, 2015) to LLM agent systems.
The original framework formalized how autonomous agents can reason about organizational structures (roles, norms, obligations, prohibitions) and act accordingly. This project adapts those ideas to a new kind of agent: LLMs with tool access.
The hybrid architecture uses LLMs for what they're good at (natural language, planning) and a deterministic logic engine for what they're bad at (consistent rule enforcement). The engine doesn't suggest compliance. It enforces it.