Files
agents_and_robots/dev/issues/012-threads.md
T
egutierrez f561f686c4 refactor: migrar tasks/ a dev/issues/ con estructura de desarrollo
Se mueve la documentación de issues/tasks de .claude/tasks/ a dev/issues/
para separar la planificación de desarrollo de la configuración de Claude.
Se añade dev/README.md como índice de la carpeta de desarrollo. Los issues
completados se mueven a dev/issues/completed/. Esto permite que dev/ sea
el punto central de documentación interna del proyecto.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 17:41:16 +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.

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