Hilos, reacciones y actividad
Hilos, reacciones y actividad
En el capítulo 4 enviaste mensajes a un canal. Ese es el piso. Este capítulo es sobre lo que pasa encima de un mensaje: las respuestas que forman un hilo, las reacciones que resumen una decisión en un glifo, y el sistema de actividad que te dice qué de todo eso merece tu atención.
Los tres temas están más conectados de lo que parece. En Buzz, si una respuesta aparece en la línea de tiempo del canal o se queda dentro del hilo, si te llega una notificación o no, y si un emoji dispara una automatización, son todas consecuencias de los mismos tags firmados en el evento. Entender esa mecánica evita dos errores caros: ahogar el canal con ruido, y perderte la respuesta que sí te tocaba.
El hilo como unidad de trabajo
Un canal es una fila lineal. Un hilo es una conversación anidada colgando de un mensaje
de esa fila. Buzz implementa hilos con NIP-10, el estándar de Nostr para respuestas:
no hay una estructura paralela ni un identificador propietario de “hilo”, solo tags e
marcados dentro del mismo evento kind:9 que ya conoces.
Una respuesta lleva dos marcadores:
["e", "<id-del-padre>", "", "reply"]— el mensaje inmediato al que respondes.["e", "<id-de-la-raíz>", "", "root"]— el mensaje que abrió el hilo.
Cuando respondes directamente al primer mensaje del hilo, padre y raíz son el mismo evento. Cuando respondes a una respuesta, la raíz sigue siendo el mensaje original.
La especificación interna del proyecto, docs/nips/NIP-CW.md, define el predicado de
forma tajante: un evento es una respuesta si y solo si lleva un tag e marcado con
reply. Un evento que solo lleva un tag root, o tags e sin marcador, o ninguno,
no es una respuesta. Esa distinción no es cosmética: de ella salen la profundidad,
la clasificación de la línea de tiempo y las notificaciones.
flowchart TD
R["Mensaje raíz — depth 0"] --> A["Respuesta directa — depth 1"]
R --> B["Otra respuesta directa — depth 1"]
A --> C["Respuesta a la respuesta — depth 2"]
C --> D["Más abajo — depth 3"]
R -.->|"vive en la línea de tiempo"| T["Timeline del canal"]
A -.->|"solo si lleva broadcast"| T
B -.-> P["Panel de hilo"]
C -.-> P
D -.-> P
La profundidad se calcula en el relay al momento de ingerir el evento: la profundidad de
una respuesta es la de su padre más uno. El relay corta en 100: pasado ese punto
rechaza el evento con thread depth limit exceeded. No es un límite que vayas a tocar
escribiendo a mano, pero sí uno que un agente en bucle puede alcanzar.
Lo que el relay valida al recibir una respuesta
El relay no acepta respuestas huérfanas ni cruzadas. Antes de guardar el evento comprueba la ascendencia y devuelve mensajes de error explícitos:
| Mensaje del relay | Qué significa |
|---|---|
reply parent not found | El evento padre no existe en este relay |
parent event belongs to a different channel | Intentaste colgar una respuesta de un mensaje de otro canal |
parent event has no channel association | El padre no es un evento de canal |
root tag does not match thread ancestry | Tu tag root no coincide con la raíz real del hilo |
thread depth limit exceeded | Superaste los 100 niveles de anidamiento |
Esto es importante para la práctica diaria: los hilos no cruzan canales. Si quieres continuar una conversación en otro canal, se pega el enlace y se abre un hilo nuevo allá.
Responder desde la terminal
El comando es el mismo buzz messages send del capítulo anterior, más un flag:
buzz messages send \
--channel 9a2f1c40-6b1d-4e0a-9c77-0f9c2b3d4e55 \
--content "Reproduje el bug con Node 22. Va el stack en el próximo mensaje." \
--reply-to 4f0c9d2b1a8e7f6c5d4b3a29180716253442536170819293a4b5c6d7e8f90112
--reply-to recibe el padre inmediato, no la raíz. El CLI hace el resto: consulta ese
evento en el relay, lee sus tags NIP-10 y deriva la raíz del hilo por su cuenta. Si el
padre no tiene marcador root, entonces él mismo es la raíz. Tú nunca escribes el tag
root a mano.
Eso explica un detalle práctico: responder cuesta una consulta extra de red antes del envío, así que un script que responde en ráfaga es más lento que uno que envía mensajes sueltos.
Como cualquier envío, la respuesta acepta las mismas capacidades del capítulo 4:
# Respuesta larga leída de un archivo
buzz messages send --channel <uuid> --reply-to <event-id> --content - < analisis.md
# Respuesta con adjuntos y una mención explícita
buzz messages send --channel <uuid> --reply-to <event-id> \
--content "@Mara acá está el log completo" \
--file ./relay.log \
--mention npub1ejemplo...
El contenido tiene un tope duro de 65 536 bytes. Un log entero no cabe: súbelo como archivo.
Leer un hilo completo
buzz messages thread --channel <uuid> --event <event-id-de-la-raíz>
--event es el identificador del mensaje raíz. El CLI lanza dos filtros en una sola
llamada HTTP: uno que trae las respuestas que referencian ese evento por tag e, y otro
que trae el evento raíz por id. Después ordena todo por created_at ascendente y lo
imprime. Es decir: la salida ya viene en orden de lectura, raíz primero.
Los kinds que el filtro de respuestas incluye son 9, 40002, 40003, 40008 y 45003: el mensaje de stream normal, el mensaje enriquecido v2, la edición, el diff y el comentario de foro. Un hilo con un parche pegado aparece completo; un hilo con reacciones no las incluye, porque las reacciones se consultan aparte.
Dos flags para acotar:
| Flag | Efecto |
|---|---|
--limit <u32> | Máximo de respuestas. Default 100, tope 500 |
--depth-limit <u32> | Máxima profundidad de anidamiento incluida |
Con --depth-limit 1 obtienes solo las respuestas directas a la raíz, sin las
sub-respuestas. Es la forma barata de leer el resumen de un hilo largo antes de decidir
si bajas al detalle.
Y como todo lo del CLI, el modo compacto reduce cada evento a lo esencial para escanear
rápido. Recuerda que --format es un flag global y va antes del grupo:
buzz --format compact messages thread --channel <uuid> --event <event-id>
Los enlaces profundos a un hilo
Los enlaces buzz://message?channel=<uuid>&id=<hex> que ves pegados en el workspace
apuntan a un mensaje concreto: extraes esos dos parámetros y los pasas a
messages thread. El parámetro opcional thread que a veces trae la URL se puede
ignorar, porque el comando resuelve el hilo completo a partir del id del evento.
El resumen de hilo que ves en el cliente
Cuando el escritorio pinta la línea de tiempo, no cuenta respuestas por su cuenta. El relay le adjunta un evento firmado por él mismo, kind:39005, uno por cada fila que tenga respuestas, con este contenido:
{
"reply_count": 7,
"descendant_count": 11,
"last_reply_at": 1785312400,
"participants": ["<pubkey-hex>", "..."]
}
participants trae hasta 10 pubkeys, los más recientes primero. Ese evento se sintetiza
en el momento de la consulta y nunca se almacena: es metadato de presentación, no
historia. Por eso los contadores de un hilo siempre son consistentes con lo que hay,
aunque alguien borre una respuesta.
Responder en el canal o responder en el hilo
Esta es la decisión que más impacto tiene en la salud de un canal, y en Buzz está definida por una regla mecánica, no por convención social.
Una fila de la línea de tiempo del canal es top-level si y solo si:
- su profundidad es 0, es decir no es una respuesta; o
- su profundidad es 1 y lleva el tag
["broadcast", "1"].
Traducido: por defecto las respuestas no entran nunca a la línea de tiempo del canal. Viven en el panel de hilo. Una respuesta de segundo nivel o más profunda no puede aparecer en el canal bajo ninguna circunstancia, ni con broadcast.
flowchart LR
M["Envías un mensaje"] --> Q{"¿Lleva tag reply?"}
Q -->|no| TL["Fila del canal — depth 0"]
Q -->|sí| D{"¿Cuál es la profundidad?"}
D -->|"depth 1"| B{"¿Lleva broadcast 1?"}
D -->|"depth 2 o más"| HI["Solo dentro del hilo"]
B -->|sí| TL
B -->|no| HI
El efecto práctico es el que conoces de cualquier chat con hilos bien hechos: el canal se mantiene legible porque solo lleva aperturas de conversación, y el detalle se hunde donde corresponde. La diferencia es que en Buzz esa regla la aplica el relay al servir la ventana del canal, no el cliente al pintar. Cualquier cliente que hable con este relay ve la misma línea de tiempo.
Difundir una respuesta al canal
Cuando una respuesta deja de ser detalle y pasa a ser la conclusión que todos necesitan,
la sacas al canal con --broadcast:
buzz messages send \
--channel <uuid> \
--reply-to <event-id-de-la-raíz> \
--content "Resuelto: era el timeout del pool. Fix desplegado en staging." \
--broadcast
Lo que hace el flag es concreto y verificable: el constructor de eventos añade el tag
["broadcast", "1"] al kind:9. El relay lo lee al ingerir y lo guarda en los metadatos
del hilo; a partir de ahí, si la respuesta es de profundidad 1, la ventana del canal la
incluye como fila.
Nota sobre la ayuda del comando. El texto que muestra
buzz messages send --helppara--broadcastdice “Also publish to the Nostr network”. El efecto real en el código —constructor de eventos, ingesta del relay y especificación NIP-CW— es el que se describe aquí: sacar la respuesta a la línea de tiempo del canal. Fíate del comportamiento, no de esa línea de ayuda.
Tres consecuencias que conviene tener claras antes de usarlo:
- Solo funciona en profundidad 1. Si respondes a una respuesta, el tag viaja pero no te sube al canal. Si quieres difundir una conclusión que nació abajo en el hilo, respóndele a la raíz.
- Fuerza notificación. En el cliente de escritorio, una respuesta con broadcast se considera siempre notificable, sin importar si seguías el hilo o si silenciaste el canal. Es el mecanismo más ruidoso que tienes.
- Es una decisión del autor, no del lector. Nadie puede “bajar” tu broadcast del canal ni subir una respuesta ajena. Lo eliges al escribir.
Hoy el flag existe en buzz-cli. El cliente de escritorio lee y clasifica
correctamente los broadcast —los pinta como fila del canal y los notifica— pero no
encontrarás un interruptor de difusión en su compositor de respuestas.
Reacciones
Una reacción es un evento kind:7, el estándar NIP-25 de Nostr. El contenido del
evento es el emoji; el estándar admite además + y - como pulgar arriba y abajo
genéricos.
# Reaccionar
buzz reactions add --event <event-id> --emoji "👍"
# Quitar tu reacción
buzz reactions remove --event <event-id> --emoji "👍"
# Ver todas las reacciones de un mensaje
buzz reactions get --event <event-id>
Detalles que importan:
- No pasas canal. El relay deriva el canal de la reacción desde el tag
#edel evento objetivo. Un#hque mande el cliente se ignora para determinar el canal. - Quitar una reacción es un borrado.
reactions removebusca tu propio kind:7 con ese emoji sobre ese evento y publica un kind:5 de NIP-09 apuntándolo. Si no encuentras la reacción, el error es explícito:no reaction with emoji '👍' found for your pubkey on event <id>. getagrupa por ti. La salida no es la lista cruda de eventos sino un agregado ordenado alfabéticamente por emoji:
{
"reactions": [
{ "emoji": "🎉", "count": 2, "pubkeys": ["<hex>", "<hex>"] },
{ "emoji": "👍", "count": 5, "pubkeys": ["<hex>", "..."] }
]
}
En la aplicación de escritorio, el mismo gesto vive en la barra de acciones que aparece al pasar el cursor sobre un mensaje: un botón React que abre el selector de emoji, junto a Reply, y en el menú de tres puntos las acciones Edit message, Mark read / Mark unread y Follow thread / Unfollow thread. Los cuatro emoji de acceso rápido que trae por defecto son 👍 ❤️ 😂 🎉, y la lista se reordena sola con los que más usas, guardada localmente por comunidad.
Emoji personalizados
Cada miembro publica su propio set de emoji como un evento kind:30030. La “paleta del workspace” no es estado del servidor: es la unión del lado cliente de los sets de todos los miembros, calculada al leer.
buzz emoji list # la paleta completa del workspace
buzz emoji set --shortcode ship-it --url https://…/ship-it.png
buzz emoji rm --shortcode ship-it
buzz emoji export --scope workspace --file paleta.json
buzz emoji import --file paleta.json --dry-run
El shortcode va sin los dos puntos. import fusiona por defecto en tu set; con
--replace lo sustituye entero, y --dry-run te muestra qué publicaría sin escribir
nada.
Para reaccionar con uno de esos emoji desde el CLI se pasa la URL de la imagen; el
contenido del evento pasa entonces a ser :shortcode::
buzz reactions add --event <event-id> --emoji ship-it --emoji-url https://…/ship-it.png
Reacciones que hacen trabajo
Aquí la reacción deja de ser un gesto social. Buzz tiene un tipo de disparador de workflow
que se llama reaction_added, y con él un emoji se convierte en un botón.
name: "Aprobar despliegue a staging"
trigger:
on: reaction_added
emoji: "🚀"
steps:
- id: avisar
action: send_message
text: "{{trigger.author | npub}} aprobó el despliegue con 🚀"
- id: marcar
action: add_reaction
emoji: "✅"
Cómo funciona, exactamente:
- El campo
emojies opcional. Si lo omites, el workflow dispara con cualquier reacción en el canal. Si lo pones, la comparación es de igualdad exacta contra el contenido del evento kind:7; cualquier otro emoji se descarta en silencio. - Dentro de las condiciones
if:tienes las variablestrigger_emoji,trigger_message_idytrigger_author. En las plantillas,{{trigger.emoji}},{{trigger.message_id}}y{{trigger.author}}. - La acción
add_reactionreacciona sobre el mensaje que originó el disparo, así que exige quetrigger.message_idno esté vacío.
sequenceDiagram
participant U as Tú
participant R as Relay
participant W as Motor de workflows
participant C as Canal
U->>R: kind 7 con contenido 🚀 sobre el mensaje X
R->>W: evento de reacción del canal
W->>W: ¿coincide el emoji declarado?
W->>C: paso 1 — send_message
W->>R: paso 2 — add_reaction ✅ sobre X
C-->>U: el canal muestra el aviso y el visto
El patrón que esto habilita es el que hace que un canal se sienta una herramienta: alguien publica un diff, el equipo lo revisa dentro del hilo, y quien tiene la autoridad le pone 🚀 al mensaje raíz. La reacción es el registro firmado de quién aprobó y cuándo, y además es el gatillo.
Dos advertencias de honestidad técnica:
- Las compuertas de aprobación de workflows —el paso
request_approvalque suspende la ejecución y espera unbuzz workflows approve --token …— están en la columna 🚧 del README: la infraestructura existe, el pegamento todavía no. Una corrida que llega a esa puerta hoy no se reanuda. Un flujo basado enreaction_addedsí funciona completo. buzz workflows runsdevuelve[]hoy, porque las corridas se guardan en una tabla del relay y no como eventos Nostr.
Los workflows completos —esquema YAML, condiciones, plantillas, permisos— son el capítulo 11. Aquí solo te interesa saber que la reacción es un disparador de primera clase.
Actividad: qué existe hoy
Buzz tiene un feed de actividad servido por el relay y consumible desde el CLI:
buzz feed get
buzz feed get --types mentions,needs_action --limit 30
buzz feed get --since 1785225600 --types activity
Los tipos válidos son exactamente cuatro, y cualquier otro valor da un error de uso que lista las opciones:
| Tipo | Qué trae |
|---|---|
mentions | Eventos donde tu pubkey aparece en un tag p: mensajes de canal, notas, posts y comentarios de foro, y los eventos git de PR, issue y estado |
needs_action | Solo dos kinds, dirigidos a ti: 46010 solicitud de aprobación de workflow, y 40007 recordatorio |
activity | Mensajes, posts de foro y eventos de trabajos de agente en los canales a los que tienes acceso |
agent_activity | Alias: el relay lo canonicaliza a activity |
El límite del CLI es 20 por defecto con tope 50; el relay además corta cualquier
consulta de feed en 100 filas. Los eventos vienen ordenados por created_at
descendente.
Un detalle que explica por qué el feed se siente limpio: las trazas de ejecución de
workflows —los kinds 46001 a 46012— están excluidas a propósito de activity para no
inundarlo de ruido. Lo que sí llega es lo que tiene sentido leer como persona.
El feed en la aplicación de escritorio
El escritorio consume las mismas categorías y las agrupa en la vista de inicio. La regla
para decidir si un evento te genera una alerta está implementada en
desktop/src/features/notifications/lib/shouldNotify.ts y vale la pena conocerla porque
determina qué te llega:
flowchart TD
E["Llega un evento"] --> BR{"¿Es una respuesta con broadcast?"}
BR -->|sí| N["Notifica"]
BR -->|no| ME{"¿Te menciona por tag p?"}
ME -->|sí| N
ME -->|no| MC{"¿El canal está silenciado?"}
MC -->|sí| S["No notifica"]
MC -->|no| TR{"¿Es una respuesta de hilo?"}
TR -->|no| N
TR -->|sí| MR{"¿El hilo está silenciado?"}
MR -->|sí| S
MR -->|no| PF{"¿Participaste, lo sigues o lo abriste tú?"}
PF -->|sí| N
PF -->|no| S
En palabras: broadcast y menciones siempre pasan, por encima incluso del silenciado de canal. Los mensajes de nivel superior de un canal no silenciado notifican. Y una respuesta dentro de un hilo solo te alcanza si tienes relación con ese hilo: escribiste en él, lo abriste tú, o lo marcaste con Follow thread.
Ese “seguir hilo” es una preferencia local de esta máquina, guardada en el
localStorage de la aplicación bajo la clave buzz-thread-follows.v1:<tu-pubkey>, con un
tope de 500 hilos. No es un evento firmado y no viaja con tu identidad a otro dispositivo. Es la diferencia con tu perfil o tu estado, que sí son eventos firmados: ver
el capítulo 3.
El panel de hilo, además, se puede ver de dos formas y el conmutador está sobre el propio hilo: Show thread beside channel lo pone en un panel partido junto al canal, y Expand thread lo abre como superficie de foco. La elección se persiste: el lugar donde formas la opinión es el lugar donde estás mirando el hilo.
Qué no existe todavía
La tabla del README del proyecto separa lo que funciona hoy de lo que está en camino, y esto es lo que corresponde a este capítulo:
| Estado | Elemento |
|---|---|
| ✅ Funciona hoy | Canales, hilos, reacciones, búsqueda, registro de auditoría, aplicación de escritorio, buzz-cli, workflows YAML con disparadores de mensaje, reacción, agenda y webhook |
| 🚧 En construcción | Clientes móviles iOS y Android, compuertas de aprobación de workflows, eventos de ciclo de vida de huddles |
| 💭 Opinión firme, sin código | Notificaciones push, reputación de red de confianza entre relays, funciones de cultura |
Léelo literal: no hay notificaciones push. Lo que hay son notificaciones locales de la aplicación de escritorio mientras está abierta, y el feed que puedes consultar cuando quieras desde el cliente o desde el CLI. Si tu flujo depende de que te lleguen alertas al teléfono, ese camino todavía no está construido, y los clientes móviles están en la columna de en medio. El capítulo 13 cubre lo que sí puedes hacer hoy con clientes de terceros.
El documento de visión del feed de actividad de agentes agrega un principio que conviene tener en la cabeza al supervisar delegados: nunca quedarse a oscuras. La ausencia de un evento también es información, así que silencio, inactividad y tiempo agotado se renderizan como estados —“esperando…”, “expiró”— y no como un vacío. Es una declaración de diseño sobre la dirección del producto, no un inventario de funciones ya construidas.
Etiqueta en un espacio compartido con agentes
Todo lo anterior cambia de peso cuando en el canal hay agentes leyendo. No son personas que perdonan una ambigüedad: son procesos suscritos a filtros. Algunas reglas que se caen solas de la mecánica que acabas de ver:
Responde en el hilo por defecto, difunde por excepción. Cada --broadcast es una
notificación forzada para todo el canal, humanos incluidos, que pasa por encima del
silenciado. Úsalo para conclusiones y bloqueos, no para “gracias”.
Menciona con intención. El tag p es lo que hace que un mensaje aparezca en el feed
de mentions de alguien y lo que despierta al agente suscrito a menciones. Mencionar a
tres personas “por si acaso” son tres interrupciones. Y ojo: el CLI valida que los pubkeys
mencionados sean miembros del canal; si no lo son, falla con la lista de faltantes y el
comando exacto para añadirlos.
Una decisión, una reacción. Si el equipo acordó que 🚀 aprueba un despliegue, ese emoji
deja de ser decorativo. Ponerlo “de broma” en un mensaje del canal equivocado puede
disparar un workflow real. Conviene que el canal declare su convención en el topic o en
el canvas, y que los emoji que disparan automatizaciones sean distintos de los de uso
social.
Deja el hilo cerrado. Un hilo que termina sin una respuesta que diga el resultado obliga a todo el que llegue después —persona o agente que hace búsqueda— a reconstruirlo. Una respuesta final con broadcast que diga qué se decidió vale más que veinte mensajes de proceso. El capítulo 8 trata de cómo se encuentra eso después.
No edites para cambiar el sentido. Editar es un evento kind:40003 aparte, el original sigue existiendo, y quien ya leyó no vuelve. Si cambió la conclusión, respóndete en el hilo.
Las reacciones ajenas no son tuyas. Solo quien reaccionó puede retirarlas, publicando su propio borrado. Cualquier acción sobre contenido de terceros es materia de moderación y requiere privilegios de operador: eso se cubre en el curso de administrador, no aquí.
Errores frecuentes y qué significan
| Lo que ves | Causa | Qué hacer |
|---|---|---|
reply parent not found | El id que pasaste a --reply-to no existe en este relay | Verifica el id con buzz social event --event <id> |
parent event belongs to a different channel | Estás respondiendo a un mensaje de otro canal | Los hilos no cruzan canales: abre uno nuevo o corrige --channel |
root tag does not match thread ancestry | Un cliente mandó un root inventado | Deja que el CLI derive la raíz: pasa solo --reply-to |
thread depth limit exceeded | Más de 100 niveles de anidamiento | Responde a la raíz en lugar de seguir bajando |
invalid: reaction target event not found | Reaccionaste a un evento que el relay no conoce | Confirma que el mensaje existe y que estás en el canal |
no reaction with emoji 'X' found for your pubkey… | Intentas quitar una reacción que no pusiste tú | buzz reactions get te muestra quién puso qué |
mentioned pubkeys are not channel members | Mencionaste a alguien que no está en el canal | El error trae el comando channels add-member listo |
invalid feed type "X" | Tipo de feed inexistente | Solo mentions, needs_action, activity, agent_activity |
Un mensaje que no verás pero conviene conocer si usas un cliente Nostr de terceros: si
te suscribes solo por kind a las reacciones con {"kinds":[7]} no recibirás ninguna. El
relay mantiene estrictamente separadas las suscripciones globales de las acotadas a canal,
y las reacciones son de canal. Hay que suscribirse con
{"kinds":[7],"#h":["<channel-uuid>"]}.
Resumen
- Los hilos de Buzz son NIP-10 estándar: una respuesta lleva
["e", "<padre>", "", "reply"]y, si corresponde, un marcadorroot. El CLI deriva la raíz por ti a partir de--reply-to. - El relay valida la ascendencia al ingerir: los hilos no cruzan canales, y la profundidad máxima es 100.
buzz messages thread --channel <uuid> --event <id>devuelve el hilo ordenado; default 100 respuestas, tope 500, y--depth-limitrecorta el anidamiento.- Una respuesta nunca entra a la línea de tiempo del canal, salvo que sea de
profundidad 1 y lleve el tag
["broadcast", "1"]que añade--broadcast. - Un broadcast fuerza notificación por encima del silenciado de canal: es el recurso más ruidoso que tienes, y por eso se reserva para conclusiones.
- Las reacciones son kind:7 / NIP-25; el canal se deriva del evento objetivo.
reactions removepublica un borrado kind:5, yreactions getdevuelve el agregado emoji / count / pubkeys. - Los emoji personalizados son kind:30030 por miembro; la paleta del workspace es la unión calculada al leer, no estado del servidor.
- Una reacción puede disparar un workflow con
on: reaction_added, con emoji exacto opcional. Las compuertasrequest_approval, en cambio, todavía no se reanudan. buzz feed get --types …acepta exactamentementions,needs_action,activityyagent_activity;needs_actionson solo aprobaciones de workflow y recordatorios.- En el escritorio te notifican: broadcast, menciones, mensajes de nivel superior de canales no silenciados y respuestas de hilos con los que tienes relación. Follow thread es preferencia local, no viaja entre dispositivos.
- No hay notificaciones push, y los clientes móviles están en construcción según el README del proyecto.
Siguiente: Mensajes directos y privacidad