Cookbook REST
Receitas funcionais contra a API viva do engine: cada campo verificado contra a spec em execução.
Todo exemplo aqui roda contra o engine hospedado em https://valorbrain-api.valor.digital.
Os mesmos paths funcionam no seu engine on-premise (Enterprise; porta padrão :7438 na sua rede).
Os nomes de campo vêm da spec que o próprio engine serve em /openapi.json — se esta página e a spec divergirem, a spec vence (um rebuild regenera as páginas de referência a partir dela).
Autenticação e tenancy
Authorization: Bearer <token>Duas classes de token são aceitas nas rotas de tenant:
| Token | Formato | O que é |
|---|---|---|
| Token master do engine | qualquer string definida como VALORBRAIN_API_TOKEN | Acesso total ao engine. Só server-side. |
| API key de shadow tenant | vb_... | Criada por npx @valorbrain/cli init --agent; escopa num único tenant, expira sozinha. |
Rotas admin (/api/v1/admin/*) usam ENGINE_ADMIN_SECRET como bearer no lugar — tokens de tenant levam um 403 limpo lá.
Rotas de dinheiro (billing, credits, subscriptions) aceitam o token master ou o admin secret, e rejeitam tokens de tenant/persona por design.
Deploys multi-tenant também roteiam via header x-tenant-id (parâmetro TenantIdHeader na spec).
Com um token de engine, o header escolhe o tenant; com uma chave vb_, o tenant já está vinculado à chave.
Checagem rápida de liveness — sem autenticação:
curl -sS https://valorbrain-api.valor.digital/healthzEscrever um documento
curl -sS -X POST https://valorbrain-api.valor.digital/documents \
-H "Authorization: Bearer $VALORBRAIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"collection": "team-notes",
"path": "2026-08-31/deploy-openapi",
"title": "OpenAPI served live from routes[]",
"content": "The engine now generates /openapi.json from the routes table at request time. servers[] is rewritten from VALORBRAIN_PUBLIC_URL.",
"content_type": "milestone",
"confidence": 0.9,
"quality_score": 0.8,
"metadata": {"repo": "valorbrain", "sha": "a34e288d"}
}'Campos do request (todos verificados contra a spec):
| Campo | Tipo | Obrigatório | Default | Notas |
|---|---|---|---|---|
collection | string | sim | — | Namespace; por tenant |
path | string | sim | — | Único dentro da coleção; mesmo path re-serve o mesmo documento |
content | string | sim | — | Máx. 1 MB |
title | string | não | — | |
content_type | string | não | note | Livre; o SaaS cura um vocabulário (note, decision, problem, milestone, …) |
confidence | number | não | 0.5 | 0–1; alimenta o ranking e o gating de consolidação |
quality_score | number | não | 0.5 | 0–1 |
metadata | object | não | — | JSON arbitrário, consultável |
user_id | string | não | — | Atribuição |
run_id | string | não | — | Agrupa writes de uma sessão/job |
event_at | string | não | — | Quando o evento aconteceu (vs. hora do write) |
event_type | string | não | — |
O Document que volta carrega: id, hash, collection, path, title, content_type, visibility, embed_state, is_pinned, page_type, created_at, updated_at.
Três comportamentos que surpreendem:
- Embedding é assíncrono. O write volta imediatamente;
embed_statevai depending → synced(oufailedcomembed_error). Busca que inclui a perna densa só vê o documento quando ele está sincronizado. Faça polling emGET /documents?collection=...se precisar esperar por isso. - Conteúdo é deduplicado por hash. Os mesmos bytes não são indexados duas vezes — inclusive entre coleções (dedup cross-collection é deliberado). Mude o
pathou o conteúdo, não só o título. visibilitydistingue memória compartilhada do tenant de memória privada (sensitivity: private). Documentos privados são ocultados dos outros usuários do tenant — não é só questão de ficarem sem atribuição.
Ler: buscar, recuperar ou perguntar
Três portas, um índice:
| Endpoint | Quando usar | O que devolve |
|---|---|---|
POST /search | O ranking é problema seu; você quer a lista de hits | Resultados ranqueados com scores e snippets |
POST /retrieve | Você quer auto-roteamento e uma chamada para a maioria das perguntas | Resultados ranqueados, sensíveis ao modo |
POST /ask | Você quer uma resposta, não documentos | Resposta de LLM com citações das fontes (suporta stream) |
Busca híbrida
curl -sS -X POST https://valorbrain-api.valor.digital/search \
-H "Authorization: Bearer $VALORBRAIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"q": "how does dedup across collections behave",
"collection": "team-notes",
"limit": 10,
"mode": "hybrid",
"diverse": true
}'q(obrigatório) — a consulta.mode—auto(padrão),keyword,semantic,causal,hybrid. O pipeline de produção é BM25 + vetores densos + RRF + reranking de grafo + rerank com cross-encoder;modepolariza quais pernas dominam.expand— força liga/desliga da expansão de consulta estilo HyDE. Deixe sem setar e o servidor decide.diverse(padrãotrue) — filtro de diversidade MMR, para que dez hits não sejam dez paráfrases de um documento só.offset— paginação.
Perfis e timing
Dois knobs de request que as páginas de referência carregam mas o resumo da spec não detalha:
"profile": "speed"em/search— o caminho rápido (hybrid/FTS, sem cross-encoder). O padrão ébalanced. Usespeedem consultas interativas tecla-a-tecla onde 100 ms importam mais do que os últimos pontos de ranking."timing": true(ou headerx-search-timing: 1) — adicionahybrid_ms,rerank_ms,graph_msetotal_msà resposta. Quando a recuperação parece lenta, isso diz qual perna antes de você chutar.
Recuperação unificada
curl -sS -X POST https://valorbrain-api.valor.digital/retrieve \
-H "Authorization: Bearer $VALORBRAIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"q": "why did we switch the embedding model", "mode": "auto", "limit": 12}'mode adiciona timeline e discovery ao conjunto de busca — auto roteia perguntas de porquê para causal, perguntas de quando para timeline, perguntas de vizinhança para similar-docs. É o mesmo cérebro que memory_prepare usa no lado MCP: uma consulta bem-formulada vale mais que cinco quase-duplicadas.
Resposta RAG
curl -sS -X POST https://valorbrain-api.valor.digital/ask \
-H "Authorization: Bearer $VALORBRAIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"q": "What is the document cap for one write?", "collection": "team-notes", "limit": 8}'Campos: q, collection, limit, language, stream. A resposta cita os documentos que usou; trate a lista de citações como o contrato, não a prosa.
Feche o loop: memory_used
Depois de responder com memória recuperada, declare o que você realmente usou:
curl -sS -X POST https://valorbrain-api.valor.digital/api/v1/memory/used \
-H "Authorization: Bearer $VALORBRAIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"docids": ["#ab12cd", "#ef4567"], "verdict": "confirmed", "note": "answer relied on the dedup doc"}'docids— os documentos que sustentaram a resposta.verdict—confirmedquando o usuário concordou com o que a memória disse,correctedquando ele rebateu. O loop de feedback é o que faz o ranking aprender; uma recuperação não declarada é uma recuperação desperdiçada.note— texto livre.
Curar: pin, snooze, forget
Os três são POSTs no id do documento (corpos vazios):
curl -sS -X POST https://valorbrain-api.valor.digital/documents/$DOC_ID/pin \
-H "Authorization: Bearer $VALORBRAIN_TOKEN"
curl -sS -X POST .../documents/$DOC_ID/snooze \
-H "Authorization: Bearer $VALORBRAIN_TOKEN"
curl -sS -X POST .../documents/$DOC_ID/forget \
-H "Authorization: Bearer $VALORBRAIN_TOKEN"- pin — boost permanente de prioridade; o documento aparece acima do decaimento do ranking.
- snooze — oculta por N dias (un-snooze reverte). Use quando uma memória está errada agora mas a fonte será corrigida (uma migration em andamento, uma config velha).
- forget — remove a memória. Prefira isso a dar
pinno oposto: um fato corrigido junto do original superseded é um conflito futuro.
Visão do lifecycle (contagens de archived/forgotten/pinned/snoozed e política):
curl -sS https://valorbrain-api.valor.digital/lifecycle/status -H "Authorization: Bearer $VALORBRAIN_TOKEN"POST /lifecycle/sweep roda as políticas (dry-run por padrão — confira a resposta antes de purgar), POST /lifecycle/restore traz de volta documentos auto-arquivados (forgets manuais continuam apagados).
Confiança: conflitos e decisões
Conflitos
curl -sS ".../api/v1/conflicts?status=open" -H "Authorization: Bearer $VALORBRAIN_TOKEN"
curl -sS -X POST .../api/v1/conflicts/detect -H "Authorization: Bearer $VALORBRAIN_TOKEN"
curl -sS -X POST .../api/v1/conflicts/resolve -H "Authorization: Bearer $VALORBRAIN_TOKEN" \
-H "Content-Type: application/json" -d '{"conflict_id": "...", "strategy": "most_recent"}'Conflitos de valor (mesma chave, valores diferentes), conflitos temporais (fatos expirados ainda afirmados), conflitos de relacionamento. Existem sete estratégias de resolução; most_recent e credibility_weighted cobrem a maioria dos casos reais. A detecção também roda automaticamente no tick de consolidação.
Decisões
curl -sS -X POST .../api/v1/decisions -H "Authorization: Bearer $VALORBRAIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"category": "architecture",
"scenario": "serving OpenAPI",
"reasoning": "static YAML drifts from routes; generate from the running table",
"outcome": "live spec merged with YAML contract",
"confidence": 0.85
}'Companheiros: POST /api/v1/decisions/relations (caused / influenced / precedent_for), GET /api/v1/decisions/chain (caminha uma cadeia causal), GET /api/v1/decisions/similar (busca semântica de precedentes), GET /api/v1/decisions/impact (o que uma decisão tocou a jusante). Registros são hash-chained — a trilha de auditoria é à prova de adulteração por construção.
Medir: uso e valor
curl -sS ".../reports/usage" -H "Authorization: Bearer $VALORBRAIN_TOKEN"
curl -sS ".../api/v1/usage/answers" -H "Authorization: Bearer $VALORBRAIN_TOKEN"
curl -sS ".../api/v1/tenant/value-summary" -H "Authorization: Bearer $VALORBRAIN_TOKEN"O ledger de uso registra cada operação por canal (mcp / rest / hook / cli) com latência e contagens de resultado; value-summary serve o pré-agregado diário (stale_days reporta buracos enquanto o dia de hoje agrega ao vivo). São os endpoints que os dashboards do SaaS leem — mesmos dados, sem camada de interpretação no meio.
REST vs MCP
Tudo acima é REST. As 92 ferramentas MCP (memory_retrieve, memory_store, decisions, conflicts, kg_query, …) são uma superfície diferente sobre o mesmo engine, com ergonomia mais rica (expansão de consulta server-side, budgets de snippet, tokens de persona). Se o seu cliente fala MCP, prefira — veja Ferramentas MCP e os schemas completos. Se fala só HTTP, esta página é o jogo inteiro.
Falhas comuns
| Sintoma | Causa | Correção |
|---|---|---|
401 em toda chamada | Token ausente/rotacionado | Confira o prefixo Authorization: Bearer (sem Basic, sem aspas) |
403 em rotas admin com um token válido | Token de tenant numa rota admin | Use ENGINE_ADMIN_SECRET — ou não toque em rotas admin a partir de código de tenant |
| Busca vazia logo após um write | Embedding ainda pendente | Faça polling de embed_state; a perna densa precisa de synced |
| Write funciona, a busca nunca acha | Hash do conteúdo já indexado em outro lugar | Dedup cross-collection é por design; mude o conteúdo ou aceite a cópia existente |
| Zero linhas numa consulta que você sabe que bate | RLS: token/header resolveu outro tenant | Verifique o x-tenant-id e que a chave vb_ pertence àquele tenant |
200 mas o score parece baixo numa correspondência exata | Correspondências de string exata ranqueiam pelo pipeline completo, não por igualdade de string | Para identificadores e literais use memory_grep (MCP) ou modo keyword, não ranking semântico |
400 num body >1 MB | Teto rígido no content | Divida o documento; path é sua chave de paginação |