agec 0.1.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.
agec-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,206 @@
1
+ Metadata-Version: 2.4
2
+ Name: agec
3
+ Version: 0.1.0
4
+ Summary: Authorized Governance Execution Context for AI agents
5
+ Author-email: Onur Esmercan <onuresmercan@gmail.com>
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/onur-esmercan/agec
8
+ Project-URL: Repository, https://github.com/onur-esmercan/agec
9
+ Keywords: ai-agents,authorization,governance,audit,security
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
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
+ Classifier: Topic :: Software Development :: Libraries
17
+ Classifier: Topic :: Security
18
+ Requires-Python: >=3.10
19
+ Description-Content-Type: text/markdown
20
+ Provides-Extra: openai
21
+ Requires-Dist: openai-agents>=0.1; extra == "openai"
22
+ Provides-Extra: langchain
23
+ Requires-Dist: langchain-core>=0.2; extra == "langchain"
24
+ Provides-Extra: dev
25
+ Requires-Dist: pytest>=8.0; extra == "dev"
26
+ Requires-Dist: pytest-cov; extra == "dev"
27
+
28
+ # AGEC
29
+
30
+ Pre-execution governance layer for AI agents.
31
+
32
+ Every AI agent action should be authorized before execution. AGEC validates
33
+ intent, semantic context, execution path, and data processing permissions
34
+ before any tool call is executed. It provides deterministic authorization,
35
+ replayable decisions, and auditability for autonomous AI agents.
36
+
37
+ ---
38
+
39
+ ## Installation
40
+
41
+ ```bash
42
+ pip install agec
43
+ ```
44
+
45
+ ## Quick Start
46
+
47
+ ```python
48
+ from agec import guard, AGECBlockedError
49
+
50
+ @guard(
51
+ intent="send_email",
52
+ purpose="customer_support",
53
+ allowed_tools=["gmail.send"],
54
+ legal_basis="consent",
55
+ )
56
+ def send_email() -> str:
57
+ return "Email sent."
58
+
59
+
60
+ @guard(
61
+ intent="transfer_money",
62
+ purpose="unknown",
63
+ allowed_tools=["bank.transfer"],
64
+ intent_confidence=0.48, # below the 0.7 threshold
65
+ )
66
+ def unsafe_transfer() -> str:
67
+ return "Transferred $1M."
68
+
69
+
70
+ print(send_email()) # → Email sent.
71
+
72
+ try:
73
+ unsafe_transfer()
74
+ except AGECBlockedError as exc:
75
+ print("AGEC BLOCKED EXECUTION")
76
+ print(f"Reason: {exc.reason}")
77
+ print(f"Audit ID: {exc.agec.agec_id}")
78
+ ```
79
+
80
+ If validation fails, execution is blocked **before** the wrapped function runs.
81
+
82
+ ---
83
+
84
+ ## Why AGEC?
85
+
86
+ Traditional authorization systems answer:
87
+
88
+ ```text
89
+ Can this identity access this resource?
90
+ ```
91
+
92
+ AGEC answers a different question:
93
+
94
+ ```text
95
+ Should this exact action execute right now?
96
+ ```
97
+
98
+ AGEC introduces a mandatory governance layer between agent planning and tool
99
+ execution — combining intent validation, policy enforcement, and tamper-evident
100
+ audit logging in a single decorator.
101
+
102
+ ---
103
+
104
+ ## What AGEC Validates
105
+
106
+ | Check | What it enforces |
107
+ |---|---|
108
+ | **Intent** | Declared intent must be in the policy allowlist |
109
+ | **Confidence** | Intent confidence must meet the minimum threshold |
110
+ | **Execution path** | Every tool step must be explicitly permitted |
111
+ | **Purpose** | Data processing purpose must be allowed |
112
+ | **Legal basis** | GDPR-aligned legal basis must be declared and allowed |
113
+ | **Data categories** | Blocked data categories are rejected before execution |
114
+ | **Expiry (TTL)** | Stale contexts are cancelled automatically |
115
+
116
+ ---
117
+
118
+ ## Architecture
119
+
120
+ ```text
121
+ User
122
+
123
+ AI Agent (planning)
124
+
125
+ AGEC ◄─── Policy + Validator
126
+ │ │
127
+ │ AuditLog ──► audit.jsonl (optional)
128
+
129
+ Tool Execution
130
+ ```
131
+
132
+ ---
133
+
134
+ ## Lower-Level API
135
+
136
+ ```python
137
+ from agec import AGEC, Intent, ExecutionPath, DataPermissions, Policy, AGECValidator
138
+
139
+ policy = Policy(
140
+ allowed_intents=["send_email"],
141
+ allowed_tools=["gmail.send"],
142
+ allowed_purposes=["customer_support"],
143
+ allowed_legal_bases=["consent", "contract"],
144
+ )
145
+
146
+ agec = AGEC(
147
+ intent=Intent(type="send_email", confidence=0.95),
148
+ context={"user_id": "123"},
149
+ execution_path=ExecutionPath(path_id="email_path", steps=["gmail.send"]),
150
+ data_permissions=DataPermissions(
151
+ purpose="customer_support",
152
+ legal_basis="consent",
153
+ allowed_operations=["send"],
154
+ data_categories=["email"],
155
+ ),
156
+ )
157
+
158
+ validator = AGECValidator(policy)
159
+ result = validator.validate(agec)
160
+
161
+ print(result.allowed) # True
162
+ print(result.reason) # AGEC validation passed.
163
+ print(agec.status) # AGECStatus.ACTIVE
164
+ ```
165
+
166
+ ### Persisting the Audit Log
167
+
168
+ ```python
169
+ from agec import AuditLog
170
+
171
+ log = AuditLog()
172
+ # ... pass log to AGECValidator(policy, audit_log=log) ...
173
+
174
+ # Save all recorded events to disk
175
+ log.save_json("audit.jsonl")
176
+
177
+ # Reload later for replay or compliance review
178
+ restored = AuditLog.load_json("audit.jsonl")
179
+ ```
180
+
181
+ ---
182
+
183
+ ## Roadmap
184
+
185
+ - [ ] OpenAI Agents SDK adapter
186
+ - [ ] LangGraph adapter
187
+ - [ ] CrewAI adapter
188
+ - [ ] AutoGen adapter
189
+ - [ ] CLI demo runner
190
+ - [ ] Policy manifest (YAML/JSON) support
191
+ - [x] Replayable audit log (JSON persistence)
192
+ - [x] Deterministic execution path hashing
193
+
194
+ ---
195
+
196
+ ## Contributing
197
+
198
+ See [CONTRIBUTING.md](CONTRIBUTING.md).
199
+
200
+ ## Changelog
201
+
202
+ See [CHANGELOG.md](CHANGELOG.md).
203
+
204
+ ## License
205
+
206
+ Apache-2.0
agec-0.1.0/README.md ADDED
@@ -0,0 +1,179 @@
1
+ # AGEC
2
+
3
+ Pre-execution governance layer for AI agents.
4
+
5
+ Every AI agent action should be authorized before execution. AGEC validates
6
+ intent, semantic context, execution path, and data processing permissions
7
+ before any tool call is executed. It provides deterministic authorization,
8
+ replayable decisions, and auditability for autonomous AI agents.
9
+
10
+ ---
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ pip install agec
16
+ ```
17
+
18
+ ## Quick Start
19
+
20
+ ```python
21
+ from agec import guard, AGECBlockedError
22
+
23
+ @guard(
24
+ intent="send_email",
25
+ purpose="customer_support",
26
+ allowed_tools=["gmail.send"],
27
+ legal_basis="consent",
28
+ )
29
+ def send_email() -> str:
30
+ return "Email sent."
31
+
32
+
33
+ @guard(
34
+ intent="transfer_money",
35
+ purpose="unknown",
36
+ allowed_tools=["bank.transfer"],
37
+ intent_confidence=0.48, # below the 0.7 threshold
38
+ )
39
+ def unsafe_transfer() -> str:
40
+ return "Transferred $1M."
41
+
42
+
43
+ print(send_email()) # → Email sent.
44
+
45
+ try:
46
+ unsafe_transfer()
47
+ except AGECBlockedError as exc:
48
+ print("AGEC BLOCKED EXECUTION")
49
+ print(f"Reason: {exc.reason}")
50
+ print(f"Audit ID: {exc.agec.agec_id}")
51
+ ```
52
+
53
+ If validation fails, execution is blocked **before** the wrapped function runs.
54
+
55
+ ---
56
+
57
+ ## Why AGEC?
58
+
59
+ Traditional authorization systems answer:
60
+
61
+ ```text
62
+ Can this identity access this resource?
63
+ ```
64
+
65
+ AGEC answers a different question:
66
+
67
+ ```text
68
+ Should this exact action execute right now?
69
+ ```
70
+
71
+ AGEC introduces a mandatory governance layer between agent planning and tool
72
+ execution — combining intent validation, policy enforcement, and tamper-evident
73
+ audit logging in a single decorator.
74
+
75
+ ---
76
+
77
+ ## What AGEC Validates
78
+
79
+ | Check | What it enforces |
80
+ |---|---|
81
+ | **Intent** | Declared intent must be in the policy allowlist |
82
+ | **Confidence** | Intent confidence must meet the minimum threshold |
83
+ | **Execution path** | Every tool step must be explicitly permitted |
84
+ | **Purpose** | Data processing purpose must be allowed |
85
+ | **Legal basis** | GDPR-aligned legal basis must be declared and allowed |
86
+ | **Data categories** | Blocked data categories are rejected before execution |
87
+ | **Expiry (TTL)** | Stale contexts are cancelled automatically |
88
+
89
+ ---
90
+
91
+ ## Architecture
92
+
93
+ ```text
94
+ User
95
+
96
+ AI Agent (planning)
97
+
98
+ AGEC ◄─── Policy + Validator
99
+ │ │
100
+ │ AuditLog ──► audit.jsonl (optional)
101
+
102
+ Tool Execution
103
+ ```
104
+
105
+ ---
106
+
107
+ ## Lower-Level API
108
+
109
+ ```python
110
+ from agec import AGEC, Intent, ExecutionPath, DataPermissions, Policy, AGECValidator
111
+
112
+ policy = Policy(
113
+ allowed_intents=["send_email"],
114
+ allowed_tools=["gmail.send"],
115
+ allowed_purposes=["customer_support"],
116
+ allowed_legal_bases=["consent", "contract"],
117
+ )
118
+
119
+ agec = AGEC(
120
+ intent=Intent(type="send_email", confidence=0.95),
121
+ context={"user_id": "123"},
122
+ execution_path=ExecutionPath(path_id="email_path", steps=["gmail.send"]),
123
+ data_permissions=DataPermissions(
124
+ purpose="customer_support",
125
+ legal_basis="consent",
126
+ allowed_operations=["send"],
127
+ data_categories=["email"],
128
+ ),
129
+ )
130
+
131
+ validator = AGECValidator(policy)
132
+ result = validator.validate(agec)
133
+
134
+ print(result.allowed) # True
135
+ print(result.reason) # AGEC validation passed.
136
+ print(agec.status) # AGECStatus.ACTIVE
137
+ ```
138
+
139
+ ### Persisting the Audit Log
140
+
141
+ ```python
142
+ from agec import AuditLog
143
+
144
+ log = AuditLog()
145
+ # ... pass log to AGECValidator(policy, audit_log=log) ...
146
+
147
+ # Save all recorded events to disk
148
+ log.save_json("audit.jsonl")
149
+
150
+ # Reload later for replay or compliance review
151
+ restored = AuditLog.load_json("audit.jsonl")
152
+ ```
153
+
154
+ ---
155
+
156
+ ## Roadmap
157
+
158
+ - [ ] OpenAI Agents SDK adapter
159
+ - [ ] LangGraph adapter
160
+ - [ ] CrewAI adapter
161
+ - [ ] AutoGen adapter
162
+ - [ ] CLI demo runner
163
+ - [ ] Policy manifest (YAML/JSON) support
164
+ - [x] Replayable audit log (JSON persistence)
165
+ - [x] Deterministic execution path hashing
166
+
167
+ ---
168
+
169
+ ## Contributing
170
+
171
+ See [CONTRIBUTING.md](CONTRIBUTING.md).
172
+
173
+ ## Changelog
174
+
175
+ See [CHANGELOG.md](CHANGELOG.md).
176
+
177
+ ## License
178
+
179
+ Apache-2.0
@@ -0,0 +1,50 @@
1
+ [project]
2
+ name = "agec"
3
+ version = "0.1.0"
4
+ description = "Authorized Governance Execution Context for AI agents"
5
+ readme = "README.md"
6
+ requires-python = ">=3.10"
7
+ license = "Apache-2.0"
8
+ authors = [
9
+ { name = "Onur Esmercan", email = "onuresmercan@gmail.com" }
10
+ ]
11
+ keywords = ["ai-agents", "authorization", "governance", "audit", "security"]
12
+ classifiers = [
13
+ "Development Status :: 3 - Alpha",
14
+ "Intended Audience :: Developers",
15
+ "Programming Language :: Python :: 3",
16
+ "Programming Language :: Python :: 3.10",
17
+ "Programming Language :: Python :: 3.11",
18
+ "Programming Language :: Python :: 3.12",
19
+ "Topic :: Software Development :: Libraries",
20
+ "Topic :: Security",
21
+ ]
22
+ dependencies = []
23
+
24
+ [project.optional-dependencies]
25
+ openai = ["openai-agents>=0.1"]
26
+ langchain = ["langchain-core>=0.2"]
27
+ dev = ["pytest>=8.0", "pytest-cov"]
28
+
29
+ [project.urls]
30
+ Homepage = "https://github.com/onur-esmercan/agec"
31
+ Repository = "https://github.com/onur-esmercan/agec"
32
+
33
+ [build-system]
34
+ requires = ["setuptools>=68", "wheel"]
35
+ build-backend = "setuptools.build_meta"
36
+
37
+ [tool.setuptools.packages.find]
38
+ where = ["src"]
39
+
40
+ [tool.pytest.ini_options]
41
+ testpaths = ["tests"]
42
+ addopts = "-v --tb=short"
43
+
44
+ [tool.coverage.run]
45
+ source = ["agec"]
46
+ branch = true
47
+
48
+ [tool.coverage.report]
49
+ show_missing = true
50
+ fail_under = 80
agec-0.1.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,44 @@
1
+ """AGEC — Authorized Governance Execution Context.
2
+
3
+ A pre-execution governance layer for AI agents. Every agent action is
4
+ validated for intent, semantic context, execution path, and data
5
+ processing permissions before the tool call is allowed to run.
6
+
7
+ Quick start::
8
+
9
+ from agec import guard
10
+
11
+ @guard(
12
+ intent="send_email",
13
+ purpose="customer_support",
14
+ allowed_tools=["gmail.send"],
15
+ )
16
+ def send_email() -> str:
17
+ return "Email sent."
18
+ """
19
+
20
+ from .audit import AuditEvent, AuditLog
21
+ from .core import AGEC, AGECStatus, AGECTransitionError, DataPermissions, ExecutionPath, Intent
22
+ from .guard import AGECBlockedError, guard
23
+ from .policies import DEFAULT_LEGAL_BASES, Policy
24
+ from .validator import AGECValidator, ValidationResult, validate
25
+
26
+ __version__ = "0.1.0"
27
+
28
+ __all__ = [
29
+ "AGEC",
30
+ "AGECStatus",
31
+ "AGECTransitionError",
32
+ "AGECBlockedError",
33
+ "AGECValidator",
34
+ "AuditEvent",
35
+ "AuditLog",
36
+ "DEFAULT_LEGAL_BASES",
37
+ "DataPermissions",
38
+ "ExecutionPath",
39
+ "Intent",
40
+ "Policy",
41
+ "ValidationResult",
42
+ "guard",
43
+ "validate",
44
+ ]
@@ -0,0 +1,114 @@
1
+ """Audit logging for AGEC governance decisions.
2
+
3
+ Records every validation allow/deny event with a timestamp and
4
+ structured metadata. Events can be persisted to and loaded from
5
+ JSON files for replay and compliance auditing.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json
11
+ from dataclasses import asdict, dataclass
12
+ from datetime import datetime, timezone
13
+ from pathlib import Path
14
+ from typing import Any
15
+
16
+
17
+ @dataclass
18
+ class AuditEvent:
19
+ """A single governance decision recorded by AGEC.
20
+
21
+ Attributes:
22
+ agec_id: UUID of the AGEC context that produced this event.
23
+ event_type: Dot-separated event type, e.g. ``validation.allowed``.
24
+ message: Human-readable description of the outcome.
25
+ metadata: Arbitrary structured data attached to the event.
26
+ timestamp: ISO-8601 UTC timestamp of when the event was recorded.
27
+ """
28
+
29
+ agec_id: str
30
+ event_type: str
31
+ message: str
32
+ metadata: dict[str, Any]
33
+ timestamp: str
34
+
35
+
36
+ class AuditLog:
37
+ """Append-only log of :class:`AuditEvent` records.
38
+
39
+ Events are stored in memory and can optionally be persisted to a
40
+ newline-delimited JSON file (one JSON object per line) for replay
41
+ and compliance use-cases.
42
+
43
+ Example::
44
+
45
+ log = AuditLog()
46
+ log.record("abc-123", "validation.allowed", "Passed.", {"intent": "send_email"})
47
+ log.save_json("audit.jsonl")
48
+ restored = AuditLog.load_json("audit.jsonl")
49
+ """
50
+
51
+ def __init__(self) -> None:
52
+ self.events: list[AuditEvent] = []
53
+
54
+ def record(
55
+ self,
56
+ agec_id: str,
57
+ event_type: str,
58
+ message: str,
59
+ metadata: dict[str, Any] | None = None,
60
+ ) -> None:
61
+ """Append a new event to the log.
62
+
63
+ Args:
64
+ agec_id: UUID of the originating AGEC context.
65
+ event_type: Dot-separated event identifier.
66
+ message: Human-readable outcome description.
67
+ metadata: Optional structured data to attach.
68
+ """
69
+ self.events.append(
70
+ AuditEvent(
71
+ agec_id=agec_id,
72
+ event_type=event_type,
73
+ message=message,
74
+ metadata=metadata or {},
75
+ timestamp=datetime.now(timezone.utc).isoformat(),
76
+ )
77
+ )
78
+
79
+ def to_list(self) -> list[dict[str, Any]]:
80
+ """Return all events as a list of plain dicts."""
81
+ return [asdict(event) for event in self.events]
82
+
83
+ def save_json(self, path: str | Path, *, append: bool = False) -> None:
84
+ """Persist events to a newline-delimited JSON file.
85
+
86
+ Args:
87
+ path: File path to write to.
88
+ append: If ``True``, append to an existing file instead of
89
+ overwriting it. Useful for long-running processes.
90
+ """
91
+ mode = "a" if append else "w"
92
+ with open(path, mode, encoding="utf-8") as fh:
93
+ for event in self.events:
94
+ fh.write(json.dumps(asdict(event), ensure_ascii=False) + "\n")
95
+
96
+ @classmethod
97
+ def load_json(cls, path: str | Path) -> "AuditLog":
98
+ """Load events from a previously saved newline-delimited JSON file.
99
+
100
+ Args:
101
+ path: File path to read from.
102
+
103
+ Returns:
104
+ A new :class:`AuditLog` pre-populated with the stored events.
105
+ """
106
+ log = cls()
107
+ with open(path, encoding="utf-8") as fh:
108
+ for line in fh:
109
+ line = line.strip()
110
+ if not line:
111
+ continue
112
+ data = json.loads(line)
113
+ log.events.append(AuditEvent(**data))
114
+ return log