aferiq
docs · v0.2.5

Aferiq em 1 linha.

Quickstart, API reference e troubleshooting. Se você quer ver o código sem ler doc, vai em /dashboard/integrate — o gerador de prompt monta as instruções pra Claude Code/Cursor instrumentar seu repo automaticamente.

1 · Quickstart

Setup completo, do zero ao primeiro trace.

Cliente novo: fazer signup, criar API key, instalar SDK, instrumentar bot — tudo em ~5 minutos.

.env + main.py
# 1. instalar
pip install aferiq-eval

# 2. .env (na raiz do projeto) — 1 env var (estilo Sentry):
AFERIQ_DSN=https://rg_pk_live_xxx@seu-deploy.com.br/api/v1/traces
# (gere em /dashboard/api-keys — clique "Baixar .env" pra ter o DSN pronto)

# 3. main.py — UMA linha, qualquer framework:
import openai          # ou anthropic — import ANTES do start() pro auto-patch
import aferiq
aferiq.start()         # lê AFERIQ_DSN, registra handler, auto-patcheia o SDK

# Pronto. A próxima chain.invoke / agent.run / chat.completions.create vira trace.

Depois de rodar seu app, abre /dashboard/traces e o primeiro trace aparece em ~30 segundos. Se não aparecer, vai em Troubleshooting abaixo.

2 · API reference

Funções públicas

aferiq.start()

Configura tracing pro cloud aferiq em UMA linha. Lê AFERIQ_DSN (ou AFERIQ_API_KEY + AFERIQ_INGEST_URL legacy), registra handler, ativa redação BR PII, e auto-patcheia openai/anthropic se estiverem importados. Idempotente, no-op se config ausente, seguro chamar várias vezes. Para versões antigas/uso avançado, veja também aferiq.init() (mesma assinatura sem auto-patch default).

aferiq.start(
    dsn: str | None = None,        # default: lê AFERIQ_DSN do env (Sentry-style)
    api_key: str | None = None,    # legacy: lê AFERIQ_API_KEY se DSN ausente
    ingest_url: str | None = None, # legacy: lê AFERIQ_INGEST_URL se DSN ausente
    verbose: bool = False,         # imprime resumo do setup no boot
) -> bool                          # True = handler registrado, False = config ausente

# start() chama init() + auto-patch dos SDKs (openai/anthropic) que estão
# importados. Equivalente a init(auto_patch=True). Idempotente.

aferiq.handler()

Factory que retorna RAGEvalCallbackHandler. Cada chamada retorna instância nova — passe por requisição, não compartilhe.

aferiq.handler() -> RAGEvalCallbackHandler

# Retorna nova instância a cada chamada (concorrência segura).
# Use por requisição:
chain.invoke(input, config={"callbacks": [aferiq.handler()]})

@aferiq.trace decorator

Captura input/output de qualquer função Python. Detecta argumento de query (query/question/prompt/input/user_message/message/text/etc) e context (context/chunks/documents) por nome. Quando context não é detectado (caso de agentes tool-calling), emite com lista vazia.

import aferiq

aferiq.start()

@aferiq.trace
def my_rag(query: str, context: list[str]) -> str:
    chunks = retriever.search(query)
    return llm.generate(query, chunks)
3 · Frameworks suportados

11 stacks. Mesma API.

O gerador de prompt em /dashboard/integrate monta o código exato pra cada framework — você cola num agente IA (Claude Code/Cursor/etc) e ele instrumenta seu repo.

FrameworkComo instrumentar
LangChain (RAG)aferiq.start() + callback aferiq.handler() em cada chain.invoke
LangGraph (multi-step)aferiq.start() + aferiq.agent_handler(goal=...) captura steps
LlamaIndexaferiq.start() + @aferiq.trace na função RAG
CrewAIaferiq.start() (auto-patch openai) + @aferiq.trace no kickoff()
Haystackaferiq.start() + @aferiq.trace no pipeline.run()
AutoGenaferiq.start() + @aferiq.trace no initiate_chat()
Pydantic AIaferiq.start() + @aferiq.trace no Agent.run()
OpenAI SDK diretoaferiq.start() — auto-patcheia chat.completions.create
Anthropic Claude SDKaferiq.start() — auto-patcheia messages.create
Função Python custom@aferiq.trace decorator funciona em qualquer função
n8n workflowHTTP Request node + redact JS inline (sem SDK)

Exemplo: LangChain RAG

import aferiq
aferiq.start()  # lê AFERIQ_DSN + redação PII BR

# Em CADA chain criada (RetrievalQA, ConversationalRetrievalChain, ou LCEL):
chain = RetrievalQA.from_chain_type(
    llm=llm,
    retriever=vectorstore.as_retriever(),
    callbacks=[aferiq.handler()],
)
4 · Redação PII

Inline. Auditável. Não é flag mágica.

aferiq.start() ativa redação default. CPF/CNPJ/RG/CEP/email/telefone BR são removidos via regex ANTES de qualquer chamada de rede. Você lê o regex no source da SDK (rageval/cloud.py).

from aferiq import redact_pii_br

# CPF/CNPJ/RG/CEP/email/telefone BR são redatados via regex.
# Idempotente, retorna a string redacted.
redact_pii_br("João, CPF 123.456.789-09")
# → "João, CPF [CPF]"

# Pra desativar redação (não recomendado em prod):
aferiq.start(redact=False)

Limites conhecidos: regex não cobre PII em prosa (nomes próprios, endereços), número de processo judicial, OAB, dados clínicos não-estruturados. Pra esses casos, redate antes de chamar chain.invoke() ou implemente handler custom — o source é todo público em aferiq-eval no PyPI.

5 · Troubleshooting

Os 5 problemas mais comuns

  • Coloquei aferiq.start() mas nada aparece em /dashboard/traces

    Verifica nessa ordem: (1) AFERIQ_DSN no .env não tá com placeholder <COLE_AQUI>; (2) python-dotenv carrega o .env (chamou load_dotenv() no entry point?); (3) start() retornou True — rode aferiq.start(verbose=True) e confira o probe (200 OK ou 405); (4) se você usa LangChain, anexou o handler? passou config={"callbacks": [aferiq.handler()]}? Em diagnóstico, faz POST manual: httpx.post(<url>, headers={"Authorization": f"Bearer <api_key>"}, json={"query":"x","context":["y"],"answer":"z"}) e confere o status code.

  • AttributeError: module 'aferiq' has no attribute 'start'

    Você tá em uma versão < 0.2.2. aferiq.start() existe a partir de 0.2.2. Atualiza com `pip install --upgrade aferiq-eval` e confere `pip show aferiq-eval` que mostra 0.2.2+ (idealmente 0.2.5+ que tem auto-emit de traces standalone). Pra versões 0.2.0/0.2.1, use o pattern antigo: aferiq.init() + patch_openai() (do submódulo rageval.integrations.openai_patch).

  • ImportError: rageval.integrations.langchain requires langchain-core

    Em versões < 0.2.3, `import aferiq` carregava langchain-core de forma eager — quebrava pra quem usava só OpenAI/Anthropic SDK puro. Resolvido em 0.2.3+: o handler do LangChain agora é importado lazy quando você chama aferiq.handler(). `pip install --upgrade aferiq-eval` resolve.

  • Conflito de deps: openai==2.24.0 vs langchain-openai 0.2.x

    litellm (dep transitiva da SDK) puxa openai 2.x. Se seu projeto tá em langchain-openai 0.2.x, force openai<2.0 no requirements.txt do seu projeto. Em roadmap pra 0.3.0: split de litellm em extra opcional [eval].

  • Estou enviando dados sensíveis e a redação default não cobre tudo

    Os patterns default cobrem CPF/CNPJ/RG/CEP/email/telefone. Pra adicionar (ex: OAB, número de processo, dados clínicos), use redact_pii_br() pra redatar antes do trace OU desative a redação default com aferiq.start(redact=False) e implemente seu próprio handler que faz o redact custom antes do POST.

  • Trace aparece com query="" ou context=[]

    Em LCEL com retriever aninhado em RunnableParallel, on_retriever_end nem sempre dispara. Desde 0.1.1 o handler emite mesmo sem context (com lista vazia). Pra OpenAI SDK direto via auto-patch (0.2.5+), context é SEMPRE [] (não há retrieval visível no nível do patch). Se faltar query, é provável que o input do chain não tem chave "query"/"question"/"input". Verifica com handler.last_trace.

Não achou seu caso? hi@aferiq.com.br — resposta em horas, não dias.

Próximo passo

Cliente novo: começa por aqui.

Cria conta com magic link, ganha 500 traces grátis por mês, e em 5 minutos tem o primeiro trace fluindo. BYOK opcional — você pode usar sua própria chave OpenAI ou a key compartilhada do aferiq pra começar.