aegis-firewall 2.0.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.
- aegis_firewall-2.0.0/PKG-INFO +285 -0
- aegis_firewall-2.0.0/README.md +245 -0
- aegis_firewall-2.0.0/aegis/__init__.py +93 -0
- aegis_firewall-2.0.0/aegis/cache.py +117 -0
- aegis_firewall-2.0.0/aegis/client.py +293 -0
- aegis_firewall-2.0.0/aegis/errors.py +50 -0
- aegis_firewall-2.0.0/aegis/firewall.py +248 -0
- aegis_firewall-2.0.0/aegis/metrics.py +206 -0
- aegis_firewall-2.0.0/aegis/policy.py +219 -0
- aegis_firewall-2.0.0/aegis/types.py +134 -0
- aegis_firewall-2.0.0/aegis/websocket.py +149 -0
- aegis_firewall-2.0.0/aegis_firewall.egg-info/PKG-INFO +285 -0
- aegis_firewall-2.0.0/aegis_firewall.egg-info/SOURCES.txt +16 -0
- aegis_firewall-2.0.0/aegis_firewall.egg-info/dependency_links.txt +1 -0
- aegis_firewall-2.0.0/aegis_firewall.egg-info/requires.txt +18 -0
- aegis_firewall-2.0.0/aegis_firewall.egg-info/top_level.txt +1 -0
- aegis_firewall-2.0.0/pyproject.toml +74 -0
- aegis_firewall-2.0.0/setup.cfg +4 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: aegis-firewall
|
|
3
|
+
Version: 2.0.0
|
|
4
|
+
Summary: Python SDK for Aegis LLM Inference Firewall
|
|
5
|
+
Author-email: Aegis Team <team@aegis-firewall.dev>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/xaseai/aegis
|
|
8
|
+
Project-URL: Documentation, https://aegis-firewall.dev/docs
|
|
9
|
+
Project-URL: Repository, https://github.com/xaseai/aegis
|
|
10
|
+
Project-URL: Issues, https://github.com/xaseai/aegis/issues
|
|
11
|
+
Keywords: aegis,llm,firewall,security,ai-security,prompt-injection
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Security
|
|
22
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
|
+
Requires-Python: >=3.8
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
Requires-Dist: httpx>=0.25.0
|
|
26
|
+
Requires-Dist: pydantic>=2.5.0
|
|
27
|
+
Requires-Dist: cbor2>=5.5.0
|
|
28
|
+
Requires-Dist: cryptography>=41.0.0
|
|
29
|
+
Provides-Extra: websocket
|
|
30
|
+
Requires-Dist: websockets>=12.0; extra == "websocket"
|
|
31
|
+
Provides-Extra: all
|
|
32
|
+
Requires-Dist: websockets>=12.0; extra == "all"
|
|
33
|
+
Provides-Extra: dev
|
|
34
|
+
Requires-Dist: pytest>=7.4.0; extra == "dev"
|
|
35
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
36
|
+
Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
|
|
37
|
+
Requires-Dist: black>=23.7.0; extra == "dev"
|
|
38
|
+
Requires-Dist: ruff>=0.0.285; extra == "dev"
|
|
39
|
+
Requires-Dist: mypy>=1.5.0; extra == "dev"
|
|
40
|
+
|
|
41
|
+
# aegis-firewall
|
|
42
|
+
|
|
43
|
+
Python SDK for Aegis LLM Inference Firewall.
|
|
44
|
+
|
|
45
|
+
## Installation
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install aegis-firewall
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Quick Start
|
|
52
|
+
|
|
53
|
+
### Synchronous Client
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
from aegis import AegisClient, AegisFirewall
|
|
57
|
+
|
|
58
|
+
# Create client
|
|
59
|
+
client = AegisClient(
|
|
60
|
+
base_url="http://localhost:8080",
|
|
61
|
+
api_key="your-api-key",
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
# Create firewall wrapper
|
|
65
|
+
firewall = AegisFirewall(client)
|
|
66
|
+
|
|
67
|
+
# Add user message
|
|
68
|
+
user_span = firewall.add_user_message("Send email to john@example.com")
|
|
69
|
+
|
|
70
|
+
# Execute tool call with taint tracking
|
|
71
|
+
result = firewall.safe_execute_tool_call(
|
|
72
|
+
"tool.send_email",
|
|
73
|
+
{"to": "john@example.com", "subject": "Hello"},
|
|
74
|
+
[user_span.id]
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
if result["success"]:
|
|
78
|
+
print("Tool call executed successfully")
|
|
79
|
+
else:
|
|
80
|
+
print(f"Tool call failed: {result['error']}")
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Asynchronous Client
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
import asyncio
|
|
87
|
+
from aegis import AegisAsyncClient, AegisAsyncFirewall
|
|
88
|
+
|
|
89
|
+
async def main():
|
|
90
|
+
async with AegisAsyncClient(
|
|
91
|
+
base_url="http://localhost:8080",
|
|
92
|
+
api_key="your-api-key",
|
|
93
|
+
) as client:
|
|
94
|
+
firewall = AegisAsyncFirewall(client)
|
|
95
|
+
|
|
96
|
+
# Add user message
|
|
97
|
+
user_span = await firewall.add_user_message("Send email")
|
|
98
|
+
|
|
99
|
+
# Execute tool call
|
|
100
|
+
result = await firewall.safe_execute_tool_call(
|
|
101
|
+
"tool.send_email",
|
|
102
|
+
{"to": "john@example.com"},
|
|
103
|
+
[user_span.id]
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
print(f"Success: {result['success']}")
|
|
107
|
+
|
|
108
|
+
asyncio.run(main())
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Features
|
|
112
|
+
|
|
113
|
+
- ✅ **Type-safe API** - Full type hints with Pydantic
|
|
114
|
+
- ✅ **Async support** - Both sync and async clients
|
|
115
|
+
- ✅ **Taint tracking** - Automatic span management
|
|
116
|
+
- ✅ **Policy builder** - Programmatic policy creation
|
|
117
|
+
- ✅ **Approval workflows** - Human-in-the-loop support
|
|
118
|
+
- ✅ **Error handling** - Rich error types
|
|
119
|
+
|
|
120
|
+
## API Reference
|
|
121
|
+
|
|
122
|
+
### AegisClient
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
client = AegisClient(
|
|
126
|
+
base_url="http://localhost:8080",
|
|
127
|
+
api_key="optional-api-key",
|
|
128
|
+
timeout=30.0,
|
|
129
|
+
retries=3,
|
|
130
|
+
)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
#### Methods
|
|
134
|
+
|
|
135
|
+
- `validate_tool_call(tool_call)` - Validate tool call
|
|
136
|
+
- `create_span(span_data)` - Create new span
|
|
137
|
+
- `get_span(span_id)` - Get span by ID
|
|
138
|
+
- `list_decisions(session_id=None)` - List decisions
|
|
139
|
+
- `get_approval(approval_id)` - Get approval
|
|
140
|
+
- `list_approvals()` - List pending approvals
|
|
141
|
+
- `approve(approval_id)` - Approve request
|
|
142
|
+
- `deny(approval_id, reason)` - Deny request
|
|
143
|
+
- `get_trace(session_id)` - Get trace
|
|
144
|
+
- `verify_trace(bundle_data)` - Verify trace
|
|
145
|
+
- `health()` - Health check
|
|
146
|
+
|
|
147
|
+
### AegisFirewall
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
firewall = AegisFirewall(client)
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
#### Methods
|
|
154
|
+
|
|
155
|
+
- `add_user_message(content)` - Add user message
|
|
156
|
+
- `add_document(content, sensitivity=...)` - Add RAG document
|
|
157
|
+
- `add_system_prompt(content)` - Add system prompt
|
|
158
|
+
- `execute_tool_call(capability, args, source_span_ids)` - Execute tool call
|
|
159
|
+
- `safe_execute_tool_call(...)` - Safe execution with error handling
|
|
160
|
+
- `get_session_spans()` - Get all spans
|
|
161
|
+
- `clear_session()` - Clear session
|
|
162
|
+
|
|
163
|
+
### PolicyBuilder
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
from aegis import PolicyBuilder, TrustLevel
|
|
167
|
+
|
|
168
|
+
policy = (
|
|
169
|
+
PolicyBuilder()
|
|
170
|
+
.allow("tool.read_calendar", TrustLevel.UNTRUSTED_USER)
|
|
171
|
+
.allow("tool.send_email", TrustLevel.UNTRUSTED_USER, requires_approval=True)
|
|
172
|
+
.deny("payments.*", TrustLevel.UNTRUSTED_DOCUMENT)
|
|
173
|
+
.block_untrusted_documents()
|
|
174
|
+
.block_secret_data()
|
|
175
|
+
.require_approval_for_high_risk()
|
|
176
|
+
.auto_deny_after(30)
|
|
177
|
+
.build()
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
# Export as .aegis format
|
|
181
|
+
aegis_format = PolicyBuilder().allow("tool.send_email").to_aegis_format()
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Examples
|
|
185
|
+
|
|
186
|
+
### RAG with Document Isolation
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
from aegis import AegisClient, AegisFirewall, SensitivityLevel
|
|
190
|
+
|
|
191
|
+
client = AegisClient(base_url="http://localhost:8080")
|
|
192
|
+
firewall = AegisFirewall(client)
|
|
193
|
+
|
|
194
|
+
# Add user query
|
|
195
|
+
user_span = firewall.add_user_message("What is our pricing?")
|
|
196
|
+
|
|
197
|
+
# Add retrieved documents (automatically marked as untrusted)
|
|
198
|
+
doc = firewall.add_document("Pricing: $99/month", SensitivityLevel.PUBLIC)
|
|
199
|
+
|
|
200
|
+
# Tool call sourced only from documents will be BLOCKED
|
|
201
|
+
result = firewall.safe_execute_tool_call(
|
|
202
|
+
"tool.send_email",
|
|
203
|
+
{"to": "attacker@evil.com"},
|
|
204
|
+
[doc.id] # Only document source - blocked by taint tracking!
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
assert not result["success"], "Should be blocked"
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Approval Workflow
|
|
211
|
+
|
|
212
|
+
```python
|
|
213
|
+
def handle_approval(approval_id: str):
|
|
214
|
+
print(f"Waiting for approval: {approval_id}")
|
|
215
|
+
# Notify admin, poll for status, etc.
|
|
216
|
+
|
|
217
|
+
result = firewall.safe_execute_tool_call(
|
|
218
|
+
"tool.execute_code",
|
|
219
|
+
{"code": "print('hello')"},
|
|
220
|
+
[user_span.id],
|
|
221
|
+
on_approval_required=handle_approval
|
|
222
|
+
)
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Async Example
|
|
226
|
+
|
|
227
|
+
```python
|
|
228
|
+
import asyncio
|
|
229
|
+
from aegis import AegisAsyncClient, AegisAsyncFirewall
|
|
230
|
+
|
|
231
|
+
async def main():
|
|
232
|
+
async with AegisAsyncClient("http://localhost:8080") as client:
|
|
233
|
+
firewall = AegisAsyncFirewall(client)
|
|
234
|
+
|
|
235
|
+
user_span = await firewall.add_user_message("Hello")
|
|
236
|
+
result = await firewall.execute_tool_call(
|
|
237
|
+
"tool.search_web",
|
|
238
|
+
{"query": "weather"},
|
|
239
|
+
[user_span.id]
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
print(f"Allowed: {result.allowed}")
|
|
243
|
+
|
|
244
|
+
asyncio.run(main())
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## Error Handling
|
|
248
|
+
|
|
249
|
+
```python
|
|
250
|
+
from aegis import (
|
|
251
|
+
CapabilityBlockedError,
|
|
252
|
+
ApprovalRequiredError,
|
|
253
|
+
NetworkError,
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
try:
|
|
257
|
+
result = client.validate_tool_call(tool_call)
|
|
258
|
+
except CapabilityBlockedError as e:
|
|
259
|
+
print(f"Blocked: {e.capability} - {e.reason}")
|
|
260
|
+
except ApprovalRequiredError as e:
|
|
261
|
+
print(f"Approval needed: {e.approval_id}")
|
|
262
|
+
await handle_approval(e.approval_id)
|
|
263
|
+
except NetworkError as e:
|
|
264
|
+
print(f"Network error: {e.status_code}")
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
## Development
|
|
268
|
+
|
|
269
|
+
```bash
|
|
270
|
+
# Install dev dependencies
|
|
271
|
+
pip install -e ".[dev]"
|
|
272
|
+
|
|
273
|
+
# Run tests
|
|
274
|
+
pytest
|
|
275
|
+
|
|
276
|
+
# Format code
|
|
277
|
+
black aegis/
|
|
278
|
+
|
|
279
|
+
# Type check
|
|
280
|
+
mypy aegis/
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
## License
|
|
284
|
+
|
|
285
|
+
MIT
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# aegis-firewall
|
|
2
|
+
|
|
3
|
+
Python SDK for Aegis LLM Inference Firewall.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install aegis-firewall
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
### Synchronous Client
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from aegis import AegisClient, AegisFirewall
|
|
17
|
+
|
|
18
|
+
# Create client
|
|
19
|
+
client = AegisClient(
|
|
20
|
+
base_url="http://localhost:8080",
|
|
21
|
+
api_key="your-api-key",
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
# Create firewall wrapper
|
|
25
|
+
firewall = AegisFirewall(client)
|
|
26
|
+
|
|
27
|
+
# Add user message
|
|
28
|
+
user_span = firewall.add_user_message("Send email to john@example.com")
|
|
29
|
+
|
|
30
|
+
# Execute tool call with taint tracking
|
|
31
|
+
result = firewall.safe_execute_tool_call(
|
|
32
|
+
"tool.send_email",
|
|
33
|
+
{"to": "john@example.com", "subject": "Hello"},
|
|
34
|
+
[user_span.id]
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
if result["success"]:
|
|
38
|
+
print("Tool call executed successfully")
|
|
39
|
+
else:
|
|
40
|
+
print(f"Tool call failed: {result['error']}")
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Asynchronous Client
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
import asyncio
|
|
47
|
+
from aegis import AegisAsyncClient, AegisAsyncFirewall
|
|
48
|
+
|
|
49
|
+
async def main():
|
|
50
|
+
async with AegisAsyncClient(
|
|
51
|
+
base_url="http://localhost:8080",
|
|
52
|
+
api_key="your-api-key",
|
|
53
|
+
) as client:
|
|
54
|
+
firewall = AegisAsyncFirewall(client)
|
|
55
|
+
|
|
56
|
+
# Add user message
|
|
57
|
+
user_span = await firewall.add_user_message("Send email")
|
|
58
|
+
|
|
59
|
+
# Execute tool call
|
|
60
|
+
result = await firewall.safe_execute_tool_call(
|
|
61
|
+
"tool.send_email",
|
|
62
|
+
{"to": "john@example.com"},
|
|
63
|
+
[user_span.id]
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
print(f"Success: {result['success']}")
|
|
67
|
+
|
|
68
|
+
asyncio.run(main())
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Features
|
|
72
|
+
|
|
73
|
+
- ✅ **Type-safe API** - Full type hints with Pydantic
|
|
74
|
+
- ✅ **Async support** - Both sync and async clients
|
|
75
|
+
- ✅ **Taint tracking** - Automatic span management
|
|
76
|
+
- ✅ **Policy builder** - Programmatic policy creation
|
|
77
|
+
- ✅ **Approval workflows** - Human-in-the-loop support
|
|
78
|
+
- ✅ **Error handling** - Rich error types
|
|
79
|
+
|
|
80
|
+
## API Reference
|
|
81
|
+
|
|
82
|
+
### AegisClient
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
client = AegisClient(
|
|
86
|
+
base_url="http://localhost:8080",
|
|
87
|
+
api_key="optional-api-key",
|
|
88
|
+
timeout=30.0,
|
|
89
|
+
retries=3,
|
|
90
|
+
)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
#### Methods
|
|
94
|
+
|
|
95
|
+
- `validate_tool_call(tool_call)` - Validate tool call
|
|
96
|
+
- `create_span(span_data)` - Create new span
|
|
97
|
+
- `get_span(span_id)` - Get span by ID
|
|
98
|
+
- `list_decisions(session_id=None)` - List decisions
|
|
99
|
+
- `get_approval(approval_id)` - Get approval
|
|
100
|
+
- `list_approvals()` - List pending approvals
|
|
101
|
+
- `approve(approval_id)` - Approve request
|
|
102
|
+
- `deny(approval_id, reason)` - Deny request
|
|
103
|
+
- `get_trace(session_id)` - Get trace
|
|
104
|
+
- `verify_trace(bundle_data)` - Verify trace
|
|
105
|
+
- `health()` - Health check
|
|
106
|
+
|
|
107
|
+
### AegisFirewall
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
firewall = AegisFirewall(client)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
#### Methods
|
|
114
|
+
|
|
115
|
+
- `add_user_message(content)` - Add user message
|
|
116
|
+
- `add_document(content, sensitivity=...)` - Add RAG document
|
|
117
|
+
- `add_system_prompt(content)` - Add system prompt
|
|
118
|
+
- `execute_tool_call(capability, args, source_span_ids)` - Execute tool call
|
|
119
|
+
- `safe_execute_tool_call(...)` - Safe execution with error handling
|
|
120
|
+
- `get_session_spans()` - Get all spans
|
|
121
|
+
- `clear_session()` - Clear session
|
|
122
|
+
|
|
123
|
+
### PolicyBuilder
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
from aegis import PolicyBuilder, TrustLevel
|
|
127
|
+
|
|
128
|
+
policy = (
|
|
129
|
+
PolicyBuilder()
|
|
130
|
+
.allow("tool.read_calendar", TrustLevel.UNTRUSTED_USER)
|
|
131
|
+
.allow("tool.send_email", TrustLevel.UNTRUSTED_USER, requires_approval=True)
|
|
132
|
+
.deny("payments.*", TrustLevel.UNTRUSTED_DOCUMENT)
|
|
133
|
+
.block_untrusted_documents()
|
|
134
|
+
.block_secret_data()
|
|
135
|
+
.require_approval_for_high_risk()
|
|
136
|
+
.auto_deny_after(30)
|
|
137
|
+
.build()
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
# Export as .aegis format
|
|
141
|
+
aegis_format = PolicyBuilder().allow("tool.send_email").to_aegis_format()
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Examples
|
|
145
|
+
|
|
146
|
+
### RAG with Document Isolation
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
from aegis import AegisClient, AegisFirewall, SensitivityLevel
|
|
150
|
+
|
|
151
|
+
client = AegisClient(base_url="http://localhost:8080")
|
|
152
|
+
firewall = AegisFirewall(client)
|
|
153
|
+
|
|
154
|
+
# Add user query
|
|
155
|
+
user_span = firewall.add_user_message("What is our pricing?")
|
|
156
|
+
|
|
157
|
+
# Add retrieved documents (automatically marked as untrusted)
|
|
158
|
+
doc = firewall.add_document("Pricing: $99/month", SensitivityLevel.PUBLIC)
|
|
159
|
+
|
|
160
|
+
# Tool call sourced only from documents will be BLOCKED
|
|
161
|
+
result = firewall.safe_execute_tool_call(
|
|
162
|
+
"tool.send_email",
|
|
163
|
+
{"to": "attacker@evil.com"},
|
|
164
|
+
[doc.id] # Only document source - blocked by taint tracking!
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
assert not result["success"], "Should be blocked"
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Approval Workflow
|
|
171
|
+
|
|
172
|
+
```python
|
|
173
|
+
def handle_approval(approval_id: str):
|
|
174
|
+
print(f"Waiting for approval: {approval_id}")
|
|
175
|
+
# Notify admin, poll for status, etc.
|
|
176
|
+
|
|
177
|
+
result = firewall.safe_execute_tool_call(
|
|
178
|
+
"tool.execute_code",
|
|
179
|
+
{"code": "print('hello')"},
|
|
180
|
+
[user_span.id],
|
|
181
|
+
on_approval_required=handle_approval
|
|
182
|
+
)
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Async Example
|
|
186
|
+
|
|
187
|
+
```python
|
|
188
|
+
import asyncio
|
|
189
|
+
from aegis import AegisAsyncClient, AegisAsyncFirewall
|
|
190
|
+
|
|
191
|
+
async def main():
|
|
192
|
+
async with AegisAsyncClient("http://localhost:8080") as client:
|
|
193
|
+
firewall = AegisAsyncFirewall(client)
|
|
194
|
+
|
|
195
|
+
user_span = await firewall.add_user_message("Hello")
|
|
196
|
+
result = await firewall.execute_tool_call(
|
|
197
|
+
"tool.search_web",
|
|
198
|
+
{"query": "weather"},
|
|
199
|
+
[user_span.id]
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
print(f"Allowed: {result.allowed}")
|
|
203
|
+
|
|
204
|
+
asyncio.run(main())
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Error Handling
|
|
208
|
+
|
|
209
|
+
```python
|
|
210
|
+
from aegis import (
|
|
211
|
+
CapabilityBlockedError,
|
|
212
|
+
ApprovalRequiredError,
|
|
213
|
+
NetworkError,
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
try:
|
|
217
|
+
result = client.validate_tool_call(tool_call)
|
|
218
|
+
except CapabilityBlockedError as e:
|
|
219
|
+
print(f"Blocked: {e.capability} - {e.reason}")
|
|
220
|
+
except ApprovalRequiredError as e:
|
|
221
|
+
print(f"Approval needed: {e.approval_id}")
|
|
222
|
+
await handle_approval(e.approval_id)
|
|
223
|
+
except NetworkError as e:
|
|
224
|
+
print(f"Network error: {e.status_code}")
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## Development
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
# Install dev dependencies
|
|
231
|
+
pip install -e ".[dev]"
|
|
232
|
+
|
|
233
|
+
# Run tests
|
|
234
|
+
pytest
|
|
235
|
+
|
|
236
|
+
# Format code
|
|
237
|
+
black aegis/
|
|
238
|
+
|
|
239
|
+
# Type check
|
|
240
|
+
mypy aegis/
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## License
|
|
244
|
+
|
|
245
|
+
MIT
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Aegis Python SDK - LLM Inference Firewall
|
|
3
|
+
|
|
4
|
+
A comprehensive Python SDK for integrating with the Aegis LLM Inference Firewall.
|
|
5
|
+
Provides both synchronous and asynchronous clients for maximum flexibility.
|
|
6
|
+
|
|
7
|
+
Example:
|
|
8
|
+
>>> from aegis import AegisClient, AegisFirewall
|
|
9
|
+
>>> client = AegisClient(base_url="http://localhost:8080")
|
|
10
|
+
>>> firewall = AegisFirewall(client)
|
|
11
|
+
>>> span = firewall.add_user_message("Send email to john@example.com")
|
|
12
|
+
>>> result = firewall.safe_execute_tool_call(
|
|
13
|
+
... "tool.send_email",
|
|
14
|
+
... {"to": "john@example.com"},
|
|
15
|
+
... [span.id]
|
|
16
|
+
... )
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
__version__ = "2.0.0"
|
|
20
|
+
|
|
21
|
+
from .client import AegisClient, AegisAsyncClient
|
|
22
|
+
from .types import (
|
|
23
|
+
TrustLevel,
|
|
24
|
+
SensitivityLevel,
|
|
25
|
+
RiskLevel,
|
|
26
|
+
RunMode,
|
|
27
|
+
SpanSource,
|
|
28
|
+
Span,
|
|
29
|
+
Capability,
|
|
30
|
+
ToolCall,
|
|
31
|
+
ToolCallResult,
|
|
32
|
+
PolicyDecision,
|
|
33
|
+
TraceSession,
|
|
34
|
+
GatewayConfig,
|
|
35
|
+
HealthResponse,
|
|
36
|
+
ApprovalRequest,
|
|
37
|
+
)
|
|
38
|
+
from .errors import (
|
|
39
|
+
AegisError,
|
|
40
|
+
PolicyError,
|
|
41
|
+
CapabilityBlockedError,
|
|
42
|
+
ApprovalRequiredError,
|
|
43
|
+
TaintViolationError,
|
|
44
|
+
NetworkError,
|
|
45
|
+
TraceVerificationError,
|
|
46
|
+
)
|
|
47
|
+
from .policy import Policy, PolicyBuilder
|
|
48
|
+
from .firewall import AegisFirewall, AegisAsyncFirewall
|
|
49
|
+
|
|
50
|
+
# Advanced features
|
|
51
|
+
try:
|
|
52
|
+
from .websocket import AegisWebSocket, WebSocketEvent
|
|
53
|
+
from .metrics import MetricsCollector, AegisMetrics
|
|
54
|
+
from .cache import LRUCache, ResponseCache
|
|
55
|
+
except ImportError:
|
|
56
|
+
# Optional dependencies not installed
|
|
57
|
+
pass
|
|
58
|
+
|
|
59
|
+
__all__ = [
|
|
60
|
+
"AegisClient",
|
|
61
|
+
"AegisAsyncClient",
|
|
62
|
+
"AegisFirewall",
|
|
63
|
+
"AegisAsyncFirewall",
|
|
64
|
+
"PolicyBuilder",
|
|
65
|
+
"Policy",
|
|
66
|
+
"TrustLevel",
|
|
67
|
+
"SensitivityLevel",
|
|
68
|
+
"RiskLevel",
|
|
69
|
+
"RunMode",
|
|
70
|
+
"SpanSource",
|
|
71
|
+
"Span",
|
|
72
|
+
"Capability",
|
|
73
|
+
"ToolCall",
|
|
74
|
+
"ToolCallResult",
|
|
75
|
+
"PolicyDecision",
|
|
76
|
+
"TraceSession",
|
|
77
|
+
"GatewayConfig",
|
|
78
|
+
"HealthResponse",
|
|
79
|
+
"ApprovalRequest",
|
|
80
|
+
"AegisError",
|
|
81
|
+
"PolicyError",
|
|
82
|
+
"CapabilityBlockedError",
|
|
83
|
+
"ApprovalRequiredError",
|
|
84
|
+
"TaintViolationError",
|
|
85
|
+
"NetworkError",
|
|
86
|
+
"TraceVerificationError",
|
|
87
|
+
"AegisWebSocket",
|
|
88
|
+
"WebSocketEvent",
|
|
89
|
+
"MetricsCollector",
|
|
90
|
+
"AegisMetrics",
|
|
91
|
+
"LRUCache",
|
|
92
|
+
"ResponseCache",
|
|
93
|
+
]
|