Enrutamiento Multi-Agente
Objetivo: múltiples agentes aislados (workspace separado + agentDir + sesiones), más múltiples cuentas de canal (ej. dos WhatsApps) en un solo Gateway en ejecución. Los mensajes entrantes se enrutan a un agente mediante bindings.
Qué es “un agente”
Un agente es un cerebro completamente aislado con su propio:
- Workspace (archivos, AGENTS.md/SOUL.md/USER.md, notas locales, reglas de personalidad).
- Directorio de estado (
agentDir) para perfiles de autenticación, registro de modelos y configuración por agente. - Almacén de sesiones (historial de chat + estado de enrutamiento) bajo
~/.openclaw/agents/<agentId>/sessions.
Los perfiles de autenticación son por agente. Cada agente lee desde su propio:
~/.openclaw/agents/<agentId>/agent/auth-profiles.json
Las credenciales del agente principal no se comparten automáticamente. Nunca reutilices agentDir
entre agentes (causa colisiones de autenticación/sesión). Si quieres compartir credenciales,
copia auth-profiles.json al agentDir del otro agente.
Los skills son por agente vía la carpeta skills/ de cada workspace, con skills compartidos
disponibles desde ~/.openclaw/skills. Consulta Skills: por agente vs compartidos.
El Gateway puede alojar un agente (por defecto) o muchos agentes en paralelo.
Nota sobre workspace: el workspace de cada agente es el cwd por defecto, no un sandbox estricto. Las rutas relativas se resuelven dentro del workspace, pero las rutas absolutas pueden alcanzar otras ubicaciones del host a menos que el sandboxing esté habilitado. Consulta Sandboxing.
Rutas (mapa rápido)
- Configuración:
~/.openclaw/openclaw.json(oOPENCLAW_CONFIG_PATH) - Directorio de estado:
~/.openclaw(oOPENCLAW_STATE_DIR) - Workspace:
~/.openclaw/workspace(o~/.openclaw/workspace-<agentId>) - Directorio del agente:
~/.openclaw/agents/<agentId>/agent(oagents.list[].agentDir) - Sesiones:
~/.openclaw/agents/<agentId>/sessions
Modo de un solo agente (por defecto)
Si no haces nada, OpenClaw ejecuta un solo agente:
agentIdpor defecto esmain.- Las sesiones se indexan como
agent:main:<mainKey>. - El workspace por defecto es
~/.openclaw/workspace(o~/.openclaw/workspace-<profile>cuandoOPENCLAW_PROFILEestá configurado). - El estado por defecto está en
~/.openclaw/agents/main/agent.
Helper de agente
Usa el asistente de agente para agregar un nuevo agente aislado:
openclaw agents add work
Luego agrega bindings (o deja que el asistente lo haga) para enrutar los mensajes entrantes.
Verifica con:
openclaw agents list --bindings
Inicio rápido
Paso 1: Crea el workspace de cada agente
Usa el asistente o crea los workspaces manualmente:
openclaw agents add coding
openclaw agents add social
Cada agente obtiene su propio workspace con SOUL.md, AGENTS.md y USER.md opcional, más un agentDir dedicado y almacén de sesiones bajo ~/.openclaw/agents/<agentId>.
Paso 2: Crea las cuentas de canal
Crea una cuenta por agente en tus canales preferidos:
- Discord: un bot por agente, habilita Message Content Intent, copia cada token.
- Telegram: un bot por agente vía BotFather, copia cada token.
- WhatsApp: vincula cada número de teléfono por cuenta.
openclaw channels login --channel whatsapp --account work
Consulta las guías de canales: Discord, Telegram, WhatsApp.
Paso 3: Agrega agentes, cuentas y bindings
Agrega agentes bajo agents.list, cuentas de canal bajo channels.<channel>.accounts y conéctalos con bindings (ejemplos abajo).
Paso 4: Reinicia y verifica
openclaw gateway restart
openclaw agents list --bindings
openclaw channels status --probe
Múltiples agentes = múltiples personas, múltiples personalidades
Con múltiples agentes, cada agentId se convierte en una persona completamente aislada:
- Diferentes números de teléfono/cuentas (por
accountIdde canal). - Diferentes personalidades (archivos de workspace por agente como
AGENTS.mdySOUL.md). - Autenticación + sesiones separadas (sin interferencia a menos que se habilite explícitamente).
Esto permite que múltiples personas compartan un servidor Gateway manteniendo sus “cerebros” IA y datos aislados.
Un número de WhatsApp, múltiples personas (división de DM)
Puedes enrutar diferentes DMs de WhatsApp a diferentes agentes manteniéndote en una sola cuenta de WhatsApp. Haz match por E.164 del remitente (como +15551234567) con peer.kind: "direct". Las respuestas salen del mismo número de WhatsApp (sin identidad de remitente por agente).
Detalle importante: los chats directos se consolidan en la clave de sesión principal del agente, por lo que el aislamiento verdadero requiere un agente por persona.
Ejemplo:
{
agents: {
list: [
{ id: "alex", workspace: "~/.openclaw/workspace-alex" },
{ id: "mia", workspace: "~/.openclaw/workspace-mia" },
],
},
bindings: [
{
agentId: "alex",
match: { channel: "whatsapp", peer: { kind: "direct", id: "+15551230001" } },
},
{
agentId: "mia",
match: { channel: "whatsapp", peer: { kind: "direct", id: "+15551230002" } },
},
],
channels: {
whatsapp: {
dmPolicy: "allowlist",
allowFrom: ["+15551230001", "+15551230002"],
},
},
}
Notas:
- El control de acceso a DM es global por cuenta de WhatsApp (emparejamiento/lista permitida), no por agente.
- Para grupos compartidos, vincula el grupo a un agente o usa Grupos de difusión.
Reglas de enrutamiento (cómo los mensajes eligen un agente)
Los bindings son determinísticos y gana el más específico:
- Match de
peer(ID exacto de DM/grupo/canal) - Match de
parentPeer(herencia de hilo) guildId + roles(enrutamiento por roles de Discord)guildId(Discord)teamId(Slack)- Match de
accountIdpara un canal - Match a nivel de canal (
accountId: "*") - Fallback al agente por defecto (
agents.list[].default, si no el primer elemento de la lista, por defecto:main)
Si múltiples bindings coinciden en el mismo nivel, el primero en orden de configuración gana.
Si un binding establece múltiples campos de match (por ejemplo peer + guildId), todos los campos especificados son requeridos (semántica AND).
Detalle importante del alcance de cuenta:
- Un binding que omite
accountIdsolo coincide con la cuenta por defecto. - Usa
accountId: "*"para un fallback a nivel de canal entre todas las cuentas. - Si después agregas el mismo binding para el mismo agente con un ID de cuenta explícito, OpenClaw actualiza el binding existente de solo canal a alcance de cuenta en lugar de duplicarlo.
Múltiples cuentas / números de teléfono
Los canales que soportan múltiples cuentas (ej. WhatsApp) usan accountId para identificar
cada inicio de sesión. Cada accountId puede enrutarse a un agente diferente, para que un servidor pueda alojar
múltiples números de teléfono sin mezclar sesiones.
Si quieres una cuenta por defecto a nivel de canal cuando se omite accountId, configura
channels.<channel>.defaultAccount (opcional). Cuando no está configurado, OpenClaw recurre
a default si existe, de lo contrario el primer ID de cuenta configurado (ordenado).
Los canales comunes que soportan este patrón incluyen:
whatsapp,telegram,discord,slack,signal,imessageirc,line,googlechat,mattermost,matrix,nextcloud-talkbluebubbles,zalo,zalouser,nostr,feishu
Conceptos
agentId: un “cerebro” (workspace, autenticación por agente, almacén de sesiones por agente).accountId: una instancia de cuenta de canal (ej. cuenta WhatsApp"personal"vs"biz").binding: enruta mensajes entrantes a unagentIdpor(channel, accountId, peer)y opcionalmente IDs de guild/team.- Los chats directos se consolidan en
agent:<agentId>:<mainKey>(“main” por agente;session.mainKey).
Ejemplos por plataforma
Bots de Discord por agente
Cada cuenta de bot de Discord se mapea a un accountId único. Vincula cada cuenta a un agente y mantén las listas permitidas por bot.
{
agents: {
list: [
{ id: "main", workspace: "~/.openclaw/workspace-main" },
{ id: "coding", workspace: "~/.openclaw/workspace-coding" },
],
},
bindings: [
{ agentId: "main", match: { channel: "discord", accountId: "default" } },
{ agentId: "coding", match: { channel: "discord", accountId: "coding" } },
],
channels: {
discord: {
groupPolicy: "allowlist",
accounts: {
default: {
token: "DISCORD_BOT_TOKEN_MAIN",
guilds: {
"123456789012345678": {
channels: {
"222222222222222222": { allow: true, requireMention: false },
},
},
},
},
coding: {
token: "DISCORD_BOT_TOKEN_CODING",
guilds: {
"123456789012345678": {
channels: {
"333333333333333333": { allow: true, requireMention: false },
},
},
},
},
},
},
},
}
Notas:
- Invita cada bot al guild y habilita Message Content Intent.
- Los tokens residen en
channels.discord.accounts.<id>.token(la cuenta por defecto puede usarDISCORD_BOT_TOKEN).
Bots de Telegram por agente
{
agents: {
list: [
{ id: "main", workspace: "~/.openclaw/workspace-main" },
{ id: "alerts", workspace: "~/.openclaw/workspace-alerts" },
],
},
bindings: [
{ agentId: "main", match: { channel: "telegram", accountId: "default" } },
{ agentId: "alerts", match: { channel: "telegram", accountId: "alerts" } },
],
channels: {
telegram: {
accounts: {
default: {
botToken: "123456:ABC...",
dmPolicy: "pairing",
},
alerts: {
botToken: "987654:XYZ...",
dmPolicy: "allowlist",
allowFrom: ["tg:123456789"],
},
},
},
},
}
Notas:
- Crea un bot por agente con BotFather y copia cada token.
- Los tokens residen en
channels.telegram.accounts.<id>.botToken(la cuenta por defecto puede usarTELEGRAM_BOT_TOKEN).
Números de WhatsApp por agente
Vincula cada cuenta antes de iniciar el gateway:
openclaw channels login --channel whatsapp --account personal
openclaw channels login --channel whatsapp --account biz
~/.openclaw/openclaw.json (JSON5):
{
agents: {
list: [
{
id: "home",
default: true,
name: "Home",
workspace: "~/.openclaw/workspace-home",
agentDir: "~/.openclaw/agents/home/agent",
},
{
id: "work",
name: "Work",
workspace: "~/.openclaw/workspace-work",
agentDir: "~/.openclaw/agents/work/agent",
},
],
},
// Enrutamiento determinístico: la primera coincidencia gana (más específico primero).
bindings: [
{ agentId: "home", match: { channel: "whatsapp", accountId: "personal" } },
{ agentId: "work", match: { channel: "whatsapp", accountId: "biz" } },
// Sobrescritura opcional por peer (ejemplo: enviar un grupo específico al agente work).
{
agentId: "work",
match: {
channel: "whatsapp",
accountId: "personal",
peer: { kind: "group", id: "[email protected]" },
},
},
],
// Desactivado por defecto: la mensajería entre agentes debe habilitarse y listarse explícitamente.
tools: {
agentToAgent: {
enabled: false,
allow: ["home", "work"],
},
},
channels: {
whatsapp: {
accounts: {
personal: {
// Sobrescritura opcional. Por defecto: ~/.openclaw/credentials/whatsapp/personal
// authDir: "~/.openclaw/credentials/whatsapp/personal",
},
biz: {
// Sobrescritura opcional. Por defecto: ~/.openclaw/credentials/whatsapp/biz
// authDir: "~/.openclaw/credentials/whatsapp/biz",
},
},
},
},
}
Ejemplo: chat diario en WhatsApp + trabajo profundo en Telegram
Dividir por canal: enruta WhatsApp a un agente rápido de uso diario y Telegram a un agente Opus.
{
agents: {
list: [
{
id: "chat",
name: "Everyday",
workspace: "~/.openclaw/workspace-chat",
model: "anthropic/claude-sonnet-4-5",
},
{
id: "opus",
name: "Deep Work",
workspace: "~/.openclaw/workspace-opus",
model: "anthropic/claude-opus-4-6",
},
],
},
bindings: [
{ agentId: "chat", match: { channel: "whatsapp" } },
{ agentId: "opus", match: { channel: "telegram" } },
],
}
Notas:
- Si tienes múltiples cuentas para un canal, agrega
accountIdal binding (por ejemplo{ channel: "whatsapp", accountId: "personal" }). - Para enrutar un solo DM/grupo a Opus manteniendo el resto en chat, agrega un binding con
match.peerpara ese peer; los match de peer siempre ganan sobre las reglas a nivel de canal.
Ejemplo: mismo canal, un peer a Opus
Mantener WhatsApp en el agente rápido, pero enrutar un DM a Opus:
{
agents: {
list: [
{
id: "chat",
name: "Everyday",
workspace: "~/.openclaw/workspace-chat",
model: "anthropic/claude-sonnet-4-5",
},
{
id: "opus",
name: "Deep Work",
workspace: "~/.openclaw/workspace-opus",
model: "anthropic/claude-opus-4-6",
},
],
},
bindings: [
{
agentId: "opus",
match: { channel: "whatsapp", peer: { kind: "direct", id: "+15551234567" } },
},
{ agentId: "chat", match: { channel: "whatsapp" } },
],
}
Los bindings de peer siempre ganan, así que mantenlos por encima de la regla a nivel de canal.
Agente familiar vinculado a un grupo de WhatsApp
Vincula un agente familiar dedicado a un solo grupo de WhatsApp, con gate de menciones y una política de herramientas más restrictiva:
{
agents: {
list: [
{
id: "family",
name: "Family",
workspace: "~/.openclaw/workspace-family",
identity: { name: "Family Bot" },
groupChat: {
mentionPatterns: ["@family", "@familybot", "@Family Bot"],
},
sandbox: {
mode: "all",
scope: "agent",
},
tools: {
allow: [
"exec",
"read",
"sessions_list",
"sessions_history",
"sessions_send",
"sessions_spawn",
"session_status",
],
deny: ["write", "edit", "apply_patch", "browser", "canvas", "nodes", "cron"],
},
},
],
},
bindings: [
{
agentId: "family",
match: {
channel: "whatsapp",
peer: { kind: "group", id: "[email protected]" },
},
},
],
}
Notas:
- Las listas allow/deny de herramientas son herramientas, no skills. Si un skill necesita ejecutar un
binario, asegúrate de que
execesté permitido y que el binario exista en el sandbox. - Para un gate más estricto, configura
agents.list[].groupChat.mentionPatternsy mantén habilitadas las listas permitidas de grupo para el canal.
Sandbox y configuración de herramientas por agente
A partir de v2026.1.6, cada agente puede tener su propio sandbox y restricciones de herramientas:
{
agents: {
list: [
{
id: "personal",
workspace: "~/.openclaw/workspace-personal",
sandbox: {
mode: "off", // Sin sandbox para el agente personal
},
// Sin restricciones de herramientas - todas las herramientas disponibles
},
{
id: "family",
workspace: "~/.openclaw/workspace-family",
sandbox: {
mode: "all", // Siempre en sandbox
scope: "agent", // Un contenedor por agente
docker: {
// Configuración opcional de una sola vez después de crear el contenedor
setupCommand: "apt-get update && apt-get install -y git curl",
},
},
tools: {
allow: ["read"], // Solo herramienta read
deny: ["exec", "write", "edit", "apply_patch"], // Denegar otras
},
},
],
},
}
Nota: setupCommand reside bajo sandbox.docker y se ejecuta una vez al crear el contenedor.
Las sobrescrituras de sandbox.docker.* por agente se ignoran cuando el alcance resuelto es "shared".
Beneficios:
- Aislamiento de seguridad: Restringe herramientas para agentes no confiables
- Control de recursos: Pon en sandbox agentes específicos manteniendo otros en el host
- Políticas flexibles: Diferentes permisos por agente
Nota: tools.elevated es global y basado en remitente; no es configurable por agente.
Si necesitas límites por agente, usa agents.list[].tools para denegar exec.
Para targeting de grupos, usa agents.list[].groupChat.mentionPatterns para que las @menciones se mapeen limpiamente al agente deseado.
Consulta Sandbox y herramientas multi-agente para ejemplos detallados.