Documentación

Conecta un agente, envía transcripciones y lee el informe A–F — vía SDK o REST.

Visión general

Axon es la capa de calidad para agentes de IA. Envías transcripciones de conversaciones; Axon evalúa cada una con un juez LLM contra una rúbrica configurable y devuelve un informe A–F por dimensión — con evidencia citada, causa raíz y corrección concreta.

El flujo: conecta un agente → ingiere transcripciones → el juez evalúa (de forma asíncrona, en una cola durable e idempotente) → lee el informe → corrige → fíjalo en una suite de regresión → monitorea y recibe alertas de degradación.

Inicio rápido

De cero al primer informe en tres pasos.

  1. Genera una API key en Configuración → Integración. Guárdala como AXON_API_KEY.
  2. Conecta la clave de tu proveedor de IA (BYOK) en Configuración → Integración → Proveedor de IA. Las evaluaciones corren en esa clave.
  3. Instala el SDK (pnpm add @gabrielonrails/axon-sdk) o usa cURL.
  4. Envía una transcripción y lee el boletín. El agente se crea en la primera ingesta.
quickstart.ts
$ pnpm add @gabrielonrails/axon-sdk
 
import { Axon } from "@gabrielonrails/axon-sdk";
const axon = new Axon({ apiKey: process.env.AXON_API_KEY! });
 
await axon.ingest("cobranca", [{
  id: "conv-001",
  channel: "voz",
  turns: [
    { role: "client", text: "Quero um desconto." },
    { role: "agent",  text: "Posso aplicar 20% agora." },
  ],
}]);
 
const report = await axon.getReport("cobranca");
console.log(report.overall, report.dimensions);

BYOK — tu clave de IA

La evaluación corre en la clave de proveedor de IA que conectas — Anthropic, OpenAI o cualquier endpoint compatible. Es obligatoria: sin ella el juez no corre y el boletín queda vacío.

Dónde conectar: en la app, Configuración → Integración → Proveedor de IA. Pega la clave, elige el proveedor y (opcional) el modelo. La clave se cifra en reposo (AES-256-GCM).

Si la clave es inválida o sin saldo, la conversación queda en pending/failed y no se genera boletín — corrige la clave y reenvía. Axon nunca usa una clave gestionada.

Autenticación

Toda petición se autentica con una API key (por org) en el header Authorization: Authorization: Bearer axon_sk_….

Las keys se generan y revocan en Configuración → Integración. Solo guardamos un hash SHA-256 — la key completa se muestra una vez. La revocación es inmediata.

Authorization: Bearer axon_sk_xxxxxxxxxxxxxxxxxxxxxxxx

SDK Node

El @gabrielonrails/axon-sdk oficial es tipado, sin dependencias (fetch nativo, Node 18+), idempotente y reintenta errores transitorios automáticamente.

Define id en cada transcripción: reenviar la misma id actualiza la conversación en vez de duplicar — seguro para reintentos y replays.

Opciones del constructor

new Axon({
  apiKey: string,          // axon_sk_... (obrigatório)
  baseUrl?: string,        // default: https://axon-dev.com
  maxRetries?: number,     // default: 3 (429/5xx/rede, backoff)
  timeoutMs?: number,      // default: 30000
  fetch?: typeof fetch,    // fetch custom (opcional)
})

baseUrl usa la URL actual de la app por defecto y es configurable; apúntala a tu propio dominio o a un deploy self-hosted.

Métodos

axon.ingest(agent, transcripts)            // → AxonIngestResult
axon.getConversation(agent, externalId)    // → AxonConversationStatus
axon.getReport(agent)                      // → AxonReport
axon.runRegression(agent, { version? })    // → AxonRegressionResult (gate de CI)
axon.waitForEvaluation(agent, externalId, { timeoutMs?, intervalMs? })
axon.agent(name) // → { ingest, getReport, getConversation, waitForEvaluation }

Tipos

interface AxonTranscript {
  id?: string;        // chave de idempotência (reenviar = atualiza, não duplica)
  channel?: "voz" | "chat" | "whatsapp";
  turns: {
    role: "client" | "agent" | "tool";
    text: string;
    // tool calls deste turno → habilitam a avaliação de TRAJETÓRIA do agente
    toolCalls?: { name: string; arguments?: unknown; result?: unknown }[];
  }[];
  // Trace de agente (opcional) — quanto mais rico, mais profunda a avaliação:
  system?: string;        // prompt de sistema do agente (aderência/trajetória)
  context?: string[];     // contexto recuperado (RAG) → tríade faithfulness
  metadata?: Record<string, unknown>; // metadados livres (persistidos)
  // Metadados de filtro/agrupamento (não afetam a nota):
  duration?: string;  // duração da conversa, ex.: "4m12s"
  version?: string;   // rótulo da versão do agente (alimenta a comparação A/B)
  result?: string;    // desfecho, ex.: "resolvido" | "transferido" (outliers
                      // sempre avaliam, mesmo sob amostragem)
  queue?: string;     // fila/operação, ex.: "financeiro-cobranca"
}
 
interface AxonConversationStatus {
  // "blocked" = sem assinatura/crédito (pague-antes); reason explica o porquê.
  status: "pending" | "running" | "done" | "failed" | "blocked" | "unknown";
  reason?: "no_entitlement" | "llm_not_configured" | "evaluation_failed" | null;
  evaluation: { overall: Grade; confidencePct: number;
                dimensions: { key; name; grade; score }[] } | null;
}

Monitoreo en tiempo real

Axon monitorea tus agentes en streaming — no exportas un lote al final del día. El patrón es un hook de fin de conversación: en cuanto una conversación termina (el cliente cuelga, la sesión de chat se cierra, el ticket se resuelve), envía la transcripción. La evaluación corre de forma asíncrona y el dashboard se actualiza solo (la pantalla muestra un indicador "En vivo" y recarga periódicamente).

Conecta el hook donde terminan las conversaciones: un webhook call.completed de tu telefonía, el fin de la sesión de chat/WhatsApp por inactividad, o tu propio agente de IA justo tras el último mensaje.

conversation-end hook
// Chame no momento em que a conversa encerra (fim de chamada,
// sessão de chat fechada, ticket resolvido). Não bloqueie o
// encerramento esperando a Axon — o SDK já faz retry com backoff.
async function onConversationEnded(conv) {
  void axon.ingest(conv.agentName, [{
    id: conv.id,            // mesmo id em retries → não duplica
    channel: conv.channel,  // "voz" | "chat" | "whatsapp"
    turns: conv.turns,
  }]).catch((err) => console.error("[axon] ingest falhou:", err));
}

Como cada conversación se evalúa en el momento en que llega, Axon detecta degradación casi en tiempo real — dispara alertas (email/webhook) cuando una conversación recibe nota baja (D/F) o cuando el promedio reciente del agente cae respecto a la ventana anterior, sin esperar un informe semanal.

Sin el SDK

El hook es solo un POST HTTP — no necesitas SDK. Llama al endpoint de ingesta directo desde tu backend o incluso desde el webhook de tu telefonía/chat. El id mantiene los reintentos idempotentes.

conversation-end hook · cURL
# Dispare isto no fim da conversa, do seu backend ou direto do
# webhook da telefonia/chat. Sem SDK — só HTTP.
curl -X POST https://axon-dev.com/api/v1/agents/cobranca/transcripts \
  -H "Authorization: Bearer $AXON_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "transcripts": [
        { "id": "conv-001", "channel": "voz",
          "turns": [ { "role": "client", "text": "..." },
                     { "role": "agent",  "text": "..." } ] } ] }'
 
# → 202  { "accepted": 1, "status": "evaluating" }
# Reenviar o mesmo "id" é idempotente: atualiza, não duplica.

API REST

Tres endpoints, todos autenticados por API key. La ingesta devuelve 202 y evalúa de forma asíncrona; haz polling del estado o lee el informe.

URL base: https://axon-dev.com

POST · ingestão
POST /api/v1/agents/{agent}/transcripts
Authorization: Bearer axon_sk_...
Content-Type: application/json
 
{ "transcripts": [
  { "id": "conv-001", "channel": "voz",
    "turns": [ { "role": "client", "text": "..." },
               { "role": "agent",  "text": "..." } ] }
] }
 
→ 202  { "accepted": 1, "queued": 1,   // queued < accepted sob amostragem
         "agent": { "id", "name" },
         "conversation_ids": ["..."], "status": "evaluating" }
GET · status da conversa
GET /api/v1/agents/{agent}/transcripts/{externalId}
Authorization: Bearer axon_sk_...
 
→ 200  { "status": "done",
         "evaluation": { "overall": "C+", "confidencePct": 92,
                         "dimensions": [ { "key", "name", "grade", "score" } ] } }
GET · boletim do agente
GET /api/v1/agents/{agent}/report
Authorization: Bearer axon_sk_...
 
→ 200  {
  "agent": { "id", "name", "channel" },
  "overall": "C+", "degrading": true, "sample": 2430,
  "dimensions": [...],
  "problems": [
    { "severity", "title", "dimension", "impact", "rootCause",
      "evidence": { "turnIndex", "quote", "verified" } } // verified = citação conferida
  ],
  "trajectory": {  // quando há tool calls: qualidade do uso de ferramentas
    "assessed": true, "score": 78, "summary": "...",
    "findings": [ { "type": "tool-correctness", "severity", "detail" } ]
  },
  "rag": {         // quando há contexto recuperado: tríade RAG
    "assessed": true, "faithfulness": 64, "answerRelevance": 90,
    "contextRelevance": 71, "summary": "...", "findings": [...]
  },
  "correction": {                      // a correção recomendada (o diferencial)
    "tags": ["política de desconto", "concessão não autorizada"],
    "impactFrom": "C+", "impactTo": "A-",
    "fixes": [
      { "type": "PROMPT",    "title": "...", "description": "...", "code": "..." },
      { "type": "GUARDRAIL", "title": "...", "description": "...", "code": "..." },
      { "type": "EVAL",      "title": "...", "description": "...", "code": "..." }
    ]
  }                                    // null quando ainda não há correção
}

El boletín también devuelve `correction` — la corrección recomendada (causa raíz + parches concretos de PROMPT/GUARDRAIL/EVAL), o null cuando aún no hay una.

Regresión & golden sets

Fija la calidad: convierte una conversación evaluada en un golden case (el resultado esperado). La suite de regresión revisa esos casos en cada despliegue.

El ciclo: (1) marca un caso desde un boletín/corrección; (2) ejecuta la suite; (3) activa el gate de CI — un despliegue que regresiona un caso se bloquea, con aprobación de bypass auditada.

Hoy el ciclo de regresión se opera en la app (plan Team) y los casos se crean desde conversaciones marcadas. Un endpoint REST dedicado está en el roadmap.

Gate de CI (bloquea deploys malos)

Ejecuta tu suite de regresión desde CI y falla el build si el agente empeoró. El endpoint devuelve HTTP 200 si pasa y 422 si hubo regresión, así que curl --fail bloquea solo.

Ejemplo en GitHub Actions:

.github/workflows/axon-gate.yml
name: Axon quality gate
on: [pull_request]
jobs:
  gate:
    runs-on: ubuntu-latest
    steps:
      - run: |
          curl --fail -sS -X POST \
            -H "Authorization: Bearer ${{ secrets.AXON_API_KEY }}" \
            -H "content-type: application/json" \
            -d '{"version":"${{ github.sha }}"}' \
            https://axon-dev.com/api/v1/agents/YOUR_AGENT/regression

O con el SDK:

SDK
const r = await axon.runRegression("your-agent", { version: sha });
if (!r.gate) process.exit(1); // bloqueia o deploy se regrediu

Requiere el plan Pro o superior. Cada caso se reevalúa con tu clave BYOK.

FinOps & costo

Cada evaluación registra los tokens reales consumidos en tu clave (BYOK). El panel FinOps muestra costo estimado y tokens por agente, modelo y día, con presupuesto mensual y alerta al superarlo.

La visibilidad de costo vive en la app, en /finops. Un endpoint REST para leer costo/tokens está en el roadmap.

Rúbrica y notas

Cada conversación recibe nota A–F general y por dimensión (score 0–100). A/B = saludable, C = atención, D/F = crítico. La rúbrica es configurable por agente; la predeterminada tiene seis dimensiones:

Resolución
Resolvió lo que el cliente pidió, sin pendientes.
Antialucinación
No inventó hechos, políticas, valores ni promesas.
Adherencia a la instrucción
Siguió el guion, las políticas y las instrucciones del sistema.
Manejo de la incertidumbre
Manejó bien la duda; escaló cuando debía.
Tono y seguridad
Tono adecuado, respetuoso y seguro.
Eficiencia
Resolvió en pocos turnos, sin rodeos.

A/B saludable · C atención · D/F crítico

Alertas y webhooks

Axon calcula un baseline semanal por agente y dispara una alerta de degradación cuando la nota cae vs. la semana anterior.

Las alertas llegan en la app y a los canales configurados en Configuración → Integración: webhook (POST JSON) y Slack (incoming webhook).

webhook payload
POST  (seu endpoint)
{ "source": "axon", "severity": "alto",
  "title": "Queda de qualidade em Cobrança",
  "body": "A nota geral caiu 9 pontos vs. a semana anterior." }

Límites & contrato

Lo que ingeniería pregunta en la primera call:

  • El throughput de evaluación está limitado por org: 3 solicitudes/min al juez, ~8k tokens de entrada y ~2k de salida por minuto. El excedente va a una cola (FIFO). La ingesta responde 202 al instante; la evaluación corre asíncrona.
  • Los errores transitorios (429/5xx/red) reintentan automáticamente en el SDK con backoff exponencial.
  • Recomendado ≤ 50 conversaciones por solicitud y ≤ ~100 turnos por conversación.
  • Un id por conversación hace el reenvío idempotente (actualiza, no duplica).
  • El boletín devuelve los 3 problemas más relevantes por agente (sin paginación).

Errores

Los errores devuelven un cuerpo JSON { error, message } con el status HTTP apropiado.

401missing_api_keySin header Authorization / API key.
401invalid_api_keyKey inválida o revocada.
402no_entitlementSin suscripción activa ni créditos — suscríbete o compra el paquete de prueba.
403agent_limit_reachedLímite de agentes del plan alcanzado — mejora el plan para añadir más.
403upgrade_requiredLa función requiere un plan superior (ej.: regresión necesita Pro+).
400no_transcriptsNinguna transcripción válida en el cuerpo.
413too_many_transcriptsDemasiadas transcripciones en una solicitud (máx. 1000).
429rate_limitedLímite de solicitudes alcanzado — baja el ritmo (reintenta tras 60s).
404agent_not_foundAgente no encontrado en esta org.
404conversation_not_foundConversación (external id) no encontrada.
500internal_errorError inesperado del servidor — reintenta con backoff.