Skip to content

agentcontrol/agent-control

Repository files navigation

Agent Control Logo (light) Agent Control Logo (dark)

Agent Control

License Python 3.12+ PyPI version npm version CI codecov

Agent Control Website | Docs | Quickstart | Examples | Slack

Enforce runtime guardrails through a centralized control layer—configure once and apply across all agents. Agent Control evaluates inputs and outputs against configurable rules to block prompt injections, PII leakage, and other risks without changing your agent’s code.

Agent Control Overview

  • Centralized safety - define controls once, apply across agents, update without redeploying
  • Runtime configuration - manage controls via API or UI, no code changes needed
  • Pluggable evaluators - built-in (regex, list, JSON, SQL) or bring your own
  • Framework support - works with LangChain, CrewAI, Google ADK, AWS Strands, and more

Quick Start

Prerequisites: Docker and Python 3.12+.

Quick start flow:

Start server
  ↓
Install SDK
  ↓
Wrap a model or tool call with @control() and register your agent
  ↓
Create controls (UI or SDK/API)

1. Start the server

No repo clone required:

curl -L https://raw.githubusercontent.com/agentcontrol/agent-control/refs/heads/main/docker-compose.yml | docker compose -f - up -d

This starts PostgreSQL and Agent Control at http://localhost:8000, including the UI/dashboard.

Verify it is up:

curl http://localhost:8000/health

2. Install the SDK

Run this in your agent project directory.

Python:

uv venv
source .venv/bin/activate
uv pip install agent-control-sdk

TypeScript:

3. Wrap a call and register your agent

# my_agent.py

import asyncio
import agent_control
from agent_control import control, ControlViolationError

# Protect any function (like LLM calls)

@control()
async def chat(message: str) -> str:
    # In production: response = await LLM.ainvoke(message)
    # For demo: simulate LLM that might leak sensitive data
    if "test" in message.lower():
        return "Your SSN is 123-45-6789"  # Will be blocked!
    return f"Echo: {message}"

# Initialize your agent

agent_control.init(
    agent_name="awesome_bot_3000",  # Unique name
    agent_description="My Chatbot",
)

async def main():
    try:
        print(await chat("test"))  # ❌ Blocked
    except ControlViolationError as e:
        print(f"❌ Blocked: {e.control_name}")

asyncio.run(main())

Next, create a control in Step 4, then run the setup and agent scripts in order to see blocking in action.

4. Add controls

This example adds the control with a small SDK setup script. You can also create and attach controls through the UI or direct API calls.

Minimal SDK example (assumes the server is running at http://localhost:8000 and uses the same agent_name as Step 3):

# setup.py - Run once to configure agent controls

import asyncio
from datetime import datetime, UTC
from agent_control import AgentControlClient, controls, agents
from agent_control_models import Agent

async def setup():
    async with AgentControlClient() as client:  # Defaults to localhost:8000
        # 1. Register agent first
        agent = Agent(
            agent_name="awesome_bot_3000",
            agent_description="My Chatbot",
            agent_created_at=datetime.now(UTC).isoformat(),
        )
        await agents.register_agent(client, agent, steps=[])

        # 2. Create control (blocks SSN patterns in output)
        control = await controls.create_control(
            client,
            name="block-ssn",
            data={
                "enabled": True,
                "execution": "server",
                "scope": {"stages": ["post"]},
                "selector": {"path": "output"},
                "evaluator": {
                    "name": "regex",
                    "config": {"pattern": r"\b\d{3}-\d{2}-\d{4}\b"},
                },
                "action": {"decision": "deny"},
            },
        )

        # 3. Associate control directly with agent
        await agents.add_agent_control(
            client,
            agent_name=agent.agent_name,
            control_id=control["control_id"],
        )

        print("✅ Setup complete!")
        print(f"   Control ID: {control['control_id']}")

asyncio.run(setup())

Tip: If you prefer a visual flow, use the UI instead - see the UI Quickstart.

Run both scripts in order:

uv run setup.py
uv run my_agent.py

Expected output:

Blocked: block-ssn-demo

Examples:

Explore working examples for popular frameworks.

How It Works

Agent Control Architecture

Agent Control evaluates agent inputs and outputs against controls you configure at runtime. That keeps guardrail logic out of prompt code and tool code, while still letting teams update protections centrally.

Read more about Controls and Learn how controls, selectors, and evaluators work

Performance

Endpoint Scenario RPS p50 p99
Agent init Agent with 3 tool steps 509 19 ms 54 ms
Evaluation 1 control, 500-char content 437 36 ms 61 ms
Evaluation 10 controls, 500-char content 349 35 ms 66 ms
Evaluation 50 controls, 500-char content 199 63 ms 91 ms
Controls refresh 5-50 controls per agent 273-392 20-27 ms 27-61 ms
  • Agent init handles create and update as an upsert.
  • Local laptop benchmarks are directional, not production sizing guidance.

Benchmarked on Apple M5 (16 GB RAM), Docker Compose (postgres:16 + agent-control).

Contributing

See CONTRIBUTING.md for contribution guidelines, development workflow, and quality checks.

License

Apache 2.0. See LICENSE for details.

About

Centralized agent control plane for governing runtime agent behavior at scale. Configurable, extensible, and production-ready.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors