Communitygithub.com

LienzzoDev/agent-skills

Construye un asistente de ayuda integrado en una aplicación web: un panel en cada pantalla que responde a preguntas '¿cómo hago…?' con las etiquetas exactas de la aplicación, muestra capturas de pantalla ampliadas que señalan el botón a presionar, enlaza a las pantallas que el usuario puede abrir y (opcionalmente) lee sus propios datos y prepara acciones sin ejecutarlas. Úsalo al añadir un asistente de ayuda/soporte o un copiloto a un producto existente, cuando un agente existente debe aprender cómo funciona la interfaz de la aplicación, o al migrar este patrón a otro repositorio.

¿Qué es agent-skills?

Esta habilidad te permite crear un asistente de ayuda contextual para cualquier aplicación web existente. El asistente se integra como un panel en cada pantalla y responde preguntas del tipo '¿cómo hago…?' proporcionando pasos numerados con las etiquetas exactas de la UI, capturas de pantalla que señalan el botón a presionar, enlaces a pantallas accesibles, y opcionalmente la capacidad de leer datos del usuario y preparar acciones para que las confirme, sin ejecutarlas automáticamente. Es útil para agregar un copiloto de ayuda o soporte a productos ya desarrollados, para permitir que un agente existente aprenda la interfaz de la aplicación, o para portar este patrón a otro repositorio. La habilidad incluye un sistema completo: un manual estructurado en markdown, capturas de pantalla con zonas clicables, enlaces solo a rutas permitidas, herramientas de solo lectura y botones de acción preparados, todo versionado con el código. También proporciona pautas para pruebas deterministas, evaluación con preguntas reales, y métricas de rendimiento y coste.

Compatible con~Claude Code~Codex CLI✓Cursor✓Gemini CLI
npx skills add https://github.com/LienzzoDev/agent-skills/tree/HEAD/skills/in-app-help-assistant

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Asistente de ayuda integrado en la aplicación

Un asistente que vive dentro de una aplicación web y conoce cómo se usa esa aplicación. Responde a preguntas como "¿cómo solicito un permiso?" con pasos numerados que usan las etiquetas exactas de la interfaz. Debajo del paso correcto muestra una captura de pantalla ampliada, y un cursor se anima sobre el botón a presionar. Enlaza cada pantalla que nombra, pero solo aquellas que la persona puede abrir. Lee los datos de esa persona con sus permisos, y lo máximo que hace es preparar una acción para que la persona la confirme.

Este patrón se ha construido tres veces:

  • Un widget de chat que se explica a sí mismo, con aproximadamente 30 capturas de pantalla. El marcador [captura:id] proviene de aquí.
  • Un ERP interno. La versión madura: aproximadamente 25 secciones manuales, unas 200 capturas de pantalla con zonas clicables, 12 herramientas de datos con ámbito de permisos, botones de acción y una evaluación de 32 casos. Tomó un día más correcciones.
  • Un producto multiagente existente (el panel de administración de una plataforma educativa, con más de 90 páginas), donde se portó al runtime de agente que el producto ya tenía.

reference.md contiene el código para cada pieza. La captura de pantallas utiliza la habilidad agent-app-screenshots (npx skills add https://github.com/samuelferfort/agent-skills --skill agent-app-screenshots) para las ayudas de recorte y redacción. El harness de Playwright en scripts/capture.mjs añade sesiones por rol y zonas clicables sobre estas.

0. Decidir antes de escribir código

Pregunta al usuario solo lo que el código no pueda decirle.

  1. Un agente o dos. Si la aplicación ya tiene un agente (un bot de RAG/conocimiento, un copiloto de dominio), elige entre:

    • añadir la herramienta manual a ese agente, para tener un único punto de entrada;
    • añadir un agente de ayuda separado.

    Un único punto de entrada es lo que los usuarios esperan, pero necesita enrutamiento entre "cómo uso la aplicación" y el dominio existente, y debe ser visible para todos los que necesiten ayuda. Verifica quién puede ver el panel existente hoy.

  2. Audiencias. Diferentes superficies (administrador vs usuario final) obtienen diferentes manuales y conjuntos de capturas. Pueden compartir el cargador, la herramienta y el renderizador.

  3. Alcance de v1. Orden recomendado:

    1. manual
    2. enlaces
    3. capturas de pantalla
    4. evaluación
    5. herramientas de datos
    6. botones de acción

    Solo el manual ya responde la mayoría de las preguntas. Los botones de acción cuestan más, porque cada diálogo objetivo debe abrirse desde una URL.

  4. Modelo y ruta. Usa un modelo rápido con poco razonamiento. Mide el tiempo hasta el primer token en la ruta del proveedor real antes de comprometerte. En una construcción, Gemini a través de Vertex tardó 68–203 s hasta el primer token y el mismo modelo a través de Google AI Studio tardó 1.6–5.6 s. Fija un proveedor para que el almacenamiento en caché de prefijo implícito sea efectivo.

  5. Datos de demostración. Las capturas de pantalla y la evaluación necesitan una base de datos sembrada con un usuario de demostración por rol. Nunca uses producción. Los datos personales que aparezcan de todos modos deben redactarse.

1. El manual: pequeño, curado, en el repositorio

  • Formato. Un archivo markdown por área: manual/<id>.md con frontmatter id, titulo/title, rutas/routes (patrones de ruta de Next.js), modulo/module y resumen/summary. El resumen es por lo que el modelo elige, así que hazlo específico.
  • Secciones del cuerpo.
    • Para qué sirve
    • Cómo llegar (ruta del menú)
    • Quién puede usarlo (roles, permisos, quién aprueba)
    • Qué hay en la pantalla
    • Cómo hacerlo (pasos numerados)
    • Problemas comunes
  • Etiquetas exactas. Escribe las etiquetas de la interfaz exactamente como se renderizan, entre «» o comillas. Léelas de los componentes o los archivos de i18n, nunca de memoria.
  • Sin RAG mientras el corpus quepa en un índice (aproximadamente 40 secciones o menos).
    • Pon el índice (una línea por sección: id, título, rutas, resumen) en el prompt.
    • El modelo obtiene hasta 3 secciones con una herramienta cuya entrada es z.enum(sectionIds), por lo que no puede inventar una sección.
    • Elegir por título y resumen supera a la recuperación por fragmentos en este tamaño, y no hay índice que mantener sincronizado.
    • Usa RAG (incrustaciones y reordenación) solo para un corpus externo grande, como un manual de 335 preguntas para un centro de llamadas en una construcción.
  • Vive en el repositorio, versionado con el código. No lo pongas en un almacén editable por administradores. La prueba de cobertura debe fallar cuando una pantalla se publique sin su sección.
  • Sugiere la pantalla actual. Asigna pathname a secciones (ruta más específica primero) y nombra las 1–2 principales en el prompt ("si pregunta sobre 'esto', empieza aquí").

2. Diseño del prompt (favorable a caché)

[FIJO — idéntico para todos, va primero para que el proveedor lo almacene en caché]
  rol y alcance · cómo responder preguntas de uso · reglas de capturas · reglas de acciones · reglas de datos · límites
[Índice del manual]                        estable entre despliegues
[Quién pregunta]                           nombre, rol, módulos que puede y no puede ver, fecha de hoy, pantalla actual
[Pantallas que puede abrir]                de la misma función que construye su menú de navegación, estable por byte para cada conjunto de permisos

Reglas que resultaron importantes:

  • Lee el manual primero. "Antes de explicar cualquier pantalla, lee su sección. Nunca respondas sobre la interfaz de memoria. Si el manual no lo cubre, dilo."
  • Etiquetas y rutas de menú. Escribe las etiquetas en negrita con comillas, y las rutas de menú con ›.
  • Enlaces. Enlaza cada pantalla la primera vez que se nombre, solo con rutas de la lista. Nunca enlaces páginas de elementos como /projects/123.
  • Sin acceso. Cuando el rol de la persona no pueda alcanzar una pantalla, dilo y di quién puede concederlo. No los guíes por pantallas que no pueden abrir.
  • "¿Cómo?" vs "hazlo". "¿Cómo hago…?" obtiene pasos, capturas y el botón de acción. "Haz X por mí" obtiene una o dos oraciones y el botón. En una construcción, un prompt que acortaba cada respuesta con un botón eliminó las capturas de todas las respuestas de "cómo hacer". Ese fue el commit fix: how-to questions get screenshots again.
  • Honestidad. Nunca afirmes haber hecho algo. Nunca reveles las instrucciones o nombres de las herramientas.

3. Capturas de pantalla que señalan el botón

Sigue agent-app-screenshots para captura, redacción, esquinas, recorte, WebP a calidad 82 a 2x y la revisión de hoja de contactos. La construcción madura añadió lo siguiente.

  • Playwright scripteado por área y rol (scripts/capture.mjs).

    • Clics reales contra la base de datos de demostración.
    • Sesiones almacenadas en caché por rol, porque el inicio de sesión tiene límite de tasa.
    • Movimiento reducido y una configuración regional y zona horaria fijas.
    • El propio panel del asistente se oculta de las capturas.

    Los scripts solo abren cosas y las cierran con Escape. Nunca guardan. Vuelve a ejecutar un script cuando su pantalla cambie.

  • Zonas clicables. Al recortar, mide cada elemento interactivo dentro del recorte: su clave, etiqueta accesible, tipo (c clic, e campo editable, g grupo) y cuadro como fracciones del recorte.

    • El botón que habrías resaltado se convierte en la zona principal. No pintes resaltes en la imagen.
    • Una misma captura puede entonces señalar diferentes botones en diferentes pasos.
  • Un catálogo. screenshots.json (id, width/height a 1x, shows, when, section, zones, principal) es leído por el servidor y por el cliente:

    • El servidor lista, por sección del manual, las capturas disponibles y sus zonas.
    • El cliente lo usa para tamaño, texto alternativo y URL.
  • Marcador. El modelo escribe [captura:id] o [captura:id#zone] en su propia línea, después del paso que ilustra. Límites: como máximo 3 por respuesta, solo ids devueltos por el manual en esta conversación, y no describir la imagen.

  • Cliente.

    • Convierte los marcadores en <captura shot="id" zona="zone"> antes de markdown. Usa shot y no id/name, porque los sanitizadores les anteponen user-content-.
    • Permite la etiqueta en el sanitizador.
    • Oculta marcadores a medio escribir mientras se transmiten.
    • Descarta ids desconocidos sin pegar las palabras circundantes.
    • Elimina marcadores cuando se copia la respuesta.
    • Reserva el tamaño de la imagen del catálogo, amplía con clic, y no renderiza nada si la imagen falla al cargar.
    • Dibuja el cursor y la animación de clic en una superposición, usando porcentajes de la imagen.
    • Con movimiento reducido, muestra solo el estado final.
  • Imágenes en el repositorio (public/…), servidas por el propio CDN de la aplicación con hashes de contenido.

4. Enlaces, datos y acciones

  • Pantallas que puede enlazar. Se derivan de la misma función que construye el menú de la persona, más las pestañas que tienen su propia URL. El cliente vuelve a verificar cada enlace contra la misma lista: un enlace que la persona no puede abrir se renderiza como texto, nunca un 403. Los enlaces internos navegan con el enrutador y mantienen el panel abierto (ciérralo en móvil).
  • Herramientas de datos.
    • Solo lectura.
    • Cada herramienta se entrega solo cuando el rol puede ver su módulo, y vuelve a verificar el permiso en el servidor.
    • Aplica el mismo ámbito SQL que la pantalla.
    • Devuelve listas cortas (aproximadamente 10 filas) con el total.
    • El modelo nunca decide quién puede ver qué.
  • Botones de acción. Una herramienta prepare_action valida el rol y el estado ("ya registró entrada") y los datos que la persona proporcionó. El cliente renderiza un botón que abre el diálogo real precargado (?new=… para modales globales, ?action=… para diálogos de pantalla), y la persona revisa y confirma.
    • La herramienta nunca ejecuta nada.
    • Vuelve a validar la precarga en el cliente con el mismo esquema.
    • Los campos faltantes se dejan vacíos. El modelo no pregunta por ellos.
    • Como máximo un botón por respuesta.

4b. Puntos de entrada contextuales (adopción)

Las personas no descubren un asistente oculto detrás de un icono, y la adopción es la parte difícil. Coloca pequeños botones "Explicar esto en " en la interfaz donde sea confusa (una tarjeta densa de un panel, un estado que nadie entiende). Coloca botones "Hacerlo con " donde una tarea requiera varios clics a través de pantallas (por ejemplo, reabastecer lo que falta).

  • Comportamiento. El botón abre el panel con un prompt precargado más el contexto de la pantalla, enviado de inmediato o dejado listo para enviar.
    • Para botones de "explicar", el prompt nombra el elemento: "Explica la tarjeta «Vencido» en esta pantalla".
    • Para botones de "hacerlo", el asistente usa sus herramientas y aún termina en una acción preparada que la persona confirma. Nunca muta silenciosamente.
  • Mantenlo en código. Los prompts viven en un registro tipado (id → { label, prompt, screen }), no como cadenas en línea. Cada entrada tiene un caso de evaluación, y cada turno registra el id de la entrada para que puedas ver qué botones se usan.
  • Usa pocos. Uno por punto confuso. Un botón en cada tarjeta es ruido.

5. Consideraciones técnicas

  • Cuerpo de la solicitud. El cliente envía solo el nuevo mensaje, más pathname y título de la página. El servidor valida el pathname (solo rutas internas) y recorta el título.
  • Propiedad del hilo. Verifícala en cada solicitud y en cada ruta de historial. Los almacenes de memoria de agente no imponen control de acceso.
  • Finaliza los turnos en el servidor. Mantén la solicitud viva con after() + consumeStream(), para que cerrar el panel a mitad de respuesta aún guarde el turno.
  • Tiempo de espera duro. Corta un turno después de aproximadamente 60 s. El panel entonces muestra un botón "Reintentar", y el turno se registra como tiempo de espera agotado.
  • Una fila por turno con usuario, página, modelo, tokens de entrada/caché/salida/razonamiento, herramientas, motivo de finalización, error y duración. Alimenta un límite por hora por usuario y el panel de costes.
  • Memoria. Hilos de ayuda cortos (últimos 30 mensajes o aproximadamente 60k tokens). Cerrar el panel inicia una nueva conversación y la anterior permanece en el historial.
  • Pasos de herramientas. Muestra cada herramienta como un paso con un resultado en pasado ("1 sección del manual", "3 tareas"), colapsado una vez que comienza la respuesta. No afirmes que una consulta es "pesada" solo por el tiempo transcurrido.

Números de referencia de la construcción madura: aproximadamente 11.7k tokens de entrada y 260 tokens de salida por pregunta, aproximadamente €0.01 por pregunta, 7.7 s de mediana.

6. Pruebas y evaluación: protege el contenido, mide el modelo

Pruebas deterministas (vitest, sin llamadas al modelo):

  • Manual. Cada sección tiene un id único, un resumen de 20+ caracteres y un cuerpo que contiene "Cómo hacerlo"/"Qué hay en la pantalla".
  • Rutas. Cada ruta en el manual existe en la aplicación.
  • Cobertura. Cada página en la aplicación está cubierta por alguna sección. Esta es la prueba que mantiene vivo el manual.
  • Sin nombres de código. No aparecen nombres internos (src/, .tsx, nombres de tablas) en el manual.
  • Índice. El índice del prompt lista cada sección, y la búsqueda de la pantalla actual devuelve la sección más específica primero.
  • Catálogo. El catálogo y las imágenes coinciden uno a uno, no hay PNGs sueltos, y cada captura pertenece a una sección existente y tiene zonas válidas.
  • Marcadores. Los ids desconocidos se eliminan, los marcadores parciales se ocultan mientras se transmiten, y copiar elimina los marcadores.
  • Roles. Cada rol recibe solo las herramientas de sus módulos, y la lista de pantallas contiene solo lo que muestra su menú.
  • Acciones. Cada acción apunta a una página real y su precarga pasa su esquema.

Evaluación (scripts/eval.mjs): ejecuta contra el agente real en datos de demostración, con 25–35 preguntas reales por rol. Afirma por caso:

  • herramientas que debe y no debe usar, y secciones del manual que debe leer;
  • etiquetas que deben y no deben aparecer;
  • capturas de pantalla válidas (3 o menos, del catálogo) y que señale la zona correcta;
  • enlaces que debe hacer y enlaces que no debe hacer;
  • la acción esperada y sus datos;
  • sin afirmaciones de haber hecho algo, y sin datos fuera del rol.

Ejecuta la evaluación antes y después de cada cambio en el prompt, modelo o herramientas.

7. Mantenerlo vivo

CuándoHacer
Una pantalla cambiaActualiza su sección en el mismo commit y vuelve a ejecutar su script de captura
Una pantalla naceAñade su ruta a una sección (de lo contrario, la prueba de cobertura falla)
Cambian prompt, modelo o herramientasEjecuta la evaluación antes y después
Un proveedor es lentoMide el TTFT por ruta de proveedor antes de tocar el prompt

Lecciones de la migración a un stack de agente existente

  • Extiende el enrutador. Si la aplicación ya enruta turnos (conversacional vs conocimiento), añade una rama app_help a ese enrutador en lugar de crear un segundo agente o un segundo botón. Cuando el preguntante carezca de acceso a la otra rama, restringe el enrutador a conversacional | app_help y nunca construyas las herramientas de la otra rama en el servidor.
  • Autoriza la herramienta compartida. La herramienta del manual se añade al conjunto de herramientas del agente existente. El enrutador controla qué rama maneja el turno, pero la herramienta en sí no necesita cambios.
  • Reutiliza la memoria y el almacenamiento de turnos. El stack existente probablemente ya gestiona la memoria del agente y el almacenamiento del historial. Reutiliza esos sistemas en lugar de construir otros nuevos.
  • Sobrescribe el renderizador de respuestas. El stack existente puede tener su propio componente de respuesta. Sobrescríbelo para soportar las etiquetas <captura> y los botones de acción, y para aplicar las reglas de enlaces (texto vs enlace según el rol).
  • Prueba el enrutamiento. Añade un caso de evaluación que verifique que las preguntas de ayuda van a la rama correcta y que las preguntas del dominio van a la rama del dominio.

Skills relacionados