Skip to main content
A biblioteca niadra é o SDK de Python: um cliente síncrono, Niadra, e um gêmeo assíncrono, AsyncNiadra, com os mesmos métodos. É de código aberto, sob Apache 2.0, pede Python 3.10 ou mais novo e depende só de httpx e pydantic. Cada método desta página corresponde a uma rota da referência da API.

Instalação

O cliente

AsyncNiadra recebe os mesmos argumentos, com http_client: httpx.AsyncClient. Uma instância por processo basta, e ela é segura entre threads. O cliente também funciona como gerenciador de contexto: sair do bloco chama close(), e um gancho de saída esvazia a fila por até dois segundos.

Propriedades

Seguro por padrão, estrito quando você pede

Sem chave, o cliente avisa uma vez e não faz nada. Cada método público captura e registra as próprias falhas e devolve um valor seguro: um Context vazio (veja context.error), um resultado vazio, False ou None. Os logs levam nome do método, status, código de erro e id da requisição, nunca handle nem texto. Com strict=True, as mesmas falhas levantam as exceções de Erros.

Tempo máximo

O SDK tem o próprio tempo máximo por método, independente do que a plataforma em volta permite.
Novas tentativas: respostas 5xx, 429 e erros de rede são repetidos com espera crescente; 421 (o espaço está mudando de célula) é repetido na hora, numa conexão nova; as outras respostas 4xx são definitivas.

O cache de contexto

Dentro de uma conversa ou tarefa (uma chamada com conversation_id ou task_id), os contextos ficam em memória:
  • com menos de 10 s: devolvidos sem requisição;
  • até 10 minutos mais velhos: devolvidos na hora, enquanto uma requisição em segundo plano atualiza;
  • quando uma requisição falha: o último contexto bom, se tiver menos de 30 minutos;
  • no máximo 1.000 contextos, saindo primeiro o usado há mais tempo.
A atualização manda o ETag guardado, então um contexto que não mudou custa uma resposta not_modified em vez do texto inteiro, e só uma atualização por contexto roda de cada vez. Um 401 ou 403 não é indisponibilidade: os contextos guardados saem (todos no 401, o pedido no 403), então cortar o acesso de um fornecedor corta também o que ele tinha em cache. Uma leitura comum e uma leitura com delta da mesma conversa dividem a mesma entrada, e cada delta é entregue uma vez só.

A fila de escrita

track(), action() e handoff() só enfileiram. Uma thread em segundo plano (uma task, no AsyncNiadra) manda um lote quando 15 itens estão esperando ou um segundo depois de o primeiro chegar, com três tentativas e espera crescente. Com a fila cheia, os itens novos são descartados e contados em dropped.

Handles

Handles identificam um sujeito num canal ou sistema. Os ajudantes são funções de primeiro nível que normalizam o valor e levantam ValueError quando a entrada não pode ser válida, então um telefone malformado falha no ponto em que entra no seu código. Todo método que recebe handle aceita também o modelo Handle ou um dicionário com os campos dele ({"type": "phone_e164", "value": "+14155550123"}). Objetos entram como "invoice:erp:0823" ou como ObjectRef.

context()

O contexto de uma pessoa, de uma organização ou de um objeto de negócio. Corresponde a POST /v1/context.
Devolve um Context: todos os campos da resposta da API mais o que o SDK sabe da chamada.
Busca no histórico inteiro de um sujeito, por palavra e por significado. Corresponde a POST /v1/history/search.
Devolve um SearchResult com items, recurrence (quantas vezes a mesma categoria aconteceu e como terminou a última), withheld, as_of, tokens_used, degraded e, em caso de falha, error.

timeline()

Uma página do histórico do sujeito, do mais recente para o mais antigo. Corresponde a POST /v1/history/timeline.
limit vai de 1 a 100. Devolve uma TimelinePage com items, next_cursor, withheld, as_of e, em caso de falha, error. Passe next_cursor como cursor para continuar.

open()

Abre um episódio ou objeto encontrado por search() ou timeline(). Corresponde a GET /v1/history/items/{item_id}.
Devolve um OpenedItem (summary, requested, promises, outcome, resolution, derived, timeline) ou None quando ele não está disponível. O trecho literal, excerpt, só volta para chaves com escopo elevado.

object_state() e object_timeline()

Leituras de um objeto de negócio. Correspondem a GET /v1/objects/{object_type}/{namespace}/{external_id} e à linha do tempo dele.
ObjectState traz ref, state, as_of, source_id, record_ref e as open_items. O estado vem só do que os sistemas de registro informaram; a ação de um agente conta quando um sistema a confirma. ObjectTimeline traz ref, items, next_cursor e as_of: eventos de sistema e ações de agente, do mais recente para o mais antigo, nunca o que alguém disse. Ids de objeto são ids de registro, não dado pessoal, então vão na URL; um id com barra não pode ser endereçado assim.

track()

Enfileira uma mensagem, um evento de sistema, uma ação ou qualquer outro item de lote, e volta na hora. Corresponde a POST /v1/batch.
Aceita um EventItem ou um dicionário com os campos dele. Um dicionário sem channel recebe o canal padrão do cliente; idempotency_key (um UUIDv7) e occurred_at (agora) são preenchidos quando você não passa. Use o id da mensagem no provedor como idempotency_key quando houver, para um lote repetido nunca duplicar nada. Devolve False quando o item foi descartado: inválido, impossível de serializar, fila cheia ou cliente desligado.

action()

Registra o que um agente fez num sistema de registro. Vai para a fila, como track().
A ação fica declared até o sistema de registro confirmar com o próprio evento. Registrar ação exige o escopo act na chave.

identify()

Afirma que dois ou mais handles são do mesmo sujeito. Sai na hora, sem fila, para o context() seguinte enxergar; se a requisição falhar, o item vai para a fila de envio e o método devolve None.

verify()

Eleva o nível de verificação de uma conversa ou tarefa, depois que você provou. A Niadra nunca deduz o nível. Sai na hora, e o contexto guardado daquela conversa é descartado, para o próximo context() já vir no nível novo.
method é otp_whatsapp, otp_sms, login, kba, network_attestation ou human_agent. Um nível acima do teto da fonte volta como erro de item verification_not_allowed.

feedback()

Corrige o que a Niadra derivou sobre um sujeito. Sai na hora e vira evento, então é auditado como qualquer outro. Corresponde a POST /v1/feedback.
Cada ação pede os próprios campos: value vai até 2.000 caracteres e reason até 500. Devolve None quando a correção não pôde ser entregue.

upload_media()

Entrega um arquivo à Niadra, como a gravação de uma ligação, e devolve a referência para o evento. Mídia nunca viaja dentro do evento. Corresponde a POST /v1/media/uploads.
O método calcula o hash dos bytes, reserva o upload e manda os bytes direto para o armazenamento pela URL assinada, de vida curta. Ele envia exatamente os upload_headers que a API devolveu, que são os cabeçalhos cobertos pela assinatura, e nada além: nunca a sua chave. A URL precisa ser HTTPS, a não ser no emulador local. O armazenamento confere o corpo contra o tamanho e o hash declarados. Com subject, o arquivo fica guardado sob aquela pessoa, então apagar a pessoa apaga o arquivo, mesmo que nenhum evento o cite. Devolve um MediaUpload com media_ref, media_sha256, content_type, size_bytes e expires_at, ou None quando o upload falhou. Cada tentativa da transferência tem o tempo máximo upload, 60 s por padrão.

handoff()

Registra uma transferência para um humano ("human") ou para outro agente ("agent"). Vai para a fila. A medição do aproveitamento do contexto lê esse registro para contar transferências em que o destino não leu o contexto.

conversation()

Uma conversa com um cliente, usada como gerenciador de contexto. Sair do bloco emite conversation.ended, mesmo quando o bloco levantou exceção.
Sem conversation_id, o SDK cria um. channel vem do cliente quando não é passado. agent_id identifica o seu agente dentro da fonte e vai carimbado nos turnos e nas ações dele. O primeiro context() recebe o contexto que o servidor fixa para a conversa. As leituras seguintes pedem também o delta, e a conversa guarda cada delta que chega, em ordem, então turn_block leva todas as mudanças desde a fixação, seguidas dos turnos ao vivo. Quando o servidor fixa um contexto novo, depois de verify() por exemplo, os deltas guardados saem: o contexto novo já os contém. Uma leitura com query= é avulsa e não mexe neles. Chame mark_injected() toda vez que puser o contexto num prompt. É assim que a Niadra distingue um contexto que chegou depois de o agente falar de um contexto que o agente tinha e não usou. A sessão guarda também context_injected_at e first_agent_turn_at, o primeiro de cada, para as suas próprias checagens.
current_session() devolve a conversa ou tarefa cujo bloco está rodando na thread ou task atual, se houver.

task()

O mesmo para um agente interno (cobrança, pedidos, tickets). Emite task.ended na saída.
Com object, o contexto fica centrado nele; use uma view de tarefa como task:billing. Uma tarefa tem os mesmos métodos de uma conversa, menos handoff().

tools()

O kit do histórico como ferramentas de chamada de função, amarrado a um cliente. O cliente fica amarrado aqui, fora do alcance do modelo: o modelo escolhe a consulta, nunca o perfil, e é isso que impede uma injeção de prompt de trocar de cliente.
AsyncNiadra.tools() devolve um AsyncToolKit, com call() aguardado. As definições também saem em GET /v1/history/tools.

subject_token()

Emite um token assinado, de 15 minutos, que amarra uma conexão MCP a um cliente. Chame do seu backend. Corresponde a POST /v1/subject-tokens.
Devolve um SubjectToken com token, expires_at e headers, o cabeçalho Niadra-Subject-Token que vai junto da chave da fonte quando o agente abre a conexão com mcp_url. Com about, a organização fica amarrada como o sujeito. Veja MCP com qualquer LLM.

wrap()

Embrulha o cliente Python da OpenAI, ou qualquer cliente com o mesmo formato, para toda chamada dentro de um bloco de conversa ou tarefa receber o contexto e registrar a resposta.
Dentro de um bloco (ou para a sessão que você passar), chat.completions.create e chat.completions.parse, síncronos ou assíncronos, com streaming ou sem, recebem o contexto fixado como mensagem de sistema logo depois das suas mensagens de sistema iniciais, e o turn_block como mensagem de sistema no fim. A injeção é carimbada com mark_injected(), e a resposta do modelo é registrada como turno do agente: quando o stream termina ou é fechado e, por with_raw_response, quando você chama parse(). Fora de um bloco, as chamadas passam intactas. O embrulho devolve um proxy e nunca altera o seu cliente. Nada do que ele faz derruba a chamada ao modelo: um contexto que não chega fica de fora, e uma falha ao registrar a resposta vai para o log, sem conteúdo.

flush() e close()

flush() manda tudo o que está na fila a partir da thread que chamou e devolve True quando não sobra nada. close() esvazia a fila por até timeout segundos e libera as conexões. No AsyncNiadra, os dois são aguardados.

AsyncNiadra

AsyncNiadra tem os mesmos métodos. As leituras, identify(), verify(), feedback(), upload_media(), subject_token(), flush() e close() são aguardados; track(), action(), handoff(), conversation(), task() e tools() não. Conversas e tarefas são gerenciadores de contexto assíncronos.

Erros

Com strict=True, ou nos ajudantes que você chama direto, como ApiKey.parse() e as funções de handle, o SDK levanta: O catálogo completo de códigos está em Erros. Cite request_id quando falar com o suporte.

Emulador local

niadra-mock, instalado junto da biblioteca, é um emulador local, em memória, da mesma API. Nos testes, rode o SDK contra ele no mesmo processo:
Os turnos recentes viram um contexto pequeno, cada delta sai uma vez por mudança, a busca casa palavras, a verificação só sobe por verify(), os objetos tiram o estado dos eventos de sistema, a correção vira um evento feedback.* e os uploads de mídia vão para mock.cell.media. mock.cell também deixa inspecionar eventos e provocar falhas (fail_next, revoke, cut, put_in_holdout). No terminal, niadra-mock --port 8765 serve o emulador por HTTP.

Próximos passos

SDK de TypeScript

A mesma superfície para Node e runtimes de borda.

Início rápido

Da chave ao primeiro contexto entregue.

O contexto e as views

O que entra no contexto e por quê.

Erros

O catálogo de códigos e o que fazer com cada um.