Most AI agent frameworks give you zero enforcement. Your agent can call any tool, take any action, and there is no audit trail. Here is how we think about enforcement at three levels.
The problem
When an AI agent runs in production, you need to answer two questions:
- Was the agent allowed to do what it did?
- Can you prove it?
Most teams have logging. But logs can be edited. Mutable logs give auditors nothing to verify.
Three tiers
Strong enforcement
The agent never has direct tool access. All tool calls go through a proxy that checks policy before forwarding.
Agent -> MCP Proxy -> Policy Check -> Tool
-> DENIED (if blocked)
The proxy signs both the request and the response as a bilateral receipt. The agent cannot skip the check because it does not know where the tool lives.
In asqav-mcp this is enforced_tool_call:
enforced_tool_call(
tool_name="sql:execute",
agent_id="agt_xxx",
arguments='{"query": "SELECT * FROM users"}',
tool_endpoint="http://sql-service/execute"
)
Bounded enforcement
The agent calls a gate before acting. The gate signs the decision (approve or deny). After the action completes, the agent reports back and the outcome gets signed too, creating a bilateral receipt.
# Before acting
gate_action(action_type="data:delete", agent_id="agt_xxx")
# Returns: {"decision": "APPROVED", "gate_id": "..."}
# After acting
complete_action(gate_id="...", result="Deleted 42 records")
# Returns: bilateral receipt linking approval + outcome
The agent could skip the gate call. But the absence of a gate signature is detectable during audit.
Detectable enforcement
Every action gets a quantum-safe signature (ML-DSA-65) hash-chained to the previous one. If someone tampers with an entry or omits one, the chain breaks.
import asqav
agent = asqav.Agent.create("my-agent")
agent.sign("data:read", {"table": "users"})
agent.sign("data:write", {"table": "users", "rows": 5})
# Each signature chains to the previous. Break one, break all.
This does not prevent bad actions. It proves what happened after the fact.
When to use which
High-risk mutations (database writes, payments, deletions) go through strong enforcement. Routine operations use bounded. Everything gets the detectable layer regardless.
Most teams need all three. Forcing everything into one tier either blocks too much or catches too little.
Hidden tools
For the strongest isolation, mark a tool as hidden in its policy. The agent cannot discover or call it. You cannot be prompt-injected into calling a tool you do not know exists.
create_tool_policy(
tool_name="admin:reset",
hidden=True
)
Try it
pip install asqav-mcp
export ASQAV_API_KEY="sk_..."
asqav-mcp
All three tiers are free. No credit card required.
Top comments (0)