agent-execution-guard
Deterministic ALLOW / HOLD / DENY execution boundary for AI agent actions.
pip install agent-execution-guard
The problem
AI agents execute actions without structural constraints. Prompts can be bypassed. Guardrails can be reasoned around.
This library puts a deterministic gate between decision and execution.
Quickstart
from datetime import datetime, timezone
from agent_execution_guard import ExecutionGuard, Intent, ALLOW_ALL
guard = ExecutionGuard()
intent = Intent(
actor="agent.finance",
action="wire_transfer",
payload="wire_transfer amount=50000 to=external",
timestamp=datetime.now(timezone.utc),
)
# policy is required — no policy = no execution (fail-closed)
# use ALLOW_ALL to skip identity check and rely on risk scoring only
try:
result = guard.evaluate(intent, policy=ALLOW_ALL)
print(result.risk_score) # 0–100
except Exception as e:
print(e) # DENY or HOLD
Example 1 — DENY
from agent_execution_guard import ExecutionGuard, Intent, GuardDeniedError, ALLOW_ALL
from datetime import datetime, timezone
# halt_threshold=39: wire_transfer scores 40 → DENY
guard = ExecutionGuard(halt_threshold=39)
intent = Intent(
actor="agent.finance",
action="wire_transfer",
payload="wire_transfer amount=50000 to=external",
timestamp=datetime.now(timezone.utc),
)
try:
guard.evaluate(intent, policy=ALLOW_ALL)
except GuardDeniedError as e:
print(f"Denied: {e.reason}")
print(f"Proof: {e.boundary_id}")
Output:
Denied: General command
Proof: 3f9a1c2d-...
Every denial issues a signed proof. The agent cannot retry past it.
Example 2 — Severity-adaptive gate
from agent_execution_guard import ExecutionGuard, Intent, SystemSeverity, GuardDeniedError
from datetime import datetime, timezone
guard = ExecutionGuard()
intent = Intent(
actor="campaign_ai",
action="aggressive_targeting",
payload="launch targeted ad campaign segment=undecided_voters",
timestamp=datetime.now(timezone.utc),
)
# score=0.60 → COOLDOWN state → threshold drops 80 → 30 → risk(40) > 30 → DENY
high = SystemSeverity(score=0.60, source="risk_model")
low = SystemSeverity(score=0.10, source="baseline")
try:
guard.evaluate(intent, severity=high, policy=ALLOW_ALL)
except GuardDeniedError:
print("DENY (COOLDOWN — threshold=30)")
result = guard.evaluate(intent, severity=low, policy=ALLOW_ALL)
print("ALLOW (ACTIVE — threshold=80)")
Output:
DENY (COOLDOWN — threshold=30)
ALLOW (ACTIVE — threshold=80)
Same action. Different severity state. Different outcome.
Policy guard
policy is required. No policy = no execution (fail-closed by default).
# policy.yaml
defaults:
unknown_agent: DENY
unknown_action: DENY
identity:
agents:
- agent_id: "agent.finance"
allowed_actions:
- action: "wire_transfer"
import yaml
with open("policy.yaml") as f:
policy = yaml.safe_load(f)
guard.evaluate(intent, policy=policy)
# unknown agent → immediate DENY, signed proof issued
To skip identity check and rely on risk scoring only:
from agent_execution_guard import ALLOW_ALL
guard.evaluate(intent, policy=ALLOW_ALL)
How it works
Intent → Risk Score → Severity State → Guard Decision → Signed Proof
| Component | What it does |
|---|---|
| Risk scoring | Rule-based 0–100 score per action |
| Severity gate | ACTIVE / OBSERVE / COOLDOWN — tightens threshold as risk rises |
| Policy guard | Unknown agent or action → immediate DENY |
| Decision trail | Every decision signed (ED25519) + ledgered (SHA-256 chain) |
States
| State | Severity | Threshold |
|---|---|---|
| ACTIVE | < 0.20 | risk ≥ 80 → DENY |
| OBSERVE | ≥ 0.20 | risk ≥ 60 → DENY |
| COOLDOWN | ≥ 0.40 | risk ≥ 30 → DENY |
Outcomes
| Outcome | Meaning |
|---|---|
ALLOW |
Proceed. Signed proof issued. |
DENY |
Blocked. Signed negative proof. Agent cannot retry. |
HOLD |
Awaiting human approval. Deadline enforced. |
Cryptographic proof
Every decision — ALLOW and DENY — is signed and ledgered.
- ED25519 signatures
- Append-only NDJSON hash chain
- Offline verification, no external dependencies
Requirements
- Python 3.10+
cryptography>=42.0.0
Optional:
pip install pyyaml # policy.yaml support
pip install opentelemetry-api # OTel span export
Roadmap
- Risk scoring + ALLOW / DENY
- ED25519 cryptographic proof + hash-chain ledger
- Severity-driven state machine (ACTIVE / OBSERVE / COOLDOWN)
- Policy guard (unknown agent/action → DENY)
- HOLD state + human approval checkpoint
- LangChain adapter (
GuardedTool) - OTel-native decision trail export
- MCP integration
License
Apache 2.0
Release files for agent-execution-guard 0.2.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| agent_execution_guard-0.2.2.tar.gz | 25.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| agent_execution_guard-0.2.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 55.3 kB
Release files / agent_execution_guard-0.2.2.tar.gz
| Download URL | agent_execution_guard-0.2.2.tar.gz |
|---|---|
| Size | 25.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c41bc2a34bee9ebd8a31aaff94a95d3ee84febc7305599761ad596625c5aa40d
|
|
BLAKE2b-256 checksum How to use checksums |
920e82bb4dc110182191a6d93a8ec7b99fcb18daafc8fae5276ca5c523081776
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|
Release files / agent_execution_guard-0.2.2-py3-none-any.whl
| Download URL | agent_execution_guard-0.2.2-py3-none-any.whl |
|---|---|
| Size | 30.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6ec909cea6f963ac6c9b2d0c810bcbdf519386945fb5a334544a21983a2b089f
|
|
BLAKE2b-256 checksum How to use checksums |
f8fc1cb02d69b94b3ea491e42800f771131302b591b6b8b4d83ae7812d85ae29
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|