Saltar al contenido principal

24 · En la práctica

Implementación paso a paso

Un asistente de soporte construido de punta a punta: conocimiento con Adapta, un agente gobernado con docket, trabajo seguido en Tack y un chat en producción.

16 minCaso de estudio: Adapta (se abre en una ventana nueva) · docket (se abre en una ventana nueva) · Tack (se abre en una ventana nueva)

Las lecciones anteriores explican cada pieza por separado. Esta sigue un solo caso para mostrar cómo encajan: responder desde documentos, enseñarle al modelo una forma fija de respuesta, dejarlo actuar solo con la aprobación de una persona y seguir el trabajo de construir todo eso. Es la lección que más apunta al código; los enlaces abren cada repositorio en su rama principal.

Una advertencia: Adapta es un prototipo funcional sin auditar, docket es software beta para un solo operador y la flota de ejecución de Tack no está en un release etiquetado (ver cada README: Adapta, docket, Tack). Ninguno está endurecido para producción. Los usamos porque su código se puede leer línea por línea.

El escenario y la arquitectura

Adapta aporta el conocimiento (y el comportamiento, si hace falta), docket gobierna las acciones y Tack registra el trabajo de construirlo. En el diagrama, tu app recibe de Adapta una respuesta con citas y, si el modelo quiere abrir un ticket, docket retiene esa acción hasta que una persona la aprueba.

App de soportetu código, donde pregunta el empleado
  • Adaptaconocimiento: respuestas con citas
  • docketacciones: una persona aprueba cada ticket
  • Tacksigue el trabajo de construirla
Tu app está en el centro y cada producto cubre una parte. Solo la parte de docket cambia otro sistema, por eso es la que tiene a una persona en el circuito.

Ningún producto de estos trae la "app de soporte"; ese código, el inicio de sesión de usuarios y la interfaz son tuyos.

1. Conocimiento: responder desde los manuales con Adapta

Responder desde los manuales implica encontrar los fragmentos que importan para cada pregunta y entregárselos al modelo. Eso es (Embeddings y RAG), y Adapta lo empaqueta como servicio. make up (README.md) levanta su API, un worker en segundo plano y sus bases de datos (docker-compose.yml). Para RAG basta con una CPU común.

En Adapta

  1. Tu aplicacióncualquier cliente compatible con OpenAI
  2. Servicio de APIresponde preguntas, nunca entrena
    • Buscar y responder
    • Proyectos, llaves, uso
  3. Worker de entrenamientojobs lentos en GPU, tomados de una cola
    • Entrenar el adapter
    • Eval gate
  4. Almacenamientoen tu propio servidor
    • RegistrosPostgres
    • VectoresChroma
    • Cola de jobsRedis
Adapta corre como unos pocos contenedores en hardware tuyo. El servicio que responde nunca entrena: los jobs lentos de entrenamiento esperan en una cola a un worker aparte. Fuente: Architecture

Usarlo requiere cuatro llamadas a su API: crear un proyecto de tipo rag, subir los manuales, crear un endpoint y emitir una llave de acceso. Los comandos están en la guía de Adapta Knowledge and behavior (en inglés). Esto es lo que pasa por dentro:

  1. Subida. upload_file valida el tipo de archivo, lo guarda y responde de inmediato, dejando la indexación en segundo plano.
  2. Indexación. _index_file extrae el texto, lo corta en chunks (chunk_text) y los guarda con sus (index_chunks). Reindexar reemplaza los chunks de un archivo en lugar de duplicarlos.
  3. Endpoint. create_endpoint se niega a crear uno para un proyecto RAG sin nada indexado.
  4. Pregunta. _resolve_endpoint verifica la llave. retrieve encuentra los mejores fragmentos, _build_system los agrega, numerados, a las instrucciones del modelo y _fit_context descarta los menos relevantes si no caben.

La app llama al endpoint con cualquier cliente compatible con OpenAI y recibe las citas junto con la respuesta.

2. Comportamiento: cuándo vale la pena entrenar un adapter

RAG aporta hechos. No logra de forma confiable que el modelo responda con una forma fija, como una etiqueta de una lista cerrada o la misma estructura JSON cada vez. Cuando las instrucciones solas no sostienen esa forma, entrenas un , un pequeño complemento que ajusta el comportamiento del modelo (Fine-tuning, LoRA y QLoRA). Aquí, el candidato natural es el clasificador de tickets. El riesgo es servir un adapter que no aprendió nada, y Adapta lo impide con un : una prueba que el adapter debe pasar antes de poder servirse.

El puntaje mide qué tan bien predice el adapter las respuestas reservadas, no si acierta la etiqueta, así que igual necesitas tus propias verificaciones (Evaluar modelos).

3. Actuar con seguridad: una herramienta gobernada con docket

Abrir un ticket, a diferencia de responder, cambia otro sistema. Como explica Gobernanza y human-in-the-loop, la decisión de ejecutar una acción la toma el código, no el modelo. En docket, cada llamada a una herramienta pasa por un único punto de control que aplica reglas, consulta a una persona cuando hace falta y registra el resultado.

Tu aplicación usa docket como librería, docket-runtime, que se construye desde el código fuente y no está publicada en ningún índice de paquetes (DOCKET Architecture). En el ejemplo del repositorio (examples/runtime_embed.py), la aplicación registra cada herramienta, indicando si escribe, y envía cada llamada a través del runtime en lugar de invocar la función directamente.

En docket

  1. Tu aplicaciónregistra herramientas, envía cada llamada
  2. docket-runtimeun punto de control para cada llamada
    • Reglas
    • Aprobación humana
    • Traza
    • Log de auditoría
  3. Herramientaaquí, el sistema de tickets
La aplicación nunca llama a la herramienta directamente. El punto de control permite la llamada, la deniega o espera a una persona, y en todos los casos registra el resultado. Fuente: DOCKET Architecture

Las reglas son archivos JSON en ~/.docket/policies/, que se comparan con cada llamada convertida en una línea de texto que empieza con el nombre de la herramienta. Esta política ilustrativa, con el formato de la plantilla real high-risk-deploy.json, exige aprobación para cada llamada a open_ticket:

{
  "id": "approve-open-ticket",
  "applies_to": ["*"],
  "hook": "pre_tool_call",
  "match": {"type": "regex", "pattern": "^open_ticket\\b"},
  "action": "require_approval",
  "message": "Opening a ticket needs a support lead."
}

Dentro de dispatch_tool, una llamada pasa por estos pasos:

  1. Herramienta desconocida, o argumentos faltantes o ilegibles: se deniega.
  2. Se revisan las reglas (evaluate_tool_call) y gana el veredicto más restrictivo.
  3. Si hace falta aprobación, docket guarda una solicitud con los valores sensibles ocultos (approval_create) y espera (wait_for_approval) a que una persona responda, desde la línea de comandos o por HTTP, o Telegram. Sin respuesta antes del plazo, se deniega.
  4. Cada decisión va a un en el que cada entrada queda encadenada a la anterior mediante un hash, así que cualquier edición posterior se nota (audit_log, verify_chain).

docket policies test prueba una regla sin ejecutar nada (docs/commands.md), y run_agent_turn permite que docket maneje el bucle completo del por el mismo punto de control.

4. Seguir el trabajo: ítems y runners en Tack

Construir el asistente es un proyecto en sí mismo. Tack es un gestor de proyectos que además puede entregar un ítem de trabajo a un (como Claude Code o Codex) y registrar la ejecución en el historial del ítem. Su documentación lo describe en dos partes: un tablero que decide y registra, y que hacen el trabajo.

En Tack

  • Tablerouno; el plan y el registro
    • Ítems y flujos de trabajo
    • Elige qué corre y cuándo
    • Guarda el historial y el costo de cada ejecución
    • No ejecuta código ni tiene llaves
  • Runnersvarios; en tus máquinas
    • Piden trabajo al tablero
    • Corren el agente en una copia aparte del código
    • Guardan las llaves del modelo
El tablero planifica y lleva el registro; cada runner trabaja en una máquina que ya tiene el código y las llaves. Los runners piden trabajo al tablero, así que las llaves nunca salen de ellos. Fuente: Introduction

Agregas un ítem y luego creas una ejecución que lo asigna a un runner, la máquina que ejecuta al agente (agent-runners.md). Un scheduler elige un runner con las capacidades adecuadas (select_runner). El runner anota lo que va a hacer antes de tocar cualquier archivo (run_claimed) y luego lanza al agente. Cada ejecución pasa por un conjunto fijo de estados (validate_transition); cómo sobrevive a una caída se explica en Ejecución durable de agentes.

5. Un chat desplegado: el widget de yielab.com

Como contraste, el widget de chat de preventa de este sitio sí está desplegado. Su repositorio es privado, así que solo describimos la arquitectura.

  • Runtime y modelo. Next.js sobre Cloudflare Workers con OpenNext. El navegador reenvía la conversación en cada turno y el servidor la trata como no confiable. Cada turno hace una sola llamada, sin reintentos, a un modelo de Anthropic a través de Vercel AI Gateway, que guarda la llave y pone un tope de gasto.
  • Controles, del más barato al más caro. Tamaño y origen, un control anti-bot con Turnstile, un ticket firmado para los turnos siguientes, un tope de turnos, un límite de peticiones por dirección y un contador diario. Todos fallan cerrados, bloqueando la petición ante la duda, y la llamada al modelo va al final.
  • Grounding. Sin RAG: el catálogo de servicios cabe en las instrucciones y se arma con una lista explícita de campos permitidos, para que los precios nunca lleguen al modelo.
  • Salida. Cada respuesta se revisa completa en busca de menciones de dinero, de una marca oculta que delataría una filtración de las instrucciones y de exceso de largo; si algo falla, se muestra un mensaje fijo. El correo del lead se arma con datos validados, nunca con texto libre del modelo.
  • Monitoreo y . Las conversaciones se trazan en Langfuse (región UE) vía OpenTelemetry. Una suite de pruebas offline corre en cada build; una comparación pagada entre modelos sigue pendiente.

6. Antes de producción real

Área Qué agregar
Inicio de sesión Inicio de sesión único (SSO) para empleados delante de tu app
Permisos Filtro de documentos por usuario; docket no distingue clientes o tenants separados
Secretos Un gestor de secretos; rotar las credenciales por defecto de Adapta; TLS delante de docket serve
Evals Un golden set con los documentos esperados; casos adversarios de open_ticket, en cada cambio
Monitoreo El chequeo de salud profundo de Adapta; alertas por aprobaciones pendientes
Auditoría de datos Adapta aún no tiene log de auditoría ni borrado lógico (TODO.md)

En la práctica

  • Decide qué compras, qué adoptas y qué escribes. La aplicación, el inicio de sesión y la integración con el helpdesk son siempre tuyos.
  • Pide a cada componente evidencia de su estado real: límites conocidos, roadmap, tests.
  • Presupuesta una revisión de seguridad antes de que un prototipo toque datos sensibles.

Fuentes

Para profundizar

La documentación de cada producto profundiza en la arquitectura que recorre esta lección (en inglés):

  • Architecture muestra los contenedores de Adapta y sigue paso a paso una pregunta y un job de entrenamiento a través de ellos.
  • DOCKET Architecture explica cómo está organizado en capas el código de docket, qué estado guarda (incluido el log de auditoría encadenado) y cómo una aplicación integra su runtime.
  • Introduction presenta la división de Tack en un tablero y runners, y por qué se mantienen separados.
  • Agent Runners & Fleet Execution cubre cómo registrar runners, dónde viven las credenciales y qué partes del proceso están probadas de punta a punta hoy.

Para llevar

  • Los componentes resuelven partes del problema; la aplicación, la identidad y el código que los une son tuyos. Tack sigue el trabajo de construir, no el asistente en ejecución.
  • Adapta solo sirve un adapter después de que pasa un eval gate con ejemplos que nunca usó para entrenar.
  • En docket, toda acción pasa por un punto de control: reglas, luego una aprobación humana que deniega ante el silencio y luego una entrada de auditoría a prueba de alteraciones.
  • En producción, los controles baratos van antes del modelo y la salida se revisa completa antes de que alguien la vea.

Comprueba lo aprendido

¿Qué impide que Adapta sirva un adapter que no aprendió nada?

El eval gate: el adapter tiene que sacar un buen puntaje con ejemplos que nunca usó para entrenar, o superar claramente al modelo base en ellos. Un job que no pasa nunca obtiene un endpoint.

Nadie responde la aprobación de `open_ticket`. ¿Qué pasa, y por qué es el comportamiento correcto por defecto?

Vence el plazo y la llamada se deniega, así que no se abre ningún ticket. Tratar el silencio como un "no" evita que una solicitud olvidada termine en una acción sin aprobar.

¿Por qué el chat de yielab.com no usa RAG ni un motor de aprobaciones?

Su conocimiento es un catálogo pequeño que cabe en las instrucciones, y no tiene herramientas que actúen. Sus riesgos están en la entrada, el costo y la salida.