Skip to content

Commit 15fb73a

Browse files
feat(ai): add policy gateway, agent collaboration runtime, and LLM gateway hooks
- Policy gateway: regex-based content detection, sanitization, deny/allow/sanitize/require-approval actions with preflight, postflight, stream, and tool-call stages - Agent collaboration runtime: bounded multi-agent orchestration with hop limits, deque-based message routing, and optional policy gateway integration - LLM gateway hooks: request_hook/response_hook seams on LlmGatewaySettings, threaded through sync and async complete() paths - Policy-to-LLM bridge: build_llm_policy_hooks() integration + PolicyViolationError - End-to-end recipe: offline demo combining all three components - Documentation: user guides, recipes, API reference, component maturity model, mkdocs nav, README updates - Tests: 21 new tests across policy gateway, agent collaboration, and LLM gateway hooks (164 total passing)
1 parent fc27d61 commit 15fb73a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+2082
-14
lines changed

README.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ ElectriPy Studio is a curated collection of production-ready Python components a
4040
- 🤖 **AI building blocks**: Provider-agnostic LLM Gateway with sync/async clients and structured-output helpers, plus a RAG Evaluation Runner for retrieval benchmarking.
4141
- 📊 **AI Telemetry**: Provider-agnostic telemetry primitives and adapters (JSONL, optional OpenTelemetry) for HTTP resilience, LLM gateway, policy decisions, and RAG evaluation runs.
4242
- 🧠 **AI product engineering utilities**: Streaming chat primitives, deterministic agent runtime helpers, RAG quality/drift metrics, grounding checks for hallucination reduction, response robustness helpers for structured outputs, prompt templating and composition, token budget tracking and truncation, priority-based context window assembly, rule-based model routing, sliding-window conversation memory, and a declarative tool registry with JSON schema generation.
43+
- 🛡️ **AI policy and collaboration runtime**: Deterministic policy gateway checks for preflight/postflight/stream/tool flows, plus bounded agent-to-agent collaboration runtime for specialist orchestration patterns.
4344

4445
## Quick Start
4546

@@ -123,8 +124,11 @@ Full documentation is available in the [docs/](docs/) directory:
123124
- [CLI Guide](docs/user-guide/cli.md)
124125
- [LLM Gateway & AI](docs/user-guide/ai-llm-gateway.md)
125126
- [AI Telemetry](docs/user-guide/ai-telemetry.md)
127+
- [AI Policy Gateway](docs/user-guide/ai-policy-gateway.md)
128+
- [AI Agent Collaboration Runtime](docs/user-guide/ai-agent-collaboration.md)
126129
- [RAG Evaluation Runner](docs/user-guide/ai-rag-eval-runner.md)
127130
- [AI Product Engineering Utilities](docs/user-guide/ai-product-engineering.md)
131+
- [Component Maturity Model](docs/user-guide/component-maturity.md)
128132
- [Recipes](docs/recipes/cli-tool.md)
129133
- [API Reference](docs/api.md)
130134

@@ -153,7 +157,7 @@ electripy-studio/
153157
│ ├── core/ # Config, logging, errors, typing
154158
│ ├── concurrency/ # Retry & rate limiting
155159
│ ├── io/ # JSONL utilities
156-
── cli/ # CLI commands
160+
── cli/ # CLI commands
157161
│ └── ai/ # AI building blocks and product-engineering utilities
158162
│ ├── llm_gateway/ # Provider-agnostic LLM client + structured output helpers
159163
│ ├── rag_eval_runner/# Dataset + eval runner + CLI benchmarking
@@ -167,11 +171,15 @@ electripy-studio/
167171
│ ├── context_assembly/ # Priority-based context window packing
168172
│ ├── model_router/ # Rule-based model selection and routing
169173
│ ├── conversation_memory/ # Sliding window and token-aware chat history
170-
│ └── tool_registry/ # Declarative tool definitions and JSON schema
174+
│ ├── policy_gateway/ # Deterministic pre/post/tool/stream policy decisions
175+
│ ├── tool_registry/ # Declarative tool definitions and JSON schema
176+
│ └── agent_collaboration/ # Bounded multi-agent handoff orchestration
171177
├── tests/ # Test suite
172178
├── docs/ # Documentation
173179
├── recipes/ # Example recipes
174-
│ └── 01_cli_tool/ # CLI tool example
180+
│ ├── 01_cli_tool/ # CLI tool example
181+
│ ├── 02_llm_gateway/ # LLM gateway examples
182+
│ └── 03_policy_collaboration/ # End-to-end policy + multi-agent flow
175183
├── packages/ # NPM packages
176184
│ └── electripy-cli/ # NPM CLI wrapper
177185
├── pyproject.toml # Project config

docs/api.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,28 @@ Complete API reference for ElectriPy modules.
141141
- `ToolRegistry()`: Register, look up, and export tools.
142142
- `ToolRegistry.to_openai_tools() -> list[dict]`: Export in OpenAI function-calling format.
143143

144+
### Policy Gateway
145+
146+
- `PolicyGateway(rules=..., settings=..., telemetry=...)`: deterministic policy evaluation service.
147+
- `PolicyRule(rule_id, code, description, stage, pattern, ...)`: rule model.
148+
- `PolicyDecision`: action/result model with reason codes and optional sanitized text.
149+
- `PolicyAction`: `allow`, `sanitize`, `deny`, `require_approval`.
150+
- `build_llm_policy_hooks(gateway) -> tuple[request_hook, response_hook]`: bridge for LLM Gateway hooks.
151+
152+
### Agent Collaboration Runtime
153+
154+
- `CollaborationTask(task_id, objective, metadata=...)`: top-level collaboration task.
155+
- `AgentMessage(...)`: typed handoff envelope.
156+
- `AgentCollaborationRuntime(agents, settings=..., policy_gateway=...)`: bounded orchestration runtime.
157+
- `CollaborationRuntimeSettings(max_hops=..., fail_on_blocked_handoff=...)`: reliability controls.
158+
- `make_message(...) -> AgentMessage`: deterministic message factory.
159+
160+
### LLM Gateway Policy Hooks
161+
162+
- `LlmGatewaySettings.request_hook`: preflight request transform/block seam.
163+
- `LlmGatewaySettings.response_hook`: postflight response transform/block seam.
164+
- `PolicyViolationError(stage, reasons)`: raised by policy hooks when blocked.
165+
144166
---
145167

146168
For more detailed examples, see the [User Guide](user-guide/core.md) and [Recipes](recipes/cli-tool.md).

docs/index.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ ElectriPy Studio is a curated collection of production-ready Python components a
2020
- **AI & LLM Gateway**: Provider-agnostic LLM clients with structured output and safety seams, plus a RAG Evaluation Runner for benchmarking retrieval quality.
2121
- **AI Telemetry**: Provider-agnostic telemetry primitives and adapters for HTTP resilience, LLM gateway, policy decisions, and RAG evaluation, with a safe-by-default posture.
2222
- **AI Product Engineering Utilities**: Streaming chat, deterministic agent runtime helpers, RAG quality/drift metrics, hallucination-risk grounding checks, response robustness helpers, prompt templating, token budget management, priority-based context assembly, rule-based model routing, conversation memory, and declarative tool registry.
23+
- **AI Policy Gateway**: Deterministic preflight/postflight/stream/tool policy decisions with allow/sanitize/deny/require-approval actions.
24+
- **AI Agent Collaboration Runtime**: Bounded specialist-agent orchestration with deterministic handoffs and optional policy checks.
2325

2426
## Documentation Map
2527

@@ -37,7 +39,10 @@ ElectriPy Studio is a curated collection of production-ready Python components a
3739
- [LLM Gateway & AI](user-guide/ai-llm-gateway.md)
3840
- [AI Product Engineering Utilities](user-guide/ai-product-engineering.md)
3941
- [AI Telemetry](user-guide/ai-telemetry.md)
42+
- [AI Policy Gateway](user-guide/ai-policy-gateway.md)
43+
- [AI Agent Collaboration Runtime](user-guide/ai-agent-collaboration.md)
4044
- [RAG Evaluation Runner](user-guide/ai-rag-eval-runner.md)
45+
- [Component Maturity Model](user-guide/component-maturity.md)
4146

4247
## Requirements
4348

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# Recipe: Specialist Agent Collaboration
2+
3+
This recipe demonstrates a planner -> retriever -> verifier pipeline using the Agent Collaboration Runtime.
4+
5+
## Scenario
6+
7+
You want to run multiple specialist agents while keeping execution bounded and deterministic.
8+
9+
## Example
10+
11+
```python
12+
from electripy.ai.agent_collaboration import (
13+
AgentCollaborationRuntime,
14+
AgentTurnResult,
15+
CollaborationTask,
16+
make_message,
17+
)
18+
19+
class PlannerAgent:
20+
def handle(self, message, *, task):
21+
return AgentTurnResult(
22+
produced_messages=[
23+
make_message(
24+
task_id=task.task_id,
25+
seq=1,
26+
from_agent="planner",
27+
to_agent="retriever",
28+
content=f"find evidence for: {task.objective}",
29+
)
30+
]
31+
)
32+
33+
class RetrieverAgent:
34+
def handle(self, message, *, task):
35+
return AgentTurnResult(
36+
produced_messages=[
37+
make_message(
38+
task_id=task.task_id,
39+
seq=2,
40+
from_agent="retriever",
41+
to_agent="verifier",
42+
content="evidence: runbook#42",
43+
)
44+
]
45+
)
46+
47+
class VerifierAgent:
48+
def handle(self, message, *, task):
49+
return AgentTurnResult(completed=True, outcome="verified")
50+
51+
runtime = AgentCollaborationRuntime(
52+
agents={
53+
"planner": PlannerAgent(),
54+
"retriever": RetrieverAgent(),
55+
"verifier": VerifierAgent(),
56+
}
57+
)
58+
result = runtime.run(
59+
task=CollaborationTask(task_id="incident-7", objective="recover API service"),
60+
entry_agent="planner",
61+
input_text="start",
62+
)
63+
64+
print(result.success, result.terminal_status, result.hop_count)
65+
```
66+
67+
## Notes
68+
69+
- Keep message payloads concise and structured.
70+
- Enforce max hops to prevent runaway loops.
71+
- Combine with Policy Gateway for handoff safety checks.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Recipe: Policy + Collaboration End-to-End
2+
3+
This recipe demonstrates a complete local flow that combines:
4+
5+
- LLM Gateway request/response policy hooks
6+
- deterministic policy decisions
7+
- bounded agent collaboration
8+
- telemetry event capture
9+
10+
## Scenario
11+
12+
You want one run that proves policy, orchestration, and observability work together without network dependencies.
13+
14+
## Run the demo script
15+
16+
```bash
17+
python recipes/03_policy_collaboration/run_demo.py
18+
```
19+
20+
## Expected behavior
21+
22+
- inbound prompt content is evaluated in policy preflight
23+
- sensitive prompt fragments can be sanitized by request hooks
24+
- postflight checks run on model output before downstream usage
25+
- collaboration runtime executes bounded handoffs with deterministic results
26+
- policy decisions and outcomes are observable through telemetry
27+
28+
## Key wiring
29+
30+
```python
31+
from electripy.ai.llm_gateway import LlmGatewaySettings
32+
from electripy.ai.policy_gateway import PolicyGateway, build_llm_policy_hooks
33+
34+
policy = PolicyGateway(rules=[...])
35+
request_hook, response_hook = build_llm_policy_hooks(policy)
36+
37+
settings = LlmGatewaySettings(
38+
request_hook=request_hook,
39+
response_hook=response_hook,
40+
)
41+
```

docs/recipes/policy-gateway.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Recipe: Policy-Governed LLM + Tool Flow
2+
3+
This recipe shows how to enforce deterministic policy decisions around LLM calls and tool invocations.
4+
5+
## Scenario
6+
7+
You want to:
8+
9+
- Sanitize PII from user prompts.
10+
- Require approval for high-risk tool calls.
11+
- Deny responses containing restricted markers.
12+
13+
## Example
14+
15+
```python
16+
from electripy.ai.policy_gateway import (
17+
PolicyAction,
18+
PolicyGateway,
19+
PolicyRule,
20+
PolicySeverity,
21+
PolicyStage,
22+
after_llm_response,
23+
authorize_tool_call,
24+
before_llm_request,
25+
)
26+
27+
gateway = PolicyGateway(
28+
rules=[
29+
PolicyRule(
30+
rule_id="pii-email",
31+
code="PII_EMAIL",
32+
description="Mask emails in inbound prompts.",
33+
stage=PolicyStage.PREFLIGHT,
34+
pattern=r"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+",
35+
action=PolicyAction.SANITIZE,
36+
),
37+
PolicyRule(
38+
rule_id="tool-delete",
39+
code="TOOL_DELETE",
40+
description="Delete operations require approval.",
41+
stage=PolicyStage.TOOL_CALL,
42+
pattern=r"drop|delete",
43+
action=PolicyAction.REQUIRE_APPROVAL,
44+
severity=PolicySeverity.HIGH,
45+
),
46+
PolicyRule(
47+
rule_id="secret-leak",
48+
code="SECRET_LEAK",
49+
description="Block secret markers in output.",
50+
stage=PolicyStage.POSTFLIGHT,
51+
pattern=r"SECRET_[A-Z0-9]+",
52+
action=PolicyAction.DENY,
53+
),
54+
]
55+
)
56+
57+
request_decision = before_llm_request(gateway, "Email me at [email protected]")
58+
if request_decision.action == PolicyAction.SANITIZE:
59+
prompt = request_decision.sanitized_text or ""
60+
elif request_decision.blocked:
61+
raise RuntimeError("Prompt blocked by policy")
62+
else:
63+
prompt = "Email me at [email protected]"
64+
65+
tool_decision = authorize_tool_call(gateway, "db.execute", {"sql": "drop table users"})
66+
if tool_decision.blocked:
67+
raise RuntimeError("Tool call blocked or requires approval")
68+
69+
response_decision = after_llm_response(gateway, "ok")
70+
if response_decision.blocked:
71+
raise RuntimeError("Response blocked")
72+
```
73+
74+
## Notes
75+
76+
- Keep rules versioned and reviewable.
77+
- Start with redaction and explicit deny lists.
78+
- Integrate telemetry for audit trails.
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# AI Agent Collaboration Runtime
2+
3+
The Agent Collaboration Runtime orchestrates bounded, deterministic handoffs between specialist agents.
4+
5+
## Why it exists
6+
7+
As AI systems move from single-agent flows to specialist-agent teams, reliability depends on explicit message contracts and hop limits. This runtime coordinates those handoffs in-process and works with the Policy Gateway for safety.
8+
9+
## Core concepts
10+
11+
- `CollaborationTask`: top-level objective and metadata.
12+
- `AgentMessage`: typed message envelope between agents.
13+
- `CollaborationAgentPort`: handler protocol each agent implements.
14+
- `AgentCollaborationRuntime`: deterministic orchestration service.
15+
16+
## Quick example
17+
18+
```python
19+
from electripy.ai.agent_collaboration import (
20+
AgentCollaborationRuntime,
21+
AgentTurnResult,
22+
CollaborationTask,
23+
make_message,
24+
)
25+
26+
class PlannerAgent:
27+
def handle(self, message, *, task):
28+
return AgentTurnResult(
29+
produced_messages=[
30+
make_message(
31+
task_id=task.task_id,
32+
seq=1,
33+
from_agent="planner",
34+
to_agent="verifier",
35+
content="plan ready",
36+
)
37+
]
38+
)
39+
40+
class VerifierAgent:
41+
def handle(self, message, *, task):
42+
return AgentTurnResult(completed=True, outcome="verified")
43+
44+
runtime = AgentCollaborationRuntime(
45+
agents={"planner": PlannerAgent(), "verifier": VerifierAgent()}
46+
)
47+
result = runtime.run(
48+
task=CollaborationTask(task_id="incident-1", objective="triage outage"),
49+
entry_agent="planner",
50+
input_text="begin",
51+
)
52+
```
53+
54+
## Reliability guardrails
55+
56+
- Deterministic message ordering.
57+
- Configurable max-hop limits.
58+
- Optional policy checks on inbound/outbound handoffs.
59+
- Full transcript output for replay and debugging.

docs/user-guide/ai-llm-gateway.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ Use the LLM Gateway when you want:
4949
- Observability hook: `LlmGatewaySettings.on_llm_call` – optional
5050
callback invoked after each successful LLM call with
5151
`(request, response, latency_ms)`.
52+
- Policy hooks: `LlmGatewaySettings.request_hook` and
53+
`LlmGatewaySettings.response_hook` for deterministic pre/post
54+
request enforcement.
5255

5356
## Basic example: OpenAI text completion
5457

@@ -218,3 +221,33 @@ client = build_llm_sync_client("openai", settings=settings)
218221

219222
If the hook raises an exception, it is logged and ignored so that
220223
observability issues never break core LLM functionality.
224+
225+
## Request/response policy hooks
226+
227+
`LlmGatewaySettings` exposes two additional seams for enterprise policy
228+
enforcement:
229+
230+
- `request_hook(request) -> request`: runs before budget and provider call.
231+
- `response_hook(request, response) -> response`: runs after provider call
232+
and before returning to the caller.
233+
234+
If these hooks block execution they can raise
235+
`PolicyViolationError(stage=..., reasons=...)`.
236+
237+
```python
238+
from electripy.ai.llm_gateway import LlmGatewaySettings, PolicyViolationError
239+
from electripy.ai.policy_gateway import PolicyGateway, build_llm_policy_hooks
240+
241+
policy = PolicyGateway(rules=[...])
242+
request_hook, response_hook = build_llm_policy_hooks(policy)
243+
244+
settings = LlmGatewaySettings(
245+
request_hook=request_hook,
246+
response_hook=response_hook,
247+
)
248+
249+
try:
250+
response = client.complete(request)
251+
except PolicyViolationError as exc:
252+
print(exc.stage, exc.reasons)
253+
```

0 commit comments

Comments
 (0)