tollgate 1.0.5__py3-none-any.whl → 1.4.0__py3-none-any.whl
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.
- tollgate/__init__.py +34 -2
- tollgate/anomaly_detector.py +396 -0
- tollgate/audit.py +90 -1
- tollgate/backends/__init__.py +37 -0
- tollgate/backends/redis_store.py +411 -0
- tollgate/backends/sqlite_store.py +458 -0
- tollgate/circuit_breaker.py +206 -0
- tollgate/context_monitor.py +292 -0
- tollgate/exceptions.py +20 -0
- tollgate/manifest_signing.py +90 -0
- tollgate/network_guard.py +114 -0
- tollgate/policy.py +37 -0
- tollgate/policy_testing.py +360 -0
- tollgate/rate_limiter.py +162 -0
- tollgate/registry.py +225 -2
- tollgate/tower.py +182 -11
- tollgate/types.py +21 -1
- tollgate/verification.py +81 -0
- tollgate-1.4.0.dist-info/METADATA +393 -0
- tollgate-1.4.0.dist-info/RECORD +33 -0
- tollgate-1.4.0.dist-info/entry_points.txt +2 -0
- tollgate-1.0.5.dist-info/METADATA +0 -144
- tollgate-1.0.5.dist-info/RECORD +0 -21
- {tollgate-1.0.5.dist-info → tollgate-1.4.0.dist-info}/WHEEL +0 -0
- {tollgate-1.0.5.dist-info → tollgate-1.4.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tollgate
|
|
3
|
+
Version: 1.4.0
|
|
4
|
+
Summary: Runtime enforcement layer for AI agent tool calls using Identity + Intent + Policy
|
|
5
|
+
Project-URL: Homepage, https://github.com/ravi-labs/tollgate
|
|
6
|
+
Project-URL: Repository, https://github.com/ravi-labs/tollgate.git
|
|
7
|
+
Project-URL: Documentation, https://github.com/ravi-labs/tollgate#readme
|
|
8
|
+
Project-URL: Issues, https://github.com/ravi-labs/tollgate/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/ravi-labs/tollgate/blob/main/CHANGELOG.md
|
|
10
|
+
Author: Tollgate Maintainers
|
|
11
|
+
License-Expression: Apache-2.0
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: agents,ai,enforcement,llm,policy,security
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Framework :: AsyncIO
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
23
|
+
Classifier: Topic :: Security
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Requires-Dist: pyyaml>=6.0.0
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: build>=1.0.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: twine>=4.0.0; extra == 'dev'
|
|
32
|
+
Provides-Extra: redis
|
|
33
|
+
Requires-Dist: redis[hiredis]>=5.0.0; extra == 'redis'
|
|
34
|
+
Description-Content-Type: text/markdown
|
|
35
|
+
|
|
36
|
+
# tollgate
|
|
37
|
+
|
|
38
|
+
Runtime enforcement layer for AI agent tool calls using **Identity + Intent + Policy**.
|
|
39
|
+
|
|
40
|
+
`tollgate` provides a deterministic safety boundary for AI agents. It ensures every tool call is validated against a policy before execution, with support for async human-in-the-loop approvals, framework interception (MCP, Strands, LangChain, OpenAI), and structured audit logging.
|
|
41
|
+
|
|
42
|
+
> [!CAUTION]
|
|
43
|
+
> **Disclaimer**: This project is an exploratory implementation intended for learning and discussion. It is not production-hardened and comes with no guarantees.
|
|
44
|
+
|
|
45
|
+
**[Architecture](./ARCHITECTURE.md) | [Quickstart Guide](./QUICKSTART.md) | [Feature Guide](./FEATURES.md) | [Integration Comparison](./COMPARISON.md) | [Security](./SECURITY.md)**
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
+-----------------+
|
|
49
|
+
| AI Agent |
|
|
50
|
+
+--------+--------+
|
|
51
|
+
|
|
|
52
|
+
+--------------v---------------+
|
|
53
|
+
| Tollgate ControlTower |
|
|
54
|
+
|------------------------------|
|
|
55
|
+
| 1. Identity Verification |
|
|
56
|
+
| 2. Circuit Breaker Check |
|
|
57
|
+
| 3. Rate Limiting |
|
|
58
|
+
| 4. Policy Evaluation |
|
|
59
|
+
| 5. Network Guard |
|
|
60
|
+
| 6. Parameter Validation |
|
|
61
|
+
| 7. Constraint Checking |
|
|
62
|
+
+--------------+---------------+
|
|
63
|
+
|
|
|
64
|
+
+--------------------+--------------------+
|
|
65
|
+
| | |
|
|
66
|
+
v v v
|
|
67
|
+
+--------+ +--------+ +--------+
|
|
68
|
+
| ALLOW | | ASK | | DENY |
|
|
69
|
+
+---+----+ +---+----+ +---+----+
|
|
70
|
+
| | |
|
|
71
|
+
v v v
|
|
72
|
+
+--------+ +-------------+ +--------+
|
|
73
|
+
|Execute | |Human/Grant | | Block |
|
|
74
|
+
| Tool | | Approval | | & Log |
|
|
75
|
+
+---+----+ +------+------+ +---+----+
|
|
76
|
+
\ | /
|
|
77
|
+
\ | /
|
|
78
|
+
+--------+--------+--------+--------+
|
|
79
|
+
|
|
|
80
|
+
v
|
|
81
|
+
+-----------+
|
|
82
|
+
| Audit Log | --> Anomaly Detection
|
|
83
|
+
+-----------+
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Installation
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
pip install tollgate
|
|
90
|
+
|
|
91
|
+
# Optional: For Redis-backed persistent stores
|
|
92
|
+
pip install tollgate[redis]
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Core Concepts
|
|
96
|
+
|
|
97
|
+
| Concept | Description |
|
|
98
|
+
|---------|-------------|
|
|
99
|
+
| **AgentContext** | Who is asking? (`agent_id`, `version`, `owner`, `delegated_by`) |
|
|
100
|
+
| **Intent** | What is the goal? (`action`, `reason`, `confidence`) |
|
|
101
|
+
| **ToolRequest** | What tool and parameters? (`tool`, `action`, `effect`, `params`) |
|
|
102
|
+
| **Decision** | Policy result: `ALLOW`, `ASK`, or `DENY` |
|
|
103
|
+
| **Grant** | Pre-authorization that bypasses ASK for specific patterns |
|
|
104
|
+
|
|
105
|
+
## Core Principles
|
|
106
|
+
|
|
107
|
+
1. **Interception-First**: Enforcement at the tool execution boundary via adapters
|
|
108
|
+
2. **Safe Defaults**: Unknown effects or resources default to **DENY**
|
|
109
|
+
3. **Trust Model**: Tool metadata trusted only from developer-controlled **Tool Registry**
|
|
110
|
+
4. **Approval Integrity**: Approvals bound to request hash with replay protection
|
|
111
|
+
5. **Async-First**: Native async support with non-blocking approvals
|
|
112
|
+
6. **Audit Integrity**: Every decision recorded with cryptographic context
|
|
113
|
+
7. **Defense in Depth**: Multiple security layers (rate limiting, circuit breaker, network guard)
|
|
114
|
+
|
|
115
|
+
## Quick Example
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
import asyncio
|
|
119
|
+
from tollgate import (
|
|
120
|
+
ControlTower, YamlPolicyEvaluator, ToolRegistry,
|
|
121
|
+
AutoApprover, JsonlAuditSink, AgentContext, Intent,
|
|
122
|
+
ToolRequest, Effect
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
async def main():
|
|
126
|
+
# Setup
|
|
127
|
+
policy = YamlPolicyEvaluator("policy.yaml")
|
|
128
|
+
registry = ToolRegistry("manifest.yaml")
|
|
129
|
+
audit = JsonlAuditSink("audit.jsonl")
|
|
130
|
+
|
|
131
|
+
tower = ControlTower(policy, AutoApprover(), audit, registry=registry)
|
|
132
|
+
|
|
133
|
+
# Define context
|
|
134
|
+
agent = AgentContext(agent_id="my-agent", version="1.0", owner="my-team")
|
|
135
|
+
intent = Intent(action="fetch_data", reason="User requested weather info")
|
|
136
|
+
request = ToolRequest(
|
|
137
|
+
tool="api:weather",
|
|
138
|
+
action="get",
|
|
139
|
+
resource_type="weather",
|
|
140
|
+
effect=Effect.READ,
|
|
141
|
+
params={"city": "London"},
|
|
142
|
+
manifest_version="1.0.0"
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
# Execute with enforcement
|
|
146
|
+
result = await tower.execute_async(
|
|
147
|
+
agent, intent, request,
|
|
148
|
+
lambda: fetch_weather("London") # Your tool function
|
|
149
|
+
)
|
|
150
|
+
print(result)
|
|
151
|
+
|
|
152
|
+
asyncio.run(main())
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Feature Highlights
|
|
156
|
+
|
|
157
|
+
### Security Hardening
|
|
158
|
+
|
|
159
|
+
| Feature | Description |
|
|
160
|
+
|---------|-------------|
|
|
161
|
+
| **Parameter Validation** | JSON Schema validation for tool parameters |
|
|
162
|
+
| **Rate Limiting** | Per-agent, per-tool, per-effect rate limits |
|
|
163
|
+
| **Agent Identity Signing** | HMAC-SHA256 verification of agent contexts |
|
|
164
|
+
| **URL Constraints** | Per-tool URL allowlisting/blocklisting |
|
|
165
|
+
| **Webhook Alerts** | Real-time alerts for blocked/denied events |
|
|
166
|
+
| **Audit Schema Versioning** | Forward-compatible audit event schemas |
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
from tollgate import InMemoryRateLimiter, sign_agent_context, make_verifier
|
|
170
|
+
|
|
171
|
+
# Rate limiting
|
|
172
|
+
limiter = InMemoryRateLimiter([
|
|
173
|
+
{"agent_id": "*", "tool": "api:*", "max_calls": 100, "window_seconds": 60},
|
|
174
|
+
{"agent_id": "*", "effect": "write", "max_calls": 10, "window_seconds": 60},
|
|
175
|
+
])
|
|
176
|
+
|
|
177
|
+
# Agent identity signing
|
|
178
|
+
secret = b"your-secret-key"
|
|
179
|
+
signed_agent = sign_agent_context(agent, secret)
|
|
180
|
+
tower = ControlTower(..., verify_fn=make_verifier(secret), rate_limiter=limiter)
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Resilience & Protection
|
|
184
|
+
|
|
185
|
+
| Feature | Description |
|
|
186
|
+
|---------|-------------|
|
|
187
|
+
| **Circuit Breaker** | Auto-disable failing tools after threshold |
|
|
188
|
+
| **Manifest Signing** | HMAC-SHA256 integrity verification for manifests |
|
|
189
|
+
| **NetworkGuard** | Global URL policy enforcement |
|
|
190
|
+
| **Persistent Backends** | SQLite and Redis stores for grants/approvals |
|
|
191
|
+
|
|
192
|
+
```python
|
|
193
|
+
from tollgate import InMemoryCircuitBreaker, NetworkGuard, sign_manifest
|
|
194
|
+
from tollgate.backends import SQLiteGrantStore
|
|
195
|
+
|
|
196
|
+
# Circuit breaker - opens after 5 failures, 60s cooldown
|
|
197
|
+
breaker = InMemoryCircuitBreaker(failure_threshold=5, cooldown_seconds=60)
|
|
198
|
+
|
|
199
|
+
# Global network policy
|
|
200
|
+
guard = NetworkGuard(
|
|
201
|
+
default="deny",
|
|
202
|
+
allowlist=[
|
|
203
|
+
{"pattern": "https://api.github.com/*"},
|
|
204
|
+
{"pattern": "https://api.openai.com/*"},
|
|
205
|
+
],
|
|
206
|
+
blocklist=[
|
|
207
|
+
{"pattern": "http://*"}, # Block insecure
|
|
208
|
+
]
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
# Sign your manifest at build time
|
|
212
|
+
sign_manifest("manifest.yaml", secret_key=b"build-secret")
|
|
213
|
+
|
|
214
|
+
# Load with signature verification
|
|
215
|
+
registry = ToolRegistry("manifest.yaml", signing_key=b"build-secret")
|
|
216
|
+
|
|
217
|
+
tower = ControlTower(..., circuit_breaker=breaker, network_guard=guard)
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Defense in Depth
|
|
221
|
+
|
|
222
|
+
| Feature | Description |
|
|
223
|
+
|---------|-------------|
|
|
224
|
+
| **Multi-Agent Delegation** | Track and control delegation chains |
|
|
225
|
+
| **Policy Testing Framework** | CI-friendly declarative policy testing |
|
|
226
|
+
| **Context Integrity Monitor** | Detect memory/context poisoning |
|
|
227
|
+
| **Anomaly Detection** | Z-score based rate spike detection |
|
|
228
|
+
|
|
229
|
+
```python
|
|
230
|
+
from tollgate import (
|
|
231
|
+
AgentContext, PolicyTestRunner,
|
|
232
|
+
ContextIntegrityMonitor, AnomalyDetector
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
# Delegation chain tracking
|
|
236
|
+
sub_agent = AgentContext(
|
|
237
|
+
agent_id="sub-agent",
|
|
238
|
+
version="1.0",
|
|
239
|
+
owner="team-a",
|
|
240
|
+
delegated_by=("orchestrator", "router"), # Delegation chain
|
|
241
|
+
)
|
|
242
|
+
print(sub_agent.delegation_depth) # 2
|
|
243
|
+
print(sub_agent.root_agent) # "orchestrator"
|
|
244
|
+
|
|
245
|
+
# Policy testing (CI integration)
|
|
246
|
+
runner = PolicyTestRunner("policy.yaml", "test_scenarios.yaml")
|
|
247
|
+
results = runner.run()
|
|
248
|
+
assert results.all_passed # Fail CI if policy regressed
|
|
249
|
+
|
|
250
|
+
# Context integrity monitoring
|
|
251
|
+
monitor = ContextIntegrityMonitor()
|
|
252
|
+
monitor.snapshot("agent-1", "turn-1", {"system_prompt": "You are helpful..."})
|
|
253
|
+
# Later...
|
|
254
|
+
result = monitor.verify("agent-1", "turn-1", current_context)
|
|
255
|
+
if not result.is_valid:
|
|
256
|
+
print(f"Context tampered! Changed: {result.changed_fields}")
|
|
257
|
+
|
|
258
|
+
# Anomaly detection (plugs into audit pipeline)
|
|
259
|
+
detector = AnomalyDetector(z_score_threshold=3.0)
|
|
260
|
+
composite_sink = CompositeAuditSink([jsonl_sink, detector])
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### CLI Tools
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
# Test policies against scenarios (for CI)
|
|
267
|
+
tollgate test-policy policy.yaml --scenarios test_scenarios.yaml
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## Framework Integrations
|
|
271
|
+
|
|
272
|
+
### Session Grants
|
|
273
|
+
Pre-authorize specific actions to bypass human approval:
|
|
274
|
+
|
|
275
|
+
```python
|
|
276
|
+
from tollgate import Grant, InMemoryGrantStore, Effect
|
|
277
|
+
|
|
278
|
+
grant_store = InMemoryGrantStore()
|
|
279
|
+
tower = ControlTower(..., grant_store=grant_store)
|
|
280
|
+
|
|
281
|
+
# Issue a grant (after initial approval)
|
|
282
|
+
grant = Grant(
|
|
283
|
+
agent_id="my-agent",
|
|
284
|
+
effect=Effect.WRITE,
|
|
285
|
+
tool="mcp:*", # Wildcard: any MCP tool
|
|
286
|
+
action=None, # Wildcard: any action
|
|
287
|
+
resource_type=None,
|
|
288
|
+
expires_at=time.time() + 3600,
|
|
289
|
+
granted_by="admin",
|
|
290
|
+
created_at=time.time()
|
|
291
|
+
)
|
|
292
|
+
await grant_store.create_grant(grant)
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### MCP (Model Context Protocol)
|
|
296
|
+
```python
|
|
297
|
+
from tollgate.integrations.mcp import TollgateMCPClient
|
|
298
|
+
|
|
299
|
+
registry = ToolRegistry("manifest.yaml")
|
|
300
|
+
tower = ControlTower(...)
|
|
301
|
+
client = TollgateMCPClient(base_client, "my_server", tower=tower, registry=registry)
|
|
302
|
+
|
|
303
|
+
await client.call_tool("read_data", {"id": 1}, agent_ctx=ctx, intent=intent)
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### Strands / LangChain
|
|
307
|
+
```python
|
|
308
|
+
from tollgate.integrations.strands import guard_tools
|
|
309
|
+
|
|
310
|
+
guarded = guard_tools(my_tools, tower, registry)
|
|
311
|
+
await guarded[0]("input", agent_ctx=ctx, intent=intent)
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
## Policy Example
|
|
315
|
+
|
|
316
|
+
```yaml
|
|
317
|
+
# policy.yaml
|
|
318
|
+
version: "1.0"
|
|
319
|
+
rules:
|
|
320
|
+
# Allow reads for verified agents
|
|
321
|
+
- id: allow_reads
|
|
322
|
+
effect: read
|
|
323
|
+
decision: ALLOW
|
|
324
|
+
reason: "Read operations are safe"
|
|
325
|
+
|
|
326
|
+
# Block deep delegation chains
|
|
327
|
+
- id: block_deep_delegation
|
|
328
|
+
effect: write
|
|
329
|
+
decision: DENY
|
|
330
|
+
reason: "Delegation too deep"
|
|
331
|
+
agent:
|
|
332
|
+
max_delegation_depth: 2
|
|
333
|
+
|
|
334
|
+
# Require approval for writes from untrusted delegators
|
|
335
|
+
- id: ask_untrusted_writes
|
|
336
|
+
effect: write
|
|
337
|
+
decision: ASK
|
|
338
|
+
reason: "Write requires human approval"
|
|
339
|
+
agent:
|
|
340
|
+
blocked_delegators:
|
|
341
|
+
- "untrusted-agent"
|
|
342
|
+
|
|
343
|
+
# Default deny
|
|
344
|
+
- id: deny_default
|
|
345
|
+
decision: DENY
|
|
346
|
+
reason: "No matching rule"
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
## Persistent Backends
|
|
350
|
+
|
|
351
|
+
For production deployments, use persistent stores:
|
|
352
|
+
|
|
353
|
+
```python
|
|
354
|
+
# SQLite (zero dependencies, single-process)
|
|
355
|
+
from tollgate.backends import SQLiteGrantStore, SQLiteApprovalStore
|
|
356
|
+
|
|
357
|
+
grant_store = SQLiteGrantStore("tollgate.db")
|
|
358
|
+
approval_store = SQLiteApprovalStore("tollgate.db")
|
|
359
|
+
|
|
360
|
+
# Redis (multi-process, distributed)
|
|
361
|
+
from tollgate.backends import RedisGrantStore, RedisApprovalStore
|
|
362
|
+
|
|
363
|
+
grant_store = RedisGrantStore(redis_url="redis://localhost:6379/0")
|
|
364
|
+
approval_store = RedisApprovalStore(redis_url="redis://localhost:6379/0")
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
## Development
|
|
368
|
+
|
|
369
|
+
```bash
|
|
370
|
+
# Install
|
|
371
|
+
make install
|
|
372
|
+
|
|
373
|
+
# Run Tests (188 tests)
|
|
374
|
+
make test
|
|
375
|
+
|
|
376
|
+
# Run Examples
|
|
377
|
+
python examples/mcp_minimal/demo.py
|
|
378
|
+
python examples/strands_minimal/demo.py
|
|
379
|
+
python examples/mock_tickets/demo.py
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
## Documentation
|
|
383
|
+
|
|
384
|
+
- **[QUICKSTART.md](./QUICKSTART.md)** - Get started in 5 minutes
|
|
385
|
+
- **[FEATURES.md](./FEATURES.md)** - Complete feature guide
|
|
386
|
+
- **[COMPARISON.md](./COMPARISON.md)** - Integration effort comparison
|
|
387
|
+
- **[SECURITY.md](./SECURITY.md)** - Security model and guarantees
|
|
388
|
+
- **[CHANGELOG.md](./CHANGELOG.md)** - Version history
|
|
389
|
+
- **[CONTRIBUTING.md](./CONTRIBUTING.md)** - How to contribute
|
|
390
|
+
|
|
391
|
+
## License
|
|
392
|
+
|
|
393
|
+
Apache-2.0
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
tollgate/__init__.py,sha256=BFlGuAW4QPHeFkVKuVLAQAgUCYj6JBGIQLFJVoXV3oU,2624
|
|
2
|
+
tollgate/anomaly_detector.py,sha256=3ODBwFNbRK4JpflrH94fgQXchI0X6LoMoZeWJBNN9NQ,13569
|
|
3
|
+
tollgate/approvals.py,sha256=lalvun6i5yaZ2EGZ-apQJBrLVmht5OfwgiUFsImPdYE,7814
|
|
4
|
+
tollgate/audit.py,sha256=ej99uu0lCRe1VRnY0Dkwpk0FE2F7gNIW5NfdpM0KcxA,4444
|
|
5
|
+
tollgate/circuit_breaker.py,sha256=JEtNZLDnw38pRR1ZAA4Scig6ulDwbcACMyEizN6o6Kc,7014
|
|
6
|
+
tollgate/context_monitor.py,sha256=sg13QA_UZTjsvDhZzvXWgqYVzpI1vc4PEJXwFh222bY,10013
|
|
7
|
+
tollgate/exceptions.py,sha256=s8VoAZYcjqnSx56cqw4FmDEbuXaHLTxyzwAGWVjVz0A,1571
|
|
8
|
+
tollgate/grants.py,sha256=H5soShiNcyQiY3gLJRqqP7ffAo2Udmnj3iU15sGi3os,5177
|
|
9
|
+
tollgate/helpers.py,sha256=ZFMi19_ogpTlV_svFtgJ9kkmA1sPte1dmDnHYVdWGyo,1657
|
|
10
|
+
tollgate/manifest_signing.py,sha256=PvJMqHX-iwhXf3a4vveVyFhsGRCfWpBJ7cHdU1ASQzo,2936
|
|
11
|
+
tollgate/network_guard.py,sha256=pslR2utlRbrIcKfJt7A9mZE_vFQpS2HqRTWUL8bSCPY,4388
|
|
12
|
+
tollgate/policy.py,sha256=wP-qfIoKdVsZY5RiXS6Yn9ESgSGFx0EmEVAtZz8OaAs,7757
|
|
13
|
+
tollgate/policy_testing.py,sha256=lwSvm56UAoZwrWG7eKO-BUJ-pfEJHkICKHRGjBJRAzU,11652
|
|
14
|
+
tollgate/rate_limiter.py,sha256=dTjAeOis2nJKpaECT9xLo5ErWABfzmJjf1OTdna2Shg,5470
|
|
15
|
+
tollgate/registry.py,sha256=9TG65057NzA2bN9pG5bBTmEp_Jl68vVihcbJSn_XJJc,11370
|
|
16
|
+
tollgate/tower.py,sha256=k2wGQPw7ojU4k_suptowJ2KEGFfRsbgL9sD2l68A2RY,14931
|
|
17
|
+
tollgate/types.py,sha256=ZL-gmsG9dVi28U2zUCdHCVl73xYreqyuO1HrYCYafEQ,4551
|
|
18
|
+
tollgate/verification.py,sha256=EBncuJ834ILquUCOdbdZ0X0nJABblnCJHxRNYT7MdnY,2437
|
|
19
|
+
tollgate/backends/__init__.py,sha256=IbsabqDZ9dlq9XeM9twMrPBREElg4eTOxzZ0YqxpQcA,1164
|
|
20
|
+
tollgate/backends/redis_store.py,sha256=vKhqBbGgCknnKqklZ8d_E_eMUNubu6bdf4gO7DIiHY8,13445
|
|
21
|
+
tollgate/backends/sqlite_store.py,sha256=LQxVuF_LnQXobEP_gBZIBWINX4mT7gfs3sjwEMb4jKE,14879
|
|
22
|
+
tollgate/integrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
23
|
+
tollgate/integrations/mcp.py,sha256=jBy1d64Yc55fO4JSVfhKqiffVCZdBMmmNLRta9SVfDE,1750
|
|
24
|
+
tollgate/integrations/strands.py,sha256=_AWsIyva_iwLFIQeTMxxbEzLSjneo0YumWfY9oayKeM,3003
|
|
25
|
+
tollgate/interceptors/__init__.py,sha256=0c3MYyVKGYrBOZ1mMolgrAowrqZrULzAl0vv-s8IFFg,305
|
|
26
|
+
tollgate/interceptors/base.py,sha256=uJxHzH0eurcGEVknbk1kQkk_2u2qNtnM--ZRCp52Wyo,1390
|
|
27
|
+
tollgate/interceptors/langchain.py,sha256=_8vXCjWkRKeTlxtXm33a67Gf4po9YiHS7faThMJLohc,2963
|
|
28
|
+
tollgate/interceptors/openai.py,sha256=cHnOQ8keQJRYBm_1RpohKWk3D9Ask22hpuQghm9iahU,3337
|
|
29
|
+
tollgate-1.4.0.dist-info/METADATA,sha256=eo3_xCfyEb35-jv61Cpi2TrSmDLGG7AAKr-ifNtRgr4,13070
|
|
30
|
+
tollgate-1.4.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
31
|
+
tollgate-1.4.0.dist-info/entry_points.txt,sha256=trBcUVx2EZAAVORkTpGcoUXtoal-_GeCp8BZshA3gm0,62
|
|
32
|
+
tollgate-1.4.0.dist-info/licenses/LICENSE,sha256=EZ9SehMCkcatlggcoT7WV0tx-ku4OsAoQf9LmJZvG1g,10806
|
|
33
|
+
tollgate-1.4.0.dist-info/RECORD,,
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: tollgate
|
|
3
|
-
Version: 1.0.5
|
|
4
|
-
Summary: Runtime enforcement layer for AI agent tool calls using Identity + Intent + Policy
|
|
5
|
-
Author: Tollgate Maintainers
|
|
6
|
-
License-Expression: Apache-2.0
|
|
7
|
-
License-File: LICENSE
|
|
8
|
-
Keywords: agents,ai,enforcement,llm,policy,security
|
|
9
|
-
Classifier: Development Status :: 3 - Alpha
|
|
10
|
-
Classifier: Intended Audience :: Developers
|
|
11
|
-
Classifier: License :: OSI Approved :: Apache Software License
|
|
12
|
-
Classifier: Programming Language :: Python :: 3
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
-
Requires-Python: >=3.10
|
|
17
|
-
Requires-Dist: pyyaml>=6.0.0
|
|
18
|
-
Provides-Extra: dev
|
|
19
|
-
Requires-Dist: build>=1.0.0; extra == 'dev'
|
|
20
|
-
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
21
|
-
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
22
|
-
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
23
|
-
Requires-Dist: twine>=4.0.0; extra == 'dev'
|
|
24
|
-
Description-Content-Type: text/markdown
|
|
25
|
-
|
|
26
|
-
# tollgate 🚪
|
|
27
|
-
|
|
28
|
-
Runtime enforcement layer for AI agent tool calls using **Identity + Intent + Policy**.
|
|
29
|
-
|
|
30
|
-
`tollgate` provides a deterministic safety boundary for AI agents. It ensures every tool call is validated against a policy before execution, with support for async human-in-the-loop approvals, framework interception (MCP, Strands, LangChain, OpenAI), and structured audit logging.
|
|
31
|
-
|
|
32
|
-
> [!CAUTION]
|
|
33
|
-
> **Disclaimer**: This project is an exploratory implementation intended for learning and discussion. It is not production-hardened and comes with no guarantees.
|
|
34
|
-
|
|
35
|
-
**[🚀 Quickstart Guide](https://github.com/ravi-labs/tollgate/blob/main/QUICKSTART.md) | [📊 Integration Comparison](https://github.com/ravi-labs/tollgate/blob/main/COMPARISON.md)**
|
|
36
|
-
|
|
37
|
-
```
|
|
38
|
-
┌────────────┐ ┌─────────────────────┐ ┌──────────────────┐
|
|
39
|
-
│ AI Agent │────▶│ Tollgate Interceptor│────▶│ Policy + Registry│
|
|
40
|
-
└────────────┘ └─────────────────────┘ └────────┬─────────┘
|
|
41
|
-
│
|
|
42
|
-
┌────────────────────────────────────┼────────────────────────────────────┐
|
|
43
|
-
│ │ │
|
|
44
|
-
▼ ▼ ▼
|
|
45
|
-
┌───────────┐ ┌───────────┐ ┌───────────┐
|
|
46
|
-
│ ALLOW │ │ ASK │ │ DENY │
|
|
47
|
-
└─────┬─────┘ └─────┬─────┘ └─────┬─────┘
|
|
48
|
-
│ │ │
|
|
49
|
-
▼ ▼ ▼
|
|
50
|
-
┌───────────┐ ┌───────────────┐ ┌───────────┐
|
|
51
|
-
│ Execute │ │Human Approval │ │ Block & │
|
|
52
|
-
│ Tool │ │ (Approved?) │ │ Audit │
|
|
53
|
-
└─────┬─────┘ └───────┬───────┘ └─────┬─────┘
|
|
54
|
-
│ ▼ ▼ │
|
|
55
|
-
│ Yes │ │ No │
|
|
56
|
-
│ ▼ ▼ │
|
|
57
|
-
│ ┌─────────┐ ┌─────────┐ │
|
|
58
|
-
│ │ Execute │ │ Block │ │
|
|
59
|
-
│ └────┬────┘ └────┬────┘ │
|
|
60
|
-
│ │ │ │
|
|
61
|
-
└─────────────────────────────┴───────────┴──────────────────────────────┘
|
|
62
|
-
│
|
|
63
|
-
▼
|
|
64
|
-
┌───────────┐
|
|
65
|
-
│ Audit Log │
|
|
66
|
-
└───────────┘
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
## ✨ v1 Core Principles
|
|
70
|
-
|
|
71
|
-
1. **Interception-First**: Enforcement happens at the tool execution boundary via adapters.
|
|
72
|
-
2. **Safe Defaults**: Any unknown tool effect or resource defaults to **DENY**.
|
|
73
|
-
3. **Trust Model**: Tool metadata is trusted only if it comes from a developer-controlled **Tool Registry**.
|
|
74
|
-
4. **Approval Integrity**: Approvals are bound to a request hash and correlation ID with replay protection.
|
|
75
|
-
5. **Async-First**: Native support for asynchronous agent loops and non-blocking approvals.
|
|
76
|
-
6. **Audit Integrity**: Every decision, approval, and outcome is recorded with full cryptographic context.
|
|
77
|
-
|
|
78
|
-
## 🚀 v1 Integrations
|
|
79
|
-
|
|
80
|
-
### 🎟️ Session Grants
|
|
81
|
-
Grants allow you to pre-authorize specific actions for an agent session, bypassing human-in-the-loop approvals for repetitive or low-risk tasks.
|
|
82
|
-
|
|
83
|
-
```python
|
|
84
|
-
from tollgate import Grant, InMemoryGrantStore, Effect
|
|
85
|
-
|
|
86
|
-
# 1. Setup a grant store
|
|
87
|
-
grant_store = InMemoryGrantStore()
|
|
88
|
-
tower = ControlTower(..., grant_store=grant_store)
|
|
89
|
-
|
|
90
|
-
# 2. Issue a grant (e.g., after initial human approval)
|
|
91
|
-
grant = Grant(
|
|
92
|
-
agent_id="my-agent",
|
|
93
|
-
effect=Effect.WRITE,
|
|
94
|
-
tool="mcp:*", # Wildcard prefix: matches any MCP tool (e.g., "mcp:server.write")
|
|
95
|
-
action=None, # Wildcard: matches any action
|
|
96
|
-
resource_type=None,
|
|
97
|
-
expires_at=time.time() + 3600, # Valid for 1 hour
|
|
98
|
-
granted_by="admin-user",
|
|
99
|
-
created_at=time.time()
|
|
100
|
-
)
|
|
101
|
-
await grant_store.create_grant(grant)
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
### MCP (Model Context Protocol)
|
|
105
|
-
Wrap an MCP client to gate all tool calls:
|
|
106
|
-
```python
|
|
107
|
-
from tollgate import ControlTower, ToolRegistry
|
|
108
|
-
from tollgate.integrations.mcp import TollgateMCPClient
|
|
109
|
-
|
|
110
|
-
registry = ToolRegistry("manifest.yaml")
|
|
111
|
-
tower = ControlTower(...)
|
|
112
|
-
client = TollgateMCPClient(base_client, server_name="my_server", tower=tower, registry=registry)
|
|
113
|
-
|
|
114
|
-
# Calls are now gated!
|
|
115
|
-
await client.call_tool("read_data", {"id": 1}, agent_ctx=ctx, intent=intent)
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
### Strands Agents
|
|
119
|
-
Gate Strands tools with minimal friction:
|
|
120
|
-
```python
|
|
121
|
-
from tollgate.integrations.strands import guard_tools
|
|
122
|
-
|
|
123
|
-
guarded = guard_tools(my_strands_tools, tower, registry)
|
|
124
|
-
|
|
125
|
-
# Use guarded tools in your agent
|
|
126
|
-
await guarded[0]("input", agent_ctx=ctx, intent=intent)
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
## 📜 Development
|
|
130
|
-
|
|
131
|
-
```bash
|
|
132
|
-
# Install
|
|
133
|
-
make install
|
|
134
|
-
|
|
135
|
-
# Run Tests
|
|
136
|
-
make test
|
|
137
|
-
|
|
138
|
-
# Run Examples (non-interactive)
|
|
139
|
-
python examples/mcp_minimal/demo.py
|
|
140
|
-
python examples/strands_minimal/demo.py
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
## ⚖️ License
|
|
144
|
-
Apache-2.0
|
tollgate-1.0.5.dist-info/RECORD
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
tollgate/__init__.py,sha256=KWxtUI6D0Cm4QHCAaVv5VdEiQIo_krw7jzbXofxW_FM,1441
|
|
2
|
-
tollgate/approvals.py,sha256=lalvun6i5yaZ2EGZ-apQJBrLVmht5OfwgiUFsImPdYE,7814
|
|
3
|
-
tollgate/audit.py,sha256=ugMhuuLoyBNdYD2S_MjGN_ac4nHdtRz15MElqElREIs,1279
|
|
4
|
-
tollgate/exceptions.py,sha256=2yYY3esnHz26dyJlx_Cd_J64ryhexrgc4KliDmiVJSs,882
|
|
5
|
-
tollgate/grants.py,sha256=H5soShiNcyQiY3gLJRqqP7ffAo2Udmnj3iU15sGi3os,5177
|
|
6
|
-
tollgate/helpers.py,sha256=ZFMi19_ogpTlV_svFtgJ9kkmA1sPte1dmDnHYVdWGyo,1657
|
|
7
|
-
tollgate/policy.py,sha256=1_6HcbdpGfZtwmgqapqeRzItc_wbEg_L-fOA-BVIWNg,6110
|
|
8
|
-
tollgate/registry.py,sha256=ENKT-GnwFq0xXZj6qNlKFhAGYsxxBwtZsAdPZp2qlHM,2031
|
|
9
|
-
tollgate/tower.py,sha256=rPG2sdVe2GpdGiyHwWz8K4k7EJCL2NqDAGsMUkKlt30,8574
|
|
10
|
-
tollgate/types.py,sha256=Ks3HNawhPzEAggTCab7NLb8zl06777ehEusASJWSj_g,3811
|
|
11
|
-
tollgate/integrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
|
-
tollgate/integrations/mcp.py,sha256=jBy1d64Yc55fO4JSVfhKqiffVCZdBMmmNLRta9SVfDE,1750
|
|
13
|
-
tollgate/integrations/strands.py,sha256=_AWsIyva_iwLFIQeTMxxbEzLSjneo0YumWfY9oayKeM,3003
|
|
14
|
-
tollgate/interceptors/__init__.py,sha256=0c3MYyVKGYrBOZ1mMolgrAowrqZrULzAl0vv-s8IFFg,305
|
|
15
|
-
tollgate/interceptors/base.py,sha256=uJxHzH0eurcGEVknbk1kQkk_2u2qNtnM--ZRCp52Wyo,1390
|
|
16
|
-
tollgate/interceptors/langchain.py,sha256=_8vXCjWkRKeTlxtXm33a67Gf4po9YiHS7faThMJLohc,2963
|
|
17
|
-
tollgate/interceptors/openai.py,sha256=cHnOQ8keQJRYBm_1RpohKWk3D9Ask22hpuQghm9iahU,3337
|
|
18
|
-
tollgate-1.0.5.dist-info/METADATA,sha256=zPDa8CQ7Qqx5GoQ6XojAZgur47ErP6KeWoUCfhTQOXs,7748
|
|
19
|
-
tollgate-1.0.5.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
20
|
-
tollgate-1.0.5.dist-info/licenses/LICENSE,sha256=EZ9SehMCkcatlggcoT7WV0tx-ku4OsAoQf9LmJZvG1g,10806
|
|
21
|
-
tollgate-1.0.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|