Diseña tarjetas de mensaje
Todo lo que publica un bot, ya venga de un webhook, de la respuesta a un comando o de la actualización tras pulsar un botón, es una tarjeta. Una buena tarjeta cuenta de un vistazo lo que ha pasado: un borde de color, un título, un estado y los detalles debajo.
Qué puedes hacer
- Muestra un estadoUna píldora de color como Open, Merged o Passing, con las líneas añadidas y eliminadas.
- Enumera los detallesFilas de etiqueta y valor que los miembros copian con un toque.
- Escribe en markdownNegrita, código en línea, bloques de código, citas y casillas.
- Muestra que estás trabajandoUn spinner mientras tu bot piensa, y después su razonamiento tras un interruptor.
En la app
Cuatro tarjetas tal como las ven los miembros. Cada una son unas pocas líneas de JSON.
Anatomía de una tarjeta
Las partes de una tarjeta, de arriba abajo. Omite lo que no necesites: una tarjeta con solo un título también vale.
- Cabecera"Message from" y un nombre: el del webhook, o el de tu comunidad en la respuesta a un comando. Una respuesta puede añadir un
badge, como el repositorio. - Título y estadoEl
title, que es un enlace si definestitle_url, con la píldora destatusal lado. - SubtítuloUna segunda línea en negrita,
sub_title. - DescripciónEl cuerpo, en markdown.
- CamposFilas de etiqueta y valor, con un botón para copiar.
- PieLa hora, y las líneas añadidas y eliminadas si las envías.
{
"message_container": {
"type": "embed_message",
"badge": "acme/web",
"color": "purple",
"title": "Pull request #212 opened",
"title_url": "https://github.com/acme/web/pull/212",
"status": { "label": "Open", "color": "green", "icon": "pull_request" },
"sub_title": "Faster search in the channel list",
"description": "Search now runs **per keystroke** with a 120 ms debounce.",
"fields": [
{ "field": "Author", "value": "maya" },
{ "field": "Reviewers", "value": "dani, sam" }
],
"additions": 86,
"deletions": 12,
"files_changed": 3
}
}Todos los campos
Van dentro de message_container. Una tarjeta necesita una descripción o un loader. Los campos marcados como "Respuestas a comandos" se descartan cuando publicas a través de un webhook.
| Campo | Tipo | Qué hace |
|---|---|---|
type | string | embed_message (por defecto) o system_message. |
badge | string | Una pequeña etiqueta tras el nombre en la cabecera, como acme/web. Respuestas a comandos |
avatar_url | string | Una imagen sobre el icono de la tarjeta. |
color | string | El color del borde. Consulta los colores más abajo. |
title | string | La primera línea, en negrita. |
title_url | string | Convierte el título en un enlace. |
sub_title | string | Una segunda línea en negrita bajo el título. |
description | string | El cuerpo, en markdown. |
fields | array | [{ "field": "…", "value": "…" }]: filas de etiqueta y valor. |
image_url, image_base64 | string | Una imagen en la tarjeta. |
images | array | [{ "image_url": "…" }]: una galería de varias imágenes. |
status | object o string | Una píldora de color junto al título. Ver más abajo. Respuestas a comandos |
additions, deletions, files_changed | number | Estadísticas de diff en el pie. Respuestas a comandos |
loader, loader_text, loader_sub_text | boolean, string | Un spinner en lugar del cuerpo. |
thinking | string | Razonamiento tras un interruptor Show thinking. Respuestas a comandos |
thinking entienden markdown: **bold**, _italic_, ~~strike~~, `inline code`, bloques de código delimitados, > quotes, casillas - [x], @menciones y :emoji:.Estado y estadísticas de diff
Una píldora de estado cuenta la historia antes de que nadie lea el texto. Va junto al título, o en el pie cuando no hay título; las estadísticas de diff aparecen junto a la hora. Ambas funcionan en respuestas a comandos, y la integración de GitHub incluida las usa. Un webhook las descarta.
{
"message_container": {
"color": "red",
"title": "Build failed on main",
"status": { "label": "Failing", "color": "red" },
"description": "`search.test.js`: 2 of 212 tests failed."
}
}| Campo | Tipo | Qué hace |
|---|---|---|
status | object o string | Un string sin más es la etiqueta: "status": "Open". |
status.label | string | El texto de la píldora. Sin él no hay píldora. |
status.color | string | green, purple, red, orange, yellow, blue o gray. |
status.icon | string | Un icono opcional de la lista de abajo. |
additions | number | Líneas añadidas, en verde como +86. |
deletions | number | Líneas eliminadas, en rojo como -12. |
files_changed | number | Archivos modificados, mostrados como 3 files. |
Iconos
| Valor | Icono | Uso habitual |
|---|---|---|
pull_request | git-pull-request | Se ha abierto una pull request |
pull_request_closed | git-pull-request-closed | Cerrada sin fusionar |
merge, merged | git-merge | Fusionada |
commit | git-commit | Un commit con push |
issue | circle-dot | Se ha abierto una issue |
issue_closed | circle-check | Se ha cerrado una issue |
check | circle-check | Tests superados, un job completado con éxito |
Una correspondencia que funciona para GitHub
La integración de GitHub incluida usa estos valores; cópialos para tus propias herramientas.
| Evento | Etiqueta | Color | Icono |
|---|---|---|---|
| Pull request abierta | Open | green | pull_request |
| Borrador | Draft | gray | pull_request |
| Fusionada | Merged | purple | merged |
| Cerrada sin fusionar | Closed | red | pull_request_closed |
| Issue abierta | Open | green | issue |
| Issue cerrada | Closed | purple | issue_closed |
| Commit con push | Commit | gray | commit |
| Tests superados | Passing | green | check |
| Tests fallidos | Failing | red | ninguno |
Loader y razonamiento
Para todo lo que tarda un poco, como una respuesta de IA o un trabajo largo, publica primero una tarjeta con un spinner y luego sustitúyela por el resultado. El loader funciona desde webhooks y en respuestas a comandos. En la respuesta a un comando también puedes poner el razonamiento del modelo en thinking: los miembros ven un interruptor Show thinking en lugar de un muro de texto.
Primero: el loader
Después: la respuesta, con el razonamiento plegado
{
"message_container": {
"type": "embed_message",
"color": "blue",
"loader": true,
"loader_text": "Thinking…",
"loader_sub_text": "Reading the last 50 messages"
}
}{
"message_container": {
"type": "embed_message",
"color": "blue",
"sub_title": "maya: when is the standup?",
"description": "Standup is at **09:30**, in #daily.",
"thinking": "Checked the pinned messages and the recurring event in #daily…"
}
}| Campo | Tipo | Qué hace |
|---|---|---|
loader | boolean | true muestra el spinner en lugar del cuerpo. |
loader_text | string | La línea junto al spinner, como "Pensando…". |
loader_sub_text | string | Una línea más pequeña debajo. |
thinking | string | Razonamiento plegado bajo la descripción, en markdown. |
Para cambiar el loader por la respuesta, actualiza el mensaje con una tarjeta nueva sin loader. Cómo hacerlo está en actualizaciones en directo.
Descripciones largas
Una descripción puede tener hasta 50.000 bytes. A partir de los primeros 1.000, los miembros ven el principio y un botón Show more que carga el resto, así que un informe largo no inunda el canal.
Mensajes del sistema
Pon "type": "system_message" para un aviso en lugar de una publicación de bot: ventanas de mantenimiento, cambios de normas, cualquier cosa que hable en nombre de la propia comunidad. Admite los mismos campos y botones.
{
"message_container": {
"type": "system_message",
"color": "orange",
"title": "Maintenance tonight",
"description": "The build servers are down from 22:00 to 23:00."
}
}Colores
El color del borde es la señal más rápida de una tarjeta. Usa siempre el mismo color para el mismo tipo de noticia.
| Color | Úsalo para |
|---|---|
green | Éxito: superado, desplegado, hecho |
red | Fallo: ha fallado, caído, rechazado |
orange | Un aviso que conviene revisar |
yellow | Pendiente de alguien: aprobaciones, preguntas |
blue | Información, el valor por defecto |
purple | Eventos de código, o algo especial |
Crea tu embed
Edita los campos o el payload JSON: los dos se mantienen sincronizados. La vista previa muestra el mensaje exactamente como aparecerá en un canal. Este es el body real del webhook; cópialo cuando todo esté bien.