Observed since 20 Oct, 21:53 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
A lightweight execution guard for AI agents. Decide ALLOW / HOLD / DENY before your agent performs real actions.
Deterministic ALLOW / HOLD / DENY execution boundary for AI agent actions.
pip install agent-execution-guard
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.
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
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.
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 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)
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) |
| State | Severity | Threshold |
|---|---|---|
| ACTIVE | < 0.20 | risk ≥ 80 → DENY |
| OBSERVE | ≥ 0.20 | risk ≥ 60 → DENY |
| COOLDOWN | ≥ 0.40 | risk ≥ 30 → DENY |
| Outcome | Meaning |
|---|---|
ALLOW | Proceed. Signed proof issued. |
DENY | Blocked. Signed negative proof. Agent cannot retry. |
HOLD | Awaiting human approval. Deadline enforced. |
Every decision — ALLOW and DENY — is signed and ledgered.
cryptography>=42.0.0Optional:
pip install pyyaml # policy.yaml support
pip install opentelemetry-api # OTel span export
GuardedTool)Apache 2.0
Download counts and popularity will appear here as the collector receives them.
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 0.2.2 | 1 Mar 2026 | 3 |
This describes our collected data; it is not a security assessment.
Observed since 20 Oct, 21:53 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:e121cf9d0b0034e7fb40683b6107950fe8d244cfd3d672fa6bbdf01c4648102d