Documentação

Conecte um agente, envie transcrições e leia o boletim A–F — via SDK ou REST.

Visão geral

A Axon é a camada de qualidade para agentes de IA. Você envia transcrições de conversas; a Axon avalia cada uma com um juiz LLM contra uma rubrica configurável e devolve um boletim A–F por dimensão — com evidência citada, causa-raiz e correção concreta.

O fluxo: conecte um agente → ingira transcrições → o juiz avalia (de forma assíncrona, numa fila durável e idempotente) → leia o boletim → corrija → trave numa suíte de regressão → monitore e receba alertas de degradação.

Início rápido

Do zero ao primeiro boletim em três passos.

  1. Gere uma chave de API em Configurações → Integração. Guarde como AXON_API_KEY.
  2. Conecte a chave do seu provedor de IA (BYOK) em Configurações → Integração → Provedor de IA. As avaliações rodam nessa chave.
  3. Instale o SDK (pnpm add @gabrielonrails/axon-sdk) ou use cURL puro.
  4. Envie uma transcrição e leia o boletim. O agente é criado na primeira ingestão.
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 — sua chave de IA

A avaliação roda na chave do provedor de IA que você conecta — Anthropic, OpenAI ou qualquer endpoint compatível. É obrigatória: sem ela o juiz não roda e o boletim fica vazio.

Onde conectar: no app, Configurações → Integração → Provedor de IA. Cole a chave, escolha o provedor e (opcional) o modelo. A chave é cifrada em repouso (AES-256-GCM).

Se a chave estiver inválida ou sem saldo, a conversa fica em pending/failed e nenhum boletim é gerado — corrija a chave e reenvie a transcrição. A Axon nunca recorre a uma chave gerenciada.

Autenticação

Toda requisição autentica com uma chave de API (por org) no header Authorization: Authorization: Bearer axon_sk_….

As chaves são geradas e revogadas em Configurações → Integração. Guardamos só um hash SHA-256 — a chave completa aparece uma vez. A revogação é imediata.

Authorization: Bearer axon_sk_xxxxxxxxxxxxxxxxxxxxxxxx

SDK Node

O @gabrielonrails/axon-sdk oficial é tipado, sem dependências (fetch nativo, Node 18+), idempotente e re-tenta erros transitórios automaticamente.

Defina id em cada transcrição: reenviar a mesma id atualiza a conversa em vez de duplicar — seguro para retries e replays.

Opções do construtor

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 assume a URL atual do app por padrão e é configurável; aponte para o seu próprio domínio ou um 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;
}

Monitoramento em tempo real

A Axon monitora seus agentes em streaming — você não exporta um lote no fim do dia. O padrão é um hook de fim de conversa: assim que uma conversa termina (o cliente desliga, a sessão de chat encerra, o ticket é resolvido), envie a transcrição. A avaliação roda de forma assíncrona e o dashboard atualiza sozinho (a tela tem indicador "Ao vivo" e recarrega periodicamente).

Plugue o hook onde as conversas terminam: um webhook call.completed da sua telefonia, o fim da sessão de chat/WhatsApp por inatividade, ou seu próprio agente de IA logo após a última mensagem.

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 conversa é avaliada no momento em que chega, a Axon detecta degradação em tempo quase real — dispara alertas (e-mail/webhook) quando uma conversa recebe nota baixa (D/F) ou quando a média recente do agente cai em relação à janela anterior, sem esperar um relatório semanal.

Sem o SDK

O hook é só um POST HTTP — não precisa de SDK. Chame o endpoint de ingestão direto do seu backend ou até do webhook da sua telefonia/chat. O id mantém os retries 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

Três endpoints, todos autenticados por chave de API. A ingestão devolve 202 e avalia de forma assíncrona; faça polling do status ou leia o boletim.

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
}

O boletim também retorna `correction` — a correção recomendada (causa-raiz + patches concretos de PROMPT/GUARDRAIL/EVAL), ou null quando ainda não há correção gerada.

Regressão & golden sets

Trave a qualidade: transforme uma conversa avaliada em um golden case (o resultado esperado). A suíte de regressão reavalia esses casos a cada deploy.

O ciclo: (1) marque um caso a partir de um boletim/correção; (2) rode a suíte; (3) ligue o gate de CI — um deploy que faz um caso regredir é bloqueado, com aprovação de bypass auditada.

Hoje o ciclo de regressão é operado no app (plano Team) e os casos são criados a partir de conversas marcadas. Um endpoint REST dedicado de regressão está no roadmap.

Gate de CI (barra deploy ruim)

Rode a suíte de regressão no CI e falhe o build se o agente regrediu. O endpoint devolve HTTP 200 quando passa e 422 quando regrediu — então o curl --fail já barra sozinho.

Exemplo no 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

Ou com o SDK:

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

Exige o plano Pro ou superior. Cada caso é reavaliado com a sua chave BYOK.

FinOps & custo

Toda avaliação registra os tokens reais consumidos na sua chave (BYOK). O painel FinOps mostra custo estimado e tokens por agente, modelo e dia, com orçamento mensal e alerta ao estourar.

A visibilidade de custo vive no app, em /finops. Um endpoint REST para ler custo/tokens está no roadmap.

Rubrica & notas

Cada conversa recebe nota A–F geral e por dimensão (score 0–100). A/B = saudável, C = atenção, D/F = crítico. A rubrica é configurável por agente; a padrão tem seis dimensões:

Resolução
Resolveu o que o cliente pediu, sem pendências.
Anti-alucinação
Não inventou fatos, políticas, valores ou promessas.
Aderência à instrução
Seguiu o roteiro, as políticas e as instruções do sistema.
Tratamento de incerteza
Lidou bem com dúvida; escalou quando devia.
Tom & segurança
Tom adequado, respeitoso e seguro.
Eficiência
Resolveu em poucos turnos, sem rodeios.

A/B saudável · C atenção · D/F crítico

Alertas & webhooks

A Axon calcula um baseline semanal por agente e dispara um alerta de degradação quando a nota cai vs. a semana anterior.

Os alertas chegam no app e nos canais configurados em Configurações → Integração: webhook (POST JSON) e 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." }

Limites & contrato

O que o time de engenharia pergunta na primeira call:

  • O throughput de avaliação é limitado por org: 3 requisições/min ao juiz, ~8k tokens de entrada e ~2k de saída por minuto. O excedente entra em fila (FIFO). A ingestão responde 202 na hora; a avaliação roda de forma assíncrona.
  • Erros transitórios (429/5xx/rede) têm retry automático no SDK, com backoff exponencial.
  • Recomendado ≤ 50 conversas por requisição e ≤ ~100 turnos por conversa. Lotes menores e frequentes batem um lote gigante.
  • Um id por conversa torna o reenvio idempotente (atualiza, nunca duplica).
  • O boletim retorna os 3 problemas mais relevantes por agente (sem paginação).

Erros

Erros devolvem um corpo JSON { error, message } com o status HTTP apropriado.

401missing_api_keySem header Authorization / chave de API.
401invalid_api_keyChave inválida ou revogada.
402no_entitlementSem assinatura ativa ou créditos — assine ou compre o pacote de teste.
403agent_limit_reachedLimite de agentes do plano atingido — faça upgrade para adicionar mais.
403upgrade_requiredRecurso exige plano superior (ex.: regressão precisa do Pro+).
400no_transcriptsNenhuma transcrição válida no corpo.
413too_many_transcriptsTranscrições demais numa requisição (máx. 1000).
429rate_limitedLimite de requisições atingido — reduza o ritmo (retry após 60s).
404agent_not_foundAgente não encontrado nesta org.
404conversation_not_foundConversa (external id) não encontrada.
500internal_errorErro inesperado do servidor — re-tente com backoff.