PLAYBOOK UC3-CHANNELS REV 1.0 FECHA 21 JUN 2026 DEPENDE P0 + UC1

Playbook · UC3 · Mac Peers Channels

Playbook UC3
Mac Peers Channels

Dos sesiones independientes de Claude Code en el mismo Mac, ambas lanzadas con cl minimax --proxy --channels. El objetivo es verificar que se ven mutuamente (ListPeers), que pueden enviarse mensajes (SendPeerMessage) y que los mensajes llegan en tiempo real vía channel-push del broker, sin polling del inbox.

Esfuerzo
15 min
Depende de
P0 (prerequisites) + UC1 (proxy)
Bloquea
UC4 (spawn) · UC5 (workspace E2E)
Criticidad
[[bad:ALTA]] — si esto falla, el ecosistema a2a está roto
Broker prod vivo a2a MCP configurado en Mac Sin verificación runtime
01

Objetivo

Dos sesiones Claude Code en Mac, ambas con cl minimax --proxy --channels, deben poder: (1) verse mutuamente vía ListPeers, (2) enviarse mensajes vía SendPeerMessage, (3) recibir los mensajes en tiempo real vía channel-push (<channel> blocks inline), sin necesidad de polling del inbox. Si esto no funciona, el ecosistema a2a está roto.

drag to pan · scroll to zoom · double-click to fit
Sesión Acl minimax--proxy --channelsSesión Bcl minimax--proxy --channelsBroker públicobroker.gateway.mks2508.systemsmcpAmcpBa2a-mcp(stdio MCP)a2a-mcp(stdio MCP) REST: ListPeersREST: SendPeerMessageREST: ListPeersREST: SendPeerMessage CHANNEL PUSH:<channel from_id="B">message</channel> CHANNEL PUSH:<channel from_id="A">message</channel>SendPeerMessage to B'hola desde A'REALTIME PUSHsin polling
Sesión Acl minimax--proxy --channelsSesión Bcl minimax--proxy --channelsBroker públicobroker.gateway.mks2508.systemsmcpAmcpBa2a-mcp(stdio MCP)a2a-mcp(stdio MCP) REST: ListPeersREST: SendPeerMessageREST: ListPeersREST: SendPeerMessage CHANNEL PUSH:<channel from_id="B">message</channel> CHANNEL PUSH:<channel from_id="A">message</channel>SendPeerMessage to B'hola desde A'REALTIME PUSHsin polling
02

Arquitectura del channel-push

1
Channel-push — Mecanismo realtimeWebSocket al broker → server-push → <channel> block inline en Claude Code
Dos mecanismos complementarios
MCP tools (REST) → SendPeerMessage, ListPeers, CheckInbox Channel-push (WS) → /ws/broker/peer/:id → push server-initiated
MCP tools13 tools vía REST al broker
  • SendPeerMessage → POST /api/peers/:id/message
  • ListPeers → GET /api/peers
  • CheckInbox → POST /api/peers/:id/inbox/read
Channel-push WSConexión persistente al broker
  • A2A_CHANNEL_PUSH=1 activa el WS
  • Recibe mensajes como notifications/claude/channel
  • Ack selectivo tras renderizado
  • Reconnect con backoff exponencial
  • Seen-cache (500 IDs) anti-duplicados
Workloads → Mensajería instantánea peer-to-peerSin polling del inbox
Requisitos para channel-push

Para que el channel-push funcione, la sesión Claude Code necesita ambas cosas:

  1. a2a MCP configuradomcpServers.agent2agent con GATEWAY_BASE_URL apuntando al broker y A2A_CHANNEL_PUSH=1
  2. dangerouslyLoadDevelopmentChannels: ["server:agent2agent"] — en el settings.json del provider dir que se está usando

Ambas cosas las mergea claudio --channels automáticamente desde ~/.claude/settings.json. NO editar settings.json manualmente — siempre usar claudio para configurar modos.

03

F1 — Preparación

3 min

Verificar configuración antes de arrancar

  • claudio minimax --env --channels → emite exports sin errores Verificar que claudio puede mergear a2a MCP + channels para MiniMax
  • cat ~/.claude-minimax/settings.json | python3 -c "import json,sys; d=json.load(sys.stdin); print('a2a' in d.get('mcpServers',{}))" → True a2a MCP está en el settings.json del provider dir
  • cat ~/.claude-minimax/settings.json | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('dangerouslyLoadDevelopmentChannels'))" → ['server:agent2agent'] Channels flag está en el settings.json
  • Broker reachable: curl -s https://broker.gateway.mks2508.systems/healthz → 200 El broker público está vivo
  • OIDC token válido: source .env.brk-extract.local && curl -s https://broker.gateway.mks2508.systems/api/peers -H "Authorization: Bearer $TOKEN" → 200 Autenticación OIDC funciona
04

F2 — Arrancar sesión A {#f2-sessionA}

3 min

Primera sesión Claude Code con channels

  • En terminal 1: ejecutar cl minimax --proxy --channels Arranca Claude Code con MiniMax vía proxy + channels activos
  • Dentro de Claude Code A, ejecutar ListPeers Debe mostrar la lista de peers (al menos ella misma)
  • Ejecutar GetPeer con el peerId de la sesión A Debe mostrar la card del peer A con status 'running'

Sesión A — comandos de verificación

Terminal 1 — Sesión A
# Arrancar sesión A
$ cl minimax --proxy --channels

# Dentro de Claude Code A:
> ListPeers
→ [
→   {
→     "id": "a1b2c3d4-...",
→     "kind": "operator",
→     "name": "Claude Code — A",
→     "status": "running",
→     ...
→   }
→ ]

> GetPeer a1b2c3d4-...
→ (card completa del peer A)

# Guardar el peerId de A para usarlo desde B
> (anotar: A_ID = "a1b2c3d4-...")
05

F3 — Arrancar sesión B y peer discovery {#f3-sessionB}

3 min

Segunda sesión — debe ver a la primera

  • En terminal 2: ejecutar cl minimax --proxy --channels (segunda instancia) Segunda sesión Claude Code independiente
  • Dentro de Claude Code B, ejecutar ListPeers Debe mostrar DOS peers: A y B
  • El peer A aparece con status 'running' en la lista de B La sesión B ve a la sesión A
  • Ejecutar SendPeerMessage de B → A con 'hola desde B' Mensaje enviado via REST al broker → entregado a A via channel-push

Sesión B — comandos de verificación

Terminal 2 — Sesión B
# Arrancar sesión B en otra terminal
$ cl minimax --proxy --channels

# Dentro de Claude Code B:
> ListPeers
→ [
→   {"id": "a1b2c3d4-...", "kind": "operator", "name": "Claude Code — A", "status": "running"},
→   {"id": "e5f6g7h8-...", "kind": "operator", "name": "Claude Code — B", "status": "running"}
→ ]

# Enviar mensaje a la sesión A:
> SendPeerMessage to=a1b2c3d4-... content="hola desde B"
→ {"delivered": true, "messageId": "msg_..."}
06

F4 — Verificar realtime channel-push

3 min

El mensaje debe aparecer en tiempo real

  • En terminal 1 (sesión A), aparece un bloque <channel> inline con el mensaje de B El bloque se ve como: <channel source='agent2agent' from_id='e5f6g7h8-...' kind='request' priority='normal'>hola desde B</channel>
  • La sesión A puede responder con SendPeerMessage to=e5f6g7h8-... content='respuesta desde A' Respuesta de vuelta a B
  • En terminal 2 (sesión B), aparece el bloque <channel> con la respuesta de A Bidireccional confirmado
  • NO se usó CheckInbox ni InboxCount en ningún momento Los mensajes llegaron por channel-push, no por polling

Verificación del channel block inline

Representación del channel block

Cuando un peer recibe un mensaje vía channel-push, Claude Code muestra un bloque inline como este — no un tool result, no un mensaje del sistema. Es un <channel> block renderizado como notificación inline, similar a un @mention.

<channel source="agent2agent" from_id="e5f6g7h8-..."
         kind="request" priority="normal">
hola desde B
</channel>
Qué ver en la terminal de la sesión A
# Después de que B envía "hola desde B", en la sesión A aparece:

<channel source="agent2agent" from_id="e5f6g7h8-..."
         kind="request" priority="normal">
hola desde B
</channel>

# La sesión A puede responder directamente:
> SendPeerMessage to=e5f6g7h8-... content="hola desde A, te he recibido!"
→ {"delivered": true}

# Y en la sesión B aparece en tiempo real:
<channel source="agent2agent" from_id="a1b2c3d4-..."
         kind="request" priority="normal">
hola desde A, te he recibido!
</channel>
Si NO aparece el channel block inline

Posibles causas:

  1. dangerouslyLoadDevelopmentChannels no está en settings.json — verificar con python3 -c "import json; d=json.load(open('$CLAUDE_CONFIG_DIR/settings.json')); print(d.get('dangerouslyLoadDevelopmentChannels'))"
  2. tengu_harbor no está pineado a true — GrowthBook puede haberlo sobreescrito. Verificar en ~/.claude-minimax/.claude.json el campo cachedGrowthBookFeatures.tengu_harbor
  3. a2a-mcp no tiene A2A_CHANNEL_PUSH=1 — verificar en el .claude.json de la sesión
  4. El broker no tiene el peer registrado — verificar con curl /api/peers
  5. El WebSocket no se pudo establecer — revisar logs del a2a-mcp en stderr

Si todo lo anterior está bien pero aún no llega, el problema está en el channel-push WS o en la integración con Claude Code. Revisar [a2a-mcp] logs.

07

F5 — Diagnóstico si falla

5 min

Diagnóstico de fallos channel-push

  • curl -s https://broker.gateway.mks2508.systems/api/peers -H 'Authorization: Bearer $JWT' | jq 'length' → ≥2 Ambos peers registrados en el broker
  • a2a inbox <peerId> → el mensaje está en el inbox (fallback polling) Si el mensaje está en el inbox pero no llegó por channel, el WS falló
  • Revisar stderr de a2a-mcp en busca de errores de WebSocket [a2a-mcp] logs — buscar 'ws error', 'reconnect', 'channel'
  • curl -s https://broker.gateway.mks2508.systems/api/broker/metrics → deliveries count Métricas del broker muestran si los mensajes se entregaron
Debe pasar4 checks
  • ListPeers muestra ambos peers Peer discovery funciona
  • SendPeerMessage → delivered: true Mensajería REST funciona
  • block aparece en la sesión destino Channel-push realtime funciona
  • Respuesta bidireccional Ciclo completo A→B→A
Puede fallar (esperable)2 checks
  • El channel block tarda >5s en aparecer Posible reconnect del WS con backoff
  • Solo funciona el polling (CheckInbox) pero no channel-push El WS está caído pero el REST funciona
Si falla → crítico1 check
  • SendPeerMessage no entrega (delivered: false) El broker no enruta mensajes — revisar peers registrados
Q1

¿Se ven los dos peers con ListPeers? discovery

Después de arrancar ambas sesiones, ejecutar ListPeers en cualquiera

Sí → 2 peers Continuar a F4 (enviar mensaje). Peer discovery funciona.
No → solo 1 peer Revisar: (1) ¿están ambas sesiones apuntando al MISMO broker? (GATEWAY_BASE_URL), (2) ¿está el broker accesible desde ambas?, (3) ¿se registró el peer correctamente? (ver logs de a2a-mcp)
Q2

¿Llega el mensaje en tiempo real? channel-push

Enviar SendPeerMessage desde B a A y observar terminal A

Sí → <channel> block UC3 VERDE. Channel-push funciona. El ecosistema a2a está sano.
No → solo inbox Channel-push roto. El REST funciona pero el WS no. Revisar logs [a2a-mcp] y métricas del broker. Posible regresión en channel-push-ws.ts.

Código channel-push

Tests existentes