Skip to main content
Message Steering lets you send guidance to a running agent without restarting it.
The user steers a long-running task mid-flight; guidance is queued and applied at the next safe boundary.
Mid-tool-loop steering is fully wired as of PR #2997 (release after 2026-07-14). Earlier releases only checked pending steering at chat/tool boundaries, so a long multi-tool run could not be steered until the loop returned to a boundary — and INTERRUPT/URGENT priorities were silently downgraded on any mid-run injection path. Upgrade to pick up per-iteration steering + preserved priorities across LiteLLM and OpenAI-native providers, sync and async.

Quick Start

1

Simple Usage

Enable with message_steering=True and use agent.steer() to send guidance.
2

Threaded Pattern

Send steering messages while the agent is actively running.
3

Async Pattern

Use async execution with real-time steering.
4

Steering a Long Multi-Tool Run

Steer an agent while it is deep inside a multi-step tool loop — the guidance lands on the next loop iteration, not only when a chat step returns.
Example user flow:

How It Works

Message steering injects guidance at the top of every chat step and every tool-loop iteration, so a long multi-tool run picks up new user guidance on its very next model call — without restarting the run. Steering messages are drained at the start of each chat step and each tool-loop iteration, then injected as user messages with a priority-aware header. The agent picks them up on its very next model call, whether it is between chat turns or deep inside a multi-tool loop.

Mid-Tool-Loop Steering

Steering messages land on the very next tool-loop iteration, so multi-step tool runs pick up new guidance without a restart.
  • Steering messages queued via agent.steer(...) are checked at the top of every tool-loop iteration, so multi-step tool runs pick them up without a restart.
  • INTERRUPT and URGENT priorities keep their headers when injected mid-loop, so the model sees [INTERRUPT USER GUIDANCE] / [URGENT USER GUIDANCE] instead of being silently downgraded to plain guidance.
  • /stop (via cancel_token or agent.interrupt_controller) is re-checked immediately before dispatching tool calls, so a cancel mid-iteration skips running the pending tools instead of executing them first.

Priority Levels

PriorityInt valueBehaviour
LOW1Whispered guidance
NORMAL5Default priority
HIGH10Acknowledged urgently in next chat step
URGENT20Injected mid tool-loop as [URGENT USER GUIDANCE] — the model acknowledges and adjusts on its very next model call
INTERRUPT30Injected mid tool-loop as [INTERRUPT USER GUIDANCE] — the model is told to stop current work and follow the new guidance immediately

CLI Usage

Enable message steering from command line:
The --message-steering flag sets message_steering=True on the agent.

YAML Usage

Enable steering per role in YAML configuration:

Configuration Options

OptionTypeDefaultDescription
message_steeringbool | MessageSteeringProtocolFalseEnable steering
max_messagesint50Queue capacity (in constructor)
check_intervalfloat0.1Poll interval in seconds
When message_steering=False (default), there’s zero overhead - the feature has no performance impact when disabled.

Agent Methods

MethodSignatureDescription
steeragent.steer(message: str, priority: int = 5) -> strQueue a steering message. Returns tracking ID.
get_steering_statusagent.get_steering_status() -> Dict[str, Any]Returns {enabled, pending_count, has_pending}
message_steering_enabled (property)agent.message_steering_enabled -> boolWhether steering is active

Custom Steering Backends

Implement MessageSteeringProtocol to plug custom backends:
Mid-loop drains rely on repeated has_pending_messages() + dequeue calls, so a custom backend must implement both correctly for mid-run injection to work.

Best Practices

Start agents in background threads to enable concurrent steering. The threaded pattern is the primary use case for message steering.
Use NORMAL (5) for style guidance, HIGH (10) for course corrections, URGENT (20) to interrupt tools, and INTERRUPT (30) only for immediate stops.
Steering messages are injected into prompts. Keep them brief and actionable for best results.
Use get_steering_status() to check pending messages and ensure your guidance is being processed.

When wrapping a steering-enabled agent in a chat bot, set the bot’s busy_mode="steer" to surface this capability to end users. See Bot Run Control.

Pre/post execution hooks (compile-time interception)

Interactive input vs background steering