Files
agents_and_robots/dev/issues/completed/0012-threads.md
T
egutierrez 8db65ed062 docs: cerrar issue 0012 — thread detection via encrypted event cache
Marca el issue 0012-threads como completado. El problema de que el agente respondia en el hilo principal en lugar del thread esta resuelto con el cache de eventos cifrados implementado en esta rama.
2026-03-08 18:06:09 +00:00

3.1 KiB

Task 011 — Matrix Thread Support

Objetivo

Permitir que los agentes mantengan conversaciones en threads de Matrix (m.thread), de forma que cada interaccion con un usuario pueda vivir en un hilo separado en lugar de la timeline principal del room.

Las respuestas del agente deben volver en el hilo y no en la rama principal

Contexto

Matrix soporta threads via m.relates_to con rel_type: "m.thread". Un thread siempre referencia un evento raiz y opcionalmente incluye m.in_reply_to como fallback para clientes sin soporte de threads.

{
  "m.relates_to": {
    "rel_type": "m.thread",
    "event_id": "$rootEventId",
    "is_falling_back": true,
    "m.in_reply_to": {
      "event_id": "$lastEventInThread"
    }
  }
}

Prerequisito

  • Task: Reply simple (m.in_reply_to) ya implementado.

Plan de implementacion

1. Detectar threads entrantes en el Listener

  • En shell/matrix/listener.go, al parsear el evento, extraer m.relates_to
  • Si rel_type == "m.thread", capturar event_id como ThreadRootID
  • Propagar ThreadRootID en MessageContext

2. Extender MessageContext

  • pkg/decision/types.go: anadir ThreadRootID string (el evento raiz del thread)
  • Esto es dato puro, no rompe la arquitectura

3. Extender ReplyAction

  • pkg/decision/types.go: anadir ThreadRootID string a ReplyAction
  • El runner usara esto para decidir si enviar como thread o como mensaje normal

4. SendThreadMarkdown en Client

  • shell/matrix/client.go: nuevo metodo SendThreadMarkdown(ctx, roomID, threadRootID, inReplyTo, markdown)
  • Construye el m.relates_to con rel_type: "m.thread" + fallback m.in_reply_to

5. Actualizar effects/Runner

  • shell/effects/runner.go: si ReplyAction.ThreadRootID != "", usar SendThreadMarkdown
  • Actualizar interfaz MatrixSender con el nuevo metodo

6. Propagacion en runtime.go

  • Cuando el mensaje entrante ya esta en un thread (msgCtx.ThreadRootID != ""), las respuestas del bot deben continuar en ese thread
  • Cuando el usuario inicia una conversacion nueva, decidir segun config si crear thread o no

7. Configuracion por agente

  • internal/config/schema.go: anadir opcion matrix.threads.enabled: bool y matrix.threads.auto_thread: bool (crear thread automatico por cada conversacion nueva)
  • Default: enabled: true, auto_thread: false

8. Memory por thread

  • La window de conversacion deberia poder ser por thread en vez de por room
  • Si ThreadRootID != "", usar threadRootID como key de la window en vez de roomID
  • Esto permite conversaciones paralelas en threads distintos sin mezclarse

9. Tests

  • Unit tests para SendThreadMarkdown (verificar estructura JSON)
  • Test de integracion: listener detecta thread entrante y propaga ThreadRootID
  • Test: respuesta dentro de thread mantiene el thread root correcto

Notas

  • is_falling_back: true siempre debe estar cuando se usa thread + in_reply_to fallback
  • El event_id de m.relates_to (nivel top) siempre apunta al root del thread, nunca cambia
  • El m.in_reply_to dentro del thread apunta al ultimo mensaje respondido
  • Clientes sin soporte de threads ven el fallback como un reply normal