Agent Control
Agent Control provides an open-source runtime control plane for all your AI agents — configurable rules that evaluate inputs and outputs at every step in your agent against a set of policies managed centrally, without modifying your agent’s code. It integrates with Strands via the AgentControlPlugin or AgentControlSteeringHandler:
- AgentControlPlugin — hooks into Strands lifecycle events (
BeforeToolCallEvent,AfterModelCallEvent, etc.) and enforces hard blocks (deny) or corrective steering on violations - AgentControlSteeringHandler — integrates with Strands’ experimental steering API to convert Agent Control
steermatches intoGuide()actions, prompting the agent to rewrite its output before proceeding
Controls are defined on a central server (or locally via controls.yaml) and evaluated at runtime — no redeployment needed when rules change.
Installation
Section titled “Installation”pip install "agent-control-sdk[strands-agents]"The SDK connects to a running Agent Control server. Point it at your instance via the AGENT_CONTROL_URL environment variable (defaults to http://localhost:8000). See the Agent Control docs for server setup options.
Basic setup with AgentControlPlugin
Section titled “Basic setup with AgentControlPlugin”import agent_controlfrom agent_control.integrations.strands import AgentControlPluginfrom strands import Agentfrom strands.models.openai import OpenAIModel
# Initialize once at startup — registers the agent and fetches controlsagent_control.init(agent_name="my-agent")
# Attach the plugin — all lifecycle events are intercepted automaticallyagent_control_plugin = AgentControlPlugin(agent_name="my-agent")
agent = Agent( model=OpenAIModel(model_id="gpt-4o-mini"), system_prompt="You are a helpful assistant.", tools=[...], plugins=[agent_control_plugin],)
result = await agent.invoke_async("Hello!")When a control matches, the plugin raises an exception that should be caught above the agent call site.
Adding steering for LLM output correction
Section titled “Adding steering for LLM output correction”For cases where you want the agent to fix its output rather than hard-block, combine the plugin with AgentControlSteeringHandler:
from agent_control.integrations.strands import AgentControlPlugin, AgentControlSteeringHandlerfrom strands.hooks import BeforeToolCallEvent, AfterToolCallEvent
# Plugin handles tool-stage deny checksagent_control_plugin = AgentControlPlugin( agent_name="my-agent", event_control_list=[BeforeToolCallEvent, AfterToolCallEvent],)
# Steering handler converts steer matches into Strands Guide() retriessteering = AgentControlSteeringHandler(agent_name="my-agent")
agent = Agent( model=model, system_prompt="...", tools=[...], plugins=[agent_control_plugin, steering], # both registered as plugins)When a steer control matches on LLM output, AgentControlSteeringHandler returns a Guide(reason=<steering_context>) and the agent retries with that guidance injected.
Configuration
Section titled “Configuration”AgentControlPlugin
| Parameter | Type | Default | Description |
|---|---|---|---|
agent_name | str | required | Agent identifier, must match the name used in agent_control.init() |
event_control_list | list[type] | None | None | Strands event types to intercept. Defaults to all supported events (BeforeInvocationEvent, BeforeModelCallEvent, AfterModelCallEvent, BeforeToolCallEvent, AfterToolCallEvent, BeforeNodeCallEvent, AfterNodeCallEvent) |
on_violation_callback | Callable | None | None | Called on every violation with (info_dict, EvaluationResult). Useful for logging or metrics |
enable_logging | bool | True | Emit debug log lines for control checks and violations |
AgentControlSteeringHandler
| Parameter | Type | Default | Description |
|---|---|---|---|
agent_name | str | required | Agent identifier, must match the name used in agent_control.init() |
enable_logging | bool | True | Emit debug log lines for steering evaluations |
Environment variables
Section titled “Environment variables”| Variable | Default | Description |
|---|---|---|
AGENT_CONTROL_URL | http://localhost:8000 | Server URL |
AGENT_CONTROL_API_KEY | — | API key (if auth is enabled) |
Troubleshooting
Section titled “Troubleshooting”“AgentControl not initialized” — call agent_control.init() before creating the plugin.
Controls not triggering — verify the server is running (curl http://localhost:8000/health) and controls are attached to your agent (re-run your setup script).
Import errors — make sure you installed the strands-agents extra: pip install "agent-control-sdk[strands-agents]".