# https://github.com/agent-polis/impact-preview Project Manual

Generated at: 2026-05-31 02:57:23 UTC

## Table of Contents

- [Introduction to Agent Polis](#page-introduction)
- [Quick Start Guide](#page-quick-start)
- [System Architecture](#page-system-architecture)
- [Data Flow and Models](#page-data-flow)
- [Actions Module](#page-actions-module)
- [Governance and Policy](#page-governance-policy)
- [Security Scanners](#page-security-scanners)
- [CI Integration](#page-ci-integration)
- [MCP Server Integration](#page-mcp-server)
- [SDK Integration](#page-sdk-integration)

<a id='page-introduction'></a>

## Introduction to Agent Polis

### Related Pages

Related topics: [System Architecture](#page-system-architecture), [Quick Start Guide](#page-quick-start)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [README.md](https://github.com/agent-polis/impact-preview/blob/main/README.md)
- [src/agent_polis/__init__.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/__init__.py)
- [src/agent_polis/main.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/main.py)
- [src/agent_polis/actions/__init__.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/__init__.py)
- [src/agent_polis/actions/service.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/service.py)
- [src/agent_polis/governance/__init__.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/__init__.py)
- [src/agent_polis/governance/policy.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/policy.py)
- [src/agent_polis/mcp_server.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/mcp_server.py)
- [src/agent_polis/sdk.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/sdk.py)
- [src/agent_polis/integrations/crewai.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/integrations/crewai.py)
</details>

# Introduction to Agent Polis

Agent Polis is an **impact preview governance layer** for autonomous AI agents—providing "terraform plan" style visibility into what will change before any AI agent action executes. It serves as a critical safety layer between AI agent proposals and actual system changes, enabling human oversight and approval workflows.

Source: [README.md]()

## The Problem: Unchecked AI Agent Actions

Autonomous AI agents are increasingly powerful but pose significant risks when operating without oversight. Recent incidents demonstrate the consequences of unconstrained AI agency:

| Incident | Impact |
|----------|--------|
| Replit Agent deleted production database | Data loss, service disruption |
| Cursor YOLO mode deleted entire system | Complete system destruction |
| Claude Code bypassing safety restrictions | Policy circumvention via shell scripts |

Current solutions show what agents *want* to do, not what *will* happen. There is no equivalent to `terraform plan` for AI agent actions—developers lack visibility into actual system changes before they occur.

Source: [README.md]()

## Core Value Proposition

Agent Polis intercepts proposed actions from autonomous AI agents, analyzes their impact, presents a diff preview of changes, and requires human approval before execution. This creates a governed workflow:

```
AI Agent proposes action → Agent Polis analyzes impact → Human reviews diff → Approve/Reject → Execute
```

### Key Capabilities

- **Impact Analysis**: Pre-execution scanning of file changes, shell commands, and database operations
- **Risk Assessment**: Automatic risk level classification (LOW, MEDIUM, HIGH, CRITICAL)
- **Diff Preview**: Unified diff output showing exact changes before execution
- **Governance Policies**: Configurable rules for allow/deny/require_approval decisions
- **Audit Trail**: Complete event sourcing infrastructure for compliance and debugging
- **CI/CD Integration**: Deterministic evaluation mode for automated pipelines

Source: [README.md]()

## Architecture Overview

Agent Polis follows a modular architecture with clear separation of concerns:

```mermaid
graph TD
    subgraph "Client Layer"
        AI[AI Agent] --> MCP[MCP Server]
        AI --> SDK[Python SDK]
        AI --> HTTP[REST API]
        AI --> A2A[A2A Protocol]
    end

    subgraph "Core Services"
        MCP --> AS[Action Service]
        SDK --> AS
        HTTP --> AS
        A2A --> AS
    end

    subgraph "Governance Layer"
        AS --> SC[Scanner]
        AS --> PE[Policy Evaluator]
        AS --> DI[Descriptor Integrity]
    end

    subgraph "Event Layer"
        AS --> EB[Event Bus]
        EB --> ES[Event Store]
    end

    subgraph "Integration Layer"
        AS --> Crew[CrewAI]
        AS --> Lang[LangGraph]
    end
```

### Module Organization

The codebase is organized into distinct modules within `src/agent_polis/`:

| Module | Purpose |
|--------|---------|
| `actions` | Core impact preview, approval workflow, and execution |
| `governance` | Policy schema, evaluator, scanner, and presets |
| `agents` | Agent registration, authentication, and profiles |
| `events` | Event sourcing, event bus, and audit trail |
| `simulations` | Sandbox testing scenarios before committing |
| `a2a` | Agent-to-Agent protocol for interoperability |
| `integrations` | Framework-specific tools (CrewAI, LangGraph) |
| `ui` | Streamlit demo interface |

Source: [src/agent_polis/__init__.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/__init__.py)

## Action System

The actions module is the core of Agent Polis, handling the complete lifecycle of AI agent requests.

Source: [src/agent_polis/actions/__init__.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/__init__.py)

### Action Types

Agent Polis supports multiple action types for comprehensive coverage:

| Action Type | Description |
|-------------|-------------|
| `FILE_WRITE` | Writing or modifying files on the filesystem |
| `FILE_DELETE` | Deleting files or directories |
| `SHELL_EXECUTE` | Running shell commands |
| `DATABASE_QUERY` | Executing database queries |
| `API_REQUEST` | Making external HTTP requests |
| `ENVIRONMENT_MODIFY` | Modifying environment variables |

Source: [src/agent_polis/actions/models.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/models.py)

### Risk Levels

Actions are classified into risk levels for policy decisions:

| Level | Description | Default Policy |
|-------|-------------|----------------|
| `LOW` | Read operations, non-destructive changes | Auto-approve possible |
| `MEDIUM` | Configuration changes, moderate impact | Require approval |
| `HIGH` | Production changes, significant impact | Require approval |
| `CRITICAL` | Destructive operations, security-sensitive | Deny by default |

Source: [src/agent_polis/actions/models.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/models.py)

### Action Flow

```mermaid
sequenceDiagram
    participant AI as AI Agent
    participant AP as Agent Polis
    participant SC as Scanner
    participant PE as Policy Evaluator
    participant HUM as Human

    AI->>AP: Submit Action Request
    AP->>AP: Create ActionPreview
    AP->>SC: Scan for risks
    AP->>PE: Evaluate policy
    AP->>HUM: Request approval
    alt Approved
        HUM->>AP: Approve
        AP->>AP: Execute action
        AP->>AI: Return result
    else Rejected
        HUM->>AP: Reject
        AP->>AI: Return rejection
    end
```

Source: [src/agent_polis/actions/service.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/service.py)

## Governance System

The governance module provides policy-based control over agent actions.

Source: [src/agent_polis/governance/__init__.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/__init__.py)

### Policy Schema

Policies follow a versioned schema with rules and defaults:

```python
class PolicyConfig(BaseModel):
    version: str
    rules: list[PolicyRule]
    defaults: PolicyDefaults
    metadata: dict[str, Any]
```

Source: [src/agent_polis/governance/policy.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/policy.py)

### Policy Decisions

The policy evaluator returns one of three decisions:

| Decision | Behavior |
|----------|----------|
| `ALLOW` | Action proceeds without human approval |
| `DENY` | Action is blocked immediately |
| `REQUIRE_APPROVAL` | Human review required before execution |

Source: [src/agent_polis/governance/policy.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/policy.py)

### Deterministic Rule Evaluation

Rules are evaluated with deterministic precedence based on specificity:

1. Higher priority rules are evaluated first
2. More specific path globs take precedence over general ones
3. Risk level constraints are evaluated in order: `min_risk_level` → `max_risk_level`
4. The first matching rule determines the decision

Source: [src/agent_polis/governance/policy.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/policy.py)

### Policy Presets

Pre-configured policy bundles are available for common environments:

| Preset | Use Case |
|--------|----------|
| `startup` | Early-stage companies with rapid iteration needs |
| `fintech` | Financial services with strict compliance requirements |
| `games` | Game development with creative flexibility |

Source: [src/agent_polis/governance/__init__.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/__init__.py)

## MCP Server Integration

Agent Polis exposes its tools via the Model Context Protocol (MCP) for integration with Claude Desktop, Cursor, and other MCP-compatible clients.

Source: [src/agent_polis/mcp_server.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/mcp_server.py)

### Server Configuration

```json
{
  "mcpServers": {
    "impact-preview": {
      "url": "http://localhost:8000/mcp"
    }
  }
}
```

### Server Metadata

| Property | Value |
|----------|-------|
| Name | `io.github.agent-polis/impact-preview` |
| Version | `0.2.2` |
| Transport | `stdio` |
| Protocol | MCP |

Source: [server.json](https://github.com/agent-polis/impact-preview/blob/main/server.json)

## SDK Integration

The Python SDK provides a simple integration path for AI agents:

Source: [src/agent_polis/sdk.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/sdk.py)

### Basic Usage

```python
from agent_polis.sdk import AgentPolisClient

client = AgentPolisClient(api_key="your_api_key")

@client.require_approval(action_type="file_write")
def write_config(path: str, content: str):
    with open(path, 'w') as f:
        f.write(content)
```

The decorator automatically:
1. Submits the action for approval
2. Waits for human review (with timeout)
3. Executes only if approved

Source: [src/agent_polis/sdk.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/sdk.py)

### SDK Exception Handling

| Exception | Trigger |
|-----------|---------|
| `ActionRejectedError` | Human reviewer denies the action |
| `ActionTimedOutError` | Approval timeout exceeded |

Source: [src/agent_polis/sdk.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/sdk.py)

## Framework Integrations

Agent Polis provides native integrations with popular agent frameworks.

Source: [src/agent_polis/integrations/__init__.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/integrations/__init__.py)

### CrewAI Integration

The CrewAI integration provides tools and callbacks for CrewAI agents:

```python
from agent_polis.integrations.crewai import AgentPolisTool, SimulationCallback

# As a tool
tool = AgentPolisTool(api_url="http://localhost:8000", api_key="ap_...")

# As a callback
callback = SimulationCallback(api_url="http://localhost:8000", api_key="ap_...")
```

Source: [src/agent_polis/integrations/crewai.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/integrations/crewai.py)

## Event Sourcing

Agent Polis maintains a complete audit trail using event sourcing architecture:

Source: [src/agent_polis/events/__init__.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/events/__init__.py)

### Event Components

| Component | Purpose |
|-----------|---------|
| `EventStore` | Immutable log of all governance actions |
| `EventBus` | Pub/sub system for event distribution |
| `DomainEvent` | Base class for domain events |
| `append_event` | Add new event to the store |
| `get_events` | Query historical events |

### Audit Record Extension

Audit records include policy decisions, matched rule IDs, and scanner findings for complete traceability. This supports both compliance requirements and debugging workflows.

Source: [src/agent_polis/events/__init__.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/events/__init__.py)

## A2A Protocol Support

Agent Polis implements the Agent-to-Agent (A2A) protocol for standard agent interoperability:

Source: [src/agent_polis/a2a/__init__.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/a2a/__init__.py)

### Agent Card Endpoint

Agents can discover Agent Polis capabilities via `GET /.well-known/agent.json`:

```json
{
  "name": "Agent Polis",
  "protocol": "A2A",
  "capabilities": ["simulation", "governance"]
}
```

## Application Lifecycle

The FastAPI application handles startup and shutdown:

Source: [src/agent_polis/main.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/main.py)

### Startup Sequence

1. Initialize database connection
2. Set up structured logging
3. Register all routers and middleware
4. Start background workers

### Middleware Stack

| Middleware | Purpose |
|------------|---------|
| `CORSMiddleware` | Cross-origin request handling |
| `RateLimitMiddleware` | API rate limiting |
| `RequestLoggingMiddleware` | Request/response logging |

## Getting Started

### Installation

```bash
pip install impact-preview
```

### Running the Server

```bash
# With uvicorn (recommended)
uvicorn agent_polis.mcp_server:mcp.app --host 0.0.0.0 --port 8000

# Or run directly
python -m agent_polis.mcp_server
```

### Quick Test

```bash
python examples/quickstart.py
```

Source: [README.md]()

## Version Information

| Property | Value |
|----------|-------|
| Current Version | `0.2.2` |
| Python Support | `3.11+` |
| License | MIT |

Source: [src/agent_polis/__init__.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/__init__.py)

---

<a id='page-quick-start'></a>

## Quick Start Guide

### Related Pages

Related topics: [Introduction to Agent Polis](#page-introduction), [MCP Server Integration](#page-mcp-server), [SDK Integration](#page-sdk-integration)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [src/agent_polis/main.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/main.py)
- [src/agent_polis/actions/models.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/models.py)
- [src/agent_polis/actions/analyzer.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/analyzer.py)
- [src/agent_polis/actions/service.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/service.py)
- [src/agent_polis/governance/policy.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/policy.py)
- [src/agent_polis/governance/presets.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/presets.py)
- [src/agent_polis/ci.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/ci.py)
- [src/agent_polis/config.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/config.py)
- [src/agent_polis/integrations/crewai.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/integrations/crewai.py)
- [README.md](https://github.com/agent-polis/impact-preview/blob/main/README.md)
</details>

# Quick Start Guide

This guide walks you through getting started with Agent Polis, a governance and coordination layer for AI agents that provides impact preview, policy evaluation, and audit trail capabilities.

## Prerequisites

Before starting, ensure you have:

- **Python 3.11+** for local development
- **Docker & Docker Compose** for containerized deployment
- **Redis** (optional, for event store caching)

Source: [README.md:1-50](https://github.com/agent-polis/impact-preview/blob/main/README.md)

## Installation

### Option 1: Docker (Recommended)

The fastest way to get started is using Docker Compose:

```bash
git clone https://github.com/agent-polis/impact-preview.git
cd impact-preview
docker-compose up -d
```

This starts the Agent Polis API server on `http://localhost:8000` along with Redis for caching.

Source: [README.md:50-80](https://github.com/agent-polis/impact-preview/blob/main/README.md)

### Option 2: Local Development

For development with hot-reload:

```bash
pip install -e ".[dev]"
python -m agent_polis.main
```

Source: [README.md:80-100](https://github.com/agent-polis/impact-preview/blob/main/README.md)

## Core Concepts

Before diving into usage, understand these fundamental concepts:

### Action Request

An `ActionRequest` represents a proposed action by an AI agent that requires governance review:

```python
from agent_polis.actions import ActionRequest, ActionType

request = ActionRequest(
    action_type=ActionType.FILE_WRITE,
    target="src/main.py",
    description="Update main entry point",
    payload={"content": "# updated code..."}
)
```

Source: [src/agent_polis/actions/models.py:30-60](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/models.py)

### Action Types

The system supports multiple action types:

| Action Type | Description |
|-------------|-------------|
| `FILE_WRITE` | Modify existing file |
| `FILE_CREATE` | Create new file |
| `FILE_DELETE` | Delete file |
| `FILE_MOVE` | Rename or move file |
| `DB_QUERY` | Database read operation |
| `DB_EXECUTE` | Database write operation |
| `API_CALL` | External API request |
| `SHELL_COMMAND` | Shell command execution |

Source: [src/agent_polis/actions/models.py:30-50](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/models.py)

### Risk Levels

Actions are classified into four risk levels:

| Risk Level | Description |
|------------|-------------|
| `LOW` | Read operations, safe changes |
| `MEDIUM` | Write operations to non-critical files |
| `HIGH` | Operations with potential side effects |
| `CRITICAL` | Destructive or irreversible operations |

Source: [src/agent_polis/actions/models.py:60-80](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/models.py)

### Policy Decisions

The policy evaluator returns one of three decisions:

| Decision | Description |
|----------|-------------|
| `allow` | Action permitted without approval |
| `deny` | Action blocked |
| `require_approval` | Action needs human approval |

Source: [src/agent_polis/governance/policy.py:20-30](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/policy.py)

## Generating Impact Previews

The core feature is generating impact previews before actions execute. This shows what will change and assesses risk.

### Basic Preview Flow

```mermaid
graph TD
    A[Agent Proposes Action] --> B[Create ActionRequest]
    B --> C[ImpactAnalyzer.analyze]
    C --> D[Risk Assessment]
    D --> E[Generate Preview]
    E --> F[Policy Evaluation]
    F --> G[Approval Required?]
    G -->|Yes| H[Human Approval]
    G -->|No| I[Execute Action]
```

### Python API

```python
import asyncio
from agent_polis.actions import ImpactAnalyzer, ActionRequest, ActionType

async def preview_file_write():
    analyzer = ImpactAnalyzer(working_directory="/path/to/project")
    
    request = ActionRequest(
        action_type=ActionType.FILE_WRITE,
        target="src/config.py",
        description="Update configuration",
        payload={"content": "NEW_CONFIG = 'value'"}
    )
    
    preview = await analyzer.analyze(request)
    
    print(f"Risk Level: {preview.risk_level}")
    print(f"Risk Factors: {preview.risk_factors}")
    print(f"Summary: {preview.summary}")
    print(f"Reversible: {preview.is_reversible}")

asyncio.run(preview_file_write())
```

Source: [src/agent_polis/actions/analyzer.py:40-100](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/analyzer.py)

### Shell Command Risk Assessment

Shell commands are automatically assessed as high risk:

```python
request = ActionRequest(
    action_type=ActionType.SHELL_COMMAND,
    target="deploy.sh",
    description="Run deployment script",
    payload={"command": "bash deploy.sh --prod"}
)

preview = await analyzer.analyze(request)
# Risk level: HIGH by default
# Shell commands are marked non-reversible
```

Source: [src/agent_polis/actions/analyzer.py:120-150](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/analyzer.py)

## Policy Configuration

Policies control which actions are allowed, denied, or require approval based on rules.

### Policy Schema

A policy has this structure:

```python
from agent_polis.governance import PolicyConfig, PolicyDefaults, PolicyRule

policy = PolicyConfig(
    version="policy-1",
    metadata={"name": "My Policy"},
    defaults=PolicyDefaults(decision=PolicyDecision.REQUIRE_APPROVAL),
    rules=[
        PolicyRule(
            id="allow-docs",
            decision=PolicyDecision.ALLOW,
            priority=50,
            action_types={ActionType.FILE_WRITE, ActionType.FILE_CREATE},
            path_globs=["docs/*", "tests/*"],
            max_risk_level=RiskLevel.MEDIUM,
        )
    ]
)
```

Source: [src/agent_polis/governance/policy.py:40-80](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/policy.py)

### Rule Matching

Rules are evaluated by:

1. **Priority** - Higher priority rules match first (deterministic ordering)
2. **Action Type** - Match by action category
3. **Path Globs** - Match file paths using glob patterns
4. **Target Contains** - Match target strings (e.g., `.env`, `secrets`)
5. **Risk Level** - Match by minimum/maximum risk thresholds

Source: [src/agent_polis/governance/policy.py:80-120](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/policy.py)

## Using Policy Presets

Preset policies provide sensible defaults for common environments.

### Available Presets

| Preset | Description |
|--------|-------------|
| `startup` | General-purpose, balanced approach |
| `fintech` | Strict controls for financial systems |
| `games` | Game development workflow optimized |

### Loading a Preset

```python
from agent_polis.governance.presets import load_preset, get_available_presets

# List available presets
presets = get_available_presets()
print(presets)  # ['startup', 'fintech', 'games']

# Load a preset
policy = load_preset("startup")
```

Source: [src/agent_polis/governance/presets.py:1-100](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/presets.py)

### Startup Preset

Designed for general development with balanced controls:

- Docs and tests allowed with low/medium risk
- Shell commands require approval
- Secrets detection enabled

Source: [src/agent_polis/governance/presets.py:10-60](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/presets.py)

### Fintech Preset

Strict controls for regulated environments:

- Secrets and credentials explicitly denied
- Database writes require approval
- Critical-risk actions blocked
- Documentation edits limited to low risk

Source: [src/agent_polis/governance/presets.py:60-120](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/presets.py)

### Games Preset

Optimized for game development iteration:

- Assets and docs allowed with medium risk cap
- Tests allowed with medium risk cap
- Secrets and credentials blocked
- Shell commands require approval

Source: [src/agent_polis/governance/presets.py:120-180](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/presets.py)

## CI Integration

For automated CI environments, use the deterministic CI evaluation mode.

### CI Report Generation

```python
from agent_polis.ci import generate_ci_report, CIPolicyReport

# Evaluate actions deterministically
actions = [
    ActionRequest(
        action_type=ActionType.FILE_WRITE,
        target="src/main.py",
        description="Update main",
        payload={"content": "..."}
    )
]

report, exit_code = await generate_ci_report(
    actions=actions,
    policy=my_policy,
    working_directory="/project/path"
)

# Exit codes:
# 0 = all allowed
# 2 = requires approval
# 3 = denied
```

Source: [src/agent_polis/ci.py:40-80](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/ci.py)

### CI Report Schema

```json
{
  "schema_version": "1",
  "policy_version": "policy-1",
  "totals": {
    "allow": 5,
    "require_approval": 2,
    "deny": 0
  },
  "top_blocking_reasons": [
    {"reason_id": "secrets-detected", "count": 1}
  ],
  "actions": [...]
}
```

Source: [src/agent_polis/ci.py:20-40](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/ci.py)

### GitHub Actions Example

```yaml
name: Policy Check
on: [pull_request]

jobs:
  policy-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Run Policy Check
        run: |
          python -m agent_polis.ci \
            --actions-file actions.json \
            --policy startup \
            --working-dir .
        
      - name: Upload Report
        if: always()
        run: cat ci_report.json >> $GITHUB_STEP_SUMMARY
```

Source: [README.md:100-130](https://github.com/agent-polis/impact-preview/blob/main/README.md)

## Framework Integrations

### CrewAI Integration

Use Agent Polis as a CrewAI tool for simulation:

```python
from agent_polis.integrations.crewai import AgentPolisTool

tool = AgentPolisTool(
    api_url="http://localhost:8000",
    api_key="your-api-key"
)

# Agent can now run simulations before committing
result = tool.run({
    "name": "test-deployment",
    "description": "Test deployment script",
    "code": "subprocess.run(['./deploy.sh'])"
})
```

Source: [src/agent_polis/integrations/crewai.py:40-80](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/integrations/crewai.py)

## API Endpoints

Agent Polis exposes REST endpoints for integration:

| Endpoint | Method | Description |
|----------|--------|-------------|
| `/api/v1/actions` | POST | Submit action request |
| `/api/v1/actions/pending` | GET | List pending actions |
| `/api/v1/agents` | GET | List registered agents |
| `/.well-known/agent.json` | GET | Agent capabilities |

Source: [src/agent_polis/main.py:30-80](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/main.py)

## Configuration

Configure Agent Polis via environment variables:

| Variable | Default | Description |
|----------|---------|-------------|
| `APP_ENV` | `development` | Environment: development/production |
| `HOST` | `0.0.0.0` | Server host |
| `PORT` | `8000` | Server port |
| `REDIS_URL` | `redis://localhost:6379/0` | Redis connection URL |
| `LOG_LEVEL` | `INFO` | Logging level |
| `LOG_FORMAT` | `json` | Log format (json/text) |

Source: [src/agent_polis/config.py:20-50](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/config.py)

## Next Steps

After completing this quick start:

1. **Explore Policy Writing** - Create custom policies for your use case
2. **Review Advanced Features** - Audit trails, event sourcing, prompt injection scanning
3. **Join Community** - Contribute issues and PRs on GitHub

For the latest updates, see the [v0.2.2 release notes](https://github.com/agent-polis/impact-preview/releases/tag/v0.2.2).

---

<a id='page-system-architecture'></a>

## System Architecture

### Related Pages

Related topics: [Introduction to Agent Polis](#page-introduction), [Data Flow and Models](#page-data-flow), [Actions Module](#page-actions-module)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [src/agent_polis/main.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/main.py)
- [src/agent_polis/actions/__init__.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/__init__.py)
- [src/agent_polis/actions/service.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/service.py)
- [src/agent_polis/actions/models.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/models.py)
- [src/agent_polis/governance/__init__.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/__init__.py)
- [src/agent_polis/governance/policy.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/policy.py)
- [src/agent_polis/governance/presets.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/presets.py)
- [src/agent_polis/governance/prompt_scanner.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/prompt_scanner.py)
- [src/agent_polis/events/__init__.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/events/__init__.py)
- [src/agent_polis/ci.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/ci.py)
- [src/agent_polis/mcp_server.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/mcp_server.py)
- [src/agent_polis/simulations/__init__.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/simulations/__init__.py)
- [src/agent_polis/integrations/__init__.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/integrations/__init__.py)
</details>

# System Architecture

Agent Polis (impact-preview) is a governance and coordination layer for AI agents that provides impact preview, policy evaluation, and approval workflows before any action executes. The system intercepts proposed agent actions, assesses their impact and risk, applies configurable policy rules, and surfaces decisions to human reviewers or CI systems.

## High-Level Architecture Overview

The system follows a layered architecture with distinct modules for actions, governance, events, and integrations. Each layer has a specific responsibility and communicates through well-defined interfaces.

```mermaid
graph TD
    subgraph External Interfaces
        MCP[MCP Server<br/>Model Context Protocol]
        A2A[A2A Router<br/>Agent-to-Agent Protocol]
        REST[FastAPI REST<br/>API Endpoints]
        CI[CI Module<br/>Deterministic Mode]
    end

    subgraph Core Modules
        ACTIONS[Actions Module<br/>Impact Analysis]
        GOV[Governance Module<br/>Policy + Scanner]
        EVENTS[Events Module<br/>Audit Trail]
        SIM[Simulations Module<br/>Sandboxed Testing]
    end

    subgraph Shared Infrastructure
        MODELS[Data Models<br/>Pydantic]
        CONF[Configuration<br/>Environment]
    end

    MCP --> ACTIONS
    A2A --> ACTIONS
    REST --> ACTIONS
    CI --> ACTIONS

    ACTIONS --> GOV
    ACTIONS --> EVENTS
    ACTIONS --> SIM
    ACTIONS --> MODELS

    subgraph Integrations
        CREWAI[CrewAI Tool]
        LANGGRAPH[LangGraph Callbacks]
    end

    CREWAI --> ACTIONS
    LANGGRAPH --> ACTIONS
```

Source: [src/agent_polis/main.py:1-50](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/main.py), [src/agent_polis/actions/__init__.py:1-40](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/__init__.py)

## Core Modules

### Actions Module

The Actions module is the central wedge of the system, handling the interception, analysis, and approval of proposed agent actions.

**Responsibilities:**
- Receive action requests from AI agents via MCP, A2A, or REST
- Generate impact previews showing what will change
- Calculate risk levels based on action type and target
- Execute approved actions and track execution status

**Key Components:**

| Component | File | Purpose |
|-----------|------|---------|
| `ActionService` | `actions/service.py` | Orchestrates analysis, governance, and execution |
| `ImpactAnalyzer` | `actions/analyzer.py` | Computes impact previews and risk assessments |
| `ActionRequest` | `actions/models.py` | Request model with action type, target, payload |
| `ActionPreview` | `actions/models.py` | Response model with risk level, warnings, factors |
| `DiffGenerator` | `actions/diff.py` | Generates unified diffs for file changes |

Source: [src/agent_polis/actions/__init__.py:1-40](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/__init__.py)

**Action Types Supported:**

The system supports the following action types for interception and preview:

| Action Type | Description |
|-------------|-------------|
| `FILE_WRITE` | Modify existing files |
| `FILE_DELETE` | Delete files |
| `FILE_MOVE` | Move or rename files |
| `FILE_CREATE` | Create new files |
| `DB_QUERY` | Database read operations |
| `DB_EXECUTE` | Database write operations |
| `API_CALL` | External API requests |
| `SHELL_COMMAND` | Shell command execution |
| `CUSTOM` | User-defined action types |

Source: [src/agent_polis/actions/models.py:17-30](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/models.py)

### Governance Module

The Governance module provides policy evaluation, prompt injection scanning, and descriptor integrity checking.

**Components:**

| Component | Purpose |
|-----------|---------|
| `PolicyEvaluator` | Applies rules to actions and returns decisions |
| `PromptInjectionScanner` | Detects prompt injection and risky instructions |
| `DescriptorIntegrityChecker` | Validates MCP tool descriptors with hash pinning |
| `PolicyPresets` | Pre-configured policy packages for common environments |

Source: [src/agent_polis/governance/__init__.py:1-55](https://github.com/agent_polis/impact-preview/blob/main/src/agent_polis/governance/__init__.py)

## Policy System

### Policy Schema

Policies follow a versioned schema with rules, defaults, and metadata. The schema ensures consistent structure across all policy definitions.

```mermaid
graph LR
    A[PolicyConfig] --> B[version: str]
    A --> C[rules: List[PolicyRule]]
    A --> D[defaults: PolicyDefaults]
    A --> E[metadata: Dict]

    B --> F[Schema Validation]
    C --> F
    D --> F
    E --> F

    F --> G[Fail Fast with<br/>Actionable Errors]
```

Source: [src/agent_polis/governance/policy.py:1-60](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/policy.py)

### Policy Evaluation Flow

```mermaid
sequenceDiagram
    participant Action as ActionRequest
    participant Scanner as PromptInjectionScanner
    participant Evaluator as PolicyEvaluator
    participant Result as PolicyResult

    Action->>Scanner: scan_action_request()
    Scanner-->>Evaluator: ScanResult with findings
    Evaluator->>Evaluator: Sort rules by priority
    Evaluator->>Evaluator: Apply match predicates
    Note over Evaluator: Deterministic precedence
    Evaluator->>Result: Return decision + trace

    Result->>Result: Include matched_rule_id
    Result->>Result: Include matched_rule_priority
    Result->>Result: Include matched_rule_specificity
```

Source: [src/agent_polis/actions/service.py:60-80](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/service.py)

### Policy Decisions

The policy evaluator returns one of three decisions:

| Decision | Description | Exit Code (CI) |
|----------|-------------|----------------|
| `allow` | Action can proceed without approval | 0 |
| `require_approval` | Human review needed before execution | 2 |
| `deny` | Action is blocked | 3 |

Source: [src/agent_polis/governance/policy.py:24-30](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/policy.py), [src/agent_polis/ci.py:50-60](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/ci.py)

### Rule Matching

Policy rules support multiple match predicates:

| Predicate | Type | Description |
|-----------|------|-------------|
| `action_types` | `Set[ActionType]` | Match by action category |
| `path_globs` | `List[str]` | Match target paths using glob patterns |
| `target_contains` | `List[str]` | Match if target contains any string |
| `min_risk_level` | `RiskLevel` | Match actions at or above threshold |
| `max_risk_level` | `RiskLevel` | Match actions at or below threshold |

Rules are sorted by priority (lower value = higher precedence), and the first matching rule determines the decision.

Source: [src/agent_polis/governance/policy.py:35-55](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/policy.py)

## Risk Assessment

### Risk Levels

Actions are classified into four risk levels:

| Level | Value | Description |
|-------|-------|-------------|
| `LOW` | 0 | Read operations, safe changes |
| `MEDIUM` | 1 | Write operations to non-critical files |
| `HIGH` | 2 | Operations with broader system impact |
| `CRITICAL` | 3 | Potentially destructive or irreversible changes |

Source: [src/agent_polis/actions/models.py:45-52](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/models.py)

### Risk Factor Calculation

The `ImpactAnalyzer` computes risk based on:
- Action type (file writes are riskier than reads)
- Target path (system directories are higher risk)
- Payload size and content
- Presence of sensitive patterns in target or payload

Source: [src/agent_polis/actions/service.py:30-50](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/service.py)

## Prompt Injection Scanner

The `PromptInjectionScanner` detects prompt injection attacks and risky instructions in action requests. It is intentionally conservative and bounded to prevent abuse.

### Scanner Design

```python
class ScanFinding(BaseModel):
    reason_id: str          # Machine-readable identifier
    severity: ScanSeverity  # LOW, MEDIUM, HIGH, CRITICAL
    message: str            # Human-readable description
    field: str              # Which field was flagged
    snippet: str            # Relevant text excerpt
```

Source: [src/agent_polis/governance/prompt_scanner.py:35-45](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/prompt_scanner.py)

### Severity Mapping

| Scan Severity | Risk Level |
|---------------|------------|
| `LOW` | `LOW` |
| `MEDIUM` | `MEDIUM` |
| `HIGH` | `HIGH` |
| `CRITICAL` | `CRITICAL` |

Source: [src/agent_polis/governance/prompt_scanner.py:20-28](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/prompt_scanner.py)

## Policy Presets

The system includes pre-configured policy presets for common environments:

| Preset | Description | Default Decision |
|--------|-------------|------------------|
| `startup` | General-purpose startup environment | `require_approval` |
| `fintech` | Financial services with strict controls | `require_approval` |
| `games` | Game development with asset iteration | `require_approval` |

Source: [src/agent_polis/governance/presets.py:1-100](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/presets.py)

### Preset Loading

Presets can be loaded programmatically:

```python
from agent_polis.governance import load_policy_preset, list_policy_presets

# List available presets
presets = list_policy_presets()

# Load a specific preset
policy = load_policy_preset("fintech")
```

Source: [src/agent_polis/governance/presets.py:100-150](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/presets.py)

## CI Integration Mode

The CI module provides deterministic, non-interactive evaluation for CI/CD pipelines.

### CI Report Schema

```mermaid
graph TD
    A[CIPolicyReport] --> B[schema_version: "1"]
    A --> C[policy_version: str]
    A --> D[totals: Dict]
    A --> E[top_blocking_reasons: List]
    A --> F[actions: List[CIActionReport]]

    F --> G[action_id: str]
    F --> H[action_type: str]
    F --> H[risk_level: str]
    F --> H[decision: str]
    F --> H[reason_ids: List]
```

Source: [src/agent_polis/ci.py:1-40](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/ci.py)

### Stable Exit Codes

| Exit Code | Meaning |
|-----------|---------|
| 0 | All actions allowed |
| 2 | At least one action requires approval |
| 3 | At least one action denied |

Source: [src/agent_polis/ci.py:45-55](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/ci.py)

## Event Sourcing

The Events module provides an immutable audit trail of all governance actions.

```mermaid
graph LR
    A[DomainEvent] --> B[EventStore]
    B --> C[append_event]
    B --> D[get_events]

    A --> E[EventBus]
    E --> F[publish_event]
    E --> G[subscribe]
```

Source: [src/agent_polis/events/__init__.py:1-20](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/events/__init__.py)

## API Endpoints

The FastAPI application exposes the following endpoint groups:

| Endpoint Group | Prefix | Description |
|----------------|--------|-------------|
| Actions | `/api/v1/actions` | Submit and manage action requests |
| Agents | `/api/v1/agents` | Agent registration and queries |
| Simulations | `/api/v1/simulations` | Sandbox scenario execution |
| Legacy A2A | `/a2a` | Agent-to-Agent protocol (deprecated) |

Source: [src/agent_polis/main.py:50-70](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/main.py)

## Agent Capabilities

The agent exposes its capabilities via `/.well-known/agent.json`:

```json
{
  "capabilities": [
    "impact_preview",
    "action_approval",
    "file_diff",
    "audit_trail"
  ],
  "protocol": "a2a/1.0",
  "version": "0.2.2"
}
```

Source: [src/agent_polis/main.py:20-35](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/main.py)

## MCP Server Integration

The Model Context Protocol server provides tool interfaces for AI agents:

| Tool | Purpose |
|------|---------|
| `preview_file_write` | Preview file modifications |
| `preview_file_delete` | Preview file deletions |
| `preview_file_create` | Preview new file creation |

Source: [src/agent_polis/mcp_server.py:50-120](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/mcp_server.py)

## Simulations Module

The Simulations module provides sandboxed testing for scenarios before committing:

```mermaid
graph TD
    A[SimulationCreate] --> B[SimulationService]
    B --> C[Sandbox Execution]
    C --> D[SimulationResult]
    D --> E[SimulationResponse]
```

Source: [src/agent_polis/simulations/__init__.py:1-25](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/simulations/__init__.py)

## Integrations

### CrewAI Integration

Provides an `AgentPolisTool` for CrewAI agents to run simulations:

```python
from agent_polis.integrations.crewai import AgentPolisTool

tool = AgentPolisTool(
    api_url="http://localhost:8000",
    api_key="your-api-key"
)
```

Source: [src/agent_polis/integrations/__init__.py:1-15](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/integrations/__init__.py)

## Data Flow Summary

```mermaid
graph TD
    subgraph Request Flow
        R1[Agent Request] --> R2[ActionRequest]
        R2 --> R3[ImpactAnalyzer]
        R3 --> R4[ActionPreview]
    end

    subgraph Governance Flow
        R2 --> G1[PromptInjectionScanner]
        G1 --> G2[ScanResult]
        R2 --> G3[PolicyEvaluator]
        G2 --> G3
        G3 --> G4[PolicyResult]
    end

    subgraph Response Flow
        R4 --> E1[ActionPreviewGenerated Event]
        G4 --> E1
        E1 --> E2[Audit Trail]
    end
```

## Configuration

The application reads configuration from environment variables:

| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `DATABASE_URL` | Yes | - | PostgreSQL or MySQL connection |
| `REDIS_URL` | No | `redis://localhost:6379/0` | Redis for caching |
| `FREE_TIER_ACTIONS_PER_MONTH` | No | - | Rate limiting threshold |
| `LOG_LEVEL` | No | `INFO` | Logging verbosity |

Source: [README.md](https://github.com/agent-polis/impact-preview/blob/main/README.md)

## Related Documentation

- [Policy Schema and Parser (AP-101)](https://github.com/agent-polis/impact-preview/issues/1)
- [Policy Evaluator (AP-102)](https://github.com/agent-polis/impact-preview/issues/2)
- [Prompt Injection Scanner (AP-104)](https://github.com/agent-polis/impact-preview/issues/4)
- [Policy Presets (AP-201, AP-202)](https://github.com/agent-polis/impact-preview/issues/7)
- [CI Integration (AP-203, AP-204)](https://github.com/agent-polis/impact-preview/issues/9)

---

<a id='page-data-flow'></a>

## Data Flow and Models

### Related Pages

Related topics: [System Architecture](#page-system-architecture), [Actions Module](#page-actions-module), [Governance and Policy](#page-governance-policy)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [src/agent_polis/actions/models.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/models.py)
- [src/agent_polis/actions/service.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/service.py)
- [src/agent_polis/governance/policy.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/policy.py)
- [src/agent_polis/governance/prompt_scanner.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/prompt_scanner.py)
- [src/agent_polis/ci.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/ci.py)
- [src/agent_polis/governance/presets.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/presets.py)
- [src/agent_polis/simulations/models.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/simulations/models.py)
</details>

# Data Flow and Models

This page documents the core data models and information flow in Agent Polis, covering the action lifecycle, policy evaluation pipeline, CI reporting schema, and how components integrate through well-defined Pydantic models.

## Overview

The data layer of impact-preview is organized around two primary concerns:

1. **Action Lifecycle** – How proposed agent actions are captured, analyzed, evaluated, and executed
2. **Governance Pipeline** – How policies, scanners, and presets shape decisions on those actions

All models are Pydantic-based, ensuring type safety, serialization to JSON, and runtime validation at API boundaries. Source: [src/agent_polis/actions/models.py:1-30]()

## Core Enumerations

Three enums drive classification throughout the system.

### ActionType

Represents the category of an intercepted action. Source: [src/agent_polis/actions/models.py:21-30]()

| Value | Meaning |
|-------|---------|
| `FILE_WRITE` | Modifying an existing file |
| `FILE_DELETE` | Removing a file |
| `FILE_MOVE` | Relocating a file |
| `FILE_CREATE` | Creating a new file |
| `DB_QUERY` | Read-only database query |
| `DB_EXECUTE` | Database write or DDL operation |
| `API_CALL` | External HTTP request |
| `SHELL_COMMAND` | OS-level command execution |
| `CUSTOM` | Extension point for user-defined types |

### ApprovalStatus

Tracks where an action stands in the human-review workflow. Source: [src/agent_polis/actions/models.py:42-51]()

| Value | Meaning |
|-------|---------|
| `PENDING` | Awaiting human review |
| `APPROVED` | Human explicitly approved |
| `REJECTED` | Human explicitly rejected |
| `MODIFIED` | Human modified then approved |
| `EXECUTED` | Action completed successfully |
| `FAILED` | Execution encountered an error |
| `TIMED_OUT` | No response within the configured timeout |
| `CANCELLED` | Agent withdrew the request |

### RiskLevel

Conveys the potential blast radius of a proposed action. Source: [src/agent_polis/actions/models.py:54-58]()

| Value | Ordinal | Typical triggers |
|-------|---------|------------------|
| `LOW` | 0 | Read operations, safe changes |
| `MEDIUM` | 1 | Write operations to non-critical files |
| `HIGH` | 2 | Write operations with broad impact |
| `CRITICAL` | 3 | System-wide or irreversible changes |

The numeric ordinal is used internally by the policy evaluator to enforce `min_risk_level` and `max_risk_level` constraints in rules. Source: [src/agent_polis/governance/policy.py:19-22]()

## Action Data Models

### ActionRequest

The canonical input to the impact-preview pipeline. Agents submit this to request a preview and, optionally, approval. Source: [src/agent_polis/actions/models.py:62-79]()

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `id` | `UUID` | Auto | Unique identifier for the action request |
| `action_type` | `ActionType` | Yes | Category of the action |
| `description` | `str` | Yes | Human-readable summary of intent |
| `target` | `str` | Yes | Path, URL, or resource identifier |
| `payload` | `dict[str, Any]` | No | Action-specific data (e.g., file content, query params) |
| `context` | `dict[str, Any]` | No | Caller-supplied metadata for audit and evaluation |
| `timeout_seconds` | `int` | No | Approval timeout in seconds |
| `auto_approve_if_low_risk` | `bool` | No | Skip human review for low-risk actions |
| `callback_url` | `str` | No | Webhook URL for async status updates |

### ActionPreview

Returned by the ImpactAnalyzer after examining the request. This is the human-readable "what will change" artifact. Source: [src/agent_polis/actions/models.py:81-102]()

| Field | Type | Description |
|-------|------|-------------|
| `risk_level` | `RiskLevel` | Assessed risk of the action |
| `affected_count` | `int` | Number of entities (files, records, etc.) affected |
| `warnings` | `list[str]` | Non-blocking notices for the reviewer |
| `risk_factors` | `list[str]` | Contributing reasons for the risk level |
| `summary` | `str` | One-paragraph description of the expected outcome |
| `diff` | `FileChange \| None` | Structured diff for file operations |

### FileChange

Carries the before/after view for file-system actions. Source: [src/agent_polis/actions/models.py:127-141]()

| Field | Type | Description |
|-------|------|-------------|
| `path` | `str` | Absolute or relative file path |
| `operation` | `str` | One of: `create`, `modify`, `delete`, `move` |
| `old_content` | `str \| None` | Content before the change (null for creates) |
| `new_content` | `str \| None` | Content after the change (null for deletes) |
| `old_hash` | `str \| None` | SHA-256 of the old content |
| `new_hash` | `str \| None` | SHA-256 of the new content |

## Governance Data Models

### PolicyDecision

The three possible outcomes from policy evaluation. Source: [src/agent_polis/governance/policy.py:15-20]()

| Value | Meaning |
|-------|---------|
| `ALLOW` | Action may proceed without further review |
| `DENY` | Action is blocked outright |
| `REQUIRE_APPROVAL` | Human reviewer must explicitly approve |

### PolicyRule

A single matching rule within a PolicyConfig. Rules are sorted by priority (lower integer = higher precedence), and evaluation stops at the first match. Source: [src/agent_polis/governance/policy.py:43-63]()

| Field | Type | Description |
|-------|------|-------------|
| `id` | `str` | Unique rule identifier |
| `description` | `str \| None` | Human-readable explanation |
| `decision` | `PolicyDecision` | Outcome when rule matches |
| `priority` | `int` | Lower values take precedence (default 100) |
| `enabled` | `bool` | Whether the rule is active |
| `action_types` | `set[ActionType]` | Match by action category |
| `path_globs` | `list[str]` | Match by file path pattern |
| `target_contains` | `list[str]` | Match if target string contains any substring |
| `min_risk_level` | `RiskLevel \| None` | Match actions at or above this risk |
| `max_risk_level` | `RiskLevel \| None` | Match actions at or below this risk |
| `metadata` | `dict[str, Any]` | Arbitrary key-value data (e.g., rationale) |

### PolicyEvaluationResult

Returned by the PolicyEvaluator after running all rules. Source: [src/agent_polis/governance/policy.py:106-114]()

| Field | Type | Description |
|-------|------|-------------|
| `decision` | `PolicyDecision` | Final decision |
| `matched_rule_id` | `str \| None` | ID of the rule that produced the decision |
| `matched_rule_priority` | `int \| None` | Priority of the matched rule |
| `matched_rule_specificity` | `int \| None` | Count of predicates that matched |
| `trace` | `list[str]` | Debug log of rule evaluation steps |

This result is persisted into the audit trail so that decisions are fully traceable. Source: [src/agent_polis/actions/service.py:63-70]()

## Scanner Data Models

### ScanSeverity

Matches the PolicyDecision scale for direct alignment with policy rules.

| Value | Maps to RiskLevel |
|-------|-------------------|
| `LOW` | `LOW` |
| `MEDIUM` | `MEDIUM` |
| `HIGH` | `HIGH` |
| `CRITICAL` | `CRITICAL` |

Source: [src/agent_polis/governance/prompt_scanner.py:17-23]()

### ScanFinding

A single finding from the prompt-injection scanner. Findings are aggregated into a ScanResult and forwarded to both the preview and the audit trail. Source: [src/agent_polis/governance/prompt_scanner.py:44-50]()

| Field | Type | Description |
|-------|------|-------------|
| `reason_id` | `str` | Machine-readable identifier for the pattern |
| `severity` | `ScanSeverity` | Severity of the finding |
| `message` | `str` | Human-readable explanation |
| `field` | `str` | Which field of the ActionRequest triggered the finding |
| `snippet` | `str` | The specific text segment that matched |

## CI Report Models

The CI module produces machine-readable JSON reports for PR gate integrations. Source: [src/agent_polis/ci.py:31-45]()

### CIPolicyReport (Top-level)

| Field | Type | Description |
|-------|------|-------------|
| `schema_version` | `Literal["1"]` | Version marker for forward compatibility |
| `policy_version` | `str` | Version string of the policy that was evaluated |
| `totals` | `dict[str, int]` | Counts per decision: `allow`, `require_approval`, `deny` |
| `top_blocking_reasons` | `list[CIReasonCount]` | Sorted list of the most-frequent denial reasons |
| `actions` | `list[CIActionReport]` | Per-action evaluation details |

### CIActionReport (Per-action)

| Field | Type | Description |
|-------|------|-------------|
| `index` | `int` | Original position of the action in the input list |
| `action_type` | `str` | Action type string |
| `target` | `str` | Target resource |
| `decision` | `PolicyDecision` | Policy decision for this action |
| `risk_level` | `RiskLevel` | Assessed risk level |
| `max_scanner_severity` | `ScanSeverity \| None` | Highest scanner finding |
| `reason_ids` | `list[str]` | All scanner `reason_id` values found |
| `rule_id` | `str \| None` | Policy rule that matched |

### Stable Exit Codes

The CI module maps decisions to deterministic exit codes for shell-based gating. Source: [src/agent_polis/ci.py:47-56]()

| Exit Code | Meaning |
|-----------|---------|
| `0` | All actions allowed |
| `2` | At least one action requires approval (blocked in CI) |
| `3` | At least one action denied |

## Data Flow

The following diagram shows how a single action request flows through the system from submission to audit persistence.

```mermaid
graph TD
    A[ActionRequest] --> B[ImpactAnalyzer]
    B --> C[ActionPreview]
    B --> D[Risk Assessment]
    
    A --> E[PromptInjectionScanner]
    E --> F[ScanResult]
    
    A --> G[PolicyEvaluator]
    H[PolicyConfig] --> G
    G --> I[PolicyEvaluationResult]
    
    C --> J[ActionService]
    F --> J
    I --> J
    
    J --> K[ActionPreviewGenerated Event]
    J --> L[Audit Trail Record]
    
    M[AuditStore] --> N[Event Store]
    K --> N
    L --> N
```

## Policy Evaluation Flow

Policy evaluation uses deterministic precedence: rules are sorted by ascending priority, and evaluation stops at the first matching rule. If no rule matches, the policy default is applied. Source: [src/agent_polis/governance/policy.py:86-100]()

```mermaid
graph LR
    A[ActionRequest] --> B[Sort Rules by Priority]
    B --> C{Does Rule Match?}
    
    subgraph Evaluation Loop
        C -- Yes --> D[Record Match]
        D --> E[Return Decision]
        C -- No --> F{Next Rule Exists?}
        F -- Yes --> C
        F -- No --> G[Apply Default Decision]
    end
    
    G --> H[PolicyEvaluationResult with trace]
    E --> H
```

## Preset Infrastructure

Presets are pre-built PolicyConfig dictionaries for common environments. They encode environment-specific risk thresholds and rationale metadata. Source: [src/agent_polis/governance/presets.py:1-50]()

| Preset ID | Target Environment | Default Decision | Notable Rules |
|-----------|-------------------|-------------------|---------------|
| `startup` | Early-stage products | `REQUIRE_APPROVAL` | Allows docs/tests at medium risk; requires approval for shell commands |
| `fintech` | Financial services | `REQUIRE_APPROVAL` | Denies secrets/keys patterns; blocks critical risk; requires approval for DB writes |
| `games` | Game development | `REQUIRE_APPROVAL` | Similar to startup; tighter constraints on production assets |

Presets are loaded by ID via `load_policy_preset()`, validated against the PolicyConfig schema, and their metadata is exposed for downstream UI display. Source: [src/agent_polis/governance/presets.py:100-120]()

## Related Documentation

| Topic | Description |
|-------|-------------|
| [Policy Schema and Parser](https://github.com/agent-polis/impact-preview/issues/1) | AP-101 – schema design, validation, and error messages |
| [Policy Evaluator](https://github.com/agent-polis/impact-preview/issues/2) | AP-102 – deterministic precedence and trace emission |
| [Audit Record Extensions](https://github.com/agent-polis/impact-preview/issues/5) | AP-105 – persisting decision metadata in audit output |
| [CI Policy Report](https://github.com/agent-polis/impact-preview/issues/9) | AP-203 – machine-readable report schema for CI integrations |
| [CI Evaluation Mode](https://github.com/agent-polis/impact-preview/issues/10) | AP-204 – deterministic CI mode without prompts |

---

<a id='page-actions-module'></a>

## Actions Module

### Related Pages

Related topics: [Data Flow and Models](#page-data-flow), [Governance and Policy](#page-governance-policy), [MCP Server Integration](#page-mcp-server)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [src/agent_polis/actions/__init__.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/__init__.py)
- [src/agent_polis/actions/models.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/models.py)
- [src/agent_polis/actions/analyzer.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/analyzer.py)
- [src/agent_polis/actions/router.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/router.py)
- [src/agent_polis/actions/service.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/service.py)
- [src/agent_polis/actions/diff.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/diff.py)
- [migrations/versions/20260130_002_add_actions_table.py](https://github.com/agent-polis/impact-preview/blob/main/migrations/versions/20260130_002_add_actions_table.py)
</details>

# Actions Module

The Actions Module is the core system of Agent Polis, providing an approval-gated workflow for AI agent operations. It intercepts proposed actions from AI agents, generates impact previews showing exactly what will change, and enforces governance policies before execution.

## Overview

The module serves as a governance layer that:

- Receives proposed actions from AI agents via API
- Generates human-readable impact previews with risk assessment
- Manages an approval workflow with states: pending → approved/rejected → executed
- Enforces policy decisions (allow, deny, require_approval)
- Records audit trails for all governance decisions
- Integrates with CI systems for deterministic policy evaluation

Source: [src/agent_polis/actions/__init__.py:1-46]()

## Architecture

```mermaid
graph TD
    A[AI Agent] -->|ActionRequest| B[Action Router]
    B --> C[ActionService]
    C --> D[ImpactAnalyzer]
    C --> E[PolicyEvaluator]
    C --> F[PromptScanner]
    D --> G[DiffGenerator]
    C --> H[EventStore]
    C --> I[Database]
    
    G --> J[ActionPreview]
    E --> K[PolicyResult]
    F --> L[ScanResult]
    
    J --> M[ActionResponse]
    K --> M
    L --> M
```

### Component Responsibilities

| Component | File | Responsibility |
|-----------|------|----------------|
| Router | `router.py` | FastAPI endpoints for action CRUD and approval |
| Service | `service.py` | Orchestrates analysis, policy, and audit |
| Analyzer | `analyzer.py` | Generates impact previews and risk assessment |
| Models | `models.py` | Pydantic schemas for all action data structures |
| Diff | `diff.py` | Generates unified diffs and file change summaries |

Source: [src/agent_polis/actions/router.py:1-35]()

## Data Models

### ActionType Enum

Defines the types of actions the system can intercept:

| Value | Description |
|-------|-------------|
| `FILE_WRITE` | Modifying existing files |
| `FILE_DELETE` | Removing files |
| `FILE_MOVE` | Relocating files |
| `FILE_CREATE` | Creating new files |
| `DB_QUERY` | Database read operations |
| `DB_EXECUTE` | Database write operations |
| `API_CALL` | External API requests |
| `SHELL_COMMAND` | System command execution |
| `CUSTOM` | User-defined action types |

Source: [src/agent_polis/actions/models.py:21-32]()

### ApprovalStatus Enum

Tracks the lifecycle state of an action:

| Value | Description |
|-------|-------------|
| `PENDING` | Awaiting human review |
| `APPROVED` | Human approved the action |
| `REJECTED` | Human rejected the action |
| `MODIFIED` | Human modified then approved |
| `EXECUTED` | Action was successfully executed |
| `FAILED` | Execution failed |
| `TIMED_OUT` | No response within timeout |
| `CANCELLED` | Agent cancelled the request |

Source: [src/agent_polis/actions/models.py:35-45]()

### RiskLevel Enum

Risk assessment levels for proposed actions:

| Value | Description |
|-------|-------------|
| `LOW` | Read operations, safe changes |
| `MEDIUM` | Write operations to non-critical files |
| `HIGH` | Elevated risk operations |
| `CRITICAL` | Potentially destructive operations |

Source: [src/agent_polis/actions/models.py:48-53]()

### Core Request/Response Models

```python
class ActionRequest(BaseModel):
    action_type: ActionType
    description: str
    target: str                    # File path, DB query, etc.
    payload: dict[str, Any]        # Action-specific data
    context: dict[str, Any] | None
    timeout_seconds: int = 300
    auto_approve_if_low_risk: bool = False
    callback_url: str | None

class ActionPreview(BaseModel):
    file_changes: list[FileChange]
    risk_level: RiskLevel
    risk_factors: list[str]
    summary: str
    affected_count: int
    warnings: list[str]
    is_reversible: bool
    reversal_instructions: str | None

class ActionResponse(BaseModel):
    id: UUID
    action_type: ActionType
    status: ApprovalStatus
    target: str
    preview: ActionPreview | None
    # ... additional fields
```

Source: [src/agent_polis/actions/models.py:56-95]()

## Workflow State Machine

```mermaid
stateDiagram-v2
    [*] --> PENDING: Submit Action
    PENDING --> APPROVED: Human Approves
    PENDING --> REJECTED: Human Rejects
    PENDING --> MODIFIED: Human Modifies
    PENDING --> CANCELLED: Agent Cancels
    PENDING --> TIMED_OUT: Timeout Exceeded
    APPROVED --> EXECUTED: Execute Success
    APPROVED --> FAILED: Execute Error
    MODIFIED --> EXECUTED: Execute Success
    MODIFIED --> FAILED: Execute Error
    EXECUTED --> [*]
    FAILED --> [*]
    TIMED_OUT --> [*]
    CANCELLED --> [*]
    REJECTED --> [*]
```

## API Endpoints

### Router: `/api/v1/actions`

| Method | Endpoint | Description |
|--------|----------|-------------|
| `POST` | `/` | Submit a proposed action for approval |
| `GET` | `/` | List actions with filtering and pagination |
| `GET` | `/{id}` | Get a specific action by ID |
| `GET` | `/pending` | List all pending actions |
| `POST` | `/{id}/approve` | Approve a pending action |
| `POST` | `/{id}/reject` | Reject a pending action |
| `POST` | `/{id}/execute` | Execute an approved action |
| `DELETE` | `/{id}` | Cancel a pending action |

Source: [src/agent_polis/actions/router.py:35-80]()

### Submit Action Endpoint

```
POST /api/v1/actions/
```

**Request Body:**

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `action_type` | ActionType | Yes | Type of action being proposed |
| `description` | string | Yes | Human-readable description |
| `target` | string | Yes | Target resource (path, query, etc.) |
| `payload` | object | Yes | Action-specific data |
| `context` | object | No | Additional context for analysis |
| `timeout_seconds` | integer | No | Timeout for approval (default: 300) |
| `auto_approve_if_low_risk` | boolean | No | Auto-approve low-risk actions |
| `callback_url` | string | No | URL to notify on status change |

**Response:** `ActionResponse` with embedded `ActionPreview`

Source: [src/agent_polis/actions/router.py:37-65]()

## Impact Analyzer

The `ImpactAnalyzer` class generates previews showing exactly what will change if an action is approved.

### Analysis Flow

```mermaid
graph LR
    A[ActionRequest] --> B{action_type}
    B -->|FILE_WRITE| C[Read Current File]
    B -->|FILE_CREATE| D[Generate Preview]
    B -->|FILE_DELETE| E[Read File Metadata]
    B -->|SHELL_COMMAND| F[Parse Command]
    B -->|DB_QUERY| G[Preview Query Plan]
    
    C --> H[Generate Unified Diff]
    D --> H
    E --> H
    
    H --> I[Calculate Risk Level]
    I --> J[Identify Risk Factors]
    
    J --> K[ActionPreview]
```

### Risk Factor Detection

The analyzer identifies risk factors based on:

1. **File patterns**: Sensitive paths like `*.pem`, `*.env`, `credentials/`
2. **Operation type**: Shell commands are highest risk by default
3. **Dangerous commands**: `rm`, `dd`, `mkfs`, `format` elevate to CRITICAL
4. **Privilege escalation**: Commands with `sudo` are flagged
5. **Reversibility**: Destructive operations are marked non-reversible

Source: [src/agent_polis/actions/analyzer.py:1-200]()

### Risk Assessment Logic

```python
# High-risk operations
if "sudo" in command.lower() or "admin" in command.lower():
    risk_level = RiskLevel.CRITICAL

# Dangerous commands
dangerous_commands = ["rm", "rmdir", "del", "format", "dd", "mkfs"]
if any(cmd in command.lower() for cmd in dangerous_commands):
    risk_level = RiskLevel.CRITICAL
```

Source: [src/agent_polis/actions/analyzer.py:145-158]()

## Diff Generation

The diff module provides multiple output formats for file changes:

| Function | Purpose |
|----------|---------|
| `generate_unified_diff()` | Standard unified diff format |
| `generate_file_change()` | Structured file change object |
| `format_diff_terminal()` | Terminal-friendly colored output |
| `format_diff_plain()` | Plain text without colors |
| `format_diff_summary()` | Brief summary of changes |

Source: [src/agent_polis/actions/diff.py:1-50]()

## Action Service

The `ActionService` class orchestrates the entire action lifecycle:

### Service Operations

| Method | Description |
|--------|-------------|
| `submit()` | Submit new action, run analysis and policy |
| `get()` | Retrieve action by ID |
| `list_pending()` | Get all pending actions |
| `approve()` | Approve a pending action |
| `reject()` | Reject with optional reason |
| `execute()` | Execute an approved action |
| `cancel()` | Cancel a pending action |

Source: [src/agent_polis/actions/service.py:1-100]()

### Audit Trail Integration

Every action submission records:

1. **Scanner findings**: Prompt injection and risky instruction detection
2. **Policy evaluation**: Decision, matched rule ID, priority, specificity
3. **Trace payload**: Full decision tree for debugging

```python
# From service.py - audit recording
scan_result = _audit_scanner.scan_action_request(audit_request)
policy_result = _policy_evaluator.evaluate(policy, audit_request, risk_level=preview.risk_level)

governance = {
    "policy": {
        "version": policy.version,
        "decision": policy_result.decision.value,
        "matched_rule_id": policy_result.matched_rule_id,
        "matched_rule_priority": policy_result.matched_rule_priority,
        "trace": policy_result.trace,
    },
    "scanner": {
        "max_severity": scan_result.max_severity().value,
        "reason_ids": sorted({f.reason_id for f in scan_result.findings}),
    }
}
```

Source: [src/agent_polis/actions/service.py:45-70]()

## Database Schema

Actions are persisted in PostgreSQL with the following structure:

```sql
CREATE TABLE actions (
    -- Identity
    id UUID PRIMARY KEY,
    agent_id UUID NOT NULL,
    
    -- Action details
    action_type VARCHAR(50) NOT NULL,
    description TEXT NOT NULL,
    target TEXT NOT NULL,
    payload JSONB DEFAULT '{}',
    context TEXT,
    
    -- Status
    status VARCHAR(20) DEFAULT 'pending',
    
    -- Preview/analysis results
    preview JSONB,
    risk_level VARCHAR(20),
    
    -- Timestamps
    created_at TIMESTAMP,
    updated_at TIMESTAMP,
    expires_at TIMESTAMP
);
```

Source: [migrations/versions/20260130_002_add_actions_table.py:25-45]()

## Integration with CI Systems

The Actions module supports deterministic CI evaluation mode (see [AP-204](https://github.com/agent-polis/impact-preview/issues/10)):

```mermaid
graph LR
    A[CI Pipeline] --> B[Load Actions JSON]
    B --> C[Evaluate Policies]
    C --> D[Generate Report]
    D --> E[Exit Code by Decision]
    
    E -->|allow| F[Exit 0]
    E -->|require_approval| G[Exit 1]
    E -->|deny| H[Exit 2]
```

### Machine-Readable Report Schema

The CI report includes:

- `policy_version`: Version of policy used
- `totals`: Count by decision type
- `top_blocking_reasons`: Sorted list of blocking reasons
- `actions`: Individual action results with governance data

This supports AP-203 requirements for PR gate integrations.

Source: [src/agent_polis/ci.py:1-50]()

## Streamlit UI

The module includes a Streamlit demo interface (`src/agent_polis/ui/app.py`) that provides:

- Action list with status filtering
- Detailed action view with preview/diff
- Approval/rejection workflow
- Risk level visualization
- Agent information display

Source: [src/agent_polis/ui/app.py:1-100]()

## Usage Example

```python
from agent_polis.actions import ActionService, ActionRequest, ActionType

# Create action request
request = ActionRequest(
    action_type=ActionType.FILE_WRITE,
    description="Update configuration file",
    target="/app/config.yaml",
    payload={"content": "new: value"},
)

# Submit for approval
service = ActionService(db_session)
action, preview = await service.submit(request, agent)

# Check preview
print(f"Risk: {preview.risk_level}")
print(f"Changes: {preview.affected_count}")
print(f"Summary: {preview.summary}")

# Approve and execute
await service.approve(action.id, agent)
await service.execute(action.id)
```

## Module Exports

```python
from agent_polis.actions import (
    # Models
    ActionType,
    ApprovalStatus,
    ActionRequest,
    ActionPreview,
    ActionResponse,
    RiskLevel,
    FileChange,
    
    # Core
    ActionService,
    ImpactAnalyzer,
    get_analyzer,
    
    # Utilities
    generate_unified_diff,
    generate_file_change,
    format_diff_terminal,
    format_diff_plain,
    format_diff_summary,
    
    # Router
    router,
)
```

Source: [src/agent_polis/actions/__init__.py:15-46]()

## Related Documentation

- **Policy System**: Actions are governed by policies defined in `src/agent_polis/governance/policy.py`
- **Presets**: Pre-configured policy sets for [startup, fintech, games environments](https://github.com/agent-polis/impact-preview/issues/8)
- **CI Integration**: Deterministic evaluation mode for [CI pipelines](https://github.com/agent-polis/impact-preview/issues/10)
- **Audit Records**: Extended with [policy/scanner context](https://github.com/agent-polis/impact-preview/issues/5)

---

<a id='page-governance-policy'></a>

## Governance and Policy

### Related Pages

Related topics: [Actions Module](#page-actions-module), [Security Scanners](#page-security-scanners), [CI Integration](#page-ci-integration)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [src/agent_polis/governance/policy.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/policy.py)
- [src/agent_polis/governance/presets.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/presets.py)
- [src/agent_polis/governance/__init__.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/__init__.py)
- [src/agent_polis/governance/prompt_scanner.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/prompt_scanner.py)
- [src/agent_polis/ci.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/ci.py)
- [src/agent_polis/actions/service.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/service.py)
</details>

# Governance and Policy

The Governance and Policy system is the security and compliance layer of Agent Polis. It provides deterministic policy evaluation, rule-based decision making, and risk assessment for all agent actions before execution. This module implements the core governance primitives required for safe AI agent operation in production environments.

## Overview

The governance module (`agent_polis.governance`) enforces security policies on agent actions by:

- Evaluating incoming action requests against configurable policy rules
- Determining whether actions should be allowed, denied, or require human approval
- Scanning for prompt injection and risky instructions
- Verifying MCP descriptor integrity through hash pinning
- Generating machine-readable audit reports for CI integration

The system is designed to be deterministic: given the same policy, action request, and risk level, it will always produce the same decision with full traceability.

## Architecture

```mermaid
graph TD
    A[Action Request] --> B[Impact Analyzer]
    B --> C[Risk Level Assessment]
    C --> D[Policy Evaluator]
    C --> E[Prompt Injection Scanner]
    E --> F[Scan Findings]
    D --> G[Policy Decision]
    F --> H[Audit Trail]
    G --> H
    H --> I[CI Report Generator]
    
    J[Policy Config] --> D
    K[Policy Presets] --> J
    
    G --> L{Decision}
    L -->|allow| M[Execute Action]
    L -->|deny| N[Block Action]
    L -->|require_approval| O[Queue for Human Review]
```

## Policy Schema

Policies define the rules governing agent behavior. The schema follows a versioned format with support for defaults, rules, and metadata.

### Schema Structure

```python
PolicyConfig {
    version: str              # Version identifier for the policy
    defaults: PolicyDefaults  # Default behavior when no rules match
    rules: list[PolicyRule]   # Ordered list of matching rules
    metadata: dict[str, Any]  # Optional policy metadata
}
```

Source: [src/agent_polis/governance/policy.py:46-57]()

### PolicyDefaults

When no rules match an incoming action, the system falls back to default behavior:

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `decision` | `PolicyDecision` | `require_approval` | Default decision when no rules match |

Source: [src/agent_polis/governance/policy.py:35-38]()

### PolicyRule

Each rule specifies matching conditions and the resulting decision:

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `id` | `str` | (required) | Unique rule identifier |
| `description` | `str` | `None` | Human-readable rule description |
| `decision` | `PolicyDecision` | (required) | Decision to apply when rule matches |
| `priority` | `int` | `100` | Rule precedence (lower = higher priority) |
| `enabled` | `bool` | `true` | Whether the rule is active |
| `action_types` | `set[ActionType]` | `set()` | Match specific action types |
| `path_globs` | `list[str]` | `[]` | Match file paths using glob patterns |
| `target_contains` | `list[str]` | `[]` | Match target strings containing these values |
| `min_risk_level` | `RiskLevel` | `None` | Match actions at or above this risk level |
| `max_risk_level` | `RiskLevel` | `None` | Match actions at or below this risk level |
| `metadata` | `dict[str, Any]` | `{}` | Additional metadata including rationale |

Source: [src/agent_polis/governance/policy.py:41-55]()

### Policy Decisions

Three possible decisions can be returned:

| Decision | Exit Code (CI) | Description |
|----------|----------------|-------------|
| `allow` | `0` | Action is permitted to proceed |
| `deny` | `3` | Action is blocked |
| `require_approval` | `2` | Action requires human review before execution |

Source: [src/agent_polis/governance/policy.py:17-23]()

## Policy Evaluator

The `PolicyEvaluator` class provides deterministic rule evaluation with full tracing capabilities.

### Evaluation Flow

```mermaid
graph LR
    A[Input] --> B[Sort Rules by Priority]
    B --> C{First Matching Rule?}
    C -->|Yes| D[Return Decision + Rule ID]
    C -->|No| E[Apply Default Decision]
    D --> F[Build Trace Payload]
    E --> F
```

### Evaluation Result

The evaluator returns a `PolicyEvaluationResult` containing:

| Field | Type | Description |
|-------|------|-------------|
| `decision` | `PolicyDecision` | The final policy decision |
| `matched_rule_id` | `str \| None` | ID of the first matching rule |
| `matched_rule_priority` | `int \| None` | Priority of the matched rule |
| `matched_rule_specificity` | `int` | Specificity score of the match |
| `trace` | `list[dict]` | Debug information for auditing |

Source: [src/agent_polis/governance/policy.py:88-98]()

### Deterministic Precedence

Rules are evaluated in strict priority order (lowest number = highest priority). The first matching rule wins, ensuring consistent behavior across invocations.

Source: [src/agent_polis/governance/policy.py:101-130]()

## Policy Presets

The system includes pre-built policy presets for common environments. These provide sensible defaults without requiring manual policy configuration.

### Available Presets

| Preset | Description | Default Decision | Key Rules |
|--------|-------------|-------------------|-----------|
| `startup` | General-purpose startup environments | `require_approval` | Deny secrets, allow docs/tests at low risk |
| `fintech` | Regulated financial services | `require_approval` | Deny secrets, deny critical risk, require approval for DB writes |
| `games` | Game development workflows | `require_approval` | Deny secrets, allow assets/docs at medium risk |

Source: [src/agent_polis/governance/presets.py:1-100]()

### Loading Presets

```python
from agent_polis.governance import load_policy_preset, list_policy_presets

# List available presets
presets = list_policy_presets()
# Returns: ["startup", "fintech", "games"]

# Load a specific preset
policy = load_policy_preset("fintech")
```

### Preset Metadata

Each preset includes metadata for downstream UX:

```python
@dataclass
class PolicyPresetMetadata:
    id: str
    name: str
    description: str
    version: str
    environment: str
    default_decision: str
    rule_count: int
```

Source: [src/agent_polis/governance/presets.py:115-122]()

## Prompt Injection Scanner

The `PromptInjectionScanner` detects potentially malicious input patterns in action requests.

### Scanner Design

The scanner is intentionally conservative and bounded to prevent:
- Recursive payload walking (avoids depth crashes)
- Excessive CPU usage (caps text scanning volume)

Source: [src/agent_polis/governance/prompt_scanner.py:1-20]()

### Severity Levels

| Severity | Maps To | Description |
|----------|---------|-------------|
| `LOW` | `RiskLevel.LOW` | Minor concerns, informational |
| `MEDIUM` | `RiskLevel.MEDIUM` | Suspicious patterns detected |
| `HIGH` | `RiskLevel.HIGH` | Likely injection attempt |
| `CRITICAL` | `RiskLevel.CRITICAL` | Definite malicious pattern |

Source: [src/agent_polis/governance/prompt_scanner.py:24-43]()

### Scan Findings

Each finding includes:

| Field | Type | Description |
|-------|------|-------------|
| `reason_id` | `str` | Machine-readable identifier for the finding |
| `severity` | `ScanSeverity` | Severity level of the finding |
| `message` | `str` | Human-readable description |
| `field` | `str` | Which field contained the finding |
| `snippet` | `str` | Relevant text snippet |

Source: [src/agent_polis/governance/prompt_scanner.py:46-54]()

## CI Integration

The CI module (`agent_polis.ci`) provides deterministic policy evaluation for non-interactive environments.

### Machine-Readable Report Schema

```python
CIPolicyReport {
    schema_version: Literal["1"]
    policy_version: str
    totals: dict[str, int]           # Count by decision type
    top_blocking_reasons: list[CIReasonCount]
    actions: list[CIActionReport]
}
```

Source: [src/agent_polis/ci.py:43-49]()

### Exit Codes

| Exit Code | Meaning |
|-----------|---------|
| `0` | All actions allowed |
| `2` | At least one action requires approval |
| `3` | At least one action denied |

Source: [src/agent_polis/ci.py:54-64]()

### Generating CI Reports

```python
from agent_polis.ci import generate_ci_report

report, exit_code = await generate_ci_report(
    actions=[action_request],
    policy=policy_config,
    working_directory="/path/to/project"
)

# report is a CIPolicyReport with model_dump() serialization
# exit_code is suitable for CI gate integration
```

## Audit Trail Integration

Policy decisions and scanner findings are automatically recorded in the audit trail with machine-readable reason IDs.

```mermaid
sequenceDiagram
    participant A as Action Request
    participant S as Scanner
    participant P as Policy Evaluator
    participant E as Event Store
    
    A->>S: scan_action_request()
    S-->>E: ScanResult with reason_ids
    A->>P: evaluate(policy, request, risk_level)
    P-->>E: PolicyEvaluationResult with matched_rule_id
    E->>E: append_event(ActionPreviewGenerated)
```

Source: [src/agent_polis/actions/service.py:80-100]()

### Audit Fields

| Field | Source | Description |
|-------|--------|-------------|
| `policy.version` | Policy config | Version of applied policy |
| `policy.decision` | PolicyEvaluator | Final decision |
| `policy.matched_rule_id` | PolicyEvaluator | ID of matching rule |
| `policy.matched_rule_priority` | PolicyEvaluator | Rule priority |
| `scanner.max_severity` | PromptInjectionScanner | Highest severity found |
| `scanner.reason_ids` | ScanFinding | Sorted unique reason IDs |

## API Reference

### Core Classes

| Class | Module | Purpose |
|-------|--------|---------|
| `PolicyEvaluator` | `governance.policy` | Main policy evaluation engine |
| `PolicyConfig` | `governance.policy` | Policy data model |
| `PolicyRule` | `governance.policy` | Individual rule definition |
| `PromptInjectionScanner` | `governance.prompt_scanner` | Security scanner |
| `DescriptorIntegrityChecker` | `governance.descriptor_integrity` | Hash pinning for MCP descriptors |
| `load_policy_preset` | `governance.presets` | Preset loader function |
| `generate_ci_report` | `ci` | CI report generator |

### Loading Policies

```python
from agent_polis.governance import (
    load_policy_from_file,
    load_policy_from_dict,
    load_policy_preset,
)

# From file
policy = load_policy_from_file("policy.json")

# From dictionary
policy = load_policy_from_dict({"version": "1.0", "rules": [], ...})

# From preset
policy = load_policy_preset("startup")
```

### Evaluating Actions

```python
from agent_polis.governance import PolicyEvaluator, PolicyEvaluationInput

evaluator = PolicyEvaluator()
result = evaluator.evaluate(
    policy=policy_config,
    request=action_request,
    risk_level=RiskLevel.MEDIUM
)

print(result.decision)        # PolicyDecision.DENY
print(result.matched_rule_id) # "deny-secrets"
print(result.trace)           # Debug information
```

## Related Issues

- **AP-101**: Policy schema and parser - Foundation for the policy system
- **AP-102**: Policy evaluator with deterministic precedence - Core evaluation logic
- **AP-103**: MCP descriptor integrity checks - Hash pinning for tool descriptors
- **AP-104**: Prompt-injection scanner - Security scanning implementation
- **AP-105**: Extend audit records with policy/scanner context - Audit trail enhancement
- **AP-201**: Preset infrastructure and loader - Preset system
- **AP-202**: Policy preset packs - Pre-built presets
- **AP-203**: Machine-readable CI report output - CI integration
- **AP-204**: Deterministic CI evaluation mode - Non-interactive mode
- **AP-205**: Stage 2 docs and CI integration examples - Documentation

---

<a id='page-security-scanners'></a>

## Security Scanners

### Related Pages

Related topics: [Governance and Policy](#page-governance-policy)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [src/agent_polis/governance/prompt_scanner.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/prompt_scanner.py)
- [src/agent_polis/governance/descriptor_integrity.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/descriptor_integrity.py)
- [src/agent_polis/actions/service.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/service.py)
- [src/agent_polis/ci.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/ci.py)
- [src/agent_polis/governance/__init__.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/__init__.py)
</details>

# Security Scanners

Security scanners in Agent Polis provide defense-in-depth for AI agent operations by detecting malicious inputs, injection attempts, and integrity violations before actions execute. The system implements two complementary scanning mechanisms: **prompt-injection scanning** for detecting adversarial instructions in task inputs, and **descriptor integrity checking** for verifying MCP tool descriptor integrity through hash pinning.

## Overview

Agent Polis operates as a governance layer between AI agents and their potential actions. Security scanners serve as the first line of defense, analyzing incoming requests for known attack patterns before they reach the policy evaluation stage.

```mermaid
graph TD
    A[Action Request] --> B[Prompt Injection Scanner]
    B --> C{Threats Found?}
    C -->|Yes| D[Flag Findings]
    C -->|No| E[Descriptor Integrity Check]
    E --> F{Descriptor Valid?}
    F -->|Yes| G[Policy Evaluation]
    F -->|No| H[Block Action]
    D --> G
    G --> I[Governance Decision]
    
    style B fill:#ffcccc
    style E fill:#ffe6cc
    style H fill:#ff9999
```

**Related Issues:**
- [AP-104: Prompt-injection and risky-instruction scanner](https://github.com/agent-polis/impact-preview/issues/4) - Core scanner implementation
- [AP-103: MCP descriptor integrity checks](https://github.com/agent-polis/impact-preview/issues/3) - Hash pinning for tool descriptors

## Prompt Injection Scanner

The prompt injection scanner (`PromptInjectionScanner`) is a rule-based security scanner designed to detect adversarial instructions embedded in AI agent task inputs and tool metadata.

### Purpose and Scope

The scanner identifies:
- Instructions attempting to override agent behavior
- Attempts to reveal protected system/developer prompts
- Bypass attempts for safety controls
- Other risky instruction patterns

**Key Design Principles:**
- **Conservative and bounded**: Avoids recursive payload walking to prevent depth crashes
- **CPU-abuse prevention**: Caps scanned text to reduce resource exhaustion risks
- **Deterministic**: Same input always produces same output for predictable CI behavior

Source: [src/agent_polis/governance/prompt_scanner.py:1-20](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/prompt_scanner.py)

### Severity Levels

The scanner classifies findings into four severity tiers:

| Severity | Risk Mapping | Description |
|----------|--------------|-------------|
| `LOW` | `RiskLevel.LOW` | Minor concerns, informational |
| `MEDIUM` | `RiskLevel.MEDIUM` | Moderate risk, review recommended |
| `HIGH` | `RiskLevel.HIGH` | Significant threat, requires attention |
| `CRITICAL` | `RiskLevel.CRITICAL` | Severe attack attempt, should block |

Source: [src/agent_polis/governance/prompt_scanner.py:23-45](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/prompt_scanner.py)

### Detection Rules

The scanner ships with a default rule set targeting common prompt injection techniques:

| Reason ID | Severity | Pattern Target |
|-----------|----------|----------------|
| `prompt_injection.ignore_instructions` | CRITICAL | "ignore all previous instructions" variants |
| `prompt_injection.exfiltrate_system_prompt` | HIGH | Attempts to reveal system/developer prompts |
| `prompt_injection.bypass_safety_controls` | HIGH | Attempts to disable safety mechanisms |
| `risky_instruction.*` | Varies | Additional risky instruction patterns |

**Example Rule Pattern:**
```python
_ScannerRule(
    reason_id="prompt_injection.ignore_instructions",
    severity=ScanSeverity.CRITICAL,
    message="Instruction override attempt detected",
    pattern=re.compile(
        r"\bignore\s+(all\s+)?(previous|prior|above)\s+"
        r"(instructions?|prompts?)\b",
        flags=re.IGNORECASE,
    ),
)
```

Source: [src/agent_polis/governance/prompt_scanner.py:85-105](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/prompt_scanner.py)

### Resource Bounds

To prevent denial-of-service through malicious payloads, the scanner enforces strict limits:

| Parameter | Default Value | Purpose |
|-----------|---------------|---------|
| `DEFAULT_MAX_TEXT_CHARS` | 20,000 | Maximum text length scanned |
| `DEFAULT_MAX_PAYLOAD_STRINGS` | 500 | Maximum strings extracted from payload |
| `DEFAULT_MAX_PAYLOAD_DEPTH` | 32 | Maximum nested depth for payload traversal |

These bounds ensure scanning remains predictable for untrusted inputs while preventing resource exhaustion attacks.

Source: [src/agent_polis/governance/prompt_scanner.py:67-72](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/prompt_scanner.py)

### Scan Result Model

Results are returned as structured `ScanResult` objects containing individual findings:

```python
class ScanFinding(BaseModel):
    reason_id: str          # Machine-readable identifier
    severity: ScanSeverity  # Classification level
    message: str            # Human-readable description
    field: str              # Which field contained the threat
    snippet: str            # Matched text snippet
```

The `ScanResult` class provides aggregation methods:

```python
def max_severity(self) -> ScanSeverity:
    """Return the highest severity observed across findings."""

def max_risk_level(self) -> RiskLevel:
    """Return the highest risk level implied by findings."""

def to_risk_factors(self) -> list[str]:
    """Render findings as risk factors compatible with preview output."""
```

Source: [src/agent_polis/governance/prompt_scanner.py:47-82](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/prompt_scanner.py)

## Descriptor Integrity Checker

The descriptor integrity checker provides hash-based verification for MCP tool descriptors, ensuring that tool definitions have not been tampered with or replaced by malicious third-party descriptors.

### Purpose and Scope

When agents use MCP (Model Context Protocol) tools, the tool descriptors define what actions the tools can perform. An attacker could potentially:
- Replace a legitimate tool descriptor with a malicious one
- Modify descriptor parameters to expand attack surface
- Inject tools that exfiltrate data or bypass controls

The integrity checker detects these scenarios by:
1. Computing a canonical hash of the descriptor
2. Comparing against an allowlist of known-good hashes
3. Failing closed (blocking) on mismatch

Source: [src/agent_polis/governance/descriptor_integrity.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/descriptor_integrity.py)

### Hash Computation

The checker uses deterministic canonicalization to ensure the same descriptor always produces the same hash:

```python
def canonicalize_descriptor(descriptor: dict) -> str:
    """Normalize descriptor for consistent hashing."""

def compute_descriptor_hash(descriptor: dict) -> str:
    """Compute hash of a descriptor."""

def normalize_hash_pin(hash_pin: str) -> str:
    """Normalize hash pin format for comparison."""
```

This approach prevents hash mismatches due to formatting differences while detecting actual content tampering.

Source: [src/agent_polis/governance/descriptor_integrity.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/descriptor_integrity.py)

### Policy-Based Allowlist

The descriptor integrity system uses a policy model:

```python
class DescriptorIntegrityPolicy(BaseModel):
    """Policy for descriptor integrity checks."""
    
class DescriptorIntegrityResult(BaseModel):
    """Result of descriptor integrity verification."""
    
class DescriptorIntegrityChecker:
    """Performs descriptor integrity verification."""
```

Policies can be loaded from:
- Dictionary: `load_descriptor_integrity_policy_from_dict(data)`
- File: `load_descriptor_integrity_policy_from_file(path)`

Source: [src/agent_polis/governance/descriptor_integrity.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/descriptor_integrity.py)

## Integration with Audit Trail

Scanner results feed directly into the audit trail, satisfying requirement AP-105 for extended audit records with policy/scanner context.

### Audit Event Recording

In the action service, scanner results are recorded alongside policy decisions:

```python
scan_result = _audit_scanner.scan_action_request(audit_request)

event = ActionPreviewGenerated(
    stream_id=f"action:{action.id}",
    data={
        # ... other fields ...
        "governance": {
            "scanner": {
                "max_severity": scan_result.max_severity().value,
                "reason_ids": sorted({f.reason_id for f in scan_result.findings}),
                "findings": [ /* detailed findings */ ],
            },
        },
    },
)
```

Source: [src/agent_polis/actions/service.py:1-50](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/service.py)

### CI Report Output

Scanner findings are included in machine-readable CI policy reports per AP-203:

```python
scanner_reason_ids = sorted({
    f.reason_id 
    for f in scan_result.findings
})

report = CIPolicyReport(
    policy_version=policy.version,
    totals=totals,
    top_blocking_reasons=top_reasons,
    actions=action_reports,  # Contains scanner_max_severity, scanner_reason_ids
)
```

Source: [src/agent_polis/ci.py:1-80](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/ci.py)

## Module Exports

The governance module exports all scanner components:

```python
from agent_polis.governance import (
    # Descriptor Integrity
    DescriptorIntegrityChecker,
    DescriptorIntegrityPolicy,
    DescriptorIntegrityResult,
    canonicalize_descriptor,
    compute_descriptor_hash,
    normalize_hash_pin,
    
    # Prompt Scanner
    PromptInjectionScanner,
    ScanFinding,
    ScanResult,
    ScanSeverity,
    severity_to_risk_level,
)
```

Source: [src/agent_polis/governance/__init__.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/__init__.py)

## Usage Example

### Scanning an Action Request

```python
from agent_polis.governance import PromptInjectionScanner

scanner = PromptInjectionScanner()

# Scan action request fields
result = scanner.scan(request.description, field="description")
result = scanner.scan(request.payload.get("content", ""), field="payload.content")

if result.findings:
    print(f"Found {len(result.findings)} threats")
    print(f"Max severity: {result.max_severity()}")
    print(f"Risk factors: {result.to_risk_factors()}")
```

### Verifying Descriptor Integrity

```python
from agent_polis.governance import (
    DescriptorIntegrityChecker,
    load_descriptor_integrity_policy_from_file,
)

policy = load_descriptor_integrity_policy_from_file("policy.yaml")
checker = DescriptorIntegrityChecker(policy)

result = checker.check(descriptor)
if not result.is_valid:
    raise SecurityError(f"Descriptor integrity violation: {result.reason}")
```

## Test Coverage

Scanner behavior is validated through Stage 1 platform tests (AP-106), including:
- Unit tests for individual rules with malicious fixtures
- Regression tests for bypass attempt detection
- Integration tests for end-to-end decision flow

Source: [src/agent_polis/governance/prompt_scanner.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/prompt_scanner.py)

## Related Documentation

- [Policy Evaluator](governance-policy.md) - How scanner results influence policy decisions
- [CI Integration](ci-integration.md) - Machine-readable report output for CI pipelines
- [Audit Trail](audit-trail.md) - How scanner findings are persisted

---

<a id='page-ci-integration'></a>

## CI Integration

### Related Pages

Related topics: [Governance and Policy](#page-governance-policy)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [src/agent_polis/ci.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/ci.py)
- [src/agent_polis/actions/models.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/models.py)
- [src/agent_polis/actions/service.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/service.py)
- [src/agent_polis/governance/policy.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/policy.py)
- [src/agent_polis/governance/prompt_scanner.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/prompt_scanner.py)
- [README.md](https://github.com/agent-polis/impact-preview/blob/main/README.md)
</details>

# CI Integration

Agent Polis provides a deterministic CI evaluation mode designed for PR gate integrations. This mode ensures no interactive prompts are reachable, produces machine-readable JSON reports, and exits with stable status codes based on policy decisions.

## Overview

The CI Integration feature addresses the need for automated governance checks in continuous integration pipelines. It transforms Agent Polis from an interactive approval system into a headless policy enforcement tool that can gate pull requests and deployments.

Key capabilities include:

- **Deterministic Evaluation**: No prompts or interactive paths are reachable in CI mode
- **Machine-Readable Reports**: JSON-formatted policy reports for programmatic consumption
- **Stable Exit Codes**: Predictable exit status based on policy decisions
- **Policy Presets**: Pre-configured policy packs for common environments
- **Prompt Injection Detection**: Built-in scanner for risky instructions

Source: [src/agent_polis/ci.py:1-20]()

## Architecture

```mermaid
graph TD
    A[CI Pipeline] --> B[Actions JSON File]
    B --> C[generate_ci_report]
    C --> D[ImpactAnalyzer]
    C --> E[PolicyEvaluator]
    C --> F[PromptInjectionScanner]
    D --> G[Action Previews]
    E --> H[Policy Decisions]
    F --> I[Scan Results]
    G --> J[CIPolicyReport]
    H --> J
    I --> J
    J --> K[JSON Report File]
    J --> L[Exit Code]
```

The CI evaluation flow processes action requests through three parallel analysis paths:

1. **Impact Analysis**: Analyzes what will change for each action
2. **Policy Evaluation**: Determines allow/deny/require_approval decisions
3. **Prompt Scanning**: Detects prompt injection and risky instructions

Source: [src/agent_polis/ci.py:78-110]()

## Report Schema

The machine-readable CI report follows a versioned schema to ensure backward compatibility with downstream integrations.

### Top-Level Report Model

```python
class CIPolicyReport(BaseModel):
    schema_version: Literal["1"] = REPORT_SCHEMA_VERSION
    policy_version: str
    totals: dict[str, int]
    top_blocking_reasons: list[CIReasonCount]
    actions: list[CIActionReport]
```

Source: [src/agent_polis/ci.py:56-61]()

### Schema Fields

| Field | Type | Description |
|-------|------|-------------|
| `schema_version` | `Literal["1"]` | Report schema version for compatibility tracking |
| `policy_version` | `string` | Version of the policy configuration used |
| `totals` | `dict[str, int]` | Aggregate counts by decision type |
| `top_blocking_reasons` | `list[CIReasonCount]` | Top 10 blocking reasons sorted by frequency |
| `actions` | `list[CIActionReport]` | Per-action detailed reports |

### Per-Action Report

Each evaluated action produces a detailed report entry:

```python
class CIActionReport(BaseModel):
    index: int
    action_type: str
    target: str
    risk_level: str
    policy_decision: str
    policy_matched_rule_id: str | None
    scanner_max_severity: str
    scanner_reason_ids: list[str]
```

Source: [src/agent_polis/ci.py:43-52]()

### Example Report Output

```json
{
  "schema_version": "1",
  "policy_version": "startup-v1.0",
  "totals": {
    "allow": 5,
    "require_approval": 2,
    "deny": 1
  },
  "top_blocking_reasons": [
    {"reason": "HIGH_RISK_SHELL_COMMAND", "count": 2},
    {"reason": "PROMPT_INJECTION_DETECTED", "count": 1}
  ],
  "actions": [
    {
      "index": 0,
      "action_type": "shell_command",
      "target": "rm -rf node_modules",
      "risk_level": "high",
      "policy_decision": "deny",
      "policy_matched_rule_id": "rule-001",
      "scanner_max_severity": "medium",
      "scanner_reason_ids": []
    }
  ]
}
```

## Exit Codes

The CI integration uses deterministic exit codes that integrate directly with CI/CD pipeline failure handling:

| Exit Code | Meaning | Trigger Condition |
|-----------|---------|-------------------|
| `0` | Success | All actions allowed |
| `2` | Approval Required | At least one action requires approval |
| `3` | Denied | At least one action denied |

```python
def _decision_exit_code(decisions: list[PolicyDecision]) -> int:
    if any(d == PolicyDecision.DENY for d in decisions):
        return 3
    if any(d == PolicyDecision.REQUIRE_APPROVAL for d in decisions):
        return 2
    return 0
```

Source: [src/agent_polis/ci.py:63-73]()

## Usage

### Command-Line Interface

The CI module can be invoked directly from the command line:

```bash
agentpolis-ci \
    --actions actions.json \
    --policy startup \
    --output report.json \
    --working-directory /path/to/project
```

### Python API

```python
from agent_polis.ci import generate_ci_report, load_policy_preset

# Load policy preset
policy = load_policy_preset("startup")

# Load actions from JSON file
from agent_polis.ci import _load_actions_from_json
actions = _load_actions_from_json("actions.json")

# Generate report
report, exit_code = await generate_ci_report(
    actions=actions,
    policy=policy,
    working_directory="/path/to/project"
)

# Write report to file
from agent_polis.ci import _write_report
_write_report(report, "report.json")

# Exit with appropriate code
import sys
sys.exit(exit_code)
```

Source: [src/agent_polis/ci.py:78-127]()

### Input Format

Actions are provided as a JSON file with the following structure:

```json
{
  "actions": [
    {
      "action_type": "file_write",
      "target": "src/config.py",
      "description": "Update database configuration",
      "payload": {
        "content": "DATABASE_URL = 'postgresql://prod...'"
      }
    },
    {
      "action_type": "shell_command",
      "target": "deploy.sh",
      "description": "Deploy to production",
      "payload": {
        "command": "./deploy.sh --env prod"
      }
    }
  ]
}
```

The loader also accepts a plain JSON array of actions without the wrapper object.

Source: [src/agent_polis/ci.py:129-152]()

## GitHub Actions Integration

A complete GitHub Actions workflow example for PR gate integration:

```yaml
name: Agent Polis Policy Check

on:
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  policy-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install Agent Polis
        run: pip install impact-preview

      - name: Generate actions from agent
        run: |
          cat << 'EOF' > actions.json
          {
            "actions": ${{ steps.agent.outputs.proposed_actions }}
          }
          EOF

      - name: Run CI evaluation
        id: polis
        run: |
          report=$(agentpolis-ci \
            --actions actions.json \
            --policy fintech \
            --output polis-report.json)
          
          echo "exit_code=$?" >> $GITHUB_OUTPUT
          cat polis-report.json

      - name: Upload report artifact
        uses: actions/upload-artifact@v4
        with:
          name: polis-report
          path: polis-report.json

      - name: Fail on policy violation
        if: steps.polis.outputs.exit_code != '0'
        run: |
          echo "Policy check failed with exit code ${{ steps.polis.outputs.exit_code }}"
          exit 1
```

Source: [README.md:89-130]()

## Policy Presets

CI mode supports policy presets that encode environment-specific risk defaults:

| Preset | Use Case | Default Risk Thresholds |
|--------|----------|------------------------|
| `startup` | Early-stage projects | Lenient defaults, focuses on critical operations |
| `fintech` | Financial services | Strict rules for data access and transactions |
| `games` | Gaming applications | Moderate rules with specific cheats detection |

```python
from agent_polis.governance.presets import load_policy_preset

policy = load_policy_preset("fintech")
```

Each preset includes:

- Rule definitions with deterministic precedence
- Risk thresholds per action type
- Rationale metadata for audit compliance
- Test fixtures for validation

Source: [src/agent_polis/governance/policy.py]()

## Deterministic Mode Guarantees

The CI mode enforces several guarantees to ensure reliable pipeline execution:

1. **No Interactive Prompts**: All code paths that would normally prompt for user input are eliminated or return deterministic defaults
2. **Stable Output**: Same inputs always produce identical reports
3. **Reproducible Decisions**: Policy evaluation uses deterministic rule precedence
4. **Controlled Resource Usage**: Scanner caps text scanning to prevent CPU abuse

Source: [src/agent_polis/governance/prompt_scanner.py:1-20]()

## Audit Trail Integration

CI evaluation results are automatically recorded to the audit trail with full governance context:

- Policy version and matched rule details
- Scanner findings with reason IDs
- Decision metadata for compliance reporting

```python
# From action service - governance context in audit
governance={
    "policy": {
        "version": policy.version,
        "decision": policy_result.decision.value,
        "matched_rule_id": policy_result.matched_rule_id,
        "trace": policy_result.trace,
    },
    "scanner": {
        "max_severity": scan_result.max_severity().value,
        "reason_ids": sorted({f.reason_id for f in scan_result.findings}),
    }
}
```

Source: [src/agent_polis/actions/service.py:89-105]()

## Configuration Reference

| Environment Variable | Description | Default |
|---------------------|-------------|---------|
| `AGENT_POLIS_CI_MODE` | Enable CI mode explicitly | `true` when `--ci` flag used |
| `AGENT_POLIS_WORKING_DIR` | Project working directory | Current directory |
| `AGENT_POLIS_POLICY` | Policy preset or path | `default` |
| `AGENT_POLIS_REDIS_URL` | Redis connection for audit | `redis://localhost:6379/0` |
| `AGENT_POLIS_LOG_LEVEL` | Logging verbosity | `INFO` |

## Related Issues

The following community issues track CI Integration development:

- [AP-203: Machine-readable CI policy report output](https://github.com/agent-polis/impact-preview/issues/9) - Report schema standardization
- [AP-204: Deterministic CI evaluation mode](https://github.com/agent-polis/impact-preview/issues/10) - Non-interactive mode requirements
- [AP-205: Stage 2 docs and CI integration examples](https://github.com/agent-polis/impact-preview/issues/11) - Documentation and GitHub Actions examples

---

<a id='page-mcp-server'></a>

## MCP Server Integration

### Related Pages

Related topics: [Quick Start Guide](#page-quick-start), [Actions Module](#page-actions-module), [SDK Integration](#page-sdk-integration)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [src/agent_polis/mcp_server.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/mcp_server.py)
- [src/agent_polis/actions/models.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/models.py)
- [src/agent_polis/actions/analyzer.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/analyzer.py)
- [src/agent_polis/actions/diff.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/diff.py)
- [src/agent_polis/governance/policy.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/governance/policy.py)
- [src/agent_polis/ci.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/ci.py)
- [src/agent_polis/integrations/crewai.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/integrations/crewai.py)
- [README.md](https://github.com/agent-polis/impact-preview/blob/main/README.md)
</details>

# MCP Server Integration

The MCP (Model Context Protocol) Server Integration provides a standardized interface for AI agents to access Agent Polis impact preview capabilities. This integration enables AI coding assistants like Claude Desktop and Cursor to intercept, analyze, and preview potentially dangerous operations before execution, following a "terraform plan" philosophy.

## Overview

The MCP server exposes Agent Polis as a tool suite that AI agents can invoke prior to performing file modifications, shell commands, or database operations. This allows AI assistants to:

- **Preview changes** before writing, creating, or deleting files
- **Analyze shell commands** for potential risks
- **Evaluate database queries** before execution
- **Enforce governance policies** consistently across interactions

The server operates as an HTTP endpoint using the FastMCP framework, providing both human-readable previews and machine-processable outputs suitable for CI/CD integration scenarios. Source: [src/agent_polis/mcp_server.py:32-38]()

## Architecture

### Component Diagram

```mermaid
graph TD
    subgraph "AI Agent Client"
        A[Claude Desktop / Cursor]
    end

    subgraph "MCP Server"
        M[MCP Server<br/>:8000/mcp]
        T1[preview_file_write]
        T2[preview_file_create]
        T3[preview_file_delete]
        T4[preview_shell_command]
        T5[preview_database_query]
        T6[check_path_risk]
    end

    subgraph "Agent Polis Core"
        IA[ImpactAnalyzer]
        PE[PolicyEvaluator]
        SC[PromptInjectionScanner]
        DI[DiffGenerator]
    end

    A -->|MCP Protocol| M
    M --> T1
    M --> T2
    M --> T3
    M --> T4
    M --> T5
    M --> T6
    
    T1 --> IA
    T2 --> IA
    T3 --> IA
    T4 --> IA
    T5 --> IA
    T6 --> IA
    
    IA --> PE
    IA --> SC
    IA --> DI
```

### Request Flow

```mermaid
sequenceDiagram
    participant Agent as AI Agent
    participant MCP as MCP Server
    participant Analyzer as ImpactAnalyzer
    participant Policy as PolicyEvaluator
    participant Scanner as PromptScanner

    Agent->>MCP: preview_file_write(path, content, description)
    MCP->>Analyzer: analyze(ActionRequest)
    
    Analyzer->>Scanner: scan(action)
    Scanner-->>Analyzer: ScanResult
    
    Analyzer->>Policy: evaluate(policy, request)
    Policy-->>Analyzer: PolicyResult
    
    Analyzer-->>MCP: ActionPreview
    MCP-->>Agent: Formatted preview with risk assessment
```

## Available Tools

The MCP server exposes six primary tools for impact preview:

| Tool | Purpose | Input Parameters |
|------|---------|-------------------|
| `preview_file_write` | Preview file edits before writing | `path`, `content`, `original_content`, `description` |
| `preview_file_create` | Preview new file creation | `path`, `content`, `description` |
| `preview_file_delete` | Preview file deletion | `path`, `description` |
| `preview_shell_command` | Analyze shell commands for risk | `command`, `working_directory`, `description` |
| `preview_database_query` | Analyze SQL queries | `query`, `connection_info`, `description` |
| `check_path_risk` | Quick risk check for any path | `path`, `description` |

Source: [src/agent_polis/mcp_server.py:55-83]()

### Tool Response Format

Each tool returns a formatted preview containing:

- **Target**: The file path or resource being acted upon
- **Risk Level**: LOW 🟢, MEDIUM 🟡, HIGH 🟠, or CRITICAL 🔴
- **Size/Scope**: Line counts, byte sizes, affected areas
- **Risk Factors**: List of identified concerns
- **Warnings**: Additional advisory information
- **Summary**: Human-readable impact description

Source: [src/agent_polis/mcp_server.py:98-116]()

## Action Request Model

The `ActionRequest` model defines the structure for all action preview requests:

```python
class ActionRequest(BaseModel):
    action_type: ActionType
    target: str
    description: str | None = None
    payload: dict[str, Any] = Field(default_factory=dict)
    context: dict[str, Any] = Field(default_factory=dict)
```

Source: [src/agent_polis/actions/models.py:1-1]()

### Supported Action Types

| ActionType | Description |
|------------|-------------|
| `FILE_WRITE` | Modifying an existing file |
| `FILE_DELETE` | Removing a file |
| `FILE_MOVE` | Relocating a file |
| `FILE_CREATE` | Creating a new file |
| `DB_QUERY` | Database read operations |
| `DB_EXECUTE` | Database write/modification |
| `API_CALL` | External API requests |
| `SHELL_COMMAND` | Shell script or command execution |
| `CUSTOM` | User-defined action types |

Source: [src/agent_polis/actions/models.py:28-39]()

### Risk Level Classification

| RiskLevel | Emoji | Description |
|-----------|-------|-------------|
| `LOW` | 🟢 | Read operations, safe changes |
| `MEDIUM` | 🟡 | Write operations to non-critical files |
| `HIGH` | 🟠 | Potentially destructive operations |
| `CRITICAL` | 🔴 | System-level or irreversible changes |

Source: [src/agent_polis/actions/models.py:51-56]()

## Configuration

### Claude Desktop Setup

To integrate with Claude Desktop, add the following to `~/.config/claude/claude_desktop_config.json`:

```json
{
    "mcpServers": {
        "impact-preview": {
            "url": "http://localhost:8000/mcp"
        }
    }
}
```

Source: [src/agent_polis/mcp_server.py:17-26]()

### Server Deployment

#### Using uvicorn (Recommended for Production)

```bash
uvicorn agent_polis.mcp_server:mcp.app --host 0.0.0.0 --port 8000
```

#### Direct Execution

```bash
python -m agent_polis.mcp_server
```

#### Environment Configuration

| Variable | Description | Default |
|----------|-------------|---------|
| `WORKING_DIRECTORY` | Base directory for path resolution | Current working directory |
| `LOG_LEVEL` | Logging verbosity | `INFO` |
| `REDIS_URL` | Event store backend | `redis://localhost:6379/0` |
| `FREE_TIER_ACTIONS_PER_MONTH` | Rate limit for free tier | `100` |

Source: [README.md:100-113]()

## MCP Server Endpoints

### Tool Endpoint (`/mcp`)

The MCP server exposes tools via the Model Context Protocol streamable HTTP transport. Each tool invocation follows this pattern:

```python
@mcp.tool()
async def preview_file_write(
    path: str,
    content: str,
    original_content: str | None = None,
    description: str = "Write file",
) -> str:
```

Source: [src/agent_polis/mcp_server.py:87-100]()

### Health Check

The server includes a built-in health mechanism through the FastMCP framework. Clients can verify connectivity by checking the `/mcp` endpoint availability.

## Integration with Governance

### Policy Evaluation

Every action preview integrates with the policy evaluator to determine the appropriate governance decision:

```python
policy_result = _policy_evaluator.evaluate(
    policy,
    audit_request,
    risk_level=preview.risk_level,
)
```

Source: [src/agent_polis/actions/service.py:70-75]()

### Decision Outcomes

| Decision | Meaning |
|----------|---------|
| `allow` | Action can proceed automatically |
| `deny` | Action is blocked |
| `require_approval` | Human review required before execution |

Source: [src/agent_polis/governance/policy.py:19-25]()

### Audit Trail Integration

Actions performed through MCP tools automatically generate audit records containing:

- Policy version and matched rule information
- Scanner findings (prompt injection detection)
- Risk assessment results
- Decision metadata with reason IDs

Source: [src/agent_polis/actions/service.py:78-91]()

## CI/CD Integration

The MCP server works in conjunction with the CI evaluation mode for automated policy enforcement:

### CI Mode Features

- Deterministic evaluation with no prompts
- Stable exit codes based on decision severity
- Machine-readable JSON report output
- No TTY required

Source: [src/agent_polis/ci.py:1-1]()

### Report Schema

The CI report includes:

```json
{
  "schema_version": "1",
  "policy_version": "preset-startup-1",
  "totals": {"deny": 2, "allow": 5, "require_approval": 1},
  "top_blocking_reasons": [
    {"reason": "deny-secrets-touching", "count": 2}
  ],
  "actions": [...]
}
```

Source: [src/agent_polis/ci.py:44-55]()

## Related Community Issues

The MCP Server Integration relates to several active development efforts:

| Issue | Focus | Status |
|-------|-------|--------|
| [AP-204](https://github.com/agent-polis/impact-preview/issues/10) | Deterministic CI evaluation mode | Active |
| [AP-203](https://github.com/agent-polis/impact-preview/issues/9) | Machine-readable CI policy report | Active |
| [AP-205](https://github.com/agent-polis/impact-preview/issues/11) | Stage 2 docs and CI integration examples | Active |

## Framework Integrations

### CrewAI Integration

Agent Polis provides a native CrewAI tool for simulation:

```python
from agent_polis.integrations.crewai import AgentPolisTool

tool = AgentPolisTool(
    api_url="http://localhost:8000",
    api_key="your-key"
)
```

The tool enables agents to run simulations before committing to actions, providing sandbox-based validation of proposed changes.

Source: [src/agent_polis/integrations/crewai.py:1-1]()

## Best Practices

1. **Always preview before writing**: Use `preview_file_write` before any file modification
2. **Check risky paths**: Use `check_path_risk` for paths containing secrets or configuration
3. **Review shell commands**: Even simple commands can have unexpected side effects
4. **Use CI mode for automation**: Enable deterministic evaluation in automated workflows
5. **Configure presets**: Select appropriate policy presets (`startup`, `fintech`, `games`) for your environment

## Security Considerations

The MCP server implements several security measures:

- **Hash pinning** for descriptor integrity checks
- **Prompt injection scanning** to detect malicious instructions
- **Policy-based access control** with deterministic precedence
- **Fail-closed behavior** on integrity mismatches

Source: [src/agent_polis/governance/descriptor_integrity.py:1-1]()

## Roadmap

| Version | Feature | Status |
|---------|---------|--------|
| v0.2.0 | File operation preview | Current |
| v0.3.0 | Database operation preview | Planned |
| v0.4.0 | API call preview | Planned |
| v0.5.0 | IDE integrations (Cursor, VS Code) | Planned |
| v1.0.0 | Production ready | Planned |

Source: [README.md:89-96]()

---

<a id='page-sdk-integration'></a>

## SDK Integration

### Related Pages

Related topics: [Quick Start Guide](#page-quick-start), [MCP Server Integration](#page-mcp-server), [Actions Module](#page-actions-module)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [src/agent_polis/sdk.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/sdk.py)
- [src/agent_polis/integrations/__init__.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/integrations/__init__.py)
- [src/agent_polis/actions/service.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/service.py)
- [src/agent_polis/actions/models.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/models.py)
- [src/agent_polis/actions/router.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/router.py)
- [src/agent_polis/main.py](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/main.py)
- [README.md](https://github.com/agent-polis/impact-preview/blob/main/README.md)
</details>

# SDK Integration

The Agent Polis SDK provides a streamlined client library for integrating impact preview and action approval workflows directly into AI agent codebases. Rather than making raw HTTP calls to the Agent Polis API, developers use the SDK's declarative decorator pattern to automatically route operations through the governance layer with minimal code changes.

## Overview

The SDK serves as the primary integration point for AI agents that want to participate in Agent Polis governance. It abstracts the complexity of the REST API behind a Pythonic interface, allowing agents to focus on their core logic while the SDK handles:

- Submitting proposed actions for approval
- Waiting for human authorization
- Executing only approved actions
- Handling errors and timeouts gracefully

Source: [src/agent_polis/sdk.py:1-30](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/sdk.py)

## Architecture

```mermaid
graph TD
    subgraph "AI Agent Code"
        A["@require_approval decorator"] --> B["Wrapped Function"]
    end
    
    subgraph "SDK Layer"
        B --> C["AgentPolisClient"]
        C --> D["HTTP Client (httpx)"]
    end
    
    subgraph "Agent Polis Server"
        D --> E["/api/v1/actions endpoint"]
        E --> F["ActionService"]
        F --> G["ImpactAnalyzer"]
        F --> H["PolicyEvaluator"]
        F --> I["PromptInjectionScanner"]
    end
    
    G --> J["Impact Preview Response"]
    H --> K["Policy Decision"]
    I --> L["Scan Findings"]
    
    J --> M["Approval Workflow"]
    M --> |"Approved"| N["Execute Action"]
    M --> |"Rejected"| O["ActionRejectedError"]
    M --> |"Timeout"| P["ActionTimedOutError"]
```

The SDK communicates with the Agent Polis FastAPI server via HTTP. The server validates requests, generates impact previews, evaluates policies, scans for prompt injection risks, and manages the approval workflow state. Source: [src/agent_polis/main.py:50-85](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/main.py)

## AgentPolisClient

The `AgentPolisClient` is the main entry point for SDK integration. It manages the HTTP connection to the Agent Polis server and provides methods for submitting actions and checking status.

### Constructor Parameters

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `api_key` | `str` | Yes | - | API key for authentication |
| `base_url` | `str` | No | `"http://localhost:8000"` | Agent Polis server URL |
| `timeout` | `int` | No | `300` | Approval wait timeout in seconds |

Source: [src/agent_polis/sdk.py:70-90](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/sdk.py)

### Basic Usage

```python
from agent_polis.sdk import AgentPolisClient

client = AgentPolisClient(
    api_key="your_api_key",
    base_url="https://your-agent-polis-server.com"
)
```

## The @require_approval Decorator

The decorator is the primary integration mechanism. It wraps any function that performs an action requiring governance oversight, automatically routing the operation through the approval flow.

### Function Signature

```python
@client.require_approval(
    action_type: str | ActionType,
    description: str | None = None,
    target: str | None = None,
    auto_approve_if_low_risk: bool = True,
    timeout_seconds: int = 300,
    callback_url: str | None = None
)
def my_function(...):
    ...
```

Source: [src/agent_polis/sdk.py:95-120](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/sdk.py)

### Decorator Parameters

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `action_type` | `str` or `ActionType` | Yes | - | Type of action being performed |
| `description` | `str` | No | Function docstring | Human-readable description |
| `target` | `str` | No | `None` | Target resource (e.g., file path) |
| `auto_approve_if_low_risk` | `bool` | No | `True` | Auto-approve low-risk actions |
| `timeout_seconds` | `int` | No | `300` | Seconds to wait for approval |
| `callback_url` | `str` | No | `None` | Webhook URL for async notifications |

Source: [src/agent_polis/sdk.py:95-115](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/sdk.py)

### Supported Action Types

The SDK supports the following action types from `ActionType`:

| Action Type | Description |
|-------------|-------------|
| `file_write` | Writing to an existing file |
| `file_delete` | Deleting a file |
| `file_move` | Moving or renaming a file |
| `file_create` | Creating a new file |
| `db_query` | Database read operations |
| `db_execute` | Database write/modify operations |
| `api_call` | External API requests |
| `shell_command` | Shell command execution |
| `custom` | User-defined action types |

Source: [src/agent_polis/actions/models.py:15-35](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/models.py)

## Complete Integration Example

```python
from agent_polis.sdk import AgentPolisClient

# Initialize the client
client = AgentPolisClient(
    api_key="your_api_key",
    base_url="http://localhost:8000"
)

@client.require_approval(
    action_type="file_write",
    description="Update application configuration",
    target="/etc/myapp/config.yaml",
    auto_approve_if_low_risk=True,
    timeout_seconds=300
)
def update_config(path: str, content: str):
    """Update the application configuration file."""
    with open(path, 'w') as f:
        f.write(content)
    return {"status": "updated", "path": path}

# This call will:
# 1. Submit the action for approval
# 2. Wait for approval (or auto-approve if low risk)
# 3. Execute the function only if approved
result = update_config("/etc/myapp/config.yaml", "new config content")
```

Source: [src/agent_polis/sdk.py:1-50](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/sdk.py)

## Error Handling

The SDK defines custom exception classes for failure scenarios.

### ActionRejectedError

Raised when an action is explicitly rejected by an approver.

```python
class ActionRejectedError(Exception):
    """Raised when an action is rejected."""
    
    def __init__(self, action_id: str, reason: str):
        self.action_id = action_id
        self.reason = reason
        super().__init__(f"Action {action_id} was rejected: {reason}")
```

Source: [src/agent_polis/sdk.py:55-62](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/sdk.py)

### ActionTimedOutError

Raised when the approval timeout expires before a decision is made.

```python
class ActionTimedOutError(Exception):
    """Raised when an action times out waiting for approval."""
    
    def __init__(self, action_id: str, timeout: int):
        self.action_id = action_id
        self.timeout = timeout
        super().__init__(
            f"Action {action_id} timed out after {timeout} seconds"
        )
```

Source: [src/agent_polis/sdk.py:65-72](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/sdk.py)

### Error Handling Pattern

```python
from agent_polis.sdk import (
    AgentPolisClient,
    ActionRejectedError,
    ActionTimedOutError
)

client = AgentPolisClient(api_key="your_api_key")

@client.require_approval(action_type="file_write", target="/path/to/file")
def write_file(path: str, content: str):
    with open(path, 'w') as f:
        f.write(content)

try:
    write_file("/path/to/file", "content")
except ActionRejectedError as e:
    print(f"Action {e.action_id} was rejected: {e.reason}")
except ActionTimedOutError as e:
    print(f"Action {e.action_id} timed out after {e.timeout}s")
```

## Underlying API Flow

When the decorator is invoked, it performs the following steps:

```mermaid
sequenceDiagram
    participant Agent as AI Agent Code
    participant SDK as AgentPolisClient
    participant API as Agent Polis API
    participant Human as Human Approver

    Agent->>SDK: Wrapped function called
    SDK->>API: POST /api/v1/actions/
    Note over SDK,API: ActionRequest payload
    API->>API: Generate Impact Preview
    API->>API: Evaluate Policy
    API->>API: Scan for Prompt Injection
    API-->>SDK: ActionResponse (pending/approved)
    
    alt Auto-approve (low risk)
        API->>API: Action auto-approved
        SDK->>Agent: Execute wrapped function
    else Requires approval
        SDK->>SDK: Wait for approval (timeout)
        Human->>API: Approve/Reject action
        API-->>SDK: Decision received
        alt Approved
            SDK->>Agent: Execute wrapped function
        else Rejected
            SDK-->>Agent: Raise ActionRejectedError
        end
    end
```

The SDK submits an `ActionRequest` to the server's `/api/v1/actions/` endpoint. The server processes this through the `ActionService`, which coordinates impact analysis, policy evaluation, and prompt injection scanning. Source: [src/agent_polis/actions/service.py:1-50](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/actions/service.py)

## SDK Configuration

### Environment Variables

The SDK can be configured using environment variables for deployment flexibility:

| Variable | Description | Default |
|----------|-------------|---------|
| `AGENT_POLIS_API_KEY` | API authentication key | - |
| `AGENT_POLIS_BASE_URL` | Server endpoint URL | `http://localhost:8000` |
| `AGENT_POLIS_TIMEOUT` | Approval timeout in seconds | `300` |

### Integration Module

Agent Polis also provides framework-specific integrations for CrewAI and LangGraph through the `agent_polis.integrations` module:

```python
from agent_polis.integrations import (
    EventStore,
    EventBus,
    DomainEvent,
    append_event,
    publish_event,
    subscribe
)
```

These components provide event sourcing infrastructure for maintaining an immutable audit trail of all governance actions. Source: [src/agent_polis/integrations/__init__.py:1-25](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/integrations/__init__.py)

## Version Compatibility

The SDK is versioned alongside the Agent Polis platform. Current supported versions:

| SDK Version | Agent Polis Version | Status |
|-------------|---------------------|--------|
| 0.2.x | 0.2.x | Current |
| 0.1.x | 0.1.x | Legacy |

The SDK reports the following capabilities to the Agent Polis server:

```python
"capabilities": [
    "impact_preview",
    "action_approval",
    "file_diff",
    "audit_trail",
]
```

Source: [src/agent_polis/main.py:40-48](https://github.com/agent-polis/impact-preview/blob/main/src/agent_polis/main.py)

## Installation

The SDK is included as part of the `impact-preview` package:

```bash
pip install impact-preview
```

For development with the SDK:

```bash
pip install impact-preview[dev]
```

Source: [README.md:1-50](https://github.com/agent-polis/impact-preview/blob/main/README.md)

## Best Practices

1. **Use descriptive targets**: Always specify the `target` parameter to clearly identify the affected resource
2. **Set appropriate timeouts**: Adjust `timeout_seconds` based on expected human review turnaround
3. **Handle all error types**: Implement try/except blocks for both `ActionRejectedError` and `ActionTimedOutError`
4. **Enable auto-approve selectively**: Use `auto_approve_if_low_risk=True` only for operations that are consistently low-risk
5. **Leverage decorators at boundaries**: Apply `@require_approval` to functions that represent system boundary crossings (file I/O, network calls, shell commands)

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Pitfall Log

Project: agent-polis/impact-preview

Summary: Found 10 structured pitfall item(s), including 0 high/blocking item(s). Top priority: Configuration risk - Configuration risk requires verification.

## 1. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Suggested check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: community_evidence:github | cevd_52a7602d08fd4a34a02a058587179586 | https://github.com/agent-polis/impact-preview/issues/1

## 2. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Suggested check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: community_evidence:github | cevd_7d4cca25cd1347289c9e6834c0f806fc | https://github.com/agent-polis/impact-preview/issues/2

## 3. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Suggested check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: community_evidence:github | cevd_71b0a0a48b3f4a3ea7107c911c8b8733 | https://github.com/agent-polis/impact-preview/issues/9

## 4. Capability evidence risk - Capability evidence risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: README/documentation is current enough for a first validation pass.
- User impact: May increase setup, validation, or first-run risk for the user.
- Suggested check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: capability.assumptions | mcp_registry:io.github.agent-polis/impact-preview:0.2.1 | https://registry.modelcontextprotocol.io/v0.1/servers/io.github.agent-polis%2Fimpact-preview/versions/0.2.1

## 5. Maintenance risk - Maintenance risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a maintenance risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Suggested check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: evidence.maintainer_signals | mcp_registry:io.github.agent-polis/impact-preview:0.2.1 | https://registry.modelcontextprotocol.io/v0.1/servers/io.github.agent-polis%2Fimpact-preview/versions/0.2.1

## 6. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Suggested check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: downstream_validation.risk_items | mcp_registry:io.github.agent-polis/impact-preview:0.2.1 | https://registry.modelcontextprotocol.io/v0.1/servers/io.github.agent-polis%2Fimpact-preview/versions/0.2.1

## 7. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Suggested check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: risks.scoring_risks | mcp_registry:io.github.agent-polis/impact-preview:0.2.1 | https://registry.modelcontextprotocol.io/v0.1/servers/io.github.agent-polis%2Fimpact-preview/versions/0.2.1

## 8. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Suggested check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: community_evidence:github | cevd_ff00c63559844328a271d0587352d351 | https://github.com/agent-polis/impact-preview/issues/5

## 9. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: issue_or_pr_quality=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Suggested check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: evidence.maintainer_signals | mcp_registry:io.github.agent-polis/impact-preview:0.2.1 | https://registry.modelcontextprotocol.io/v0.1/servers/io.github.agent-polis%2Fimpact-preview/versions/0.2.1

## 10. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: release_recency=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Suggested check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: evidence.maintainer_signals | mcp_registry:io.github.agent-polis/impact-preview:0.2.1 | https://registry.modelcontextprotocol.io/v0.1/servers/io.github.agent-polis%2Fimpact-preview/versions/0.2.1

<!-- canonical_name: agent-polis/impact-preview; human_manual_source: deepwiki_human_wiki -->
