#22486: feat: add /agent command for dynamic per-chat agent switching
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
#6084: Add dynamic Telegram agent routing for DM and groups
by Alfonsxh · 2026-02-01
67.4%
#23614: feat(routing): add sessionScope binding override for session key sc...
by hmemcpy · 2026-02-22
67.3%
#13167: feat(agents): dispatch Claude Code CLI runs as persistent, resumabl...
by gyant · 2026-02-10
66.1%
#20661: feat: agent lifecycle & parenting primitives
by brancante · 2026-02-19
65.4%
#21959: feat(config): add per-agent thinkingDefault, heartbeat thinking ove...
by heyhudson · 2026-02-20
65.2%
#10383: feat(hooks): add agentId to hook mappings
by quentintou · 2026-02-06
65.0%
#23356: feat(slack): pass agent identity via chat:write.customize
by keshav55 · 2026-02-22
65.0%
#15030: Agents: support per-agent thinking defaults
by sauerdaniel · 2026-02-12
64.3%
#19581: feat: add XMTP channel plugin for wallet-to-agent messaging
by coffeexcoin · 2026-02-18
64.0%
#19329: feat: add per-agent compaction and context pruning overrides
by curtismercier · 2026-02-17
63.5%