Skip to main content
Um time que troca um prompt, um modelo ou os dados que um agente consulta quer saber, antes de a mudança chegar aos clientes, se o agente ainda faz o que fazia nas conversas que importaram. Rodar um turno real uma vez diz pouco: modelos não são determinísticos, e um teste que falha uma vez em cinco é ruído, a menos que falhasse menos antes. O replay transforma registros de turno em cenários, roda cada turno N vezes dentro da sua empresa e transforma as N execuções num veredito estatístico. A Niadra orquestra: guarda os cenários, serve cada turno como um caso com a build em que ele rodou e decide o veredito. O seu CI executa: o executor do SDK busca os valores gravados de onde eles moram, roda o agente com as ferramentas interceptadas e avalia asserções estruturais sobre o registro novo. Nenhum valor sai da sua empresa, e nada do que o agente diz num replay vai a um cliente.

Antes de começar

  • A funcionalidade turns ligada no espaço, e turnos gravados em modo stored ou pointer, com fidelidade gold (o SDK, não OpenTelemetry) e os pinos que o documento recording exige (prompts e model por padrão). Um turno hash_only, bronze, partial ou sem um pino exigido é guardado, mas não reproduzível: o visualizador e GET /v1/turns/{turn_id} dizem por quê em replay_blockers.
  • Uma chave com o escopo replay, numa fonte própria do CI; as rotas aceitam também uma pessoa com o papel integration ou security.
  • Ferramentas gravadas com @Niadra.tool (Python) ou Niadra.tool (TypeScript): é assim que o executor as intercepta.

1. Escolha os turnos

Um cenário guarda até 50 turnos e até 50 asserções. Os turnos são copiados para fora da camada deles quando o cenário é criado e ficam scenario_days depois da última execução (180 dias por padrão, de 7 a 365); um turno que saiu do armazenamento responde replay_expired. Três jeitos de criar um:
Sem asserções, a Niadra as sugere por regra, a partir do quadro de cada turno e nunca dos valores: tool_called para cada ferramenta que respondeu ok, hard_respected quando o turno reportou restrições aplicadas, no_denial_with_results quando um resultado mostrou itens, claims_traced e claims_match_state quando houve afirmações, effect_once quando houve efeitos, handoff_when quando o turno criou uma transferência e budget com o dobro das chamadas gravadas. De um relato, as palavras da descrição (uma negativa, um preço ou um prazo, uma promessa, algo feito duas vezes, um humano) sugerem a asserção correspondente, e a descrição é lida e nunca guardada. Uma asserção sugerida vem com suggested: true; ajuste, tire ou acrescente por PATCH /v1/scenarios/{scenario_id}, que soma um à versão.

2. As asserções

Cada asserção é {id, kind, args, turn_id?}: com turn_id, vale para aquele turno; sem, para todos. O executor avalia cada uma sobre o registro do turno reproduzido e o texto que ele emitiu, e o resultado é pass, fail ou not_checked, que nunca é falha:

3. Rode no CI

O executor do SDK pede cada caso, confere os pinos, busca os blobs pelo digest, roda o agente com as ferramentas respondendo do registro e reporta a execução; a Niadra devolve o veredito. --agent nomeia uma função que cria um agente novo por execução, que recebe a entrada do caso e devolve o texto que emitiu; --build nomeia a build em execução, os mesmos pinos que os turnos de produção fixam.
Um exemplo de workflow do GitHub Actions, com a chave de replay num segredo:

O que acontece numa execução

  • A conferência dos pinos. Para todo pino fora de vary, a build em execução e a gravada precisam ser iguais quando a gravação exige o pino, e quando os dois lados o têm. Uma diferença responde 422 pin_mismatch, com pins: [{name, recorded, running}], e nenhum caso é servido. Para testar um prompt novo de propósito, nomeie o pino: --vary prompts.
  • Os valores. No modo stored, cada blob vem com o conteúdo guardado e mascarado; no modo pointer, o executor lê cada pointer com as suas credenciais, pelo resolvedor de conteúdo do SDK, e confere o digest. Um blob que não pode ser lido ou não bate é um erro de infraestrutura, contado à parte e nunca uma falha de asserção.
  • As ferramentas. Uma chamada cujos argumentos normalizados batem com o args_hash de uma chamada gravada responde com o resultado gravado, as chamadas de uma ferramenta tomadas em ordem. Uma que não bate com nenhuma só roda ao vivo quando a ferramenta foi marcada dry_run=True (dryRun: true); senão, responde vazia e conta como divergente. Uma ferramenta de framework que não foi envolvida com tool() nunca roda ao vivo num replay.
  • O que o agente lê e escreve. O contexto da época é o blob da leitura pack do registro; a memória de trabalho começa vazia e as escritas ficam no executor; uma pergunta de coordenação responde do registro. O registro do turno reproduzido fica com o executor, marcado synthetic, e nunca é enviado como turno.
  • Os modos. hermetic_turn (o padrão) roda o turno sozinho, com o contexto gravado e toda ferramenta respondendo do registro; hermetic_conversation roda os turnos do cenário em ordem, até a primeira divergência forte; era_memory roda com o contexto da época e o estado atual dos objetos que as ferramentas leem.
  • A entrada. Cada caso traz a mensagem do cliente que abriu o turno, mascarada, e o histórico da conversa até ali (no máximo as últimas 50 mensagens públicas dos 7 dias anteriores). --runs roda cada turno N vezes, numeradas a partir de 1; uma função paraphrase reescreve a entrada de algumas execuções, para um resultado intermitente ser confirmado com outras palavras.

4. Leia o veredito

Por asserção, sobre as execuções que concluíram e em que ela se aplicou (not_checked de fora): passed e failed, a linha de base (a mesma asserção na última execução anterior do cenário com veredito pass ou flaky; sem uma, a gravação, que passou tantas vezes quanto a execução conferiu), drop (a taxa de aprovação da base menos a da execução) e p_value (o teste exato de Fisher unilateral de que a execução falha mais que a base). regression é failed >= 2, drop >= 0,2 e p_value < 0,05; flaky é uma falha que não chega a regressão. Por cenário: pin_mismatch quando alguma execução parou nos pinos; infrastructure_error quando nenhuma concluiu; regression quando alguma asserção regrediu; flaky quando alguma oscilou; pass nos demais casos. needs_paraphrase diz que uma asserção passou e falhou nas mesmas execuções: rode de novo com paráfrases antes de confiar. O veredito da execução é o pior dos cenários, na ordem pass, flaky, infrastructure_error, pin_mismatch, regression, e o comando sai com 1 só numa regressão: resultados oscilantes são listados e nunca travam. Quando uma execução falha uma asserção que lê o que as ferramentas mostraram, a Niadra confere as observações do turno gravado contra os tipos declarados e abre um problema de dados para o dono do dado (null_field, out_of_vocabulary, stale_source), com até 50 referências e nenhum valor: uma regressão que é do dado, não do agente, chega a quem pode consertar.

5. Bissecte com o registro de mudanças

GET /v1/changes lista o que mudou entre builds consecutivas de cada agente, do mais novo para o mais antigo: prompt (uma versão de prompt, pelo nome), model, code (o montador ou o esquema de uma ferramenta), data (o digest do corpus), config (uma seção da configuração do espaço que o turno leu, pelo digest dela: o contrato de afirmação, os tipos, as vinculações) e compiler (a versão do compilador de contexto), com before e after e quando a build nova apareceu. Uma regressão entre duas execuções aponta para as mudanças entre as builds delas.

Privacidade

O caso leva o histórico da conversa mascarado e, no modo pointer, nenhum valor gravado: o executor os lê dentro da sua empresa. Os turnos de um cenário são dado pessoal com a finalidade quality, ficam scenario_days depois da última execução e são apagados com o resto dos turnos da pessoa. Os resultados de uma execução guardam vereditos e contagens; error e detail nunca levam dado pessoal.

Próximos passos

Registros de turno

o que um turno grava e por que ele é reproduzível ou não.

Só metadado

replay com os valores no seu bucket.

Pedir um caso de replay

a referência de POST /v1/replay/cases.

Desfechos e atribuição

o contrafactual de ferramenta, que roda pelo mesmo executor.