# rgltr Implementation Plan

## Goal
Build a lightweight tool-governance library for PydanticAI agents that:
- Filters tool exposure (MCP allow/deny patterns)
- Dynamically hides tools based on active tags + boundary rules
- Enforces policies at tool-call time with allow/deny/approval outcomes
- Audits governance decisions

This is a simplified version of agentfuse: no data taint tracking, no labeled values, no sink/source data-flow validation. Governance is based solely on tool metadata, tags activated by tool execution, and policy callbacks.

## Non-Goals
- No LLM text redaction or data-flow tracking
- No framework integrations beyond PydanticAI initially
- No policy DSL; policies are Python callables

## High-Level Milestones
1. Core governance primitives (tags, boundaries, policies, config, context)
2. Tool metadata and decorator system
3. PydanticAI integration (function tools + MCP)
4. Audit logging and coverage reporting
5. Examples + tests

## Proposed Package Layout
```
rgltr/
  __init__.py              # public API
  config.py                # global + per-agent config
  context.py               # contextvars for run state, tag tracking
  decorators.py            # tag, boundary, policy
  governance.py            # visibility + policy enforcement logic
  audit.py                 # AuditEvent + sinks
  coverage.py              # coverage report generation
  types.py                 # shared dataclasses, enums, policy structs
  pydantic_ai/
    __init__.py            # integration exports
    toolset.py             # RegulatedToolset
    agent.py               # RegulatedAgent
    mcp.py                 # RegulatedMCPAdapter + filtering
```

## Core Concepts and Data Model
- **Tag**: user-defined Enum. Active tags stored per run.
- **Boundary**: user-defined Enum. Tools may belong to a single boundary.
- **Tool metadata** (attached to functions via decorators):
  - `activates: set[Tag]`
  - `blocked_by: set[Tag]`
  - `boundary: Boundary | None`
  - `policies: PolicySet`
- **Config**:
  - `boundaries: dict[Boundary, bool | list[Tag]]`
  - `mode: "enforce" | "monitor"`
  - `require_annotations: bool`
  - `audit_sink: Callable[[AuditEvent], None] | None`
  - `report_coverage: bool`

## Step-by-Step Implementation

### 1) Types and Configuration
- Create dataclasses in `types.py`:
  - `PolicyDecision` with `allow/deny/requires_approval` helpers
  - `PolicyRequest` containing tool args, active tags, boundary, agent_id, run_id, run_context
  - `AuditEvent` (event_type, tool_name, agent_id, run_id, active_tags, reason, args/result optional)
  - `RegulatorConfig` for global/per-agent configuration
- Implement `configure()` in `config.py` with module-level defaults.
- Choose defaults:
  - Python: 3.11+ (aligns with modern async tooling and pydantic-ai)
  - PydanticAI: >=0.0.49 (match `pyproject.toml` optional dependency)
  - Audit sink: JSONL file logger by default
  - Audit path default: `rgltr-audit.jsonl` in project root (configurable)
  - Coverage reporting: enabled by default

### 2) Context and Tag Tracking
- Implement `context()` as async+sync context manager (contextvars-based):
  - Holds `run_id`, `agent_id`, `active_tags`, and pydantic_ai run context
- Allow nested contexts; child contexts inherit parent tags and emit a new `run_id`.
- Support restoring tags from tool-call history:
  - Parse tool call messages and re-activate based on current tool metadata.
  - Keep this in `context.py` or `governance.py` as helper.

### 3) Decorators and Tool Metadata
- Implement decorators in `decorators.py`:
  - `@tag(activates=[...], blocked_by=[...])`
  - `@policy(require=[...], any_of=[...], denied_message=None)`
- Store metadata on function objects in a single attribute (e.g. `__rgltr__`).
- Provide a helper to merge metadata if multiple decorators are used.

### 4) Governance Logic
- Implement tool visibility checks in `governance.py`:
  - Apply MCP filter patterns first (if any).
  - Evaluate active tags against `blocked_by` and boundary rules.
- Implement policy evaluation:
  - Run `require` policies (all must allow)
  - Run `any_of` policies (one must allow)
  - On denial, return/raise `PolicyDenied` with message
  - On approval required, raise `ApprovalRequired`
  - In monitor mode, log but still allow execution

### 5) Audit and Coverage
- Implement `AuditLogger` and event emission:
- Implement coverage reporting:
  - On agent startup, summarize which tools are sources, boundary tools, or unregulated
  - Emit event if `report_coverage=True`

### 6) PydanticAI Integration
- `RegulatedToolset`:
  - Validates metadata when `require_annotations=True`.
  - Exposes tools to PydanticAI with access to metadata.
- `RegulatedAgent`:
  - Wraps `Agent` and installs hooks:
    - `prepare` to filter tool schema based on visibility rules
    - `process_tool_call` to enforce policies and activate tags after tool execution
- `RegulatedMCPAdapter`:
  - Accepts `tools` pattern config
  - Applies tool-level and server-level metadata to MCP tools
  - Filters tool list before exposure and checks policies at call time

### 7) Examples and Tests
- Provide examples mirroring README:
  - function-only usage
  - MCP filtering + governance
- Tests:
  - Tag activation/hiding
  - Boundary visibility mapping
  - Policy outcomes (allow/deny/approval)
  - Monitor mode behavior
  - MCP tool filtering precedence (exact vs wildcard)
  - Integration tests against Context7 remote MCP server (no auth) to verify real tool filtering + calls

## Adaptations from agentfuse
- Replace label-based data-flow control with tag activation on tool execution.
- No `Labeled[T]` or safe formatting utilities.
- No sink/source default deny semantics; visibility is explicit via tags/boundaries.
- Governance occurs at tool schema construction and tool-call time only.

## Open Questions
- None
