aegize 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.
@@ -0,0 +1,32 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .eggs/
6
+ build/
7
+ dist/
8
+ .venv/
9
+ venv/
10
+
11
+ # Tooling
12
+ .pytest_cache/
13
+ .ruff_cache/
14
+ .mypy_cache/
15
+
16
+ # Aegize runtime artifacts
17
+ audit.jsonl
18
+ examples/audit.jsonl
19
+ examples/demo_audit.jsonl
20
+
21
+ # OS
22
+ .DS_Store
23
+
24
+ # Local tooling / editor
25
+ # Ignore local Claude settings, but keep the committed usage guide.
26
+ .claude/*
27
+ !.claude/README.md
28
+ .idea/
29
+ .vscode/
30
+
31
+ # Video build artifacts (PNG sequences)
32
+ build/
aegize-0.2.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Geoffrey
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
aegize-0.2.0/PKG-INFO ADDED
@@ -0,0 +1,414 @@
1
+ Metadata-Version: 2.4
2
+ Name: aegize
3
+ Version: 0.2.0
4
+ Summary: Infrastructure for autonomous AI agents: identity, policy, permissions, approval workflows, and audit.
5
+ Project-URL: Homepage, https://aegize.com
6
+ Project-URL: Repository, https://github.com/gggaswint/aegize
7
+ Project-URL: Documentation, https://github.com/gggaswint/aegize#readme
8
+ Project-URL: Issues, https://github.com/gggaswint/aegize/issues
9
+ Author-email: Geoffrey Gaswint <ggaswint@gmail.com>
10
+ License: MIT
11
+ License-File: LICENSE
12
+ Keywords: agents,ai,approval,audit,governance,identity,infrastructure,llm,permissions,policy
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
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
+ Classifier: Topic :: System :: Systems Administration
24
+ Requires-Python: >=3.9
25
+ Requires-Dist: pyyaml>=6.0
26
+ Provides-Extra: dev
27
+ Requires-Dist: pytest>=7.0; extra == 'dev'
28
+ Requires-Dist: ruff>=0.1; extra == 'dev'
29
+ Description-Content-Type: text/markdown
30
+
31
+ <p align="center">
32
+ <picture>
33
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/gggaswint/aegize/main/assets/logo-dark.png">
34
+ <img src="https://raw.githubusercontent.com/gggaswint/aegize/main/assets/logo-light.png" alt="Aegize" width="150">
35
+ </picture>
36
+ </p>
37
+
38
+ # Aegize
39
+
40
+ Infrastructure for autonomous AI agents.
41
+
42
+ **[Website](https://aegize.com)** • **[GitHub](https://github.com/gggaswint/aegize)**
43
+
44
+ [![Python](https://img.shields.io/badge/python-3.9%2B-3776ab?style=flat-square)](https://www.python.org/downloads/)
45
+ [![License: MIT](https://img.shields.io/badge/license-MIT-3fb950?style=flat-square)](./LICENSE)
46
+ [![Status](https://img.shields.io/badge/status-alpha-d29922?style=flat-square)](#roadmap)
47
+ [![Version](https://img.shields.io/badge/version-0.2.0-5b9dff?style=flat-square)](#roadmap)
48
+
49
+ Aegize is the runtime layer between autonomous AI agents and the tools they use.
50
+
51
+ It provides identity, policy enforcement, permissions, approval workflows, audit
52
+ logging, observability, and runtime governance for every AI action.
53
+
54
+ > Every agent action must have identity, permission, policy enforcement, and audit.
55
+
56
+ <p align="center">
57
+ <img src="https://raw.githubusercontent.com/gggaswint/aegize/main/assets/demo.gif" alt="Aegize demo: an agent makes three tool calls — web search allowed, email approval required, shell command denied — each governed and audited by Aegize" width="1000">
58
+ </p>
59
+
60
+ ## Architecture
61
+
62
+ <p align="center">
63
+ <img src="https://raw.githubusercontent.com/gggaswint/aegize/main/assets/architecture.svg" alt="How Aegize fits into an AI agent stack: AI frameworks send tool calls into the Aegize runtime (identity, policy engine, permissions, approval workflows, audit logging, observability); only allowed actions reach tools. Every AI action passes through Aegize before reaching the outside world." width="900">
64
+ </p>
65
+
66
+ ---
67
+
68
+ ## See it in action
69
+
70
+ One agent attempts three tool calls. Aegize **allows** the web search,
71
+ **holds the email for approval**, **blocks the shell command**, and writes an
72
+ audit record for every attempt.
73
+
74
+ ```text
75
+ $ python examples/demo_story.py
76
+
77
+ [1] web_search.search query='AI safety companies'
78
+ ALLOWED -> results for 'AI safety companies'
79
+
80
+ [2] email.send to='ceo@example.com'
81
+ APPROVAL REQUIRED -> held for human review (not executed)
82
+ reason: approval required for tool 'email'
83
+
84
+ [3] shell.execute cmd='rm -rf /var/data'
85
+ DENIED -> blocked before execution
86
+ reason: denied by rule for tool 'shell'
87
+
88
+ Audit trail:
89
+ allowed web_search search
90
+ execution_succeeded web_search search
91
+ approval_required email send
92
+ denied shell execute
93
+
94
+ 3 actions attempted · 1 allowed · 1 awaiting approval · 1 denied · 4 audit records written
95
+ ```
96
+
97
+ The gated and denied calls never reach the underlying functions. See
98
+ [Demo](#demo) to run it yourself.
99
+
100
+ ## Why Aegize?
101
+
102
+ AI systems are moving from answering questions to taking actions — running
103
+ shells, sending email, moving money, calling internal APIs. A model that only
104
+ returns text is easy to contain. An agent that *acts* is not: it needs an
105
+ identity, scoped permissions, approvals for high-impact operations, and a record
106
+ of everything it did.
107
+
108
+ That governance layer is usually missing today, and the model's own judgment
109
+ stands in for it. Aegize is the runtime infrastructure that fills the gap, so
110
+ organizations can let agents take actions without giving up control or
111
+ visibility. Security is one capability this provides; operability, reviewability,
112
+ and confidence in deployment are the rest.
113
+
114
+ ## Project Vision
115
+
116
+ > Every meaningful AI action should pass through trusted runtime infrastructure
117
+ > before reaching the outside world.
118
+
119
+ ## What Aegize provides
120
+
121
+ - **`AgentIdentity`** — a durable identity for each agent (owner, environment,
122
+ metadata).
123
+ - **`PermissionPolicy`** — a YAML policy engine that returns `allow`, `deny`, or
124
+ `require_approval`.
125
+ - **`GuardedTool` / `@guarded_tool`** — the enforcement point: wrap any callable
126
+ so it is identified, permissioned, gated, and audited.
127
+ - **`AuditLog`** — an append-only JSONL record of every attempt and outcome.
128
+ - **Typed, dependency-light, and easy to extend.** One runtime dependency
129
+ (PyYAML).
130
+
131
+ ## Install
132
+
133
+ ```bash
134
+ pip install aegize
135
+ ```
136
+
137
+ Or from source (for development):
138
+
139
+ ```bash
140
+ git clone https://github.com/gggaswint/aegize.git
141
+ cd aegize
142
+ pip install -e ".[dev]"
143
+ ```
144
+
145
+ ## Quickstart
146
+
147
+ ```python
148
+ from aegize import AgentIdentity, PermissionPolicy, GuardedTool, AuditLog
149
+
150
+ agent = AgentIdentity(
151
+ agent_id="research_bot",
152
+ name="Research Bot",
153
+ owner="Geoffrey",
154
+ environment="dev",
155
+ )
156
+
157
+ policy = PermissionPolicy.from_yaml("aegize.yaml")
158
+ audit = AuditLog("audit.jsonl")
159
+
160
+ def web_search(query: str) -> str:
161
+ return f"searched: {query}"
162
+
163
+ safe_web_search = GuardedTool(
164
+ tool_name="web_search",
165
+ operation="search",
166
+ func=web_search,
167
+ agent=agent,
168
+ policy=policy,
169
+ audit_log=audit,
170
+ risk_level="low",
171
+ )
172
+
173
+ result = safe_web_search("AI safety companies")
174
+ ```
175
+
176
+ If the policy allows the action, the function runs and two audit records are
177
+ written (authorization + result). If not, Aegize raises `PolicyDenied` or
178
+ `ApprovalRequired` and the function never executes.
179
+
180
+ ```python
181
+ from aegize import PolicyDenied, ApprovalRequired
182
+
183
+ try:
184
+ safe_web_search("AI safety companies")
185
+ except ApprovalRequired as exc:
186
+ # route to a human approval workflow
187
+ ...
188
+ except PolicyDenied as exc:
189
+ # blocked outright
190
+ ...
191
+ ```
192
+
193
+ ## Decorator quickstart (v0.2)
194
+
195
+ You don't have to wrap every function by hand. Declare a tool once with
196
+ `@guarded_tool`, bundle your agent/policy/audit into a `GuardContext`, and bind
197
+ them together when you have a context.
198
+
199
+ ```python
200
+ from aegize import (
201
+ AgentIdentity, PermissionPolicy, AuditLog,
202
+ GuardContext, guarded_tool, guard, ApprovalRequired,
203
+ )
204
+
205
+ @guarded_tool(tool_name="email", operation="send", risk_level="high")
206
+ def send_email(to: str, body: str) -> str:
207
+ ... # your real implementation
208
+
209
+ ctx = GuardContext(
210
+ agent=AgentIdentity(agent_id="research_bot", name="Research Bot", owner="Geoffrey"),
211
+ policy=PermissionPolicy.from_yaml("aegize.yaml"),
212
+ audit_log=AuditLog("audit.jsonl"),
213
+ )
214
+
215
+ # Bind to a context -> a plain, signature-preserving callable you can register.
216
+ guarded_send = guard(send_email, context=ctx)
217
+ # e.g. server.add_tool(guarded_send) # MCP / any tool registry
218
+
219
+ try:
220
+ guarded_send("ceo@example.com", "Q3 numbers")
221
+ except ApprovalRequired:
222
+ ... # gated for human approval; send_email never ran
223
+ ```
224
+
225
+ `guard()` returns a callable that preserves the original `__name__`,
226
+ docstring, and signature, so tool registries (including MCP servers) that
227
+ introspect functions keep working.
228
+
229
+ **Default context.** Inside a `with ctx:` block (or after `ctx.activate()`),
230
+ decorated tools can be called directly:
231
+
232
+ ```python
233
+ with ctx:
234
+ send_email("ceo@example.com", "Q3 numbers") # uses the active context
235
+ ```
236
+
237
+ **Per-call metadata.** Pass `guard_metadata=` to any guarded call to attach
238
+ context for policy decisions (e.g. a path for an allowlist) and the audit log.
239
+ It is stripped before your function runs:
240
+
241
+ ```python
242
+ guarded_read("report", guard_metadata={"path": "./safe_data/report.txt"})
243
+ ```
244
+
245
+ Both styles are fully supported — use `GuardedTool(...)` directly when you want
246
+ explicit objects, or the decorator when you want ergonomics. They share the same
247
+ enforcement and audit code.
248
+
249
+ ## Policy YAML
250
+
251
+ Policies are per-agent. Each agent has `allow`, `require_approval`, and `deny`
252
+ sections. Evaluation order is **deny → require_approval → allow → default-deny**,
253
+ so an explicit `deny` always wins and anything unlisted is denied.
254
+
255
+ ```yaml
256
+ agents:
257
+ research_bot:
258
+ allow:
259
+ - tool: web_search
260
+ operations: ["search"]
261
+ risk_level_max: medium # block this rule above 'medium' risk
262
+ - tool: file_reader
263
+ operations: ["read"]
264
+ paths:
265
+ - "./safe_data/**" # only inside the allowlisted path
266
+
267
+ require_approval:
268
+ - tool: email
269
+ operations: ["send"]
270
+ - tool: shell
271
+ operations: ["execute"]
272
+
273
+ deny:
274
+ - tool: payments
275
+ operations: ["charge"]
276
+ - tool: shell
277
+ operations: ["rm", "delete"]
278
+ ```
279
+
280
+ Rule fields:
281
+
282
+ | Field | Applies to | Meaning |
283
+ | ---------------- | ----------------------- | ----------------------------------------------------------------- |
284
+ | `tool` | all | Tool name to match. |
285
+ | `operations` | all | Operations the rule covers. Omit to match every operation. |
286
+ | `risk_level_max` | `allow` | Highest risk this rule permits (`low`…`critical`). |
287
+ | `paths` | `allow` | Glob allowlist; a string argument must match one of these. |
288
+
289
+ > **Path matching:** when a rule has `paths`, Aegize checks the string
290
+ > arguments of the call (and `metadata["path"]`) against the glob patterns. A
291
+ > call with no matching path is denied.
292
+
293
+ ## Audit log
294
+
295
+ Every attempt is appended to a JSONL file — one self-contained JSON object per
296
+ line, easy to tail, `grep`, or ship to a SIEM. A single allowed call:
297
+
298
+ ```json
299
+ {"timestamp": "2026-06-27T18:00:00+00:00", "event": "allowed", "agent_id": "research_bot", "tool_name": "web_search", "operation": "search", "risk_level": "low", "input_summary": "'AI safety companies'", "reason": "allowed by rule for tool 'web_search'"}
300
+ {"timestamp": "2026-06-27T18:00:00+00:00", "event": "execution_succeeded", "agent_id": "research_bot", "tool_name": "web_search", "operation": "search", "risk_level": "low", "result_summary": "'searched: AI safety companies'"}
301
+ ```
302
+
303
+ Events: `allowed`, `denied`, `approval_required`, `execution_succeeded`,
304
+ `execution_failed`. The authorization decision is always written **before** the
305
+ function runs; the result is written after. Reading the log back is one call:
306
+
307
+ ```python
308
+ for record in audit.read_all():
309
+ print(record["event"], record["tool_name"], record["operation"])
310
+ ```
311
+
312
+ ## Demo
313
+
314
+ The 60-second story — one agent, three tool calls, three outcomes, all audited:
315
+
316
+ ```bash
317
+ python examples/demo_story.py
318
+ ```
319
+
320
+ It runs the [`See it in action`](#see-it-in-action) flow above against
321
+ [`examples/demo_policy.yaml`](./examples/demo_policy.yaml) and prints the path to
322
+ the audit log it wrote.
323
+
324
+ ## Examples
325
+
326
+ More runnable scripts live in [`examples/`](./examples):
327
+
328
+ ```bash
329
+ python examples/basic_allow.py # allowed web_search runs
330
+ python examples/denied_shell.py # denied shell command is blocked
331
+ python examples/approval_email.py # email send raises ApprovalRequired
332
+ python examples/decorator_usage.py # @guarded_tool + GuardContext (v0.2)
333
+ python examples/demo_story.py # the full allow / approve / deny story
334
+ ```
335
+
336
+ ## Enforcement guarantees
337
+
338
+ - **Default deny.** No matching `allow` rule means the action is denied.
339
+ - **Deny wins.** An explicit `deny` overrides `require_approval` and `allow`.
340
+ - **Gated actions never execute.** `deny` and `require_approval` raise before
341
+ the wrapped function is called.
342
+ - **Audit-first.** The decision is recorded before any execution is attempted;
343
+ the result is recorded after.
344
+
345
+ ## Project documents
346
+
347
+ The operating documents for Aegize — useful for contributors and for
348
+ understanding where the project is headed.
349
+
350
+ **Direction**
351
+
352
+ - [Vision](./docs/vision.md) — the thesis, the problem, and the long-term ambition.
353
+ - [Roadmap](./docs/roadmap.md) — from the current SDK to runtime governance.
354
+ - [Architecture](./docs/architecture.md) — primitives, runtime flow, and trust model.
355
+
356
+ **Operating**
357
+
358
+ - [Principles](./docs/principles.md) — the engineering and product tie-breakers.
359
+ - [Anti-goals](./docs/anti-goals.md) — what Aegize is deliberately not.
360
+ - [Brand](./docs/brand.md) — positioning, messaging, and visual language.
361
+
362
+ **Process & record**
363
+
364
+ - [Decisions](./docs/decisions.md) — the record of why things are the way they are.
365
+ - [Open questions](./docs/questions.md) — unresolved product and architecture questions.
366
+ - [RFCs](./rfcs/README.md) — how significant changes are proposed and recorded.
367
+ - [Launch checklist](./docs/launch-checklist.md) — what's done and what's left to launch.
368
+ - [Next steps](./docs/next-steps.md) — the focused two-week execution plan.
369
+ - [CLAUDE.md](./CLAUDE.md) — operating instructions for AI coding sessions.
370
+
371
+ ## Roadmap
372
+
373
+ - ~~`@guarded_tool` decorator + `GuardContext` ergonomics.~~ ✅ v0.2
374
+ - Policy schema validation and a `aegize lint` CLI.
375
+ - First-class adapters for popular agent frameworks (a thin MCP registration
376
+ helper on top of the v0.2 `guard()` callable).
377
+ - Pluggable approval backends (Slack, webhook, queue) for `require_approval`.
378
+ - Pluggable audit sinks (stdout, syslog, S3, SIEM) beyond local JSONL.
379
+ - Per-environment policy overlays (`dev` / `staging` / `prod`).
380
+ - Rate limits and budget/quota controls per agent and tool.
381
+ - Signed, tamper-evident audit logs.
382
+
383
+ ## Development
384
+
385
+ ```bash
386
+ pip install -e ".[dev]"
387
+ pytest # run the test suite
388
+ ruff check . # lint
389
+ ```
390
+
391
+ CI runs the same `pytest` + `ruff` checks on every push and pull request across
392
+ Python 3.9–3.12.
393
+
394
+ ## Contributing
395
+
396
+ Contributions are welcome. See [CONTRIBUTING.md](./CONTRIBUTING.md) for the dev
397
+ setup, the project's scope and design principles, and the bar for a mergeable
398
+ change.
399
+
400
+ > **Before making major changes, read [CLAUDE.md](./CLAUDE.md) and the project
401
+ > documents in [`docs/`](./docs).** They are the source of truth for Aegize's
402
+ > direction, positioning, and design. (`python scripts/context_check.py` confirms
403
+ > they're present.)
404
+
405
+ ## Reporting vulnerabilities
406
+
407
+ Aegize governs what agents are allowed to do, so we treat weaknesses in it
408
+ seriously. Please report vulnerabilities privately — see
409
+ [SECURITY.md](./SECURITY.md). Do not open a public issue for a suspected
410
+ vulnerability.
411
+
412
+ ## License
413
+
414
+ MIT — see [LICENSE](./LICENSE).