← Back to PRs

#22486: feat: add /agent command for dynamic per-chat agent switching

by cesarfavero open 2026-02-21 06:48 View on GitHub →
channel: telegram agents size: M
## Summary Adds a native `/agent` command that allows users to dynamically switch the active agent for any chat session at runtime — without restarting the gateway or editing config files. Works across **all channels**: Telegram, Discord, WhatsApp, Signal, Slack, and any other supported surface. ## Motivation Currently, each chat is statically bound to a single agent via config bindings. Users who run multiple agents (e.g. a general assistant, a project-specific agent, a security agent) have no way to switch between them within the same chat. This feature introduces a lightweight, persistent per-chat agent override system that integrates cleanly with the existing routing architecture. ## Changes ### New files - **`src/routing/dynamic-bindings.ts`** — A persistent key-value store (`channel:peerId → agentId`) backed by `~/.openclaw/state/agent-overrides.json`. Provides get/set/clear/invalidate operations with in-memory caching. Channel-agnostic — works for any channel type. - **`src/auto-reply/reply/commands-agent.ts`** — Command handler for `/agent` across all non-Telegram channels. Supports three modes: - `/agent` — Show current active agent and list available agents - `/agent <id>` — Switch to a specific agent (validated against `agents.list`) - `/agent default|reset` — Clear override, revert to default routing ### Modified files - **`src/routing/resolve-route.ts`** — `resolveAgentRoute()` checks dynamic overrides **before** static bindings, using a new `"dynamic-override"` match type. - **`src/auto-reply/commands-registry.data.ts`** — Registered `/agent` as a text-scope command (all channels). - **`src/auto-reply/reply/commands-core.ts`** — Wired `handleAgentCommand` into the command handler chain. - **`src/telegram/bot-handlers.ts`** — Dedicated instant interceptor for Telegram that bypasses the message queue. Handles both text commands and inline button callbacks. - **`src/telegram/bot.ts`** — Separate sequential key (`agent-switch`) so `/agent` updates are not serialized behind ongoing chat processing (matches the pattern used by `/stop`). - **`src/telegram/bot-native-commands.ts`** — Menu-only entry for Telegram command list. - **`src/agents/identity.ts`** — Updated identity prefix format to `EMOJI NAME\n` (e.g. `⚡ STARK`) for clearer agent identification in responses. ## Design decisions - **Override-before-bindings**: Dynamic overrides are checked first in the routing pipeline. If no override exists, all existing binding logic remains unchanged. - **Persistence**: Overrides survive gateway restarts via a JSON file in the state directory. The store is intentionally separate from session storage because routing overrides must be resolved *before* the agent (and thus the session) is known — avoiding a chicken-and-egg dependency. - **Multi-channel**: The routing store and command handler are channel-agnostic. Telegram gets an additional instant-processing optimization via a dedicated interceptor. - **Telegram instant processing**: On Telegram, `/agent` uses a separate sequential key (like `/stop`) so it processes immediately without waiting for the current agent response to complete. - **Authorization**: Only authorized senders can switch agents. - **Validation**: Agent IDs are validated against `agents.list` in config. - **No session migration**: Switching agents changes routing for future messages. Each agent maintains its own session history independently. ## Usage ``` /agent → Show active agent and available agents /agent ordera → Switch to agent 'ordera' for this chat /agent main → Switch back to main agent /agent default → Clear override, revert to default routing ``` ## Testing Tested manually on a live Telegram bot with multiple configured agents (main, ordera, security). Verified: - [x] `/agent` shows correct current agent and available list - [x] `/agent <id>` switches routing for subsequent messages - [x] `/agent default` clears override and reverts to default - [x] Invalid agent IDs are rejected with helpful error - [x] Override persists across gateway restarts - [x] Heartbeat, updates, and other system functions unaffected - [x] Build passes (`pnpm build` clean) - [x] Instant processing on Telegram (no queue delay) - [x] Inline button callbacks work immediately - [x] Command appears in Telegram menu - [x] Handler works for non-Telegram channels via command pipeline

Most Similar PRs