useagentguard 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- useagentguard-0.2.0/PKG-INFO +411 -0
- useagentguard-0.2.0/README.md +385 -0
- useagentguard-0.2.0/pyproject.toml +45 -0
- useagentguard-0.2.0/setup.cfg +4 -0
- useagentguard-0.2.0/src/agentguard/__init__.py +52 -0
- useagentguard-0.2.0/src/agentguard/audit.py +147 -0
- useagentguard-0.2.0/src/agentguard/compliance.py +423 -0
- useagentguard-0.2.0/src/agentguard/drift.py +260 -0
- useagentguard-0.2.0/src/agentguard/guard.py +314 -0
- useagentguard-0.2.0/src/agentguard/mcp_interceptor.py +215 -0
- useagentguard-0.2.0/src/agentguard/policies.py +306 -0
- useagentguard-0.2.0/src/agentguard/policy_loader.py +229 -0
- useagentguard-0.2.0/src/agentguard/registry.py +265 -0
- useagentguard-0.2.0/src/agentguard/scopes.py +256 -0
- useagentguard-0.2.0/src/agentguard/vault.py +281 -0
- useagentguard-0.2.0/src/useagentguard.egg-info/PKG-INFO +411 -0
- useagentguard-0.2.0/src/useagentguard.egg-info/SOURCES.txt +28 -0
- useagentguard-0.2.0/src/useagentguard.egg-info/dependency_links.txt +1 -0
- useagentguard-0.2.0/src/useagentguard.egg-info/requires.txt +6 -0
- useagentguard-0.2.0/src/useagentguard.egg-info/top_level.txt +1 -0
- useagentguard-0.2.0/tests/test_audit.py +62 -0
- useagentguard-0.2.0/tests/test_compliance.py +304 -0
- useagentguard-0.2.0/tests/test_drift.py +109 -0
- useagentguard-0.2.0/tests/test_guard.py +142 -0
- useagentguard-0.2.0/tests/test_mcp_interceptor.py +212 -0
- useagentguard-0.2.0/tests/test_policies.py +248 -0
- useagentguard-0.2.0/tests/test_policy_loader.py +253 -0
- useagentguard-0.2.0/tests/test_registry.py +79 -0
- useagentguard-0.2.0/tests/test_scopes.py +84 -0
- useagentguard-0.2.0/tests/test_vault.py +78 -0
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: useagentguard
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: The Security & Cost Control Layer for AI Agents — Guard, Shield, and Sentinel tiers: budget control, per-agent credential isolation, OAuth scope enforcement, MCP policy enforcement, and compliance reporting.
|
|
5
|
+
License: MIT
|
|
6
|
+
Project-URL: Homepage, https://useagentguard.com
|
|
7
|
+
Project-URL: Repository, https://github.com/useagentguard/agentguard-sdk
|
|
8
|
+
Keywords: ai,agents,security,credentials,vault,oauth
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Topic :: Security
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
19
|
+
Requires-Python: >=3.9
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
Requires-Dist: cryptography>=41.0.0
|
|
22
|
+
Requires-Dist: pyyaml>=6.0
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
25
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
26
|
+
|
|
27
|
+
# AgentGuard SDK
|
|
28
|
+
|
|
29
|
+
**The Security & Cost Control Layer for AI Agents.**
|
|
30
|
+
|
|
31
|
+
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.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Features
|
|
36
|
+
|
|
37
|
+
| Tier | Feature |
|
|
38
|
+
|------|---------|
|
|
39
|
+
| Guard | Budget enforcement (`$0.50/run`) with graceful stop or hard raise |
|
|
40
|
+
| Shield | Per-agent encrypted credential vault (Fernet/AES-128) |
|
|
41
|
+
| Shield | Agent identity registry with metadata |
|
|
42
|
+
| Shield | OAuth scope enforcement with `ScopeViolation` exceptions |
|
|
43
|
+
| Shield | Permission drift detection (baseline snapshots + diff) |
|
|
44
|
+
| Shield | Full JSON-lines audit trail per agent |
|
|
45
|
+
| **Sentinel** | **MCP tool-call interception with policy evaluation** |
|
|
46
|
+
| **Sentinel** | **Declarative policy engine (allow/deny lists, rate limits, predicates)** |
|
|
47
|
+
| **Sentinel** | **YAML policy file support** |
|
|
48
|
+
| **Sentinel** | **Audit-ready compliance reports (EU AI Act, NIST AI RMF, ISO 42001)** |
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Install
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pip install agentguard
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
> **Requires Python 3.9+**, `cryptography`, and `pyyaml` (installed automatically).
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Quick Start
|
|
63
|
+
|
|
64
|
+
### 1. The `guard()` wrapper — Guard + Shield + Sentinel
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
import openai
|
|
68
|
+
from agentguard import guard
|
|
69
|
+
|
|
70
|
+
client = guard(
|
|
71
|
+
openai.OpenAI(),
|
|
72
|
+
budget="$0.50/run", # Guard tier — hard budget cap
|
|
73
|
+
auth="isolated", # Shield tier — use per-agent vault
|
|
74
|
+
agent_id="support-bot", # Shield / Sentinel tier — identity
|
|
75
|
+
scopes={"openai": ["chat.completions"]}, # Shield tier — allowed scopes
|
|
76
|
+
mcp_policy="policies.yaml", # Sentinel tier — MCP policy file
|
|
77
|
+
on_violation="block", # Sentinel tier — block | warn | log
|
|
78
|
+
fallback="gpt-4o-mini", # Cheaper fallback near budget limit
|
|
79
|
+
on_limit="graceful_stop", # Return sentinel instead of raising
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
response = client.chat.completions.create(
|
|
83
|
+
model="gpt-4o",
|
|
84
|
+
messages=[{"role": "user", "content": "Hello!"}],
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
if not response:
|
|
88
|
+
print(f"Budget exceeded — spent ${client.spent:.4f}")
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
### 2. Per-Agent Credential Vault
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
from agentguard.vault import AgentVault
|
|
97
|
+
|
|
98
|
+
vault = AgentVault("support-bot")
|
|
99
|
+
|
|
100
|
+
# Store an API key with allowed scopes
|
|
101
|
+
vault.store("openai", "sk-...", scopes=["chat.completions"])
|
|
102
|
+
|
|
103
|
+
# Retrieve it
|
|
104
|
+
cred = vault.get("openai")
|
|
105
|
+
print(cred.scopes) # ["chat.completions"]
|
|
106
|
+
# Raw key is available but never logged/printed automatically
|
|
107
|
+
api_key = cred.get_key()
|
|
108
|
+
|
|
109
|
+
# Rotate with automatic audit log entry
|
|
110
|
+
vault.rotate("openai", new_key="sk-new-...")
|
|
111
|
+
|
|
112
|
+
# List services in this vault
|
|
113
|
+
print(vault.list_services()) # ["openai"]
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Credentials are stored encrypted at `~/.agentguard/vaults/{agent_id}/credentials.enc`.
|
|
117
|
+
The master key lives at `~/.agentguard/master.key` (mode 0600, never logged).
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
### 3. Agent Identity Registry
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
from agentguard.registry import Registry
|
|
125
|
+
|
|
126
|
+
registry = Registry()
|
|
127
|
+
|
|
128
|
+
registry.register(
|
|
129
|
+
agent_id="support-bot",
|
|
130
|
+
owner="team-cs",
|
|
131
|
+
capabilities=["chat", "search"],
|
|
132
|
+
created_by="kevin@company.com",
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
profile = registry.get("support-bot")
|
|
136
|
+
print(profile.owner) # "team-cs"
|
|
137
|
+
print(profile.capabilities) # ["chat", "search"]
|
|
138
|
+
|
|
139
|
+
# All registered agents
|
|
140
|
+
for p in registry.list():
|
|
141
|
+
print(p.agent_id, p.owner)
|
|
142
|
+
|
|
143
|
+
# Full audit log for an agent
|
|
144
|
+
events = registry.audit_log("support-bot")
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
### 4. OAuth Scope Enforcement
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
from agentguard.scopes import ScopeManager, ScopeViolation
|
|
153
|
+
|
|
154
|
+
scopes = ScopeManager()
|
|
155
|
+
|
|
156
|
+
# Define allowed scopes
|
|
157
|
+
scopes.set("support-bot", {
|
|
158
|
+
"openai": ["chat.completions"],
|
|
159
|
+
"github": ["repos.read"],
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
# Runtime check — OK
|
|
163
|
+
scopes.check("support-bot", "openai", "chat.completions")
|
|
164
|
+
|
|
165
|
+
# Runtime check — raises ScopeViolation
|
|
166
|
+
try:
|
|
167
|
+
scopes.check("support-bot", "openai", "fine-tuning")
|
|
168
|
+
except ScopeViolation as e:
|
|
169
|
+
print(f"Blocked: {e}")
|
|
170
|
+
|
|
171
|
+
# Non-raising check
|
|
172
|
+
if scopes.is_allowed("support-bot", "github", "repos.write"):
|
|
173
|
+
... # won't reach here
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
### 5. Permission Drift Detection
|
|
179
|
+
|
|
180
|
+
```python
|
|
181
|
+
from agentguard.drift import DriftDetector
|
|
182
|
+
|
|
183
|
+
drift = DriftDetector()
|
|
184
|
+
|
|
185
|
+
# Save baseline
|
|
186
|
+
drift.snapshot("support-bot")
|
|
187
|
+
|
|
188
|
+
# ... later, scopes or capabilities change ...
|
|
189
|
+
|
|
190
|
+
changes = drift.check("support-bot")
|
|
191
|
+
for c in changes:
|
|
192
|
+
print(c.change_type, c.category, c.field)
|
|
193
|
+
# e.g.: added scope openai.fine-tuning
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
### 6. Sentinel — MCP Policy Enforcement
|
|
199
|
+
|
|
200
|
+
#### Define policies in Python
|
|
201
|
+
|
|
202
|
+
```python
|
|
203
|
+
from agentguard.policies import Policy, PolicyEngine, RateLimit
|
|
204
|
+
from agentguard.mcp_interceptor import MCPInterceptor
|
|
205
|
+
|
|
206
|
+
engine = PolicyEngine()
|
|
207
|
+
|
|
208
|
+
# Block PII table queries for all agents
|
|
209
|
+
engine.add_policy(Policy(
|
|
210
|
+
name="no-pii-queries",
|
|
211
|
+
description="Agents cannot run queries that select from PII tables",
|
|
212
|
+
agent_ids=["*"],
|
|
213
|
+
tools=["database_query"],
|
|
214
|
+
deny_if=lambda params: any(
|
|
215
|
+
t in params.get("query", "").lower()
|
|
216
|
+
for t in ["users", "credentials", "payments"]
|
|
217
|
+
),
|
|
218
|
+
))
|
|
219
|
+
|
|
220
|
+
# Read-only filesystem for support-bot
|
|
221
|
+
engine.add_policy(Policy(
|
|
222
|
+
name="read-only-filesystem",
|
|
223
|
+
description="Support bot can only read files, not write",
|
|
224
|
+
agent_ids=["support-bot"],
|
|
225
|
+
tools=["file_write", "file_delete"],
|
|
226
|
+
action="deny",
|
|
227
|
+
))
|
|
228
|
+
|
|
229
|
+
# Rate limit: max 100 API calls per minute per agent
|
|
230
|
+
engine.add_policy(Policy(
|
|
231
|
+
name="rate-limit-api",
|
|
232
|
+
description="Max 100 API calls per minute per agent",
|
|
233
|
+
agent_ids=["*"],
|
|
234
|
+
tools=["*"],
|
|
235
|
+
rate_limit=RateLimit(max_calls=100, window_seconds=60),
|
|
236
|
+
))
|
|
237
|
+
|
|
238
|
+
interceptor = MCPInterceptor(policies=engine, on_violation="block")
|
|
239
|
+
|
|
240
|
+
result = interceptor.evaluate(
|
|
241
|
+
agent_id="support-bot",
|
|
242
|
+
tool="database_query",
|
|
243
|
+
params={"query": "SELECT * FROM users"},
|
|
244
|
+
context={"user": "kevin@company.com"},
|
|
245
|
+
)
|
|
246
|
+
print(result.allowed) # False
|
|
247
|
+
print(result.reason) # "Policy 'no-pii-queries' denied this action..."
|
|
248
|
+
print(result.audit_id) # "evt_abc123..."
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
#### Or load from YAML
|
|
252
|
+
|
|
253
|
+
```yaml
|
|
254
|
+
# policies.yaml
|
|
255
|
+
policies:
|
|
256
|
+
- name: no-pii-queries
|
|
257
|
+
description: "Agents cannot query PII tables"
|
|
258
|
+
agents: ["*"]
|
|
259
|
+
tools: ["database_query"]
|
|
260
|
+
deny_params:
|
|
261
|
+
query:
|
|
262
|
+
contains_any: ["users", "credentials", "payments"]
|
|
263
|
+
|
|
264
|
+
- name: read-only-fs
|
|
265
|
+
description: "Support bot is read-only"
|
|
266
|
+
agents: ["support-bot"]
|
|
267
|
+
tools: ["file_write", "file_delete"]
|
|
268
|
+
action: deny
|
|
269
|
+
|
|
270
|
+
- name: rate-limit
|
|
271
|
+
description: "100 calls/min per agent"
|
|
272
|
+
agents: ["*"]
|
|
273
|
+
tools: ["*"]
|
|
274
|
+
rate_limit:
|
|
275
|
+
max_calls: 100
|
|
276
|
+
window_seconds: 60
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
```python
|
|
280
|
+
from agentguard.policies import PolicyEngine
|
|
281
|
+
from agentguard.mcp_interceptor import MCPInterceptor
|
|
282
|
+
|
|
283
|
+
engine = PolicyEngine.from_yaml("policies.yaml")
|
|
284
|
+
interceptor = MCPInterceptor(policies=engine)
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
**Supported `deny_params` constraints:** `contains_any`, `contains_all`, `matches` (regex), `equals`, `not_equals`.
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
### 7. Sentinel — Compliance Reports
|
|
292
|
+
|
|
293
|
+
```python
|
|
294
|
+
from agentguard.compliance import ComplianceReport
|
|
295
|
+
from agentguard.registry import Registry
|
|
296
|
+
from agentguard.policies import PolicyEngine
|
|
297
|
+
|
|
298
|
+
registry = Registry()
|
|
299
|
+
engine = PolicyEngine.from_yaml("policies.yaml")
|
|
300
|
+
|
|
301
|
+
report = ComplianceReport(registry=registry, policy_engine=engine)
|
|
302
|
+
|
|
303
|
+
# Per-agent activity summary
|
|
304
|
+
summary = report.agent_summary("support-bot", since="2026-03-01")
|
|
305
|
+
print(summary["mcp_calls"]) # total MCP tool calls
|
|
306
|
+
print(summary["denied_calls"]) # blocked calls
|
|
307
|
+
|
|
308
|
+
# All denied actions
|
|
309
|
+
violations = report.violations(since="2026-03-01")
|
|
310
|
+
for v in violations:
|
|
311
|
+
print(v["timestamp"], v["agent_id"], v["tool"], v["policy"])
|
|
312
|
+
|
|
313
|
+
# Compliance posture mapping (EU AI Act, NIST AI RMF, ISO 42001)
|
|
314
|
+
posture = report.compliance_posture()
|
|
315
|
+
for fw, controls in posture["frameworks"].items():
|
|
316
|
+
print(f"\n{fw}")
|
|
317
|
+
for ctrl in controls:
|
|
318
|
+
print(f" [{ctrl['status']}] {ctrl['control']}")
|
|
319
|
+
|
|
320
|
+
# Export to Markdown
|
|
321
|
+
report.export_markdown("compliance-report.md")
|
|
322
|
+
|
|
323
|
+
# Export to JSON
|
|
324
|
+
report.export_json("compliance-report.json")
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
### 8. Audit Trail
|
|
330
|
+
|
|
331
|
+
```python
|
|
332
|
+
from agentguard import audit_query
|
|
333
|
+
from agentguard.audit import log_event
|
|
334
|
+
|
|
335
|
+
# Query events for an agent
|
|
336
|
+
events = audit_query("support-bot", since="2026-03-01")
|
|
337
|
+
for event in events:
|
|
338
|
+
print(event["timestamp"], event["action"], event["outcome"])
|
|
339
|
+
|
|
340
|
+
# Filter by action or outcome
|
|
341
|
+
denied = audit_query("support-bot", action="scope_check", outcome="denied")
|
|
342
|
+
|
|
343
|
+
# Log a custom event
|
|
344
|
+
log_event(
|
|
345
|
+
agent_id="support-bot",
|
|
346
|
+
action="custom_action",
|
|
347
|
+
details={"info": "something happened"},
|
|
348
|
+
outcome="allowed",
|
|
349
|
+
)
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
Audit logs are written to `~/.agentguard/audit/{agent_id}/{date}.jsonl`.
|
|
353
|
+
Sensitive fields (`key`, `secret`, `token`, `password`) are automatically redacted.
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
357
|
+
## File Layout
|
|
358
|
+
|
|
359
|
+
```
|
|
360
|
+
~/.agentguard/
|
|
361
|
+
├── master.key # Fernet master key (mode 0600)
|
|
362
|
+
├── registry.json # Agent identity registry
|
|
363
|
+
├── scopes.json # Scope policies per agent
|
|
364
|
+
├── vaults/
|
|
365
|
+
│ └── {agent_id}/
|
|
366
|
+
│ └── credentials.enc # Encrypted credential store
|
|
367
|
+
├── snapshots/
|
|
368
|
+
│ └── {agent_id}.json # Drift baseline snapshots
|
|
369
|
+
└── audit/
|
|
370
|
+
└── {agent_id}/
|
|
371
|
+
└── 2026-03-27.jsonl # JSON-lines audit log
|
|
372
|
+
|
|
373
|
+
src/agentguard/
|
|
374
|
+
├── audit.py # Audit trail (all tiers)
|
|
375
|
+
├── compliance.py # Sentinel — compliance reports
|
|
376
|
+
├── drift.py # Shield — drift detection
|
|
377
|
+
├── guard.py # Guard + Shield + Sentinel wrapper
|
|
378
|
+
├── mcp_interceptor.py # Sentinel — MCP tool-call interceptor
|
|
379
|
+
├── policies.py # Sentinel — policy engine
|
|
380
|
+
├── policy_loader.py # Sentinel — YAML policy loader
|
|
381
|
+
├── registry.py # Shield — agent identity registry
|
|
382
|
+
├── scopes.py # Shield — OAuth scope enforcement
|
|
383
|
+
└── vault.py # Shield — credential vault
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
388
|
+
## Configuration
|
|
389
|
+
|
|
390
|
+
`AGENTGUARD_HOME` env var overrides the default `~/.agentguard` directory.
|
|
391
|
+
|
|
392
|
+
```bash
|
|
393
|
+
AGENTGUARD_HOME=/var/run/agentguard python my_agent.py
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
---
|
|
397
|
+
|
|
398
|
+
## Development
|
|
399
|
+
|
|
400
|
+
```bash
|
|
401
|
+
git clone https://github.com/useagentguard/agentguard-sdk
|
|
402
|
+
cd agentguard-sdk/sdk
|
|
403
|
+
pip install -e ".[dev]"
|
|
404
|
+
pytest
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
---
|
|
408
|
+
|
|
409
|
+
## License
|
|
410
|
+
|
|
411
|
+
MIT © [AgentGuard](https://useagentguard.com)
|