Ir al contenido

Implementa Session Binding en OpenClaw: Guía técnica

Seguro que te ha pasado: intentas gestionar sesiones de usuario y terminas con una mezcla caótica de lógica de entrega y detalles específicos de la plataforma. Mantener la consistencia cuando escalas a diferentes canales puede volverse una pesadilla técnica si no separas bien las responsabilidades desde el principio.

Este plan se centra en poner orden en ese caos, moviendo la lógica de vinculación al core y dejando que los adapters se encarguen de lo que mejor saben hacer.

Este documento define el modelo de vinculación de sesiones (session binding) independiente del canal a largo plazo y el alcance concreto para la próxima iteración de implementación.

Objetivos:

  • Convertir el enrutamiento de sesiones vinculadas a subagents en una capacidad core.
  • Mantener el comportamiento específico de cada canal en los adapters.
  • Evitar regresiones en el comportamiento normal de Discord.
  • Asegurar la escalabilidad para futuros canales de comunicación.

El comportamiento actual mezcla varias políticas que deberían estar separadas:

  • Política de contenido de completion.
  • Política de enrutamiento de destino.
  • Detalles específicos de Discord.
  • Gestión de estados de sesión.

Esto ha provocado casos problemáticos como:

  • Entrega duplicada en el canal principal y en el thread bajo ejecuciones concurrentes.
  • Uso de tokens obsoletos en gestores de vinculación reutilizados.
  • Falta de registro de actividad para los envíos mediante webhook.
  • Dificultad para auditar el flujo de mensajes de salida.

Esta iteración está limitada intencionadamente para asegurar la estabilidad del sistema.

1. Añadir interfaces core independientes del canal

Sección titulada «1. Añadir interfaces core independientes del canal»

Añadiremos tipos core e interfaces de servicio para las vinculaciones y el enrutamiento.

Tipos core propuestos:

export type BindingTargetKind = "subagent" | "session";
export type BindingStatus = "active" | "ending" | "ended";
export type ConversationRef = {
channel: string;
accountId: string;
conversationId: string;
parentConversationId?: string;
};
export type SessionBindingRecord = {
bindingId: string;
targetSessionKey: string;
targetKind: BindingTargetKind;
conversation: ConversationRef;
status: BindingStatus;
boundAt: number;
expiresAt?: number;
metadata?: Record<string, unknown>;
};

Contrato del servicio core:

export interface SessionBindingService {
bind(input: {
targetSessionKey: string;
targetKind: BindingTargetKind;
conversation: ConversationRef;
metadata?: Record<string, unknown>;
ttlMs?: number;
}): Promise<SessionBindingRecord>;
listBySession(targetSessionKey: string): SessionBindingRecord[];
resolveByConversation(ref: ConversationRef): SessionBindingRecord | null;
touch(bindingId: string, at?: number): void;
unbind(input: {
bindingId?: string;
targetSessionKey?: string;
reason: string;
}): Promise<SessionBindingRecord[]>;
}

2. Añadir un router de entrega core para completions de subagents

Sección titulada «2. Añadir un router de entrega core para completions de subagents»

Añadiremos una única ruta de resolución de destino para los eventos de completion.

Contrato del router:

export interface BoundDeliveryRouter {
resolveDestination(input: {
eventKind: "task_completion";
targetSessionKey: string;
requester?: ConversationRef;
failClosed: boolean;
}): {
binding: SessionBindingRecord | null;
mode: "bound" | "fallback";
reason: string;
};
}

Para esta iteración:

  • Solo task_completion se enruta a través de esta nueva ruta.
  • Las rutas existentes para otros tipos de eventos se mantienen igual.

Discord sigue siendo la primera implementación del adapter.

Responsabilidades del adapter:

  • Crear o reutilizar conversaciones de thread.
  • Enviar mensajes vinculados mediante webhook o envío directo al canal.
  • Validar el estado del thread (archivado o eliminado).
  • Mapear metadatos del adapter (identidad del webhook, IDs de thread).

4. Corregir problemas de precisión conocidos

Sección titulada «4. Corregir problemas de precisión conocidos»

En esta iteración es obligatorio:

  • Refrescar el uso de tokens al reutilizar un gestor de vinculación de thread existente.
  • Registrar la actividad de salida para los envíos de Discord basados en webhook.
  • Detener el fallback implícito al canal principal cuando se selecciona un destino de thread vinculado para un completion en modo sesión.
  • Mejorar la trazabilidad de errores de entrega en flujos vinculados.

5. Preservar los valores predeterminados de seguridad en runtime

Sección titulada «5. Preservar los valores predeterminados de seguridad en runtime»

No habrá cambios de comportamiento para los usuarios que tengan desactivado el spawn vinculado a threads.

Los valores predeterminados se mantienen:

  • channels.discord.threadBindings.spawnSubagentSessions = false

Resultado:

  • Los usuarios normales de Discord mantienen el comportamiento actual.
  • La nueva ruta core solo afecta al enrutamiento de completion de sesiones vinculadas donde esté activado.

He pospuesto explícitamente lo siguiente:

  • Objetivos de vinculación ACP (targetKind: "acp").
  • Nuevos adapters de canal más allá de Discord.
  • Reemplazo global de todas las rutas de entrega (spawn_ack, futuro subagent_message).
  • Cambios a nivel de protocolo.
  • Rediseño de la migración o versionado del store para la persistencia de vinculaciones.

Notas sobre ACP:

  • El diseño de la interfaz deja espacio para ACP.
  • La implementación de ACP no se inicia en esta iteración.

Estas reglas son obligatorias para la iteración 1:

  • La selección del destino y la generación de contenido son pasos separados.
  • Si un completion en modo sesión se resuelve en un destino vinculado activo, la entrega debe dirigirse a ese destino.
  • No habrá redirecciones ocultas desde un destino vinculado al canal principal.
  • El comportamiento de fallback debe ser explícito y observable.

Objetivo de compatibilidad:

  • Sin regresiones para usuarios con el spawn vinculado a threads desactivado.
  • Sin cambios en los canales que no sean Discord en esta iteración.

Despliegue:

  1. Implementar interfaces y el router tras las feature gates actuales.
  2. Enrutar las entregas vinculadas en modo completion de Discord a través del router.
  3. Mantener la ruta legacy para flujos no vinculados.
  4. Verificar con pruebas dirigidas y logs de runtime en canary.

Cobertura de unidad e integración necesaria:

  • La rotación de tokens del manager usa el último token tras la reutilización del manager.
  • Los envíos por webhook actualizan las marcas de tiempo de actividad del canal.
  • Dos sesiones vinculadas activas en el mismo canal solicitante no duplican mensajes al canal principal.
  • El completion para una ejecución en modo sesión vinculada se resuelve solo al destino del thread.

Core:

  • src/infra/outbound/session-binding-service.ts (nuevo)
  • src/infra/outbound/bound-delivery-router.ts (nuevo)
  • src/agents/subagent-announce.ts (integración de resolución de destino de completion)

Discord adapter y runtime:

  • src/discord/monitor/thread-bindings.manager.ts
  • src/discord/monitor/reply-delivery.ts
  • src/discord/send.outbound.ts

Tests:

  • src/discord/monitor/provider*.test.ts
  • src/discord/monitor/reply-delivery.test.ts
  • src/agents/subagent-announce.format.test.ts

Criterios de finalización para la Iteración 1

Sección titulada «Criterios de finalización para la Iteración 1»
  • Las interfaces core existen y están conectadas para el enrutamiento de completion.
  • Las correcciones de precisión mencionadas arriba están fusionadas con sus pruebas.
  • No hay entregas de completion duplicadas en el canal principal y el thread en ejecuciones vinculadas de modo sesión.
  • No hay cambios de comportamiento en despliegues con el spawn vinculado desactivado.
  • Revisar la documentación de la API de Discord para la gestión de threads.
  • Consultar los estándares de persistencia en src/infra/storage.

AI Setup Assistant

OpenClaw

OpenClaw Expert

Sigues atascado?

Si esta pagina no resolvio tu caso, pregunta a OpenClaw Expert para pasos concretos.