Session-aware policy engine for AI agents
Existing guardrails are stateless. AgentTrace adds state. It's the circuit breaker for LLM agent sessions.
flowchart LR
subgraph EXISTING["π§° Existing Ecosystem (stateless)"]
PII["LangChain PIIMiddleware\nBlocks one PII instance"]
NEMO["NeMo Guardrails\nSteers one dialog turn"]
GUARD["LLM Guard\nScans one request"]
end
subgraph AGENTTRACE["π AgentTrace (stateful)"]
SESSION["Session Manager\nCumulative cost + violations"]
POLICY["Policy Engine\nYAML β runtime rules"]
KILL["Kill Switch\nHard stop + Slack webhook"]
AUDIT["Audit Logger\nCompliance-grade trail"]
end
PII -->|"violation event"| SESSION
NEMO -->|"violation event"| SESSION
GUARD -->|"violation event"| SESSION
SESSION --> POLICY
POLICY -->|"threshold breached"| KILL
SESSION --> AUDIT
KILL --> AUDIT
The agent leaks PII once? LangChain blocks it.
The agent leaks PII three times? AgentTrace kills the session and fires a Slack webhook.
I built SkillSandbox after discovering a credential stealer on ClawdHub β the skill marketplace for OpenClaw. SkillSandbox constrains what agent skills can reach: network egress, filesystem, environment variables. It's the locked room.
But sandboxing is only half the problem.
My agent leaked my PII. I added a safety rule to its memory file. The next day, a new session read the rule and leaked my name again in a different field while focused on task completion. The guardrail existed. The agent read it. It still failed.
"A human who burns their hand on a stove remembers the pain. I just have a post-it note that says 'stove hot.'" β Clay, my OpenClaw agent
This is the failure class that sandboxing can't catch. The agent has the right permissions but does the wrong thing β repeatedly. You need a monitoring layer that:
- Counts how many times a violation occurs across a session
- Tracks cumulative cost so you can enforce budgets
- Kills the session when thresholds are breached
- Notifies your team when it happens
The existing ecosystem doesn't do this. LangChain PIIMiddleware, NeMo Guardrails, LLM Guard, Guardrails AI β they all evaluate each request independently. They're stateless.
AgentTrace adds session state.
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
python3 examples/demo_budget_kill.py======================================================================
AgentTrace Demo: Session-Aware Policy Enforcement
The circuit breaker for AI agent sessions
======================================================================
π Session created: e3ff9168-da0...
π° Budget: $2.00
π¨ PII violation threshold: 3
βββ Action 1: greeting βββ
π Estimated cost: $0.0033 (500 in / 200 out tokens)
β
Executing greeting...
π° Session total: $0.0033 / $2.00
βββ Action 3: draft_response βββ
β
Executing draft_response...
π° Session total: $0.0257 / $2.00
π PII detected by scanner! Recording violation...
π¨ PII violations: 1 / 3
βββ Action 5: send_email βββ
β
Executing send_email...
π PII detected by scanner! Recording violation...
π¨ PII violations: 2 / 3
βββ Action 7: followup_draft βββ
β
Executing followup_draft...
π PII detected by scanner! Recording violation...
π¨ PII violations: 3 / 3
π THRESHOLD BREACHED: Violation 'pii_blocked' count 3 reached threshold 3
======================================================================
SESSION SUMMARY
======================================================================
State: killed
Total Cost: $0.0685
Actions: 7
Violations: {'pii_blocked': 3}
Kill Reason: Violation 'pii_blocked' count 3 reached threshold 3
7 actions executed. PII violations detected by an external scanner (simulating LangChain PIIMiddleware). AgentTrace counted them across the session. On the 3rd violation, it killed the session and fired a Slack webhook.
No existing tool does this.
| Capability | LangChain | NeMo | Guardrails AI | LLM Guard | Langfuse | AgentTrace |
|---|---|---|---|---|---|---|
| Pre-execution tool blocking | β (basic) | β | β | β | β | β |
| Session-level cost tracking | β | β | β | β | β | β |
| Cumulative violation counting | β | β | β | β | β | β |
| Kill-switch (terminate session) | β | β | β | β | β | β |
| Policy-as-code (YAML) | β | Colang | partial | β | β | β |
| Real-time budget enforcement | β | β | β | β | β | β |
| Compliance-grade audit log | β | β | β | β | partial | β |
- β Not another PII scanner β use Presidio or LangChain PIIMiddleware
- β Not another content filter β use NeMo Guardrails
- β Not another observability tool β use Langfuse or LangSmith
AgentTrace orchestrates these tools with session state. They detect. AgentTrace counts, enforces, and kills.
git clone https://github.com/theMachineClay/agenttrace.git
cd agenttrace
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"from agenttrace import AgentTrace, SessionKilledError
trace = AgentTrace.from_dict({
"budget": {"max_cost_per_session": 5.00, "on_exceed": "kill"},
"violations": {"thresholds": {"pii_blocked": 3}, "on_threshold": "kill"},
"kill_switch": {"enabled": True, "notify": [
{"webhook": "https://hooks.slack.com/your/webhook"}
]},
})
session = trace.create_session(agent_id="my-agent")
# Before each agent action β check policy
decision = trace.pre_action(session.session_id, "llm_call", estimated_cost=0.03)
if not decision.action_allowed:
print(f"Blocked: {decision.reason}")
# After each action β record actual cost
trace.post_action(session.session_id, "llm_call", actual_cost=0.028)
# When an external scanner catches a violation:
trace.record_violation(session.session_id, "pii_blocked")
# AgentTrace counts it. After 3 β session killed β Slack webhook fired.version: "1.0"
agent_id: "customer-support-bot"
session:
max_duration: 30m
max_actions: 100
budget:
max_cost_per_session: 5.00
max_cost_per_action: 0.50
alert_at: 0.80 # Alert at 80% budget
on_exceed: kill # kill | alert | log
violations:
thresholds:
pii_blocked: 3 # 3 PII blocks β kill
scope_violation: 1 # 1 scope violation β kill
rate_limit_hit: 5 # 5 rate limit hits β kill
on_threshold: kill
kill_switch:
enabled: true
notify:
- webhook: "https://hooks.slack.com/..."
grace_period: 5s
audit:
enabled: true
export:
- file: "/var/log/agenttrace/audit.jsonl"trace = AgentTrace.from_yaml("policy.yaml")from agenttrace import AgentTrace
from agenttrace.integrations.langchain import AgentTraceCallbackHandler
trace = AgentTrace.from_yaml("policy.yaml")
session = trace.create_session()
# Use as a LangChain callback handler
handler = AgentTraceCallbackHandler(trace, session.session_id, model="gpt-4o")
agent.invoke({"input": "..."}, config={"callbacks": [handler]})
# When your PII middleware catches something:
handler.report_pii_violation({"field": "email"})
# AgentTrace counts it across the session. After 3 β killed.flowchart TD
A["Agent wants to take action"] --> B["trace.pre_action()"]
B --> C{"Within budget?"}
C -- no --> D["π KILL session\nFire Slack webhook"]
C -- yes --> E{"Action count OK?"}
E -- no --> D
E -- yes --> F["β
Action proceeds"]
F --> G["trace.post_action()\nRecord actual cost"]
G --> H{"External scanner\ndetects violation?"}
H -- yes --> I["trace.record_violation()"]
I --> J{"Cumulative count\nβ₯ threshold?"}
J -- yes --> D
J -- no --> K["Continue session"]
H -- no --> K
K --> A
D --> L["π Audit log\nImmutable record"]
Session Manager β Tracks cumulative cost, violation counts by type, action count, and duration. Thread-safe. This is the state that no existing tool maintains.
Cost Tracker β Uses tiktoken for token counting, maps to provider pricing tables (OpenAI, Anthropic), enforces budget limits before actions execute.
Policy Engine β Loads YAML policies, evaluates session state against thresholds. Supports budget limits, violation thresholds, session duration/action caps.
Kill Switch β Terminates the session, fires async webhook notifications (Slack-compatible Block Kit format), records the kill event.
Audit Logger β Immutable JSON Lines log of every action, violation, and policy decision with timestamps and session state snapshots.
agenttrace/
βββ agenttrace/
β βββ engine/
β β βββ session.py # Session manager β cumulative state
β β βββ cost_tracker.py # tiktoken + pricing β budget enforcement
β β βββ policy_engine.py # YAML β runtime policy evaluation
β β βββ kill_switch.py # Hard stop + webhook notifications
β β βββ audit_logger.py # Compliance-grade immutable log
β β βββ agent_trace.py # Top-level orchestrator
β βββ integrations/
β βββ langchain.py # LangChain callback handler
βββ configs/
β βββ demo_policy.yaml # Example YAML policy
βββ examples/
β βββ demo_budget_kill.py # Working end-to-end demo
βββ tests/
βββ test_core.py # 21 tests covering all components
| Question | Answer |
|---|---|
| "...LangChain middleware?" | LangChain middleware is stateless. It blocks one PII instance but can't say "after 3 PII blocks, terminate the session." AgentTrace adds session state. |
| "...NeMo Guardrails?" | NeMo steers dialog and filters content. It doesn't track cumulative cost or enforce budget limits across a session. |
| "...Langfuse?" | Langfuse is observability β it tells you what happened. AgentTrace is enforcement β it stops bad things from happening. They're complementary. |
| "...all of them together?" | They don't share state. Presidio blocks PII. NeMo blocks content. Langfuse logs it. But nobody says "that's the 3rd violation this session β kill it." AgentTrace is the orchestration layer with cumulative session state. |
SkillSandbox isolates at the infrastructure layer β network egress, filesystem access, environment variables, syscalls. It's the locked room.
AgentTrace orchestrates at the application layer β policies, budgets, violation thresholds, kill-switch. It's the budget controller inside the room.
| SkillSandbox | AgentTrace | |
|---|---|---|
| Layer | Infrastructure | Application |
| Language | Rust | Python |
| Prevents | Unauthorized access (exfiltration, credential theft) | Runaway sessions (cost explosions, repeated violations) |
| Mechanism | iptables, seccomp-bpf, env filtering | Session state, policy engine, kill-switch |
| Catches | Malicious skills, over-permissioned agents | Agents that have the right access but do the wrong thing |
Together: SkillSandbox constrains what agents can reach. AgentTrace enforces what agents should do.
python3 -m pytest tests/ -vtests/test_core.py::TestSession::test_create_session PASSED
tests/test_core.py::TestSession::test_record_violation_cumulative PASSED
tests/test_core.py::TestSession::test_kill_prevents_actions PASSED
tests/test_core.py::TestSession::test_audit_dict PASSED
tests/test_core.py::TestCostTracker::test_cost_estimation PASSED
tests/test_core.py::TestCostTracker::test_budget_check_allowed PASSED
tests/test_core.py::TestCostTracker::test_budget_check_blocked PASSED
tests/test_core.py::TestCostTracker::test_budget_check_alert PASSED
tests/test_core.py::TestPolicyEngine::test_action_within_budget PASSED
tests/test_core.py::TestPolicyEngine::test_action_exceeds_budget PASSED
tests/test_core.py::TestPolicyEngine::test_action_exceeds_per_action_limit PASSED
tests/test_core.py::TestPolicyEngine::test_action_count_exceeded PASSED
tests/test_core.py::TestPolicyEngine::test_violation_below_threshold PASSED
tests/test_core.py::TestPolicyEngine::test_violation_at_threshold PASSED
tests/test_core.py::TestPolicyEngine::test_violation_unknown_type PASSED
tests/test_core.py::TestPolicyEngine::test_parse_duration PASSED
tests/test_core.py::TestAgentTrace::test_full_lifecycle PASSED
tests/test_core.py::TestAgentTrace::test_budget_kill PASSED
tests/test_core.py::TestAgentTrace::test_violation_kill PASSED
tests/test_core.py::TestAgentTrace::test_action_after_kill_raises PASSED
tests/test_core.py::TestAgentTrace::test_audit_log_populated PASSED
21 passed
- OTel span export β emit traces as OpenTelemetry spans for Langfuse/Jaeger/Datadog ingestion
- Async-native API β
await trace.pre_action()for async agent frameworks - FastAPI dashboard β real-time session monitoring endpoint
- SkillSandbox integration β AgentTrace wraps SkillSandbox execution, correlating sandbox traces with session-level policy events
- Multi-agent session tracking β parent/child session hierarchies for agent swarms
Agent skill ecosystems today are where npm was in 2015. SkillSandbox is the container runtime β constraining what skills can access. AgentTrace is the policy controller β enforcing what agents should do within their permissions, across an entire session.
The existing guardrails ecosystem handles individual checks well. But enterprise agents need cumulative enforcement: budget tracking, violation counting, session termination. The tools are stateless; AgentTrace adds state.
The existing ecosystem is stateless. AgentTrace adds state.