AgentGuard SDK
The Security & Cost Control Layer for AI Agents.
AgentGuard adds per-agent credential isolation, OAuth scope enforcement, an agent identity registry, permission drift detection, MCP policy enforcement, compliance reporting, and a full audit trail to any AI agent workflow — with zero cloud dependencies.
Features
| Tier | Feature |
|---|---|
| Guard | Budget enforcement ($0.50/run) with graceful stop or hard raise |
| Shield | Per-agent encrypted credential vault (Fernet/AES-128) |
| Shield | Agent identity registry with metadata |
| Shield | OAuth scope enforcement with ScopeViolation exceptions |
| Shield | Permission drift detection (baseline snapshots + diff) |
| Shield | Full JSON-lines audit trail per agent |
| Sentinel | MCP tool-call interception with policy evaluation |
| Sentinel | Declarative policy engine (allow/deny lists, rate limits, predicates) |
| Sentinel | YAML policy file support |
| Sentinel | Audit-ready compliance reports (EU AI Act, NIST AI RMF, ISO 42001) |
Install
pip install agentguard
Requires Python 3.9+,
cryptography, andpyyaml(installed automatically).
Quick Start
1. The guard() wrapper — Guard + Shield + Sentinel
import openai
from agentguard import guard
client = guard(
openai.OpenAI(),
budget="$0.50/run", # Guard tier — hard budget cap
auth="isolated", # Shield tier — use per-agent vault
agent_id="support-bot", # Shield / Sentinel tier — identity
scopes={"openai": ["chat.completions"]}, # Shield tier — allowed scopes
mcp_policy="policies.yaml", # Sentinel tier — MCP policy file
on_violation="block", # Sentinel tier — block | warn | log
fallback="gpt-4o-mini", # Cheaper fallback near budget limit
on_limit="graceful_stop", # Return sentinel instead of raising
)
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Hello!"}],
)
if not response:
print(f"Budget exceeded — spent ${client.spent:.4f}")
2. Per-Agent Credential Vault
from agentguard.vault import AgentVault
vault = AgentVault("support-bot")
# Store an API key with allowed scopes
vault.store("openai", "sk-...", scopes=["chat.completions"])
# Retrieve it
cred = vault.get("openai")
print(cred.scopes) # ["chat.completions"]
# Raw key is available but never logged/printed automatically
api_key = cred.get_key()
# Rotate with automatic audit log entry
vault.rotate("openai", new_key="sk-new-...")
# List services in this vault
print(vault.list_services()) # ["openai"]
Credentials are stored encrypted at ~/.agentguard/vaults/{agent_id}/credentials.enc.
The master key lives at ~/.agentguard/master.key (mode 0600, never logged).
3. Agent Identity Registry
from agentguard.registry import Registry
registry = Registry()
registry.register(
agent_id="support-bot",
owner="team-cs",
capabilities=["chat", "search"],
created_by="kevin@company.com",
)
profile = registry.get("support-bot")
print(profile.owner) # "team-cs"
print(profile.capabilities) # ["chat", "search"]
# All registered agents
for p in registry.list():
print(p.agent_id, p.owner)
# Full audit log for an agent
events = registry.audit_log("support-bot")
4. OAuth Scope Enforcement
from agentguard.scopes import ScopeManager, ScopeViolation
scopes = ScopeManager()
# Define allowed scopes
scopes.set("support-bot", {
"openai": ["chat.completions"],
"github": ["repos.read"],
})
# Runtime check — OK
scopes.check("support-bot", "openai", "chat.completions")
# Runtime check — raises ScopeViolation
try:
scopes.check("support-bot", "openai", "fine-tuning")
except ScopeViolation as e:
print(f"Blocked: {e}")
# Non-raising check
if scopes.is_allowed("support-bot", "github", "repos.write"):
... # won't reach here
5. Permission Drift Detection
from agentguard.drift import DriftDetector
drift = DriftDetector()
# Save baseline
drift.snapshot("support-bot")
# ... later, scopes or capabilities change ...
changes = drift.check("support-bot")
for c in changes:
print(c.change_type, c.category, c.field)
# e.g.: added scope openai.fine-tuning
6. Sentinel — MCP Policy Enforcement
Define policies in Python
from agentguard.policies import Policy, PolicyEngine, RateLimit
from agentguard.mcp_interceptor import MCPInterceptor
engine = PolicyEngine()
# Block PII table queries for all agents
engine.add_policy(Policy(
name="no-pii-queries",
description="Agents cannot run queries that select from PII tables",
agent_ids=["*"],
tools=["database_query"],
deny_if=lambda params: any(
t in params.get("query", "").lower()
for t in ["users", "credentials", "payments"]
),
))
# Read-only filesystem for support-bot
engine.add_policy(Policy(
name="read-only-filesystem",
description="Support bot can only read files, not write",
agent_ids=["support-bot"],
tools=["file_write", "file_delete"],
action="deny",
))
# Rate limit: max 100 API calls per minute per agent
engine.add_policy(Policy(
name="rate-limit-api",
description="Max 100 API calls per minute per agent",
agent_ids=["*"],
tools=["*"],
rate_limit=RateLimit(max_calls=100, window_seconds=60),
))
interceptor = MCPInterceptor(policies=engine, on_violation="block")
result = interceptor.evaluate(
agent_id="support-bot",
tool="database_query",
params={"query": "SELECT * FROM users"},
context={"user": "kevin@company.com"},
)
print(result.allowed) # False
print(result.reason) # "Policy 'no-pii-queries' denied this action..."
print(result.audit_id) # "evt_abc123..."
Or load from YAML
# policies.yaml
policies:
- name: no-pii-queries
description: "Agents cannot query PII tables"
agents: ["*"]
tools: ["database_query"]
deny_params:
query:
contains_any: ["users", "credentials", "payments"]
- name: read-only-fs
description: "Support bot is read-only"
agents: ["support-bot"]
tools: ["file_write", "file_delete"]
action: deny
- name: rate-limit
description: "100 calls/min per agent"
agents: ["*"]
tools: ["*"]
rate_limit:
max_calls: 100
window_seconds: 60
from agentguard.policies import PolicyEngine
from agentguard.mcp_interceptor import MCPInterceptor
engine = PolicyEngine.from_yaml("policies.yaml")
interceptor = MCPInterceptor(policies=engine)
Supported deny_params constraints: contains_any, contains_all, matches (regex), equals, not_equals.
7. Sentinel — Compliance Reports
from agentguard.compliance import ComplianceReport
from agentguard.registry import Registry
from agentguard.policies import PolicyEngine
registry = Registry()
engine = PolicyEngine.from_yaml("policies.yaml")
report = ComplianceReport(registry=registry, policy_engine=engine)
# Per-agent activity summary
summary = report.agent_summary("support-bot", since="2026-03-01")
print(summary["mcp_calls"]) # total MCP tool calls
print(summary["denied_calls"]) # blocked calls
# All denied actions
violations = report.violations(since="2026-03-01")
for v in violations:
print(v["timestamp"], v["agent_id"], v["tool"], v["policy"])
# Compliance posture mapping (EU AI Act, NIST AI RMF, ISO 42001)
posture = report.compliance_posture()
for fw, controls in posture["frameworks"].items():
print(f"\n{fw}")
for ctrl in controls:
print(f" [{ctrl['status']}] {ctrl['control']}")
# Export to Markdown
report.export_markdown("compliance-report.md")
# Export to JSON
report.export_json("compliance-report.json")
8. Audit Trail
from agentguard import audit_query
from agentguard.audit import log_event
# Query events for an agent
events = audit_query("support-bot", since="2026-03-01")
for event in events:
print(event["timestamp"], event["action"], event["outcome"])
# Filter by action or outcome
denied = audit_query("support-bot", action="scope_check", outcome="denied")
# Log a custom event
log_event(
agent_id="support-bot",
action="custom_action",
details={"info": "something happened"},
outcome="allowed",
)
Audit logs are written to ~/.agentguard/audit/{agent_id}/{date}.jsonl.
Sensitive fields (key, secret, token, password) are automatically redacted.
File Layout
~/.agentguard/
├── master.key # Fernet master key (mode 0600)
├── registry.json # Agent identity registry
├── scopes.json # Scope policies per agent
├── vaults/
│ └── {agent_id}/
│ └── credentials.enc # Encrypted credential store
├── snapshots/
│ └── {agent_id}.json # Drift baseline snapshots
└── audit/
└── {agent_id}/
└── 2026-03-27.jsonl # JSON-lines audit log
src/agentguard/
├── audit.py # Audit trail (all tiers)
├── compliance.py # Sentinel — compliance reports
├── drift.py # Shield — drift detection
├── guard.py # Guard + Shield + Sentinel wrapper
├── mcp_interceptor.py # Sentinel — MCP tool-call interceptor
├── policies.py # Sentinel — policy engine
├── policy_loader.py # Sentinel — YAML policy loader
├── registry.py # Shield — agent identity registry
├── scopes.py # Shield — OAuth scope enforcement
└── vault.py # Shield — credential vault
Configuration
AGENTGUARD_HOME env var overrides the default ~/.agentguard directory.
AGENTGUARD_HOME=/var/run/agentguard python my_agent.py
Development
git clone https://github.com/useagentguard/agentguard-sdk
cd agentguard-sdk/sdk
pip install -e ".[dev]"
pytest
License
MIT © AgentGuard
Metadata
Release files for useagentguard 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| useagentguard-0.2.0.tar.gz | 39.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| useagentguard-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 71.7 kB
Release files / useagentguard-0.2.0.tar.gz
| Download URL | useagentguard-0.2.0.tar.gz |
|---|---|
| Size | 39.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8986be7cad22502d0f182f704f8adbd8b658c33992b0d2742c3e580cfa99555d
|
|
BLAKE2b-256 checksum How to use checksums |
f18144b9d90affa4ecb123c244507368419a41be367ecfc3fb88648a4db704b2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|
Release files / useagentguard-0.2.0-py3-none-any.whl
| Download URL | useagentguard-0.2.0-py3-none-any.whl |
|---|---|
| Size | 32.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
65fd407e98942af3b296e88c08d9891386b1d44520573d1c0871b59230888e9b
|
|
BLAKE2b-256 checksum How to use checksums |
12df772b684c313427a0e9fac9f65fa65b183500db8f0debc0e264415bd09113
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|