Skip to main content
Bot platform adapters now ship in the praisonai-bot package. praisonai bot serve still works exactly as documented here; for a standalone install see praisonai-bot Migration.
Bot run control provides responsive feedback during long-running agent tasks, eliminating silent blocking where follow-up messages queue invisibly.
The user sends a message while a long run is active; the bot acknowledges busy state, queues follow-ups, or honours /stop.

Quick Start

1

Enable Run Control

2

Test with Long Task

Send a long-running request like “research solar energy trends” to your bot, then immediately send another message. You’ll get instant feedback instead of silence.
3

Try /stop Command

While the bot is working, send /stop to cancel the current task. The bot responds immediately and starts fresh.

How It Works

Fixed in PR #1980 (release after 2026-06-19): earlier releases wired the interrupt controller to the wrong attribute, so /stop and busy_mode="interrupt" silently had no effect. Queued follow-ups were surfaced in metadata but never drained — upgrade to pick up the fix.
STEER mode is fully wired as of PR #2244 (release after 2026-06-24). Earlier releases declared busy_mode="steer" but silently fell back to queue mode. Upgrade to use real mid-run steering.
Extended in PR #2751 (release after 2026-07-07): /stop now aborts runs on non-OpenAI providers too (Anthropic, Gemini, Groq, local models via litellm). Previously the interrupt controller only reached the OpenAI completion path in chat_mixin — the llm/llm.py tool loop used for every other provider took no cancel token, so /stop on a Telegram/Discord bot backed by e.g. Claude would silently continue to completion. Upgrade to pick up uniform cancellation.
Extended in PR #2997 (release after 2026-07-14): /stop is now re-checked immediately before dispatching tool calls in every tool-loop iteration (both LiteLLM and OpenAI-native, sync and async). Previously the cancel token was only checked at the top of each iteration, so a /stop arriving between the model returning tool calls and the tools starting could still run the tools once before honouring the cancel.
STEER lane — when busy_mode="steer" and the agent has message_steering=True: When run_timeout is exceeded (default 300 seconds), BotSessionManager raises BotRunTimeout and cancels the in-flight run. Timeout failures are not pushed to the DLQ, so slow agents do not retry in a loop.

Choosing a Busy Mode


How STEER Mode Works

  • Enable steering on the agent with message_steering=True.
  • Set the bot’s busy_mode="steer".
  • Mid-run messages are injected into the live turn at SteeringPriority.INTERRUPT (priority 30); the agent picks them up before its next tool-loop step.
Custom integrators embedding chat_with_run_control() must call register_agent(...) on every fresh and pending run inside the drain loop — not only the first run — so STEER always has a live agent handle.

Configuration Options

Configure run control through BotConfig or directly with bot constructors:

RunDecision enum

submit() returns a RunDecision value that tells the bot how to handle the message:

Run metadata

chat_with_run_control returns {"response": str, "metadata": dict}: Acknowledgment messages: Queue drain implemented in PR #1980.

Programmatic steering

Inject real-time guidance into a running agent from outside the bot chat — useful for admin hooks, orchestrators, or test harnesses:
agent.steer(text, priority=30) queues text into the agent’s steering queue at priority 30 (SteeringPriority.INTERRUPT — highest available). The agent picks it up before its next tool-loop step without cancelling the current run. register_agent / finish_run / stop lifecycle: Fallback path: If submit() is called with busy_mode="steer" but no agent is registered (session.agent is None) or the agent has message_steering disabled, submit() falls back to QUEUE silently — no error is raised.

Programmatic cancellation

BotSessionManager exposes cancellation for admin hooks or custom integrations:

BotConfig API Reference

Full configuration options for bot settings

Common Patterns

Long Research Bot (Queue Mode)

Interactive Chat Bot (Interrupt Mode)

Real-Time Steering Bot (Steer Mode)

Example user flow:

Using /stop Mid-Task

When a bot is processing a long request:

Best Practices

Use queue mode for bots that do important work users shouldn’t lose — research bots, analysis tools, content generators. Users get acknowledgments but work continues.Use interrupt mode for conversational bots where the latest message reflects user intent — chat assistants, Q&A bots, real-time helpers.Use steer mode when you want users to nudge the agent mid-task (“focus on the API section instead”, “also include market size”) without losing the partial progress already made. The agent must be created with message_steering=True; otherwise STEER safely falls back to queue.
/stop works on stock bots without setting busy_mode. The handler tries SessionRunControl.stop() first when run control is enabled, then falls back to BotSessionManager.cancel_run() on the default session manager. Enable run control (busy_mode) when you also want mid-run pending-message handling — not as a prerequisite for /stop.
Each run gets a unique generation number. When a run finishes, it only clears the session state if its generation matches the current one. This prevents cancelled runs from overwriting fresh state when they complete.
Use SessionRunControl.cleanup_stale_sessions(max_age_seconds=3600) to clean up old sessions. This prevents memory leaks in long-running bots and removes abandoned user sessions.
If you embed BotSessionManager.chat_with_run_control() in a custom bot, attach interrupt controllers to agent.interrupt_controller (the public attribute on Agent). An earlier underscore-prefixed name was unreliable and made /stop a no-op for custom integrations. The built-in bots (TelegramBot, etc.) handle this attachment automatically.

Bot Commands

Built-in chat commands including /stop and /queue — /queue pairs naturally with busy_mode for parking follow-ups while a task runs

Messaging Bots

Complete guide to Telegram, Discord, Slack bots

Message Steering

Enable message_steering=True on the agent so STEER mode can inject mid-run guidance