> ## Documentation Index
> Fetch the complete documentation index at: https://splinter.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Control Layer Overview

> Runtime Controls for AI agents

The Control Layer provides **Runtime Controls** that prevent AI agents from causing harm. Without these controls, agents can spend unlimited money, loop forever, and break production systems.

## Why Control Matters

Without proper control mechanisms, AI agents can cause severe operational and financial damage. Agents may accumulate massive API costs by making unlimited calls to expensive services, enter infinite loops that waste computational resources, overwhelm external APIs with excessive requests leading to rate limit violations, make unauthorized changes to critical systems, or consume unbounded memory until systems crash. These scenarios can transform helpful automation into costly failures that require immediate intervention and system shutdowns.

The Control Layer prevents:

| Problem                 | Control              | What it does           |
| ----------------------- | -------------------- | ---------------------- |
| Unlimited spending      | ExecutionLimits      | Hard budget cap        |
| API rate exceeded       | RateLimiter          | Calls per minute       |
| Cascading failures      | CircuitBreaker       | Stop after N failures  |
| Infinite loops          | LoopDetection        | Detect and break loops |
| Unauthorized actions    | ToolAccessController | Per-agent permissions  |
| Flip-flopping decisions | DecisionEnforcer     | Lock decisions         |
| Transient failures      | RetryStrategy        | Retry with backoff     |
| Custom violations       | RulesEngine          | Your own rules         |
| Memory bloat            | MemoryStore          | Capped storage         |

## Quick Start

```python theme={null}
from splinter import Splinter

# Basic limits - that's it!
s = Splinter(
    openai_key="sk-...",
    max_budget=5.0,   # Stop at $5
    max_steps=50,     # Stop after 50 calls
)

result = await s.run("agent", "Do the task")
# Guaranteed to stop at $5 or 50 calls, whichever comes first
```

## Control Objects

<CardGroup cols={2}>
  <Card title="ExecutionLimits" icon="dollar-sign" href="/control/execution-limits">
    Budget, step count, and time limits
  </Card>

  <Card title="RateLimiter" icon="gauge" href="/control/rate-limiting">
    Calls per minute per agent or tool
  </Card>

  <Card title="CircuitBreaker" icon="power-off" href="/control/circuit-breakers">
    Stop after repeated failures
  </Card>

  <Card title="LoopDetection" icon="arrows-rotate" href="/control/loop-detection">
    Detect and break infinite loops
  </Card>

  <Card title="ToolAccessController" icon="key" href="/control/tool-access">
    Which agent can use which tools
  </Card>

  <Card title="DecisionEnforcer" icon="lock" href="/control/decision-enforcement">
    Lock decisions to prevent flip-flopping
  </Card>

  <Card title="RetryStrategy" icon="rotate" href="/control/retry-strategy">
    Retry failed calls with exponential backoff
  </Card>

  <Card title="RulesEngine" icon="gavel" href="/control/rules-engine">
    Custom BLOCK/WARN/LOG rules
  </Card>

  <Card title="MemoryStore" icon="database" href="/control/memory-limits">
    Capped memory with auto-eviction
  </Card>
</CardGroup>

## How Controls are Applied

```mermaid theme={null}
flowchart TB
    Request[Agent Request]
    
    RateLimit{Rate Limiter}
    RateBlock[❌ Too fast? Block]
    
    Circuit{Circuit Breaker}
    CircuitBlock[❌ Circuit open? Block]
    
    ToolAccess{Tool Access}
    ToolBlock[❌ Not allowed? Block]
    
    Rules{Rules Engine}
    RulesBlock[❌ Rule violation? Block]
    
    ExecLimits{Execution Limits}
    BudgetBlock[❌ Over budget? Block]
    
    LLM[LLM Provider]
    
    LoopDetect{Loop Detection}
    LoopBreak[❌ Loop detected? Break]
    
    Response[Agent Response]
    
    Request --> RateLimit
    RateLimit -->|✓ Pass| Circuit
    RateLimit -.->|Block| RateBlock
    
    Circuit -->|✓ Pass| ToolAccess
    Circuit -.->|Block| CircuitBlock
    
    ToolAccess -->|✓ Pass| Rules
    ToolAccess -.->|Block| ToolBlock
    
    Rules -->|✓ Pass| ExecLimits
    Rules -.->|Block| RulesBlock
    
    ExecLimits -->|✓ Pass| LLM
    ExecLimits -.->|Block| BudgetBlock
    
    LLM --> LoopDetect
    LoopDetect -->|✓ Pass| Response
    LoopDetect -.->|Break| LoopBreak
    
    style Request fill:#DBEAFE,stroke:#3B82F6,stroke-width:2px,color:#000
    style RateLimit fill:#FEE2E2,stroke:#6c0404,stroke-width:2px,color:#000
    style Circuit fill:#FEE2E2,stroke:#6c0404,stroke-width:2px,color:#000
    style ToolAccess fill:#FEE2E2,stroke:#6c0404,stroke-width:2px,color:#000
    style Rules fill:#FEE2E2,stroke:#6c0404,stroke-width:2px,color:#000
    style ExecLimits fill:#FEE2E2,stroke:#6c0404,stroke-width:2px,color:#000
    style LLM fill:#D1FAE5,stroke:#10B981,stroke-width:2px,color:#000
    style LoopDetect fill:#FEE2E2,stroke:#6c0404,stroke-width:2px,color:#000
    style Response fill:#DBEAFE,stroke:#3B82F6,stroke-width:2px,color:#000
    style RateBlock fill:#FEE2E2,stroke:#DC2626,stroke-width:2px,color:#000
    style CircuitBlock fill:#FEE2E2,stroke:#DC2626,stroke-width:2px,color:#000
    style ToolBlock fill:#FEE2E2,stroke:#DC2626,stroke-width:2px,color:#000
    style RulesBlock fill:#FEE2E2,stroke:#DC2626,stroke-width:2px,color:#000
    style BudgetBlock fill:#FEE2E2,stroke:#DC2626,stroke-width:2px,color:#000
    style LoopBreak fill:#FEE2E2,stroke:#DC2626,stroke-width:2px,color:#000
```

## Combining Controls

Controls compose naturally:

```python theme={null}
from splinter import Splinter
from splinter.types import ExecutionLimits, LoopDetectionConfig
from splinter.control import RateLimiter, CircuitBreaker, ToolAccessController

# Basic limits
s = Splinter(openai_key="sk-...", max_budget=10.0, max_steps=100)

# Add rate limiting
limiter = RateLimiter()
limiter.set_agent_limit("researcher", calls=20, window_seconds=60)

# Add circuit breaker
breaker = CircuitBreaker(
    breaker_id="openai",
    failure_threshold=5,
    timeout_seconds=60,
)

# Add tool access control
tool_ctrl = ToolAccessController()
tool_ctrl.set_allowed_tools("researcher", ["web_search", "read_file"])
tool_ctrl.set_allowed_tools("writer", ["write_file"])

# All controls work together
```

## Best Practices

<AccordionGroup>
  <Accordion title="Always set budget limits">
    Even for testing. A runaway agent can cost thousands. Default to \$5-10 for development.
  </Accordion>

  <Accordion title="Use circuit breakers for external APIs">
    If an external API is down, stop hammering it. Give it time to recover.
  </Accordion>

  <Accordion title="Enable loop detection for autonomous agents">
    Agents that run without human oversight need loop detection. They will get stuck.
  </Accordion>

  <Accordion title="Be specific with tool access">
    Don't give all agents access to all tools. Principle of least privilege.
  </Accordion>
</AccordionGroup>
