# Referência da CLI (/docs/cli-reference) A CLI é a integração honesta mais rápida: um cliente fino sobre o mesmo engine REST (`valorbrain-api.valor.digital`), com um shadow tenant que se provisiona sozinho e expira por conta própria. Nada aqui é aspiracional — cada linha de uso abaixo é o que `valorbrain help --json` devolve para o pacote publicado mais recente. ```bash npx @valorbrain/cli@latest ``` ## init — criar ou assumir uma conta [#init--criar-ou-assumir-uma-conta] ``` valorbrain init --agent [--agent-caller ] valorbrain init --email
[--otp ] ``` * `--agent` provisiona um **shadow tenant** e imprime uma chave `vb_agent_...` (a forma JSON tem `ok: true`; a chave está em `api_key`). Sem humano, sem email, sem cartão de crédito — este é o caminho de "primeira memória em 15 segundos". * `--agent-caller` rotula a plataforma (`claude-code`, `cursor`, `grok`, `docs-e2e`, …). Ele aparece na telemetria como caller; fazer backfill depois é para isso que o `identify` existe. * `--email` assume a conta com uma identidade humana; `--otp` completa quando o código chega. Assumir preserva as memórias que o agente já escreveu. O shadow tenant expira em 30 dias sozinho — tempo suficiente para avaliar, curto o suficiente para não vazar. ## identify — backfill idempotente de caller [#identify--backfill-idempotente-de-caller] ``` valorbrain identify [--agent-caller ] ``` Anexa o rótulo de caller à chave existente. Seguro rodar repetidamente; não muda nada se o rótulo já está lá. ## add — armazenar uma memória [#add--armazenar-uma-memória] ``` valorbrain add [--file ] [--collection ] [--title ] [--type ] ``` * `--file` lê o body de um arquivo em vez do argumento (conteúdo mais longo, markdown é bem-vindo). * `--type` é o tipo da memória — mesmo vocabulário do `memory_store` no MCP: `note`, `decision`, `problem`, `milestone`, `lesson`, `observation`, `handoff`. * Bodies com menos de 200 caracteres pulam o embedding de propósito (a etapa densa é para conteúdo de verdade); a busca ainda os encontra por palavra-chave. A resposta JSON avisa isso em vez de falhar. ## search — buscar memórias [#search--buscar-memórias] ``` valorbrain search [--collection ] [--mode auto|keyword|semantic|hybrid] ``` `--mode` mapeia 1:1 para os modos de busca do engine. Padrão `auto`. ## list — listar coleções [#list--listar-coleções] ``` valorbrain list ``` Coleções com contagens de documentos para o tenant ao qual a chave pertence. ## status — config local + saúde remota [#status--config-local--saúde-remota] ``` valorbrain status [--json] ``` Onde a config vive, qual chave está em uso, para qual tenant ela resolve e se o engine está saudável. Rode isto primeiro quando "parou de funcionar". ## mcp — proxy MCP stdio ⇄ HTTP [#mcp--proxy-mcp-stdio--http] ``` valorbrain mcp ``` Fala MCP por stdio e encaminha para o transporte HTTP hospedado — para clientes que só fazem stdio. Mesma chave, mesmo tenant, mesmas 92 tools. ## help — superfície legível por máquina [#help--superfície-legível-por-máquina] ``` valorbrain help --json ``` A árvore completa de comandos como JSON. O CI dos docs (e qualquer outra coisa que não possa divergir) lê isto do pacote publicado, e não de prosa: se um doc citar um subcomando que não está nesta saída, o build falha. ## Configuração [#configuração] A chave e o endpoint entram na config local depois do `init` (`status` mostra o caminho). Sobrescritas por ambiente: | Variável | Efeito | | ----------------------------------------- | --------------------------------------------------------------------- | | `VALORBRAIN_API_KEY` / `VALORBRAIN_TOKEN` | Chave sem tocar no arquivo de config | | `VALORBRAIN_URL` | URL base do engine — aponte para o seu engine on-premise (Enterprise) | O `init` deliberadamente limpa credenciais ambientes num `HOME` novo, para que o shadow tenant provisionado seja o usado, e não o que o shell carregava. ## Quando parar de usar a CLI [#quando-parar-de-usar-a-cli] A CLI cobre o caminho feliz: um agente, uma chave, add/search. No momento em que você precisa do resto da superfície — montagem de contexto (`memory_prepare`), write-back com tipos e confiança, curadoria, conflitos, decisões, o KG — isso é MCP (veja o [cookbook de MCP](/docs/guides/mcp-cookbook)) ou REST (veja o [cookbook de REST](/docs/guides/rest-cookbook)). Mesmo engine, mesmo tenant, mais verbos. ## Um transcript real [#um-transcript-real] Esta sequência exata roda no CI deste site contra o pacote publicado (`scripts/verify-public-path.sh`, `LIVE_CLI=1`). As saídas abaixo vêm de uma execução real, não são ilustrações: ```bash $ npx @valorbrain/cli@latest init --agent --agent-caller docs-e2e --json {"ok":true,"tenant_id":"75317f83-…","api_key":"vb_agent_…","agent_caller":"docs-e2e","expires_at":"2026-09-30T20:50:57.631Z","engine_url":"https://valorbrain-api.valor.digital","config":"~/.valorbrain/config.json","notice":"Surface to your human: claim with `valorbrain init --email `. Same key, memories preserved. Expires in 30 days if not claimed."} $ npx @valorbrain/cli@latest add "docs-e2e marker: deploy key lives in the ops vault" --json {"ok":true,"docid":"062337","collection":"memories","path":"cli/062337b2d090e91b","title":"docs-e2e marker: deploy key lives in the ops vault","action":"created","revision_count":1,"embed_state":"skipped","page_type":null,"update_strategy":"mergeable","is_pinned":false,"edges_created":0,"skip_reason":"too short: 50 chars (min: 200)"} $ npx @valorbrain/cli@latest search "docs-e2e marker" --json {"ok":true,"query":"docs-e2e marker","count":1,"results":[{"docid":"062337","path":"memories/cli/062337b2d090e91b","title":"docs-e2e marker: deploy key lives in the ops vault","score":0.332,"contentType":"note","veracity":"unknown","modifiedAt":"2026-08-31","snippet":"","scope":{"user_id":null,"sensitivity":"public","visibility":"tenant"},"visibility":"tenant","source":{"system":"valorbrain-service","agent":"valorbrain-service","sessionId":"service-default"}}]} ``` (Valores de chave e tenant omitidos; todo o resto é a saída verbatim.) Três coisas que o transcript ensina: 1. **`embed_state: "skipped"` com `skip_reason`** — bodies com menos de 200 caracteres pulam a etapa densa de propósito; o orçamento de embedding é para conteúdo de verdade. A busca ainda os encontra por palavra-chave. O comando não falha e não finge que embutiu — ele avisa. Se o seu CI faz assert sobre embedding, faça assert na *razão*, não num estado. 2. **O `docid` deriva do conteúdo** — rode o mesmo `add` de um shadow tenant diferente e você recebe o mesmo id curto: mesmos bytes, mesma identidade, por tenant. 3. **O aviso de claim é parte do contrato** — espera-se que um agente que se provisiona mostre o caminho de claim ao seu humano; a expiração da chave em 30 dias é o empurrão. O shadow tenant daquela execução expira sozinho; nada para limpar. # CLI (/docs/cli) Pacote: [`@valorbrain/cli`](https://www.npmjs.com/package/@valorbrain/cli) `0.1.0`. Alias do proxy stdio de MCP: [`@valorbrain/connect`](https://www.npmjs.com/package/@valorbrain/connect). ```bash npx @valorbrain/cli help --json ``` Aquele JSON é o contrato. Se um blog post ou README citar um subcomando que não está nesse objeto, o comando não existe. ## Flags globais [#flags-globais] | Flag | Alias | Significado | | -------- | --------- | -------------------------------------------------------------- | | `--json` | `--agent` | Um único objeto JSON no stdout, sem cor, sem spinner | | `--key` | | Sobrescreve a chave de API (senão `~/.valorbrain/config.json`) | | `--url` | | Sobrescreve a URL base REST | Padrões: * REST: `https://valorbrain-api.valor.digital` * MCP: `https://mcpbrain.valor.digital/mcp` * Config: `~/.valorbrain/config.json` ## Comandos [#comandos] ### `init --agent [--agent-caller ]` [#init---agent---agent-caller-platform] Cria um shadow tenant e uma chave `vb_agent_`. Veja o [Começo rápido](/docs/quickstart). ### `init --email
[--otp ]` [#init---email-address---otp-code] Vincula a chave existente a um email via OTP. A chave não muda. ### `identify ` [#identify-platform] Backfill idempotente de `agent_caller`. Autodeclarado, nunca inferido do ambiente. ### `add ` / `--file ` [#add-text----file-path] Armazena um documento. | Flag | Mapeia para | | --------------------- | ------------------------------------------------------------------------------------------------- | | `--collection ` | `collection` (o padrão depende do servidor; passe um se fizer diferença) | | `--title ` | `title` | | `--type ` | tipo de conteúdo (`decision`, `observation`, `problem`, `lesson`, `milestone`, `handoff`, `note`) | Chama `POST /documents`. O body é armazenado verbatim — sem tradução. ### `search ` [#search-query] | Flag | Significado | | ---------------------------------------- | ----------------------- | | `--collection ` | Restringe a uma coleção | | `--mode auto\|keyword\|semantic\|hybrid` | Modo de recuperação | Chama `POST /search` com `compact: true`. ### `list` [#list] `GET /collections`. ### `status` [#status] Config local mais `GET /health` no host REST. ### `mcp [--token vbm_…] [--url ]` [#mcp---token-vbm_---url-mcp-url] Proxy MCP stdio ↔ HTTP. `@valorbrain/connect` é este comando empacotado à parte, para que clientes stdio possam rodar: ```json { "mcpServers": { "valorbrain": { "command": "npx", "args": ["-y", "@valorbrain/connect", "--token", "vbm_…"] } } } ``` O prefixo do token MCP é `vbm_`, não `vb_agent_`. Misture os dois e o host MCP vai te rejeitar. ### `help [--json]` [#help---json] Texto para humanos, ou a superfície de máquina. ## On-premise (Enterprise) [#on-premise-enterprise] ```bash npx @valorbrain/cli --url https://your-engine.example.com init --agent ``` Não existe instalador público de uma linha para o engine. On-prem é um plano Enterprise — [implantação acompanhada pela nossa equipe](https://valorbrain.valor.digital/enterprise) na sua rede. # Introdução (/docs) ValorBrain **não** é um chatbot e **não** é um orquestrador de agentes. É o lugar onde sua empresa guarda a verdade: decisões, incidentes, pessoas, keyed facts e o contexto que um agente precisa antes de responder. Dois produtos compartilham o mesmo modelo mental: * **Hosted** — `valorbrain.valor.digital` (app) + `valorbrain-api.valor.digital` (REST) + `mcpbrain.valor.digital` (MCP). * **On-prem (Enterprise)** — o mesmo engine rodando na sua rede, implantado e operado junto com o nosso time. Não é um instalador self-service: [veja o que o Enterprise inclui](https://valorbrain.valor.digital/enterprise) A arquitetura do que é implantado está no guia de [on-premise](/docs/guides/on-prem). ## O que você recebe [#o-que-você-recebe] | Superfície | Para que serve | | ------------------------- | ----------------------------------------------------------------------------------------------- | | **CLI** `@valorbrain/cli` | Signup de agente, `add`, `search`. Zero dependências npm. Node 18+. | | **MCP** | O conjunto de trabalho que os agentes realmente chamam: retrieve, prepare, store, used, curate. | | **REST** | As mesmas capacidades por HTTP, para qualquer linguagem. | | **App** | Humanos: onboarding, tokens, connectors, billing. | O texto é armazenado **verbatim**. Uma frase escrita em português é recuperada em português. É uma escolha de produto, não um acidente. ## Escolha um caminho [#escolha-um-caminho] | Você é… | Comece aqui | | -------------------------------------- | ---------------------------------------------------------------------------------------------- | | Um agente de IA com shell | [Cadastre-se como agente](/docs/quickstart#cadastre-se-como-agente) | | Um humano configurando um workspace | [https://valorbrain.valor.digital](https://valorbrain.valor.digital) e depois [MCP](/docs/mcp) | | Conectando Claude Code / Cursor / Grok | [Integrações](/docs/integrations) | | Chamando HTTP do seu próprio código | [REST](/docs/rest) | ## Hosts (leia isto uma vez) [#hosts-leia-isto-uma-vez] | Host | Papel | | ------------------------------ | ---------------------------------------------------------------------------------------------------- | | `valorbrain-api.valor.digital` | REST. Busca, documentos, cadastro de agente. | | `mcpbrain.valor.digital` | Só MCP. REST não-OAuth neste host devolve 401. | | `valorbrain.valor.digital` | App SaaS, ingest com chaves `fk_`, marketing, discovery. | | `docs.valor.digital` | Este site. (`docs.valorbrain.valor.digital` é a mesma origem assim que o ACM cobrir o TLS aninhado.) | Não envie `/search` ou `/documents` para o `mcpbrain`. O engine trata todo path não-OAuth naquele host como transporte MCP. ## Para agentes lendo esta página [#para-agentes-lendo-esta-página] 1. Se você não tem chave: rode `npx @valorbrain/cli init --agent --agent-caller --json`. 2. Prefira `help --json` a adivinhar subcomandos. A CLI publicada **não** tem `setup harness`. 3. Depois de recuperar, chame `memory_used` com os docids em que você realmente se apoiou. 4. Índice completo para máquinas: [`/llms.txt`](/llms.txt) · dump completo: [`/llms-full.txt`](/llms-full.txt). # Começo rápido (/docs/quickstart) O onboarding que importa é o **caminho do agente**. Um humano pode se cadastrar depois no app e assumir a mesma chave. A chave não muda. ## Quatro comandos [#quatro-comandos] ```bash npx @valorbrain/cli init --agent --agent-caller claude-code npx @valorbrain/cli add "the deploy key lives in the ops vault" npx @valorbrain/cli search "deploy key" npx @valorbrain/cli status ``` Esse é o cadastro inteiro: sem email, sem dashboard, sem cartão. A chave é escrita em `~/.valorbrain/config.json` com modo `0600`. ### Tempo medido [#tempo-medido] Medido em 2026-08-30 contra o pacote **publicado** `@valorbrain/cli@0.1.0`, não contra um checkout local: | Passo | Tempo | | ----------------------------------------------- | -------- | | `init --agent` (frio, inclui o download do npx) | 2.5s | | `add` → `search` | 1.45s | | Shell → memória pesquisável | **\~4s** | Alvo: **menos de 15 segundos**. Referência (mem0, no mesmo dia): \~13s, dos quais 4.66s são `pip install`. O `npx` pula essa instalação. `--json` (alias `--agent`) em qualquer comando imprime um único objeto JSON. `help --json` despeja a superfície inteira. ## Cadastre-se como agente [#cadastre-se-como-agente] `init --agent` chama `POST https://valorbrain-api.valor.digital/api/v1/agents/signup`. Devolve uma chave `vb_agent_…` amarrada a um shadow tenant. O padrão é expirar em 30 dias até um humano assumi-la. **A identidade é autodeclarada.** `--agent-caller` nunca é inferido do ambiente. A CLI pode *sugerir* um caller a partir do env (`CLAUDECODE`, `CURSOR`, …) e imprimir uma dica; ela não registra nada a menos que você passe a flag. Se esqueceu: ```bash npx @valorbrain/cli identify claude-code ``` Caller ids que a CLI entende como dicas: `claude-code`, `cursor`, `codex`, `cline`, `continue`, `aider`, `goose`, `windsurf`, `kiro`, `opencode`, `hermes`, `zcode`, `grok`. Qualquer outro é armazenado como você digitou. A resposta do signup inclui uma `message` escrita **como uma instrução para você**. Mostre-a ao humano no seu próximo turno voltado para o usuário. Não pule. ## Assuma como humano [#assuma-como-humano] ```bash npx @valorbrain/cli init --email you@company.com ``` O OTP chega por email. Depois de verificar, a **mesma** chave `vb_agent_` continua funcionando. As memórias são preservadas. Esse é o critério de aceite, e foi verificado ponta a ponta em 2026-08-30. ## O que a chave pode fazer [#o-que-a-chave-pode-fazer] A chave da CLI fala **REST** com `valorbrain-api.valor.digital`. O tenant é resolvido a partir do token — você **não** envia `X-Tenant-ID`. | Comando | Endpoint | | -------------- | ---------------------------------------------------- | | `add` | `POST /documents` | | `search` | `POST /search` | | `list` | `GET /collections` | | `status` | `GET /health` + config local | | `identify` | `POST /api/v1/agents/identify` | | `init --email` | `POST /api/v1/agents/claim` e depois `/claim/verify` | MCP é uma **credencial diferente**: `vbm_…`, criada no app em Settings → MCP tokens, ou obtida via OAuth. Veja [MCP](/docs/mcp). ## Caminho humano (app) [#caminho-humano-app] Se você não é um agente: 1. Abra [valorbrain.valor.digital](https://valorbrain.valor.digital/auth/register). 2. Ative o email. 3. Crie um token MCP (`vbm_…`) ou uma chave de ingest (`fk_….sk_…`). 4. Siga [MCP](/docs/mcp) ou [REST](/docs/rest). ## Comandos fantasma [#comandos-fantasma] Estes aparecem em READMEs antigos e **não existem** no `@valorbrain/cli@0.1.0`. `help --json` é a fonte da verdade. * `valorbrain setup harness …` * `valorbrain setup status` * `valorbrain setup openclaw` * `valorbrain setup harness --detect` # Referência de API (/docs/api) ## OpenAPI — dois arquivos, não confunda [#openapi--dois-arquivos-não-confunda] | URL | O que de fato é | | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- | | `https://valorbrain.valor.digital/openapi.json` | Documento de **descoberta** do SaaS. **4 paths** (ingest, device code, health-class). \~6.7 KB. | | `https://docs.valor.digital/openapi.json` | OpenAPI do engine, regenerado no build das docs (servers reescritos para valorbrain-api). | | `docs/reference/openapi.yaml` no repositório do engine | Spec completa do engine. **116 paths**, incluindo ops/graph. Não publicada no `valorbrain-api` (esse host dá 404 em `/openapi.json`). | O arquivo de 4 paths é real e útil para descoberta por agentes no host de marketing. Ele não é uma descrição do `/search`. Use este site e a página REST para integração. ## Docs legíveis por máquina [#docs-legíveis-por-máquina] | URL | Conteúdo | | -------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | | [`/llms.txt`](/llms.txt) | Índice + roteamento para agentes | | [`/llms-full.txt`](/llms-full.txt) | Markdown completo de todas as páginas | | [`/.well-known/mcp/server-card.json`](https://valorbrain.valor.digital/.well-known/mcp/server-card.json) | Card MCP vivo (produto, não este host de docs) | | [`/.well-known/agent-card.json`](/.well-known/agent-card.json) | Nosso agent card, apontando para o MCP do **produto** | # Referência das ferramentas MCP (/docs/api/mcp-tools) Esta página é o mesmo inventário de [Ferramentas MCP](/docs/mcp/tools), mantido sob API para que leitores mentalizados em OpenAPI a encontrem. Fonte: `src/tool-catalog.ts` do engine. Tokens novos: toolset **`agent`**. Chame `tools/list` em runtime. Se um nome aqui e a lista viva divergirem, a lista viva vence e esta página está errada — [abra uma issue](https://github.com/ValorBrain/valorbrain-docs/issues). Ferramentas canônicas do agent: `memory_retrieve`, `memory_prepare`, `working_context`, `memory_grep`, `get`, `multi_get`, `keyed_facts_as_of`, `memory_store`, `memory_used`, `upsert_keyed_fact`, `assert_authority_correction`, `record_lesson`, `memory_curate`, `memory_forget`, `append_entity_card`, `diary`, `scratchpad`, `task_state`, `profile`, `team_briefing`, `team_handoff`, `team_inbox`, `team_message`, `team_notify_human`, `team_roster`, `whoami`, `memory_health`, `list_lessons`, `episodes`, `notifications`. Aliases (ainda despachados): `memory_pin` → `memory_curate`, `memory_snooze` → `memory_curate`, `diary_read` / `diary_write` → `diary`, `set_goal` / `report_progress` → `task_state`, `team_handoff_consume` → `team_handoff`, `get_memory_episode` / `list_memory_episodes` → `episodes`, `notifications_check` / `notifications_mark_read` → `notifications`, `record_decision` e família → `decisions`, `trace_lineage` / `export_provenance` → `provenance`, `detect_conflicts` / `list_conflicts` / `resolve_conflict` → `conflicts`. Deprecadas: `store`, `list_proposals`. # Referência REST (/docs/api/rest) Auth: `Authorization: Bearer `. O tenant vem do token. ## Engine (valorbrain-api) [#engine-valorbrain-api] | Método | Path | Notas | | -------- | ----------------------------- | ------------------------------------------------------------ | | `GET` | `/health` | Liveness. Sem auth. | | `GET` | `/healthz` | Alias. | | `POST` | `/search` | Busca híbrida. Body: `{ query, limit?, profile?, timing? }`. | | `POST` | `/retrieve` | Recuperação multiestratégia. | | `POST` | `/documents` | Ingestão. Body: `{ collection, path?, title?, content, … }`. | | `GET` | `/documents` | Lista, paginada. | | `GET` | `/documents/:id` | Documento completo. | | `POST` | `/documents/:id/pin` | Pin. | | `POST` | `/documents/:id/snooze` | Snooze. | | `POST` | `/documents/:id/forget` | Soft-delete. | | `POST` | `/documents/:id/feedback` | Avaliação. | | `PATCH` | `/documents/:id/visibility` | Visibilidade. | | `DELETE` | `/documents/purge` | Purga dos esquecidos. Destrutivo — escopado no tenant. | | `GET` | `/collections` | Coleções e contagens. | | `GET` | `/stats` | Estatísticas do índice. | | `GET` | `/sessions` | Resumos recentes de sessão. | | `GET` | `/timeline/:id` | Vizinhança temporal. | | `GET` | `/graph/similar/:id` | Vizinhos semânticos. | | `GET` | `/graph/causal/:id` | Links causais. | | `POST` | `/api/v1/agents/signup` | Conta de agente. Devolve chave `vb_agent_`. | | `POST` | `/api/v1/agents/identify` | Backfill de `agent_caller`. | | `POST` | `/api/v1/agents/claim` | Inicia claim de email. | | `POST` | `/api/v1/agents/claim/verify` | Conclui o claim. Mesma chave. | | `POST` | `/api/v1/memory/prepare` | Gêmea do `memory_prepare` do MCP. | | `POST` | `/api/v1/memory/store` | Gêmea do `memory_store` do MCP. | Rotas de grafo, decisões, proveniência, conflitos e ops existem no engine (116 paths em `docs/reference/openapi.yaml`). Elas são reais; não são a primeira integração. Use `decisions` / `provenance` / `conflicts` no MCP ou leia o OpenAPI do engine no repositório se precisar delas. ## SaaS (valorbrain.valor.digital) [#saas-valorbrainvalordigital] | Método | Path | Auth | | ------ | ----------------------------------- | ------------------------------ | | `POST` | `/api/v1/ingest` | `fk_….sk_…` | | `GET` | `/openapi.json` | Público, 4 paths de descoberta | | `GET` | `/llms.txt` | Brief público de marketing | | `GET` | `/.well-known/mcp/server-card.json` | Público | ## Não é REST [#não-é-rest] `https://mcpbrain.valor.digital/mcp` é MCP. O OAuth vive nesse host. Enviar `/search` lá falha com 401. # Coleções e vaults (/docs/concepts/collections-vaults) Dois eixos diferentes, constantemente confundidos: * Uma **coleção** é um namespace de *conteúdo* dentro de um tenant: `team-notes`, `_valorbrain`, `baseline-2026-05-26`. Os documentos o carregam; buscas podem ser escopadas a ele. * Um **vault** é uma *fonte de sync*: um diretório nomeado de markdown que o engine pode ingerir e manter indexado (`vault_sync`, `list_vaults`). Várias ferramentas MCP aceitam um parâmetro `vault` para escopar leituras. ## Coleções [#coleções] Todo documento tem `collection` + `path`, e `path` é único *dentro* da coleção — esse par, não o título, é a identidade contra a qual você escreve. Re-POSTar o mesmo path re-entrega o mesmo documento em vez de duplicá-lo. Quatro comportamentos que vale a pena conhecer antes de desenhar namespaces: 1. **Dedup é por hash de conteúdo, entre coleções também.** Os mesmos bytes não serão indexados duas vezes, nem em duas coleções — uma postura curatorial deliberada, não um bug. Se duas coleções precisam de "o mesmo" texto, elas precisam de conteúdos diferentes (headers, datas, contexto diferentes). 2. **Cobertura ≠ curadoria.** Puxar um corpus externo para dentro pode *prejudicar* a recuperação: milhares de documentos quase-clones poluem o pool de candidatos de toda query. Faça ingest apenas daquilo sobre o que o seu tenant realmente pergunta. 3. **`collection_settings` é onde a política mora** — incluindo `excludePatterns`, a forma deliberada de dizer "arquivos nesta coleção são recusados por política" (dados pessoais curados, sobras de experimento) para que relatórios de cobertura mostrem recusas *esperadas* em vez de divergência. 4. **`_valorbrain` é a coleção padrão** para escritas de `memory_store` que não nomeiam uma — decisões, lições e observações caem lá a menos que você diga o contrário. Endpoints: `GET /collections` (lista com contagens), `GET /collections/health` (estado de embedding/lifecycle por coleção), `POST /api/v1/collection-settings/{collection}` (política), `POST /api/v1/collection-settings/reindex` (reconstrução), `POST /collections/{id}/lifecycle` (executa o lifecycle de uma coleção). ## Vaults [#vaults] Um vault mapeia um diretório para um estado indexado e buscável: * `vault_sync` — ingere/atualiza um vault (operação longa; `run_async: true` devolve um handle, `operation_status` o consulta). * `list_vaults` — vaults configurados e seus caminhos. * O parâmetro `vault` nas ferramentas de leitura escopa a recuperação aos documentos de um vault. O vault **não** isola identidade. A identidade de uma entidade é `(tenant_id, entity_id)` — o tenant é a fronteira de isolamento, não o vault; dois vaults num mesmo tenant compartilham o grafo de entidades. Se você precisa de isolamento total entre dois mundos, isso são dois tenants. ## Escolhendo [#escolhendo] | Você quer | Use | | -------------------------------------------------------- | ---------------------------------------------------------- | | Agrupar memórias por tópico/fonte para humanos | Coleções | | Escopar a busca a documentos importados | Filtro de coleção (`collection` em `/search`, `/retrieve`) | | Manter uma pasta de markdowns sincronizada com o cérebro | Um vault + `vault_sync` | | Isolar completamente uma empresa/cliente | Um tenant separado | Dicas de nomeação que envelhecem bem: datas para baselines (`baseline-2026-05-26`), dono + propósito para coleções vivas (`team-notes`), e nunca um nome que implique que uma pessoa é a única leitora — memória de tenant é compartilhada por design, e `visibility: private` é o eixo por usuário. # Corrigibilidade (/docs/concepts/correctability) Este é o modo de falha que mais custa, então o produto tem um caminho de primeira classe para ele. ## Keyed facts vencem a prosa [#keyed-facts-vencem-a-prosa] `keyed_facts_as_of` devolve o valor mais recente por `fact_key` cujo `as_of` é na data informada ou antes dela. Cada snapshot tem uma autoridade: **human > designated > import > agent** Quando um documento recuperado contradiz um keyed fact, o keyed fact vence. Diga isso na resposta. Não escolha o documento em silêncio. Escreva um snapshot com `upsert_keyed_fact`. Corrija um valor público errado com `assert_authority_correction` para que o próximo agente não repita o erro. ## Dois documentos divergem [#dois-documentos-divergem] Se nenhum keyed fact decidir, prefira o documento mais recente e **diga que fez isso**. Conflitos do mesmo dia, ou conflitos sobre uma decisão em vez de um valor: mostre os dois e pergunte. Um corpo recuperado pode abrir com `SUPERSEDED:`. Essa linha vem de um keyed fact. Não discuta com ela a partir do documento. ## O que "corrigibilidade" (correctability) significa no produto [#o-que-corrigibilidade-correctability-significa-no-produto] Fato errado na memória → afirmar a correção → **uma nova sessão** recupera o valor correto no topo dos resultados, não o velho. Esse loop é a prioridade depois de latência e onboarding. Ferramentas relacionadas: `memory_curate` (pin / snooze), `memory_forget` (a escrita menos reversível — separada de propósito), `memory_used` com `verdict="corrected"`. # Avaliação e benchmarks (/docs/concepts/evaluation) Os números desta página vêm do registro de benchmarks do engine; o espelho público deles está na [página de benchmarks do produto](https://valorbrain.valor.digital/benchmarks). São números de evidência de recuperação, salvo rótulo em contrário — tratá-los como acurácia de resposta é um erro de categoria (veja abaixo). ## Dois tipos de número [#dois-tipos-de-número] **Recall de recuperação (R\@K)** — a evidência certa entrou no top-K? Medido contra evidência gold, sem LLM no circuito. **Acurácia de resposta** — um juiz LLM aceitou a resposta? O que leaderboards comerciais normalmente publicam. Comparar o R\@10 do ValorBrain com a acurácia julgada de outro sistema é a leitura errada mais comum desta página. Quando o engine publica acurácia (BEAM via AMB), ele avisa. ## Registro reproduzível [#registro-reproduzível] | Benchmark | Métrica | Resultado | Notas | | --------------------------------- | ---------------------- | -------------------- | ------------------------------------------------------------------------- | | **LoCoMo** | **R\@10** de evidência | **96.58%** | 1986 QAs, duas execuções idênticas e limpas (2026-07-29). A base honesta. | | LoCoMo | R\@1 / R\@5 | 69.4% / 91.3% | Mesmas execuções. | | **LongMemEval-S** (500 completas) | R\@5 / R\@10 | 95.2% / 97.6% | Pendente de reverificação com o gate de índice corrigido. | | LoCoMo, só denso | R\@10 | 63.5% | Só a perna de embedding — uma medição de componente, não do pipeline. | | BEAM-100K (harness AMB) | acurácia | ver o placar público | Par leitor/juiz fixo; comparável com o leaderboard da AMB. | O registro LoCoMo mais antigo, de **97.4% R\@10, explicitamente não é reproduzível** — foi medido num corpus meio indexado (documentos contados antes de seus vetores chegarem ao índice híbrido) e a documentação do engine o marca como *do not cite*. O delta entre 96.58% e 97.4% é sistemático, não ruído; está documentado em vez de silenciosamente esquecido. Pontos de referência que **não** são do ValorBrain: o R\@5 93.9% (LoCoMo) e o 98.4% (LongMemEval) da Engram pertencem àquele sistema. Compará-los com a tabela acima é recall-contra-recall e é justo; adotá-los como se fossem do ValorBrain, não. ## O pipeline por trás dos números [#o-pipeline-por-trás-dos-números] O R\@10 de 96.58% é o stack completo — BM25 (`pgturbohybrid`) + denso (LFM2.5-Embedding-350M-finetuned-v3, 1024-d) + RRF + rerank de grafo PPR + cross-encoder BGE-Reranker-v2-m3. Cada perna é mensurável sozinha (só denso: 63.5%); a fusão é de onde vem o resto. A troca de embedding que importou historicamente: Jina → LFM2.5 levou o R\@10 só-denso de 32.7% para 63.5% (+30.8pp) no mesmo corpus. ## Regras que o engine impõe a si mesmo [#regras-que-o-engine-impõe-a-si-mesmo] Estas vieram de erros reais e caros; um benchmark que as quebra mede o harness, não o sistema. 1. **Espere o índice, não o embedding.** Um documento só é buscável pela perna densa depois que chega ao índice híbrido. Gates que esperavam o estado de embedding mediram um corpus meio indexado e produziram o 97.4% irreproduzível. 2. **Nunca faça benchmark contra um sistema em movimento.** Sem restarts nem deploys no meio da execução; sem um segundo benchmark compartilhando as estatísticas BM25 ou o orçamento de dedup. 3. **Gere o fingerprint do corpus.** O corpus é vivo; execuções só são comparáveis sob o mesmo fingerprint. 4. **Conheça o piso de ruído antes de comparar.** No LoCoMo é ±2 documentos em 10 conversas; abaixo disso, "regressão" é clima. 5. **O juiz nunca é o respondente.** Benchmarks de qualidade de resposta usam um modelo juiz de família diferente da do leitor — o viés de autopreferência é real e mensurável. 6. **Uma resposta vazia do leitor é um defeito de harness** — contabilizada, nunca diluída na média. ## De onde vêm os números [#de-onde-vêm-os-números] * Execuções públicas canônicas: o **harness AMB** (agent-memory-benchmark, `vectorize-io`), o mesmo que o placar público usa. * Iterações de pesquisa dentro do engine (`beam-qa.ts`) usam um par prompt/juiz diferente e são rotuladas *internal* — servem para escolher o que corrigir, nunca para publicar. Numa instalação on-premise (Enterprise), para medir a sua própria instância: `bun run gate:locomo` (piso de recall do nightly, R\@10 ≥ 0.90 por padrão) e `bun run gate:beam` (acurácia via AMB) vêm com o engine. Custam tokens de LLM e tempo; são gates, não testes de unidade. # Hosts (/docs/concepts/hosts) | Hostname | Função | O que acontece se você errar | | ------------------------------ | ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | | `valorbrain-api.valor.digital` | **REST** — `/search`, `/documents`, `/api/v1/agents/*`, `/health` | É o `--url` padrão da CLI. | | `mcpbrain.valor.digital` | **MCP** — `/mcp`, descoberta OAuth | Todo caminho **não-OAuth** é tratado como transporte MCP e devolve `401 missing_bearer`. `/search` aqui não busca. | | `valorbrain.valor.digital` | **App SaaS** — UI, `/api/v1/ingest` com chaves `fk_`, `/llms.txt` (marketing), conectores | O OpenAPI de marketing aqui tem 4 paths. Não é a spec do engine. | | `docs.valor.digital` | **Esta documentação** | `llms.txt` / `llms-full.txt` gerados. O `docs.valorbrain.valor.digital` aninhado precisa de ACM. | A descoberta OAuth (`/.well-known/oauth-authorization-server`) funciona no host MCP. O Dynamic Client Registration (`POST /oauth/register`) também funciona lá. `localhost:7438` é o engine **na máquina que o executa**. Não é uma URL pública. O engine costumava anunciá-lo em `/setup/instructions`; isso foi corrigido em 2026-08-30 (`VALORBRAIN_PUBLIC_URL` agora aponta para `valorbrain-api`). ## Regra [#regra] * CLI de agente e qualquer cliente REST → `valorbrain-api` * Cliente MCP → `mcpbrain` (HTTP) ou `@valorbrain/connect` (stdio) * Usuário no navegador → `valorbrain.valor.digital` # Como a recuperação funciona (/docs/concepts/how-retrieval-works) Este é o modelo mental sobre o qual a API e as 92 ferramentas MCP se apoiam. Tudo aqui descreve o que o engine realmente faz; o contrato mecânico completo está nas páginas de referência geradas ([REST](/docs/api/generated-rest) e [schemas MCP](/mcp-schemas.md)). ## O pipeline de recuperação [#o-pipeline-de-recuperação] Uma query, cinco pernas, fundidas: ``` ┌─ BM25 (lexical, pgturbohybrid) ─────────┐ query ────────┼─ dense vectors (pgvector, LFM2.5 1024d) ├─ RRF fuse ─▶ PPR graph ─▶ cross-encoder ─▶ top-K └─ causal / timeline / neighbors (routing)┘ ``` 1. **Léxico (BM25)** — o `pgturbohybrid` mantém BM25 e denso em um *único* índice; o `tenant_hash` viaja no `INCLUDE` do índice, então o filtro de tenant acontece dentro do index scan, não como pós-filtro. Num índice multi-tenant, essa é a diferença entre um ANN que funciona e um ANN que silenciosamente passa fome nos tenants pequenos. 2. **Denso** — embeddings de 1024 dimensões em `content_vectors` (deduplicados por hash de conteúdo), HNSW com `ef_search=1000`. 3. **Fusão RRF** — a reciprocal-rank fusion mescla as pernas sem precisar de scores comparáveis. 4. **Rerank de grafo (PPR)** — o personalized PageRank sobre o grafo de entidades/tempo promove documentos *conectados* ao que você perguntou, não apenas parecidos léxica ou semanticamente. 5. **Rerank de cross-encoder** — o BGE-Reranker-v2-m3 pontua pares query-documento diretamente; o top-K que sobrevive é o que você vê. O `mode` em `/search` e `memory_retrieve` direciona o roteamento: `causal` para perguntas de porquê, `timeline` para quando, `hybrid` para forçar todas as pernas. O `auto` decide por você e acerta na maior parte do tempo. O filtro de diversidade MMR (`diverse: true`, padrão) impede que o top-K seja dez paráfrases de um documento só. **Ranking é o último suspeito, não o primeiro.** Quando a recuperação falha, a ordem honesta de investigação é: pool de candidatos (o documento foi indexado?) → hidratação (o corpo foi carregado?) → renderização de snippet/janela (a resposta estava dentro do trecho entregue?) → ranking. O histórico de debugging do próprio engine é uma cadeia de nove "correções" de ranking que não mudaram nada enquanto o documento estava sendo cortado na renderização. ## O modelo de memória [#o-modelo-de-memória] | Camada | O que é | Comportamento-chave | | ----------------------------- | ------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | | **Documentos** | O corpus. Identidade `collection` + `path`, conteúdo deduplicado por hash (entre coleções também) | Embedding assíncrono (`embed_state`); visibilidade tenant/private | | **Observações consolidadas** | Síntese de ordem superior dos documentos | Worker de consolidação, gate de confiança ≥ 0.65 | | **Keyed facts** | Snapshots `(fact_key, as_of)` com nível de autoridade | Supersedem a prosa. Um documento que contradiz um keyed fact perde | | **Tríplas de entidades (KG)** | Fatos SPO, temporais, por `(tenant_id, entity_id)` | Pre-check SHACL; rejeitadas vão para quarentena, nunca entram em silêncio | | **Episódios** | Sumários delimitados de diálogo | Recuperação episódica; `memory_prepare` com escopo | | **Decisões** | Registros de primeira classe: categoria, cenário, raciocínio, resultado, confiança | Trilha de auditoria com cadeia de hashes; links causais (`caused`/`influenced`/`precedent_for`) | | **Provenance** | Linhagem W3C PROV-O, cadeia de hashes SHA-256 | Toda escrita de trípla é rastreada; à prova de adulteração por construção | | **Conflitos de fatos** | Contradições explícitas de valor/tempo/relação | Detectadas nos ticks de consolidação e sob demanda; resolvidas por estratégia | O caminho de escrita espelha isso: documentos crus entram, a extração de entidades (GLiNER zero-shot) enriquece, a consolidação sintetiza observações, os hooks do decision-extractor promovem decisões, e toda escrita de trípla chega com provenance. ## Tenancy e identidade [#tenancy-e-identidade] * Toda tabela com escopo de tenant é **protegida por RLS** com uma policy `tenant_id`; o runtime conecta como um role de app sem `BYPASSRLS`. * A identidade vem do token — nunca adivinhada, nunca hardcoded. Zero particularidades de tenant/usuário/empresa no código-fonte. * A identidade de uma entidade é `(tenant_id, entity_id)`; o vault não isola nada por si só — quem isola é o tenant. ## Consolidação e decaimento [#consolidação-e-decaimento] Memória que nunca decai é um lixão. Três mecanismos a mantêm honesta: * **Políticas de lifecycle** arquivam documentos velhos (itens pinados ficam isentos); o `lifecycle_sweep` as executa (dry-run por padrão). * **Curation** — `pin` (+0.3 de boost permanente), `snooze` (esconde por N dias) — é a alavanca manual, movida pelo loop de feedback do `memory_used`. * **O ledger de uso** registra cada operação por canal; o `value_daily` pré-agrega tudo. O ranking aprende do uso declarado, não de palpites. ## O contrato de uma chamada [#o-contrato-de-uma-chamada] `POST /api/v1/memory/prepare` (REST) e `memory_prepare` (MCP) montam um bundle completo de contexto — recall + fatos do vault + foresights + funil (episódios, lições, keyed facts, top documents) — numa única chamada, com um orçamento de tokens. Este é o ponto de integração pretendido para prompt hooks; as ferramentas de leitura servem para aprofundar, não para você montar seu próprio bundle. # Conceitos (/docs/concepts) O ValorBrain é o **cérebro da empresa**: pessoas *e* agentes compartilham a mesma memória operacional. Não é "apenas um índice de busca" e não é "apenas um chatbot com histórico." # Como funciona a memória (/docs/concepts/memory) Uma "memória" no ValorBrain é um **documento** em uma **coleção**, dentro de um **tenant**. Agentes devem tratar a recuperação como consulta à verdade da empresa, não como um log de chat. ## Armazenar [#armazenar] Prefira a escrita tipada: * MCP: `memory_store` com `type` ∈ `decision` | `observation` | `problem` | `milestone` | `handoff` | `lesson` | `note` * REST/CLI: `POST /documents` (CLI `add`) `store` (isolado) ainda existe no catálogo MCP como alias **deprecado** de `memory_store`. Não o documente para clientes novos; não o chame. O texto é armazenado verbatim. Português continua português. Corpos curtos (abaixo de \~200 caracteres) podem pular o embedding. Eles continuam buscáveis no caminho léxico. ## Recuperar [#recuperar] O caminho padrão é híbrido: BM25 + vetores densos + RRF, e depois um rerank de cross-encoder no produto hospedado. | Ferramenta / rota | Quando | | ---------------------------------- | ------------------------------------------------------------ | | `memory_retrieve` / `POST /search` | Uma pergunta bem formulada. O servidor expande e funde. | | `memory_prepare` | Início de sessão / "me dê o contexto para esta tarefa" | | `working_context` | A orientação mais barata: fatos estáveis + decisões recentes | | `memory_grep` | String exata, id, data, chave — não uma paráfrase | Não dispare cinco recuperações quase duplicadas. Se o primeiro conjunto vier magro, troque de ferramenta: exato → `memory_grep`; mais de um acerto → `get` / `multi_get`; por quê → `find_causal_links` (toolset `graph`). ## Coleções [#coleções] Uma coleção é um bucket com nome (`decisions`, `incidents`, …). `list` / `GET /collections` mostra o que o tenant tem. Você escolhe o nome na hora de escrever; não existe taxonomia global obrigatória para clientes. ## O loop de ranking [#o-loop-de-ranking] Depois de responder com memória recuperada, chame `memory_used` com os docids que você realmente usou. Memórias usadas sobem; ignoradas decaem. `verdict` opcional: `confirmed` ou `corrected` quando o humano reage. Este é o sinal de ranking mais forte do produto. A taxa de declaração atual, no mundo real, é baixa — não faça parte desse número. # Tokens (/docs/concepts/tokens) | Prefixo | Emitido por | Fala com | Exemplo de uso | | ------------ | -------------------------------------------------------- | ---------------------------------------------------- | --------------------------------------- | | `vb_agent_…` | `valorbrain init --agent` → `POST /api/v1/agents/signup` | REST em `valorbrain-api` | CLI `add` / `search` | | `vbm_…` | App → Settings → tokens MCP, ou OAuth | MCP em `mcpbrain` | MCP no editor, `@valorbrain/connect` | | `fk_….sk_…` | App → API keys | SaaS `POST /api/v1/ingest` (e algumas rotas do SaaS) | Sistemas externos empurrando documentos | Eles **não** são intercambiáveis. Uma chave `vb_agent_` no `mcpbrain` é a audience errada. Um token `vbm_` é o que o card do servidor MCP anuncia (`tokenPrefix: "vbm_"`). ## O tenant está no token [#o-tenant-está-no-token] A CLI não envia `X-Tenant-ID`. O engine resolve o tenant a partir do bearer token e expõe o resultado como `X-Resolved-Tenant-ID`. Não invente um UUID de tenant. Não copie um de tutorial. Páginas antigas no `/docs` de marketing mostravam exemplos REST com `Authorization: Bearer vb_…` **e** `X-Tenant-ID`. Esse header não é necessário para uma chave com escopo de tenant, e o prefixo é `vb_agent_`, não um `vb_` solto. ## Escopos [#escopos] Tokens MCP têm um toolset (`agent` por padrão para tokens novos, ou `graph` / `ops` / `all`). Tokens novos veem o working set do **agent**, não o catálogo de 80 nomes. Veja [Ferramentas MCP](/docs/api/mcp-tools). ## Um token por agente [#um-token-por-agente] Use um token por agente ou persona, para que as escritas fiquem atribuíveis e a revogação não interrompa todo mundo. Nunca cole um token em chat, repositório git ou no próprio ValorBrain. # Claim de conta de agente (/docs/guides/claim) O agente já tem uma chave funcional. Um humano assume a posse depois. ```bash npx @valorbrain/cli init --email you@company.com ``` O ValorBrain envia um código de uso único por e-mail. O journal não imprime o OTP em cleartext no caminho de sucesso (corrigido em 2026-08-30). Cole o código quando o CLI pedir, ou passe `--otp`. Aceitação, verificada em 2026-08-30 de uma rede limpa: a resposta é **"Same API key. All memories preserved."** O valor `vb_agent_` não muda. Tokens MCP (`vbm_`) continuam criados no app se você quiser um editor conectado. # Corrija um fato errado (/docs/guides/correct-a-fact) 1. Recupere como de costume (`memory_retrieve` ou `search` no CLI). 2. Se o humano disser que o valor está errado, **não** armazene só mais um documento em prosa. Escreva um keyed fact: MCP: ```json { "fact_key": "docs.public.host", "fact_value": "https://docs.valor.digital", "as_of": "2026-08-30", "authority": "human" } ``` Ferramenta: `upsert_keyed_fact`. Para um valor que já enganou alguém, `assert_authority_correction`. 3. Chame `memory_used` com `verdict: "corrected"` no docid velho. 4. Numa sessão **nova**, recupere a mesma pergunta. O keyed fact deve vencer. Se um documento ainda ranquear em primeiro com o valor antigo, ele deve chegar com uma linha `SUPERSEDED:` — acredite no fato, não no corpo. Isso é corrigibilidade (correctability). Se esse loop falha, é um defeito do produto: diga isso com `feedback` em vez de contornar. # Primeira memória em 15 segundos (/docs/guides/first-memory) ```bash npx @valorbrain/cli init --agent --agent-caller claude-code --json npx @valorbrain/cli add "Gustavo prefers replies in Portuguese (pt-BR)" npx @valorbrain/cli search "Portuguese" npx @valorbrain/cli status --json ``` Espere: * `init` escreve `~/.valorbrain/config.json` (0600) com uma chave `vb_agent_` * `add` devolve um id de documento * `search` devolve esse documento. A frase em português continua em português * Relógio, pacote publicado, 2026-08-30: **\~4 segundos** no total Se `search` vier vazio, espere alguns segundos e repita — um corpo muito curto pode ainda não ter vetor denso; a busca lexical deve acertar mesmo assim. Depois, num cliente MCP, `memory_used` com esse docid para o ranking aprender. # Guias (/docs/guides) # Grafo de conhecimento (/docs/guides/knowledge-graph) O grafo do ValorBrain é temporal e explicável: cada tripla SPO carrega `valid_from`/`valid_to`, passa por um pre-check SHACL antes de entrar, e cada escrita gera linhagem PROV-O. Contratos abaixo são os schemas reais das ferramentas. ## Consultar: `kg_query` [#consultar-kg_query] ```json { "tool": "kg_query", "arguments": { "entity": "ValorBrain", "direction": "both", "max_hops": 2, "as_of": "2026-08-01" } } ``` * `entity` aceita **nome** (`"ValorBrain"`) ou **id canônico** (`"default:service:valorbrain"` — formato `vault:tipo:slug`). * `as_of` (YYYY-MM-DD): só fatos **válidos naquela data** — o grafo é uma linha do tempo, não um snapshot. * `direction`: `outgoing` / `incoming` / `both`. * `max_hops`: 1 = estrela direta; 2–3 = multihop (via SPARQL/Datalog quando o engine híbrido está ligado; default vem de `VALORBRAIN_KG_MAX_HOPS`). Perguntas que são do grafo, não da busca: "o que se relaciona com X?", "o que era verdade sobre X em Y?", "quem/o que está conectado a X?". Vizinhos semânticos de um documento são `find_similar`; relações nomeadas são daqui. ## Explicar: `kg_explain` [#explicar-kg_explain] ```json { "tool": "kg_explain", "arguments": { "subject": "engine", "predicate": "depends_on", "object": "lfm2-embed" } } ``` Devolve **por que** o fato vale — incluindo árvore de prova Datalog quando `pg_ripple.record_derivations` está ligado. Para fatos literais, use `object_literal` (mutuamente exclusivo com `object`). É a ferramenta de auditoria: fato que não se explica não se cita. ## Identidade de entidade [#identidade-de-entidade] * Identidade é `(tenant_id, entity_id)` — **o tenant isola; o vault, não**. Dois vaults no mesmo tenant compartilham o grafo. * `entity_id` canônico: `vault:tipo:slug`. O vault default é a string literal `default`. * O tipo vem da taxonomia (`src/entity-taxonomy.ts` no engine), casada com o `sh:in` da shape SHACL. ## Cartões de entidade: `append_entity_card` / `list_entity_cards` [#cartões-de-entidade-append_entity_card--list_entity_cards] Cartão = identidade estável com entradas `IDENTITY` / `ATTRIBUTE` / `RELATIONSHIP` / `INSTRUCTION`. Acréscente em vez de sobrescrever — o cartão é append-only por desenho. ## Quarentena: `kg_quarantine` [#quarentena-kg_quarantine] Tripla rejeitada pelo pre-check SHACL **nunca** entra silenciosamente — vai pra fila de curadoria: ```json { "tool": "kg_quarantine", "arguments": { "action": "list", "limit": 50 } } { "tool": "kg_quarantine", "arguments": { "action": "approve", "quarantine_id": "" } } { "tool": "kg_quarantine", "arguments": { "action": "reject", "quarantine_id": "" } } ``` * `approve` **re-valida** e persiste em `entity_triples` (aprovar não pula o SHACL). * `reject` descarta permanentemente. Uma fila limpa não significa grafo perfeito — significa nada pendente **detectado**. Dedup de entidades perto-duplicadas tem relatório próprio: `kg_entity_resolve_report`. ## RAG neuro-simbólico [#rag-neuro-simbólico] `ripple_rag_retrieve` entrega contexto de entidade (JSON) dentro de um orçamento de latência — é a ponte entre o grafo e prompts que precisam de fatos estruturados com fonte. Use quando a resposta precisa de **relações** com validade, não de parágrafos. ## Quando usar cada camada [#quando-usar-cada-camada] | Pergunta | Camada | | ------------------------------------ | ---------------------- | | "o que dizem sobre X" (prosa) | `memory_retrieve` | | "X se relaciona com quê" (estrutura) | `kg_query` | | "por que esse fato vale" | `kg_explain` | | "o que era verdade em março" | `kg_query` com `as_of` | | "documentos parecidos com este" | `find_similar` | # Cookbook MCP (/docs/guides/mcp-cookbook) A superfície MCP é como agentes devem falar com o ValorBrain. Esta página é sobre fluxos; o contrato mecânico completo das 92 ferramentas (descrição + input schema, direto dos metadados de `registerTool()`) vive em [`/mcp-schemas.md`](/mcp-schemas.md) e é regenerado a cada build da documentação. Se um campo aqui não está nesse dump, não use. Detalhes de conexão estão em [Ferramentas MCP](/docs/mcp/tools). O código abaixo mostra o nome da ferramenta e os argumentos como qualquer cliente MCP os passaria. ## O loop de sessão [#o-loop-de-sessão] Um turno de agente contra o ValorBrain são quatro chamadas, não quarenta: 1. **`memory_prepare`** — monte o contexto uma vez, no início do turno. 2. trabalhe, pense, chame o que precisar (`memory_retrieve` só se o prepare ficou curto). 3. **`memory_store`** — escreva de volta o que é durável. 4. **`memory_used`** — declare quais memórias de fato sustentaram a resposta. ### 1. Preparar o contexto [#1-preparar-o-contexto] ```json { "tool": "memory_prepare", "arguments": { "message": "the user's message for this turn", "surface_id": "claude-code", "recall_budget": 600 } } ``` Uma chamada devolve: hits de recall + fatos do vault + foresights + o funil (episódios, lições, keyed facts, top documentos). `fast_mode: true` pula a recuperação de documentos do funil para hooks críticos de latência; o recall ainda cobre documentos por categoria. Recuperação com escopo: `episode_id` vincula a um episódio de diálogo, `collection` estreita o funil. **Não** responda a partir das suas suposições antes desta chamada quando a pergunta é sobre *este* deploy — a memória é a autoridade, seus dados de treino não são. ### 2. Recuperar (quando o prepare não basta) [#2-recuperar-quando-o-prepare-não-basta] ```json { "tool": "memory_retrieve", "arguments": { "query": "one clear question", "mode": "auto", "limit": 12, "snippet_chars": 200 } } ``` * Uma consulta bem-formulada. O servidor expande e funde; cinco recuperações quase-duplicadas custam 5× e ranqueiam pior que uma. * `mode`: `auto` roteia (porquê → causal, última sessão → timeline, relacionado → vizinhos); `keyword` / `semantic` / `causal` / `timeline` / `discovery` / `complex` / `hybrid` explícitos quando você sabe melhor. * `limit` (alias `max_results`): padrão 12; 15–20 para tópicos amplos. * `budget` é um orçamento de *tokens* para recall ranqueado por categoria — um eixo diferente de `limit`. * Snippets voltam por padrão (`snippet_chars`); chame `get`/`multi_get` só quando o snippet não bastar. String exata, chave, data, identificador? Isso não é uma busca — isso é `memory_grep`: ```json { "tool": "memory_grep", "arguments": { "pattern": "VALORBRAIN_LLM_MODEL", "max_results": 20 } } ``` ### 3. Escrever de volta o que é durável [#3-escrever-de-volta-o-que-é-durável] ```json { "tool": "memory_store", "arguments": { "type": "decision", "title": "OpenAPI served live from routes[] table", "content": "Static YAML drifts from the real route table. Decision: /openapi.json is now generated per request from routes[] merged with the YAML contract; servers[] rewritten from VALORBRAIN_PUBLIC_URL. Rejected: keeping a generated file on disk (another drift source).", "tags": ["api", "openapi"], "confidence": 0.85, "visibility": "tenant" } } ``` O tipo escolhe a semântica: | `type` | Para | Confiança padrão | | ------------- | ----------------------------------------------------- | ---------------- | | `decision` | uma escolha feita, com alternativas rejeitadas | 0.8 | | `observation` | um fato aprendido sobre o sistema/domínio | 0.6 | | `problem` | um bug ou incidente (causa raiz quando conhecida) | 0.6 | | `lesson` | um aprendizado que deveria mudar comportamento futuro | 0.6 | | `milestone` | progresso que vale a pena achar depois | 0.6 | | `handoff` | contexto que a próxima sessão precisa | 0.6 | | `note` | todo o resto | 0.6 | Título de 5–200 chars (é o que a busca mostra); conteúdo ≥ 20 chars — inclua contexto, raciocínio, evidência, não só a conclusão. `visibility: "private"` esconde a memória do resto do tenant (a posse continua sua); compartilhada no tenant é o padrão e o produto. Não armazene: transcrições de chat (ingeridas automaticamente), conteúdo cru de arquivos, notas de rascunho — `scratchpad` existe para efêmeros e nunca é indexado. ### 4. Declarar uso [#4-declarar-uso] ```json { "tool": "memory_used", "arguments": { "docids": ["#ab12cd"], "verdict": "confirmed" } } ``` `verdict: "confirmed"` quando o usuário concordou com o que a memória disse, `"corrected"` quando ele rebateu. É o sinal de ranking mais forte que existe — memórias usadas sobem, ignoradas decaem. Custa uma chamada; pular isso deixa o ranking cego. ## Fatos que não podem ficar desatualizados [#fatos-que-não-podem-ficar-desatualizados] Documentos em prosa envelhecem mal; keyed facts carregam uma data e um nível de autoridade: ```json { "tool": "upsert_keyed_fact", "arguments": { "fact_key": "embedding.production.model", "fact_value": "LFM2.5-Embedding-350M-finetuned-v3", "as_of": "2026-08-31", "evidence": "systemd unit MODEL_PATH, checked on host", "authority": "human" } } ``` `authority`: `human` > `designated` > `import` > `agent`. Quando um documento contradiz um keyed fact, o fato vence. Leia com `keyed_facts_as_of` (viagem no tempo: último valor por chave com `as_of <= date`). Quando achar um documento agora *errado*, não apenas lembre do novo valor — `assert_authority_correction` persiste o fato corrigido e marca os valores anteriores como superseded. ## Maquinaria de confiança [#maquinaria-de-confiança] ### Decisões com trilha [#decisões-com-trilha] ```json { "tool": "decisions", "arguments": { "action": "record", "category": "architecture", "scenario": "serving OpenAPI", "reasoning": "routes[] is the truth; YAML is the contract", "outcome": "live merge, mtime-cached YAML", "confidence": 0.85 } } ``` Depois ligue a causalidade: `action: "relate"` com `caused` / `influenced` / `precedent_for`. Mais tarde: `find_causal_links` ("o que levou a X"), `decisions` `action: "trace"` (cadeia completa), `action: "similar"` (busca semântica de precedentes). Registros são hash-chained — a trilha é à prova de adulteração por construção. ### Conflitos [#conflitos] `conflicts` `action: "detect"` escaneia contradições de valor / temporais / de relacionamento; `action: "list"` as enfileira por severidade; `action: "resolve"` escolhe uma estratégia (`most_recent`, `credibility_weighted`, …). A detecção também roda no tick de consolidação, então uma lista limpa não significa sem conflitos — significa nenhum detectado ainda. ### Grafo de conhecimento [#grafo-de-conhecimento] `kg_query` para os relacionamentos de uma entidade (multihop com o engine híbrido ligado), `kg_explain` para o *porquê* de um fato valer (árvores de prova de derivação quando registradas), `append_entity_card` para entradas IDENTITY/ATTRIBUTE/RELATIONSHIP/INSTRUCTION num card estável. Triplas que falham no pre-check SHACL caem em `kg_quarantine` — aprove ou rejeite deliberadamente, elas nunca entram no grafo silenciosamente. ## Cure antes de se afogar [#cure-antes-de-se-afogar] ```json { "tool": "memory_curate", "arguments": { "action": "pin", "query": "priority order latency onboarding correctability" } } ``` * **pin** — boost de +0.3, permanente. Use quando o usuário declara uma restrição persistente ou corrige uma interpretação errada pela última vez. * **snooze** — oculta por N dias (`until` como data ISO, padrão 30). Use quando o contexto do vault insiste em trazer à tona algo irrelevante *agora*. Ambos resolvem memórias por consulta de busca — sem docids. `memory_pin` / `memory_snooze` são os verbos mais antigos; `memory_curate` é o que você deve usar. ## Estado de trabalho entre sessões [#estado-de-trabalho-entre-sessões] * `task_state` `action: "goal"` — o que *pronto* significa; entregue em todo bloco `__goals__`. `action: "progress"` — marcos (janela de 48h). `action: "read"` — inspecionar. * `episodes` — resumos de diálogo delimitados para recuperação episódica; `memory_arcs` — fios narrativos ligando episódios a um objetivo. * `record_lesson` / `list_lessons` — lições procedurais por surface, com scores de follow-through; verify=true quando a lição se provou de novo. * `diary` — diário observacional para eventos que valem revisão depois, em ambientes sem suporte a hook. ## Coordenação de time [#coordenação-de-time] * `team_briefing` no início da sessão: inbox não lido, handoffs pendentes, missão compartilhada, atividade recente. * `team_handoff` `action: "create"` entrega trabalho assíncrono durável a um colega (`to`, `summary`, `open_questions`, `files_changed`, `priority`). `status: "blocked_on_human"` estaciona esperando um humano — o verbo anti-loop. `action: "consume"` fecha quando terminado. * `team_message` — fire-and-forget; `team_notify_human` — puxa um humano *agora* pelo canal dele. * `notifications` — seu inbox; marque como lido depois de tratar. ## Operações (jobs longos, com segurança) [#operações-jobs-longos-com-segurança] Reindex, builds de grafo e syncs de vault são operações longas com handles: `reindex` / `build_graphs` / `vault_sync` aceitam `run_async: true` e devolvem um id; `operation_status` (com long-poll via `wait_ms`), `operation_list`, `operation_cancel` os gerenciam. Um reindex escrito pela metade é pior que nenhum — prefira o cancel cooperativo a matar o processo. Superfícies de saúde: `index_stats` (distribuição de conteúdo, staleness), `memory_health`, `usage_report`, `harness_coverage` (quem usa MCP mas nunca entrega sessões) (ops por canal/ferramenta/latência — o mesmo ledger que o REST `/reports/usage` lê), `list_vaults`. ## Quando algo está quebrado no próprio produto [#quando-algo-está-quebrado-no-próprio-produto] `feedback` `action: "submit"` — resultados vazios onde deveria existir conhecimento, ranking errado, ferramenta dando erro. Um contorno silencioso deixa o defeito no lugar para todos os outros agentes; o relato do defeito é a chamada que sustenta o sistema. # On-premise (Enterprise) (/docs/guides/on-prem) > **Rodar o engine você mesmo é o on-premise do plano Enterprise** — implantado e acompanhado pela nossa equipe ([o que o plano inclui](https://valorbrain.valor.digital/enterprise)). Não existe versão comunitária ou self-service do engine, e o código-fonte não é público. Esta página descreve a arquitetura do que é implantado, para avaliação técnica. A API hospedada em `valorbrain-api.valor.digital` é o caminho sem setup. O que se segue é o que existe dentro do perímetro de um cliente Enterprise. ## A stack [#a-stack] | Camada | O quê | Default | | --------- | -------------------------------------------------------------- | --------------------------------------------- | | Runtime | **Bun** 1.x (não é Node) | — | | Banco | **PostgreSQL 18** | `:5433`, runtime via **PgBouncer** `:6432` | | Extensões | `vector` (pgvector), `pgturbohybrid`, `pg_ripple`, `pg_deltax` | proprietárias | | Engine | REST + MCP HTTP num processo Bun | `:7438` | | Embedding | LFM2.5-Embedding-350M (1024d) | `:7997`, ou endpoint cloud compatível | | Reranker | BGE-Reranker-v2-m3 cross-encoder | `:8096` (opcional; fallback em processo) | | LLM | gateway compatível com OpenAI | `:8201/v1`, modelo via `VALORBRAIN_LLM_MODEL` | GPU é opcional — sem ela, embedding/rerank/LLM apontam para endpoints cloud. Sem as extensões proprietárias do Postgres, o engine sobe em modo degradado (pgvector + BM25 via tsvector): serve para avaliação, sem o RRF híbrido completo nem o grafo. ## Bancos — regra número um [#bancos--regra-número-um] | Banco | Uso | | -------------------- | ---------------------------------------------------------------- | | `valorbrain` | Produção. Dados reais dos tenants. | | `valorbrain_test` | Suíte de testes (recusa banco com nome fora do padrão `*_test*`) | | `valorbrain_staging` | Staging em `:7439` | Conexões de runtime vão pelo PgBouncer; migrations e DDL direto no `:5433` como papel `postgres`. O papel da aplicação (`valorbrain_app`) roda sob RLS e nunca faz DDL. Regra permanente: nenhum `TRUNCATE`/`DROP`/`DELETE` em massa sem `WHERE tenant_id` — RLS não bloqueia `TRUNCATE`. ## Serviços e portas [#serviços-e-portas] O inventário de um host de produção: | Serviço | Porta | Função | | ---------------------------------- | -------- | ----------------------------------- | | `valorbrain.service` | **7438** | Engine de produção | | `valorbrain-staging.service` | 7439 | Staging (banco próprio) | | `valorbrain-embed-worker.service` | — | Worker contínuo de embedding | | `valorbrain-watcher.service` | — | File watcher + pipeline de extração | | `valorbrain-entity-worker.service` | — | Extração de entidades | | `lfm2-embed.service` | 7997 | Embeddings (CUDA) | | `bge-reranker.service` | 8096 | Reranker (CUDA) | | `gliner-ner.service` | 8103 | NER (CUDA) | O engine binda em `127.0.0.1` por padrão. A exposição pública usa túnel/proxy com `VALORBRAIN_PUBLIC_URL` configurado — o `/openapi.json` vivo reescreve `servers[]` a partir dela. ## Verificar o engine no ar [#verificar-o-engine-no-ar] ```bash curl -sS http://localhost:7438/healthz curl -sS http://localhost:7438/openapi.json | jq '.servers, .info["x-valorbrain-live-operations"]' ``` O spec de `/openapi.json` é gerado em runtime da tabela de rotas do processo — `x-valorbrain-live-operations` conta o que este build registra de verdade. `/openapi.yaml` serve o mesmo documento em YAML. ## Gates de qualidade [#gates-de-qualidade] Dois gates de benchmark acompanham o engine (custam LLM e tempo — não são teste unitário): | Gate | O que protege | | ------------- | ----------------------------------------------------------------- | | `gate:locomo` | Piso de recall LoCoMo (R\@10 ≥ 0,90; variação completa para SOTA) | | `gate:beam` | Acurácia no BEAM-100K via arreio AMB, par fixo leitor/juiz | Os números públicos estão na página de [avaliação](/docs/concepts/evaluation) e no [site](https://valorbrain.valor.digital/benchmarks). A suíte unitária roda contra `valorbrain_test`; qualquer falha é regressão, sem banda de tolerância. ## Upgrade [#upgrade] Migrations são aditivas, com checksum registrado; o papel de runtime pula DDL no boot por desenho. O acompanhamento Enterprise cobre backup pré-upgrade, aplicação de migrations, restart e checagem de saúde — junto com o seu time. # Cookbook REST (/docs/guides/rest-cookbook) 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`](/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 [#autenticação-e-tenancy] ``` Authorization: Bearer ``` 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: ```bash curl -sS https://valorbrain-api.valor.digital/healthz ``` ## Escrever um documento [#escrever-um-documento] ```bash 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: 1. **Embedding é assíncrono.** O write volta imediatamente; `embed_state` vai de `pending → synced` (ou `failed` com `embed_error`). Busca que inclui a perna densa só vê o documento quando ele está sincronizado. Faça polling em `GET /documents?collection=...` se precisar esperar por isso. 2. **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 `path` ou o conteúdo, não só o título. 3. **`visibility`** distingue 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 [#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 [#busca-híbrida] ```bash 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; `mode` polariza quais pernas dominam. * `expand` — força liga/desliga da expansão de consulta estilo HyDE. Deixe sem setar e o servidor decide. * `diverse` (padrão `true`) — filtro de diversidade MMR, para que dez hits não sejam dez paráfrases de um documento só. * `offset` — paginação. ### Perfis e timing [#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`. Use `speed` em consultas interativas tecla-a-tecla onde 100 ms importam mais do que os últimos pontos de ranking. * `"timing": true` (ou header `x-search-timing: 1`) — adiciona `hybrid_ms`, `rerank_ms`, `graph_ms` e `total_ms` à resposta. Quando a recuperação parece lenta, isso diz *qual perna* antes de você chutar. ### Recuperação unificada [#recuperação-unificada] ```bash 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 [#resposta-rag] ```bash 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 [#feche-o-loop-memory_used] Depois de responder com memória recuperada, declare o que você realmente usou: ```bash 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` — `confirmed` quando o usuário concordou com o que a memória disse, `corrected` quando 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 [#curar-pin-snooze-forget] Os três são POSTs no id do documento (corpos vazios): ```bash 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 `pin` no oposto: um fato corrigido junto do original superseded é um conflito futuro. Visão do lifecycle (contagens de archived/forgotten/pinned/snoozed e política): ```bash 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 [#confiança-conflitos-e-decisões] ### Conflitos [#conflitos] ```bash 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 [#decisões] ```bash 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 [#medir-uso-e-valor] ```bash 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 [#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](/docs/mcp/tools) e os [schemas completos](/mcp-schemas.md). Se fala só HTTP, esta página é o jogo inteiro. ## Falhas comuns [#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 | # Team OS (/docs/guides/team-os) Team OS é a camada de coordenação do ValorBrain: humanos e agentes compartilham inbox, handoffs e missão — tudo dentro do mesmo cérebro de tenant, tudo auditável. Os contratos abaixo vêm dos schemas reais (`registerTool()`), regenerados a cada build. ## A rotina de sessão [#a-rotina-de-sessão] **Início de sessão: `team_briefing`.** Uma chamada devolve: inbox não lido, handoffs pendentes pra você, a missão compartilhada do time (foundations) e atividade recente. É o "o que precisa de atenção" sem precisar perguntar a ninguém. ```json { "tool": "team_briefing", "arguments": {} } ``` **Fim de trabalho: handoff ou mensagem.** Três verbos, três intenções: | Verbo | Quando | Espera resposta? | | ----------------------- | ------------------------------------------------------------------ | ----------------------------------------------------------------- | | `team_handoff` (create) | Trabalho durável que alguém vai **executar** | Não — aparece no briefing do destinatário até ser consumido | | `team_message` | Contexto, pergunta, coordenação | Não — fire-and-forget | | `team_notify_human` | Decisão/aprovação que **só um humano** pode dar e não pode esperar | Não — empurra no canal dele (Telegram/Discord/…) e grava no inbox | ## Handoff: o contrato completo [#handoff-o-contrato-completo] ```json { "tool": "team_handoff", "arguments": { "action": "create", "to": "ana", "summary": "Aplicar migration 0192 no staging e conferir parity", "open_questions": ["rodar sync:test-db antes ou depois?"], "files_changed": ["migrations/engine/0192-*.sql"], "priority": "high", "status": "pending" } } ``` * `summary` (5–500 chars): o que precisa ser **feito**, não o que você fez. * `open_questions`: o que o destinatário precisa resolver — vai direto no contexto dele. * `files_changed`: os arquivos envolvidos. * `priority`: `low` / `normal` / `high` / `critical`. * `status`: **`pending`** = trabalho acionável; **`blocked_on_human`** = estacionado esperando humano. `blocked_on_human` é o verbo anti-loop: não re-escalone o mesmo handoff. **Fechar**: `action: "consume"` com `handoff_id` (e `note` opcional). Consumir sem fazer é pior que não criar — o briefing mente. ```json { "tool": "team_handoff", "arguments": { "action": "consume", "handoff_id": 42, "note": "aplicada; parity ok" } } ``` ## Quem é quem: `team_roster` [#quem-é-quem-team_roster] Humanos e agentes, papéis e canais. Chame **antes** de mensagens para não escalar pro destinatário errado. ## Puxar humano: `team_notify_human` [#puxar-humano-team_notify_human] ```json { "tool": "team_notify_human", "arguments": { "to": "gustavo", "title": "Preciso de decisão: ACM TLS pro host aninhado", "body": "Plano Free não cobre. Comprar ACM ou seguir só no host canônico?", "priority": "high" } } ``` `to` aceita nome, papel, ou `manager`/`lead`/`human` (qualquer humano do time). A mensagem **também** vai pro inbox — o canal é o gatilho, o inbox é o registro. Reservado para o que genuinamente precisa de humano; spam destrói o valor do canal. ## Inbox: `notifications` [#inbox-notifications] * `notifications` `action: "check"` — não lidos + recentes (`all` inclui lidos; `N-XXXX` busca um item). * `notifications` `action: "mark_read"` — por id ou `all`, **depois de tratar**. ## Regras de ouro [#regras-de-ouro] 1. **Briefing no início, consume no fim.** Handoff não consumido é trabalho fantasma. 2. **`blocked_on_human` não se re-escala.** O estado existe exatamente para quebrar loops de agente. 3. **Notificar humano é rota de exceção**, não de conveniência. 4. **Tudo que vira handoff mereceria ser memória também** — o contexto do handoff é operacional; `memory_store` com `type: "handoff"` preserva o aprendizado depois que o item morre. # Uso e valor entregue (/docs/guides/usage-value) ValorBrain mede o que entrega por tenant a partir de um **ledger** — cada operação por canal (MCP, REST, hook, CLI), com latência e resultado. Nada aqui é estimativa: a contagem vem direto do `usage_events`. ## `usage_report` [#usage_report] ```json { "tool": "usage_report", "arguments": { "period": "month" } } ``` * `period`: `today` / `week` / `month` (padrão, 30 dias) / `quarter`. * Devolve: operações por canal, por ferramenta, por pessoa/agente, latência p50/p95, resultados devolvidos e a série diária. É a fonte para "quantas consultas fizemos este mês" e para dimensionar valor. O dashboard do SaaS lê o mesmo dado — sem camada de interpretação no meio. ## O agregado diário: `value_daily` [#o-agregado-diário-value_daily] O job noturno pré-agrega o ledger em `value_daily` (por tenant, por dia). A leitura pública é REST: ```bash curl -sS ".../api/v1/tenant/value-summary" -H "Authorization: Bearer $VALORBRAIN_TOKEN" ``` Dias completos vêm do agregado; **hoje** e dias faltantes são computados ao vivo — e o campo `stale_days` reporta os buracos. Famílias de valor (search / context / write / collab) agrupam o que cada operação entregou. ## Respostas entregues [#respostas-entregues] ```bash curl -sS ".../api/v1/usage/answers" -H "Authorization: Bearer $VALORBRAIN_TOKEN" ``` O corte por **respostas** (não por chamadas): quantas respostas citaram memória, com fonte — a métrica que importa para "o produto está entregando conhecimento ou só latência?". ## Saúde do índice [#saúde-do-índice] * `index_stats` — distribuição por tipo de conteúdo, staleness (quanto tempo sem re-embed), saúde geral. Use antes de culpar o ranking. * `memory_health` — propostas/conflitos abertos, itens de alta prioridade e fontes canônicas com drift. É a chamada de **fim de sessão substantiva**: mede dívida de conhecimento, não infra. ## O loop que fecha o valor [#o-loop-que-fecha-o-valor] Uso medido sem `memory_used` é metade da história: 1. `memory_retrieve` / `memory_prepare` entregam contexto. 2. A resposta cita as fontes (`docids`). 3. `memory_used` declara o que sustentou a resposta — e o `verdict` (`confirmed`/`corrected`) alimenta o ranking. O ledger registra a operação; o `memory_used` registra o **desfecho**. Sem o passo 3, o relatório mostra atividade, não valor. ## No SaaS [#no-saas] O que o tenant vê no dashboard é construído sobre essas mesmas superfícies. Se um número do dashboard e um `usage_report` da API divergirem, o bug é nosso — reporte com `feedback`. # Claude Code (/docs/integrations/claude-code) ## Hospedado (recomendado) [#hospedado-recomendado] ```bash claude mcp add --transport http valorbrain https://mcpbrain.valor.digital/mcp ``` Autentique com OAuth quando pedido, ou coloque um token `vbm_` na configuração de headers do cliente. Depois: ```bash npx @valorbrain/cli init --agent --agent-caller claude-code ``` A chave da CLI serve para a REST (`add` / `search`). A conexão MCP é um token `vbm_` ou OAuth. Você pode usar os dois: CLI para o shell, MCP para as ferramentas dentro do editor. Alternativa stdio: ```json { "mcpServers": { "valorbrain": { "command": "npx", "args": ["-y", "@valorbrain/connect", "--token", "vbm_…"] } } } ``` ## O contrato que instalamos [#o-contrato-que-instalamos] Quando você usa o repositório público de harness ([ValorBrain/valorbrain-harness](https://github.com/ValorBrain/valorbrain-harness)) para editores da família Claude, a instrução permanente é o mesmo loop de qualidade: consulte o ValorBrain antes de responder perguntas operacionais; chame `memory_used` depois. ## Primeiras ferramentas [#primeiras-ferramentas] `whoami` → `memory_prepare` ou `working_context` → trabalho → `memory_store` para qualquer coisa durável → `memory_used`. # Conectores (/docs/integrations/connectors) O app traz cinco conectores OAuth: **Notion, Google Drive, Slack, GitHub, Linear**. Eles são BYOK — você cola o cliente OAuth do seu workspace. O sync roda em background e ingere no engine do tenant. Eles vivem em [valorbrain.valor.digital/connectors](https://valorbrain.valor.digital/connectors) depois do login. Exigem **Starter ou acima**, não o plano gratuito. Isto não é MCP. Conectores abastecem coleções; agentes depois recuperam via MCP ou REST. Watchers de filesystem e webhooks são caminhos de ingestão adicionais em instalações on-premise (Enterprise). Clientes hospedados que só precisam de "coloca esse documento no cérebro" devem usar o `add` da CLI, o `memory_store` do MCP, ou `POST /api/v1/ingest` com uma chave `fk_`. # Cursor e Windsurf (/docs/integrations/cursor) Cursor e Windsurf falam MCP com OAuth 2.1. Aponte a URL do servidor MCP para: ``` https://mcpbrain.valor.digital/mcp ``` Discovery: ``` https://mcpbrain.valor.digital/.well-known/oauth-authorization-server ``` `POST /oauth/register` (RFC 7591) nesse host devolve 201. Você não precisa pré-registrar um cliente. Se o editor não completar o OAuth, crie um token dedicado no app (Settings → MCP tokens) e passe `Authorization: Bearer vbm_…`. ```bash npx @valorbrain/cli init --agent --agent-caller cursor ``` # Grok (/docs/integrations/grok) O harness do Grok vive em [`valorbrain-harness/grok`](https://github.com/ValorBrain/valorbrain-harness/tree/main/grok): um markdown de contrato e um `mcp.example.toml` de exemplo. Nada do nosso tenant está nesse repositório. MCP hospedado via stdio: ```toml # ~/.grok/config.toml [mcp_servers.valorbrain] command = "npx" args = ["-y", "@valorbrain/connect", "--token=vbm_YOUR_TOKEN_HERE"] ``` Instale o contrato a partir de um clone do repositório de harness: ```bash ./install.sh grok ``` O `install.sh` desse repositório é **por harness** (`grok`, `zcode`, …). Ele não chama uma CLI `valorbrain setup`, porque esse comando de CLI não está publicado. ```bash npx @valorbrain/cli init --agent --agent-caller grok ``` # Hermes (/docs/integrations/hermes) O Hermes conversa com o ValorBrain como **MemoryProvider**, não como um cliente MCP genérico com uma lista fixa de dez ferramentas. Numa máquina que já tem o engine, o plugin vem da árvore do engine (`src/hermes/` → `~/.hermes/plugins/valorbrain`). Esse caminho existe na instalação **on-premise (Enterprise)**. Não é o que um cliente hospedado copia. **Hermes hospedado:** use o mesmo caminho MCP HTTP/stdio de qualquer outro cliente (`mcpbrain` + `vbm_`, ou `@valorbrain/connect`). O plugin nativo do Hermes é a integração mais profunda quando você roda o engine. A página de marketing em `/docs` que diz "Plugin nativo com 10 tools" está desatualizada. O catálogo vivo é [Ferramentas MCP](/docs/api/mcp-tools); um token novo recebe o toolset **agent**, não uma lista de dez. ```bash npx @valorbrain/cli init --agent --agent-caller hermes ``` # Integrações (/docs/integrations) O ValorBrain conversa com qualquer cliente MCP e qualquer cliente HTTP. As páginas abaixo são as combinações que nós mesmos rodamos ou para as quais publicamos instaladores. ## Hospedado vs on-premise [#hospedado-vs-on-premise] **Hospedado (comece por aqui):** nenhum engine na sua máquina. O harness fala com o `mcpbrain` com um token `vbm_`, ou com a REST com uma chave `vb_agent_` vinda da CLI. **On-premise (Enterprise):** o engine na sua rede é parte do plano Enterprise — não existe versão comunitária ou self-service, nem `docker compose up` público; a implantação é acompanhada pela nossa equipe. [O que o Enterprise inclui](https://valorbrain.valor.digital/enterprise). ## O loop de qualidade (todo harness) [#o-loop-de-qualidade-todo-harness] 1. **Consulte antes de responder** — a memória manda na operação; os dados de treino, não. 2. **Declare o que você usou** — `memory_used` com os docids em que você se apoiou. Quando o humano confirmar ou corrigir, passe `verdict`. Se um README mandar rodar `valorbrain setup harness `, esse subcomando **não** existe na CLI publicada. Use a página daquele harness. # OpenClaw (/docs/integrations/openclaw) O OpenClaw integra como um plugin `kind: memory`: injeção de contexto por turno e extração no fim da sessão. Os hooks de ciclo de vida existem para o modelo não precisar lembrar de chamar o retrieve. **Hospedado:** MCP via `@valorbrain/connect` ou HTTP para o `mcpbrain`, como qualquer editor. O README público do harness ainda diz `valorbrain setup openclaw`. Esse subcomando **não** existe no `@valorbrain/cli@0.1.0`. Use MCP + o plugin da árvore do engine na instalação on-premise (Enterprise); use o caminho MCP hospedado quando não tem uma. ```bash npx @valorbrain/cli init --agent --agent-caller unspecified ``` Passe uma string de caller estável que você vá reutilizar (`openclaw` serve). # ZCode (/docs/integrations/zcode) O ZCode é um harness de primeira classe. O plugin vive em [`valorbrain-harness/zcode`](https://github.com/ValorBrain/valorbrain-harness/tree/main/zcode) e é publicado no marketplace `valor-digital` como `valorbrain`. O que ele instala: * Recall de memória por prompt * Bootstrap de sessão * Lembretes de escrita * Uma skill de loop de qualidade (`valorbrain-memory`) * Hooks de ciclo de vida (`session-start`, `user-prompt-submit`, `stop`, `post-tool-use`) ```bash # from a clone of valorbrain-harness ./install.sh zcode # or the plugin's own installer ./zcode/install.sh ``` ```bash npx @valorbrain/cli init --agent --agent-caller zcode ``` # MCP (/docs/mcp) O ValorBrain expõe um servidor Model Context Protocol. * **Transporte:** Streamable HTTP * **Endpoint:** `https://mcpbrain.valor.digital/mcp` * **Auth:** OAuth 2.1 (registro dinâmico de cliente) **ou** `Authorization: Bearer vbm_…` * **Protocolo:** `2025-11-25` (veja o [server card](https://valorbrain.valor.digital/.well-known/mcp/server-card.json)) ## HTTP (Claude Code, Cursor, Windsurf) [#http-claude-code-cursor-windsurf] Clientes que falam Streamable HTTP: ```json { "mcpServers": { "valorbrain": { "url": "https://mcpbrain.valor.digital/mcp", "headers": { "Authorization": "Bearer vbm_" } } } } ``` Claude Code: ```bash claude mcp add --transport http valorbrain https://mcpbrain.valor.digital/mcp ``` Depois autentique (OAuth) ou adicione o header bearer na configuração do cliente. Clientes com OAuth 2.1 DCR descobrem o auth a partir de: `https://mcpbrain.valor.digital/.well-known/oauth-authorization-server` ## stdio (via CLI) [#stdio-via-cli] Clientes que só falam stdio: ```json { "mcpServers": { "valorbrain": { "command": "npx", "args": ["-y", "@valorbrain/connect", "--token", "vbm_"] } } } ``` `@valorbrain/connect` é um alias publicado de `valorbrain mcp`. Não é um protocolo separado. ## Primeiras chamadas [#primeiras-chamadas] 1. `tools/list` — confie no schema vivo, não num screenshot. 2. `whoami` — confirme tenant e usuário. Pare se algum dos dois estiver errado. 3. `memory_retrieve` ou `memory_prepare` — depois `memory_used`. O toolset padrão **agent** é o conjunto de trabalho. Não é o catálogo completo. Veja [Ferramentas MCP](/docs/api/mcp-tools). ## O que não fazer [#o-que-não-fazer] * Não aponte a REST para o `mcpbrain`. `/search` lá não é busca. * Não envie uma chave `vb_agent_` como bearer MCP. Tokens MCP começam com `vbm_`. * Não chame a ferramenta deprecada `store`. A escrita canônica é `memory_store`. # Ferramentas MCP (/docs/mcp/tools) Fonte da verdade: `src/tool-catalog.ts` no engine. Contagens e nomes desta página vêm desse arquivo, não de um README. Tokens MCP novos usam o toolset **agent** por padrão. Tokens criados antes de 2026-08-17 veem `all` (fail-open). `graph` e `ops` são aditivos. Ferramentas deprecadas continuam visíveis em `all` durante a janela de alias. Não as ensine a um cliente novo. ## Toolset agent (padrão) [#toolset-agent-padrão] Recall: | Ferramenta | Serve para | | ------------------- | --------------------------------------------------------------------------------- | | `memory_retrieve` | Uma pergunta bem formada. O servidor expande e funde. Gêmea REST: `POST /search`. | | `memory_prepare` | Montar contexto para uma tarefa. Gêmea REST: `POST /api/v1/memory/prepare`. | | `working_context` | Início de sessão mais barato: fatos estáveis + decisões recentes. | | `memory_grep` | String exata, id, data, chave. | | `get` / `multi_get` | Corpo completo de um doc que você já achou. | | `keyed_facts_as_of` | Snapshots de fatos com viagem no tempo. | | `whoami` | Confirmar tenant / usuário / agente. Só HTTP. | | `memory_health` | Saúde do índice e do pipeline. | Escrita e correção: | Ferramenta | Serve para | | ----------------------------- | ----------------------------------------------------------------------- | | `memory_store` | Resultado durável e tipado (`decision`, `problem`, `lesson`, …). | | `memory_used` | Declarar os docids em que você realmente se apoiou. `verdict` opcional. | | `upsert_keyed_fact` | Escrever um snapshot de fato datado. | | `assert_authority_correction` | Corrigir um valor errado para a próxima sessão ver a verdade. | | `record_lesson` | Um aprendizado que deve mudar comportamento futuro. | | `memory_curate` | pin / snooze / unpin / unsnooze. | | `memory_forget` | A escrita menos reversível — standalone de propósito. | | `append_entity_card` | Caminho de escrita no KG que agentes realmente usam. | | `diary` | Leitura/escrita do diário do agente. | Estado de trabalho e time: | Ferramenta | Serve para | | ------------------------------------------------------------------- | -------------------------------------------- | | `scratchpad` | Rascunho de sessão. | | `task_state` | Ledger de objetivo / progresso. | | `profile` | Perfil do usuário. | | `team_briefing` | Inbox, handoffs, missão. | | `team_handoff` | create / consume. | | `team_inbox` / `team_message` / `team_notify_human` / `team_roster` | Team OS (no-op se o tenant não tem membros). | | `episodes` | list / get de memórias episódicas. | | `notifications` | check / mark\_read. | | `list_lessons` | Lições gravadas para este tenant. | ## Toolset graph [#toolset-graph] Grafo de conhecimento, decisões, proveniência, conflitos. Nomes canônicos: `kg_query`, `kg_explain`, `kg_entity_resolve_report`, `kg_quarantine`, `list_entity_cards`, `find_causal_links`, `memory_evolution_status`, `provenance`, `conflicts`, `memory_arcs`, `timeline`, `find_similar`, `decisions`. `ripple_rag_retrieve` é **beta**. Nomes antigos (`record_decision`, `trace_lineage`, `detect_conflicts`, …) são **aliases** dessas ferramentas canônicas. Continuam funcionando. ## Toolset ops [#toolset-ops] Curadoria e medição: `lifecycle_*`, `reindex`, `index_stats`, `import_docs`, `export_docs`, `vault_sync`, `list_vaults`, `beads_sync`, `build_graphs`, `operations`, `usage_report`, `feedback`. ## Deprecadas — não ensine [#deprecadas--não-ensine] | Nome | Realidade | | ---------------- | --------------------------------------------- | | `store` | Duplicata só-HTTP de `memory_store`. | | `list_proposals` | Só HTTP; `memory_health` já mostra propostas. | A página de marketing em `/docs` ainda diz "MCP store tool". Esse nome é o deprecado. Chame `memory_store`. # REST (/docs/rest) URL base: `https://valorbrain-api.valor.digital` ```bash curl -sS https://valorbrain-api.valor.digital/health ``` Auth: `Authorization: Bearer `. O tenant é resolvido a partir do token. Você **não** precisa de `X-Tenant-ID` para uma chave normal. ## Busca [#busca] ```bash curl -sS -X POST https://valorbrain-api.valor.digital/search \ -H "Authorization: Bearer $VALORBRAIN_API_KEY" \ -H "Content-Type: application/json" \ -d '{"query":"deploy key","limit":5}' ``` Opcional: `"profile": "speed"` para o caminho rápido (híbrido/FTS, sem cross-encoder). O padrão é `balanced`. `"timing": true` ou o header `x-search-timing: 1` adiciona `hybrid_ms` / `rerank_ms` / `graph_ms` / `total_ms`. `POST /retrieve` é a gêmea multiestratégia da busca (`memory_retrieve` no MCP roteia sozinho; esta é a forma explícita REST). ## Ingestão [#ingestão] ```bash curl -sS -X POST https://valorbrain-api.valor.digital/documents \ -H "Authorization: Bearer $VALORBRAIN_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "collection": "decisions", "path": "ADR-001.md", "title": "We chose PostgreSQL", "content": "## Decision\nPostgreSQL is the primary store." }' ``` É isso que o `add` da CLI chama. ### Ingestão SaaS (chave de API do workspace) [#ingestão-saas-chave-de-api-do-workspace] Para sistemas que já falam com o app, não com o engine: ```bash curl -sS -X POST https://valorbrain.valor.digital/api/v1/ingest \ -H "Authorization: Bearer fk_.sk_" \ -H "Content-Type: application/json" \ -d '{ "collection": "decisions", "path": "ADR-001.md", "title": "We chose PostgreSQL", "content": "## Decision\nPostgreSQL is the primary store." }' ``` Chaves `fk_` autenticam a ingestão no host SaaS. Elas não substituem a busca no engine em `valorbrain-api`. ## Leitura / curadoria [#leitura--curadoria] | Método | Path | Significado | | ------ | ------------------------- | ----------------------------------- | | `GET` | `/documents/:id` | Documento completo | | `GET` | `/documents` | Lista, paginada | | `GET` | `/collections` | Coleções e contagens | | `POST` | `/documents/:id/pin` | Pin (foundation) | | `POST` | `/documents/:id/snooze` | Esconde da recuperação por um tempo | | `POST` | `/documents/:id/forget` | Soft-delete | | `POST` | `/documents/:id/feedback` | `POSITIVE` / `NEGATIVE` | | `GET` | `/health` | Liveness | | `GET` | `/stats` | Estatísticas do índice | O arquivo OpenAPI do engine no repositório descreve **116 paths**, incluindo ops e graph. O JSON em `valorbrain.valor.digital/openapi.json` é um **documento de descoberta de 4 paths** para agentes que acessam o site de marketing. Não é a mesma spec. Este site de docs publica a superfície pública de integração; veja a [Referência de API](/docs/api). ## Cadastro de agente (REST) [#cadastro-de-agente-rest] ```bash curl -sS -X POST https://valorbrain-api.valor.digital/api/v1/agents/signup \ -H "Content-Type: application/json" \ -d '{"agent_name":"my-agent","agent_caller":"claude-code"}' ``` Precisa acertar o **valorbrain-api**. O mesmo path no mcpbrain é engolido pelo transporte MCP. Tabela completa: [Referência REST](/docs/api/rest). # MCP tool schemas (generated) (/docs/api/generated-mcp-schemas) {/* generated by scripts/generate-reference.py — do not edit */} The live tool descriptions and Zod input shapes are dumped as plain markdown so MDX does not try to parse `<` in prose or `{` in schemas. * Machine dump: [/mcp-schemas.md](/mcp-schemas.md) * Also included in [/llms-full.txt](/llms-full.txt) # MCP catalog (generated) (/docs/api/generated-mcp) {/* generated by scripts/generate-reference.py — do not edit */} Source: `/opt/valorbrain/src/tool-catalog.ts`. New tokens default to the **agent** toolset. **99 names** in the catalog (canonical + aliases + deprecated). ## agent [#agent] * **`memory_retrieve`** · REST `POST /search` · top tool, 63% share with the next four * **`memory_recent`** · REST `GET /api/v1/memory/team-activity` · FB-0095: author+recency retrieval — 'what did agent X do recently'; topic search can't answer author questions * **`memory_prepare`** · REST `POST /api/v1/memory/prepare` * **`working_context`** · cheapest session-start orientation * **`memory_grep`** · exact-match lookups (ids, values, dates) * **`get`** · absorbs multi\_get via paths\[] in WS3 * **`multi_get`** · merge into get (WS3) * **`keyed_facts_as_of`** · temporal fact snapshots * **`memory_store`** · REST `POST /api/v1/memory/store` * **`memory_used`** · quality feedback loop — skill must require it * **`upsert_keyed_fact`** * **`assert_authority_correction`** · correctability priority * **`authority_restore_demotion`** · FB-0092/0093 — undo prose demotion (restore confidence, unhide, cancel pending work) by fact\_key/demotion\_work\_id * **`record_lesson`** * **`memory_curate`** · canonical pin/snooze/unpin/unsnooze (WS3); memory\_forget stays separate — least reversible write, MRTR gate * **`memory_pin`** · `alias` · → `memory_curate` · REST `POST /documents/:id/pin` * **`memory_snooze`** · `alias` · → `memory_curate` * **`memory_forget`** · REST `POST /documents/:id/forget` · 294 REST calls — never judge by MCP alone; stays standalone (reversibility boundary) * **`append_entity_card`** · KG write path agents actually use * **`diary`** · canonical read/write (WS3); write action is write-scope gated per action * **`diary_read`** · `alias` · → `diary` * **`diary_write`** · `alias` · → `diary` * **`scratchpad`** · REST `/api/v1/scratchpad` · gains ledger mode → task\_state (WS3/WS5) * **`set_goal`** · `alias` · → `task_state` · ORPHAN no more: task\_state + skill teaching when to open a goal * **`report_progress`** · `alias` · → `task_state` · demand real era REST /plans * **`profile`** * **`team_briefing`** * **`team_handoff`** · WS3: gained action create|consume (default create); both verbs write-scoped as before * **`team_handoff_consume`** · `alias` · → `team_handoff` * **`team_inbox`** * **`team_message`** * **`team_notify_human`** * **`team_roster`** * **`whoami`** · http-only * **`memory_health`** · REST `GET /api/v1/memory/health` · http-only * **`acl_me`** · REST `GET /api/v1/acl/me` · ADR-031 A4: domínios efetivos do chamador (união user+role+agent) com a fonte de cada grant — o trace real do simulador de governança * **`list_lessons`** * **`episodes`** · canonical list/get (WS3); moved agent←graph 2026-08-17 — real usage (hermes-default calls list\_memory\_episodes) and episodic memory is core product, not curation * **`get_memory_episode`** · `alias` · → `episodes` * **`list_memory_episodes`** · `alias` · → `episodes` * **`notifications`** · canonical check/mark\_read (WS3); mark\_read is write-scope gated per action * **`notifications_check`** · `alias` · → `notifications` * **`notifications_mark_read`** · `alias` · → `notifications` ## graph [#graph] * **`timeline`** · REST `GET /timeline/:id` · retrieve auto-routes last-session; extended surface * **`find_similar`** · REST `GET /graph/similar/:id` · retrieve auto-routes related; extended * **`ripple_rag_retrieve`** · `beta` · VB-3203 experiment * **`decisions`** · canonical record/relate/trace/similar/list (WS3); record/relate write-scope gated per action; auto-populated by decision-extractor hook (119 calls) * **`record_decision`** · `alias` · → `decisions` · REST `POST /api/v1/decisions` * **`list_decisions`** · `alias` · → `decisions` · REST `GET /api/v1/decisions` * **`trace_decision_chain`** · `alias` · → `decisions` · REST `GET /api/v1/decisions/chain` * **`find_similar_decisions`** · `alias` · → `decisions` · REST `GET /api/v1/decisions/similar` * **`add_decision_relation`** · `alias` · → `decisions` · REST `POST /api/v1/decisions/relations` * **`kg_query`** · REST `/api/v1/kg/explore` * **`kg_explain`** · ORPHAN: we sell KG explainability; skill teaches it in WS5 * **`kg_entity_resolve_report`** * **`kg_quarantine`** · canonical list/approve/reject (WS3); approve/reject write-scope gated per action * **`list_kg_quarantine`** · `alias` · → `kg_quarantine` · REST `/api/v1/kg/quarantine` * **`approve_kg_quarantine`** · `alias` · → `kg_quarantine` * **`reject_kg_quarantine`** · `alias` · → `kg_quarantine` * **`entity_cards`** · canonical: lista cards + curadoria de apelido (propose/merge/reject — o tenant decide) * **`list_entity_cards`** · `alias` · → `entity_cards` * **`find_causal_links`** · retrieve auto-routes why→causal * **`memory_evolution_status`** · curation niche * **`provenance`** · canonical trace/export (WS3) * **`trace_lineage`** · `alias` · → `provenance` · REST `/api/v1/provenance/lineage` * **`export_provenance`** · `alias` · → `provenance` · REST `/api/v1/provenance` * **`conflicts`** · canonical detect/list/resolve (WS3); resolve write-scope gated per action * **`detect_conflicts`** · `alias` · → `conflicts` · REST `POST /api/v1/conflicts/detect` · also auto-detected by consolidation tick * **`list_conflicts`** · `alias` · → `conflicts` · REST `GET /api/v1/conflicts` * **`resolve_conflict`** · `alias` · → `conflicts` · REST `POST /api/v1/conflicts/resolve` * **`memory_arcs`** · canonical create/list (WS3); create write-scope gated per action; kills the list\_arcs≡list\_memory\_arcs duplicate * **`create_memory_arc`** · `alias` · → `memory_arcs` · orphan; re-teach after task\_state lands * **`list_arcs`** · `alias` · → `memory_arcs` · DUPLICATE of list\_memory\_arcs — merge in WS3 * **`list_memory_arcs`** · `alias` · → `memory_arcs` ## ops [#ops] * **`lifecycle_status`** · REST `GET /lifecycle/status` * **`lifecycle_sweep`** · REST `POST /lifecycle/sweep` * **`lifecycle_restore`** · REST `POST /lifecycle/restore` · SaaS restore button lives here (94 REST calls) * **`reindex`** * **`index_stats`** * **`import_docs`** * **`export_docs`** * **`vault_sync`** * **`list_vaults`** * **`beads_sync`** * **`build_graphs`** * **`operations`** · canonical status/list/cancel (WS3); cancel keeps write scope via alias list until window closes * **`operation_status`** · `alias` · → `operations` * **`operation_list`** · `alias` · → `operations` * **`operation_cancel`** · `alias` · → `operations` * **`usage_report`** * **`harness_coverage`** · runtime delivery signal: MCP-active agents with zero ingestion — what file-level setup status cannot see * **`feedback`** · canonical submit/check (WS3); submit write-scope gated per action * **`feedback_submit`** · `alias` · → `feedback` * **`feedback_check`** · `alias` · → `feedback` * **`secrets`** · cofre: memória guarda referência secret://\, valor só sai por get auditado; escopo fail-closed secrets:read/secrets:write * **`acl_grants`** · REST `GET/POST/DELETE /api/v1/acl/grants` · ADR-031 A4: admin CRUD de grants do source ACL (user|role|agent → domínio, reason obrigatória, validade temporal); escopo fail-closed acl\_grants:read/acl\_grants:write; mutação vai ao mutation\_audit * **`read_log`** · REST `GET /api/v1/read-log` · ADR-031 B3: trilha 'quem leu, qual versão' (1 linha por consulta; query só como hash — LGPD; docs\_touched = pares hash+revisão); escopo fail-closed read\_log:read; a própria consulta é auditada em mutation\_audit * **`list_proposals`** · `deprecated` · http-only; memory\_health already surfaces proposals — kill in WS3 * **`store`** · `deprecated` · http-only duplicate of memory\_store — kill in WS3 # REST (generated) (/docs/api/generated-rest) {/* generated by scripts/generate-reference.py — do not edit */} Source: `https://valorbrain-api.valor.digital/openapi.json (live, generated from routes[])`. Public base: `https://valorbrain-api.valor.digital`. Admin and ops routes are listed because they exist; a tenant token will 403 them. **232 operations** across 20 tags. ## Admin [#admin] ### `POST /api/v1/admin/tenants` [#post-apiv1admintenants] Create a tenant (admin only) * Auth: bearer * Body: object( `name`\* (string), `metadata` (object( )) ) * operationId: `adminCreateTenant` ```yaml post: operationId: adminCreateTenant summary: Create a tenant (admin only) tags: - Admin security: - adminSecret: [] requestBody: required: true content: application/json: schema: type: object required: - name properties: name: type: string metadata: type: object additionalProperties: true responses: '200': description: Tenant created content: application/json: schema: type: object properties: ok: type: boolean tenant_id: type: string '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' ``` ### `POST /api/v1/admin/tenants/{tenantId}/users` [#post-apiv1admintenantstenantidusers] Create a user in a tenant (admin only) * Auth: bearer * Params: `tenantId`\* * Body: object( `email`\* (string), `name` (string), `role` (string) ) * operationId: `adminCreateUser` ```yaml post: operationId: adminCreateUser summary: Create a user in a tenant (admin only) tags: - Admin security: - adminSecret: [] parameters: - name: tenantId in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object required: - email properties: email: type: string format: email name: type: string role: type: string responses: '200': description: User created content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' ``` ### `DELETE /api/v1/admin/tenants/{tenantId}` [#delete-apiv1admintenantstenantid] Delete a tenant (admin only) * Auth: bearer * Params: `tenantId`\* * operationId: `adminDeleteTenant` ```yaml delete: operationId: adminDeleteTenant summary: Delete a tenant (admin only) tags: - Admin security: - adminSecret: [] parameters: - name: tenantId in: path required: true schema: type: string responses: '200': description: Tenant deleted content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' ``` ### `GET /api/v1/admin/errors` [#get-apiv1adminerrors] List error log (admin only) * Auth: bearer * Params: `limit`, `unresolved_only` * operationId: `adminListErrors` ```yaml get: operationId: adminListErrors summary: List error log (admin only) tags: - Admin security: - adminSecret: [] parameters: - name: limit in: query schema: type: integer default: 50 - name: unresolved_only in: query schema: type: boolean default: true responses: '200': description: Error list content: application/json: schema: type: object properties: errors: type: array items: type: object '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' ``` ### `POST /api/v1/admin/errors/{errorId}/resolve` [#post-apiv1adminerrorserroridresolve] Resolve an error (admin only) * Auth: bearer * Params: `errorId`\* * operationId: `adminResolveError` ```yaml post: operationId: adminResolveError summary: Resolve an error (admin only) tags: - Admin security: - adminSecret: [] parameters: - name: errorId in: path required: true schema: type: integer responses: '200': description: Error resolved content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' ``` ### `GET /api/v1/admin/test-error` [#get-apiv1admintest-error] Trigger a test error (admin only) * Auth: bearer * operationId: `adminTestError` ```yaml get: operationId: adminTestError summary: Trigger a test error (admin only) tags: - Admin security: - adminSecret: [] responses: '200': description: Test error triggered content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' ``` ### `POST /admin/l0-l1/run` [#post-adminl0-l1run] Trigger L0/L1 generation * Auth: bearer * operationId: `l0l1Run` ```yaml post: operationId: l0l1Run summary: Trigger L0/L1 generation tags: - Admin responses: '200': description: L0/L1 generation initiated content: application/json: schema: type: object properties: ok: type: boolean ``` ## Agents [#agents] ### `POST /api/v1/agents/signup` [#post-apiv1agentssignup] Register a new agent (public) — Public endpoint — no auth required. Creates a shadow tenant and returns an API key. * Auth: none * Body: object( `agent_name`\* (string), `capabilities` (array\[string]), `metadata` (object( )) ) * operationId: `agentSignup` ```yaml post: operationId: agentSignup summary: Register a new agent (public) description: 'Public endpoint — no auth required. Creates a shadow tenant and returns an API key. ' tags: - Agents security: [] requestBody: required: true content: application/json: schema: type: object required: - agent_name properties: agent_name: type: string capabilities: type: array items: type: string metadata: type: object additionalProperties: true responses: '200': description: Agent registered with API key content: application/json: schema: type: object properties: ok: type: boolean tenant_id: type: string api_key: type: string '400': $ref: '#/components/responses/BadRequest' ``` ### `POST /api/v1/agents/identify` [#post-apiv1agentsidentify] Identify an agent by API key * Auth: none * Body: object( `key`\* (string) ) * operationId: `agentIdentify` ```yaml post: operationId: agentIdentify summary: Identify an agent by API key tags: - Agents security: [] requestBody: required: true content: application/json: schema: type: object required: - key properties: key: type: string responses: '200': description: Agent identity content: application/json: schema: type: object properties: agent_name: type: string tenant_id: type: string '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /api/v1/agents/claim` [#post-apiv1agentsclaim] Request ownership claim for an agent * Auth: none * Body: object( `agent_name`\* (string), `email`\* (string) ) * operationId: `agentClaim` ```yaml post: operationId: agentClaim summary: Request ownership claim for an agent tags: - Agents security: [] requestBody: required: true content: application/json: schema: type: object required: - agent_name - email properties: agent_name: type: string email: type: string format: email responses: '200': description: Claim request initiated content: application/json: schema: type: object '400': $ref: '#/components/responses/BadRequest' ``` ### `POST /api/v1/agents/claim/verify` [#post-apiv1agentsclaimverify] Verify an agent ownership claim * Auth: none * Body: object( `token`\* (string) ) * operationId: `agentClaimVerify` ```yaml post: operationId: agentClaimVerify summary: Verify an agent ownership claim tags: - Agents security: [] requestBody: required: true content: application/json: schema: type: object required: - token properties: token: type: string responses: '200': description: Claim verified content: application/json: schema: type: object properties: ok: type: boolean api_key: type: string '400': $ref: '#/components/responses/BadRequest' ``` ## Ask [#ask] ### `POST /ask` [#post-ask] RAG chat with LLM answer and source citations — Retrieve relevant context, run through LLM reasoning, and return a grounded answer with source citations. Supports streaming (SSE). * Auth: bearer * Params: `None` * Body: object( `q`\* (string), `collection` (string), `stream` (boolean), `language` (enum(pt-BR, en)), `limit` (integer) ) * operationId: `ask` ```yaml post: operationId: ask summary: RAG chat with LLM answer and source citations description: 'Retrieve relevant context, run through LLM reasoning, and return a grounded answer with source citations. Supports streaming (SSE). ' tags: - Ask parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - q properties: q: type: string description: User question collection: type: string stream: type: boolean default: false description: Enable SSE streaming language: type: string enum: - pt-BR - en default: pt-BR limit: type: integer default: 5 description: Max source documents to retrieve responses: '200': description: 'RAG answer. When stream=false, returns JSON with answer and sources. When stream=true, returns text/event-stream. ' content: application/json: schema: type: object properties: answer: type: string sources: type: array items: $ref: '#/components/schemas/SearchResult' trace_id: type: string text/event-stream: schema: type: string description: SSE stream of answer chunks '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /api/v1/traces` [#get-apiv1traces] List recent ask traces * Auth: bearer * Params: `limit`, `offset` * operationId: `listTraces` ```yaml get: operationId: listTraces summary: List recent ask traces tags: - Ask parameters: - name: limit in: query schema: type: integer default: 50 - name: offset in: query schema: type: integer default: 0 responses: '200': description: Trace log entries content: application/json: schema: type: object properties: traces: type: array items: type: object count: type: integer ``` ## Billing [#billing] ### `GET /api/v1/credits/balance` [#get-apiv1creditsbalance] Get credit balance * Auth: bearer * Params: `None` * operationId: `getCreditsBalance` ```yaml get: operationId: getCreditsBalance summary: Get credit balance tags: - Billing parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Credit balance content: application/json: schema: $ref: '#/components/schemas/CreditBalance' '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /api/v1/credits/transactions` [#get-apiv1creditstransactions] Get credit transaction history * Auth: bearer * Params: `None`, `limit` * operationId: `getCreditsTransactions` ```yaml get: operationId: getCreditsTransactions summary: Get credit transaction history tags: - Billing parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: limit in: query schema: type: integer default: 50 responses: '200': description: Transaction list content: application/json: schema: type: object properties: transactions: type: array items: type: object properties: id: type: string amount: type: number action: type: string created_at: type: string format: date-time '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /api/v1/credits/grant` [#post-apiv1creditsgrant] Grant credits to tenant — Repeatable manual operator adjustment; the required reason is recorded in the credit ledger. * Auth: bearer * Params: `None` * Body: object( `amount`\* (number), `reason`\* (string), `metadata` (object( )) ) * operationId: `grantCredits` ```yaml post: operationId: grantCredits summary: Grant credits to tenant description: Repeatable manual operator adjustment; the required reason is recorded in the credit ledger. tags: - Billing security: - moneyAdminAuth: [] parameters: - $ref: '#/components/parameters/MoneyTenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - amount - reason properties: amount: type: number exclusiveMinimum: 0 reason: type: string minLength: 1 metadata: type: object additionalProperties: true responses: '200': description: Credits granted content: application/json: schema: type: object required: - ok - balance_after properties: ok: type: boolean balance_after: type: number '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' ``` ### `GET /api/v1/pricing/actions` [#get-apiv1pricingactions] List pricing actions * Auth: bearer * Params: `None` * operationId: `listPricingActions` ```yaml get: operationId: listPricingActions summary: List pricing actions tags: - Billing parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Pricing action list content: application/json: schema: type: object properties: actions: type: array items: type: object properties: action: type: string cost: type: number currency: type: string '401': $ref: '#/components/responses/Unauthorized' ``` ### `PUT /api/v1/pricing/actions/{action}` [#put-apiv1pricingactionsaction] Set pricing for an action * Auth: bearer * Params: `None`, `action`\* * Body: object( `cost`\* (number) ) * operationId: `setPricingAction` ```yaml put: operationId: setPricingAction summary: Set pricing for an action tags: - Billing security: - moneyAdminAuth: [] parameters: - $ref: '#/components/parameters/MoneyTenantIdHeader' - name: action in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object required: - cost properties: cost: type: number responses: '200': description: Pricing updated content: application/json: schema: type: object '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' ``` ### `GET /api/v1/plans` [#get-apiv1plans] List available subscription plans * Auth: bearer * operationId: `listPlans` ```yaml get: operationId: listPlans summary: List available subscription plans tags: - Billing responses: '200': description: Plan list content: application/json: schema: type: object properties: plans: type: array items: type: object properties: id: type: string name: type: string credits: type: number price: type: number ``` ### `GET /api/v1/subscription` [#get-apiv1subscription] Get current subscription * Auth: bearer * Params: `None` * operationId: `getSubscription` ```yaml get: operationId: getSubscription summary: Get current subscription tags: - Billing parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Subscription details content: application/json: schema: type: object properties: plan_id: type: string status: type: string current_period_end: type: string format: date-time '401': $ref: '#/components/responses/Unauthorized' ``` ### `PUT /api/v1/subscription` [#put-apiv1subscription] Update subscription plan * Auth: bearer * Params: `None` * Body: object( `plan_id` (string) ) * operationId: `updateSubscription` ```yaml put: operationId: updateSubscription summary: Update subscription plan tags: - Billing security: - moneyAdminAuth: [] parameters: - $ref: '#/components/parameters/MoneyTenantIdHeader' requestBody: required: true content: application/json: schema: type: object properties: plan_id: type: string responses: '200': description: Subscription updated content: application/json: schema: type: object '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' ``` ### `POST /api/v1/subscription/grant` [#post-apiv1subscriptiongrant] Grant legacy Stripe invoice credits idempotently — Compatibility endpoint for older Stripe contracts with monthly credits. Writes a credit\_grant event with source stripe:invoice and source\_id equal to invoice\_id. It does not activate or change the subscription itself. * Auth: bearer * Params: `None` * Body: SubscriptionCreditGrantRequest * operationId: `grantSubscriptionCredits` ```yaml post: operationId: grantSubscriptionCredits summary: Grant legacy Stripe invoice credits idempotently description: 'Compatibility endpoint for older Stripe contracts with monthly credits. Writes a credit_grant event with source stripe:invoice and source_id equal to invoice_id. It does not activate or change the subscription itself. ' tags: - Billing security: - moneyAdminAuth: [] parameters: - $ref: '#/components/parameters/MoneyTenantIdHeader' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/SubscriptionCreditGrantRequest' responses: '200': description: Credits granted once, or an identical invoice replay skipped content: application/json: schema: $ref: '#/components/schemas/SubscriptionCreditGrantResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/BillingConflict' '422': $ref: '#/components/responses/BillingUnprocessable' ``` ### `POST /api/v1/billing/events/apply` [#post-apiv1billingeventsapply] Apply a verified billing event idempotently — Applies an externally verified billing effect in one tenant-scoped transaction. The tenant row is locked before replay lookup and before any subscription lock. Subscription events update entitlement/quota; credit\_grant updates only balance and ledger and returns subscription null. Older periods are journaled as immutable stale no-ops. The final non-null result is inserted once with the event after all effects are built; a global source-key or settlement-proof conflict rolls back every effect. Payment verification and private signing material stay outside this API. * Auth: bearer * Params: `None` * Body: BillingEventApplyRequest * operationId: `applyBillingEvent` ```yaml post: operationId: applyBillingEvent summary: Apply a verified billing event idempotently description: 'Applies an externally verified billing effect in one tenant-scoped transaction. The tenant row is locked before replay lookup and before any subscription lock. Subscription events update entitlement/quota; credit_grant updates only balance and ledger and returns subscription null. Older periods are journaled as immutable stale no-ops. The final non-null result is inserted once with the event after all effects are built; a global source-key or settlement-proof conflict rolls back every effect. Payment verification and private signing material stay outside this API. ' tags: - Billing security: - moneyAdminAuth: [] parameters: - $ref: '#/components/parameters/MoneyTenantIdHeader' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/BillingEventApplyRequest' responses: '200': description: Event applied once or returned as an identical replay content: application/json: schema: $ref: '#/components/schemas/BillingEventApplyResult' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/BillingConflict' '422': $ref: '#/components/responses/BillingUnprocessable' ``` ### `GET /api/v1/billing/events` [#get-apiv1billingevents] Find tenant billing events for reconciliation — Admin-only, tenant-scoped journal lookup. Supply event\_id, the complete source/source\_id pair, or provider\_subscription\_id. Combined selectors use AND. Results are ordered by created\_at descending and never expose another tenant's event. * Auth: bearer * Params: `None`, `event_id`, `source`, `source_id`, `provider_subscription_id`, `limit` * operationId: `findBillingEvents` ```yaml get: operationId: findBillingEvents summary: Find tenant billing events for reconciliation description: 'Admin-only, tenant-scoped journal lookup. Supply event_id, the complete source/source_id pair, or provider_subscription_id. Combined selectors use AND. Results are ordered by created_at descending and never expose another tenant''s event. ' tags: - Billing security: - moneyAdminAuth: [] parameters: - $ref: '#/components/parameters/MoneyTenantIdHeader' - name: event_id in: query schema: type: string format: uuid - name: source in: query description: Must be supplied together with source_id. schema: type: string maxLength: 128 - name: source_id in: query description: Must be supplied together with source. schema: type: string maxLength: 512 - name: provider_subscription_id in: query schema: type: string maxLength: 512 - name: limit in: query schema: type: integer minimum: 1 maximum: 50 default: 20 responses: '200': description: Matching tenant billing events content: application/json: schema: $ref: '#/components/schemas/BillingEventsResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' ``` ## Canonical [#canonical] ### `POST /api/v1/documents/{id}/canonical` [#post-apiv1documentsidcanonical] Mark a document as canonical * Auth: bearer * Params: `None`, `id`\* * Body: object( `canonical` (boolean) ) * operationId: `setCanonical` ```yaml post: operationId: setCanonical summary: Mark a document as canonical tags: - Canonical parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object properties: canonical: type: boolean responses: '200': description: Canonical status set content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /api/v1/documents/{id}/suggest-filters` [#post-apiv1documentsidsuggest-filters] Suggest retrieval filters for a document * Auth: bearer * Params: `None`, `id`\* * operationId: `suggestFilters` ```yaml post: operationId: suggestFilters summary: Suggest retrieval filters for a document tags: - Canonical parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string responses: '200': description: Suggested filters content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /api/v1/documents/{id}/probes` [#post-apiv1documentsidprobes] Register a validation probe for a document * Auth: bearer * Params: `None`, `id`\* * operationId: `registerProbe` ```yaml post: operationId: registerProbe summary: Register a validation probe for a document tags: - Canonical parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string responses: '200': description: Probe registered content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /api/v1/conflicts` [#get-apiv1conflicts] List canonical conflicts * Auth: bearer * Params: `None` * operationId: `listConflicts` ```yaml get: operationId: listConflicts summary: List canonical conflicts tags: - Canonical parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Conflict list content: application/json: schema: type: object properties: conflicts: type: array items: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /api/v1/proposals` [#get-apiv1proposals] List update proposals * Auth: bearer * Params: `None` * operationId: `listProposals` ```yaml get: operationId: listProposals summary: List update proposals tags: - Canonical parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Proposal list content: application/json: schema: type: object properties: proposals: type: array items: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /api/v1/proposals/{id}/pick` [#post-apiv1proposalsidpick] Pick a proposal variant * Auth: bearer * Params: `None`, `id`\* * Body: object( `variant` (string) ) * operationId: `pickProposal` ```yaml post: operationId: pickProposal summary: Pick a proposal variant tags: - Canonical parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object properties: variant: type: string responses: '200': description: Proposal picked content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /api/v1/proposals/{id}/resolve` [#post-apiv1proposalsidresolve] Resolve a proposal * Auth: bearer * Params: `None`, `id`\* * Body: object( `status` (string) ) * operationId: `resolveProposal` ```yaml post: operationId: resolveProposal summary: Resolve a proposal tags: - Canonical parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object properties: status: type: string responses: '200': description: Proposal resolved content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /api/v1/probes` [#get-apiv1probes] List validation probes * Auth: bearer * Params: `None` * operationId: `listProbes` ```yaml get: operationId: listProbes summary: List validation probes tags: - Canonical parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Probe list content: application/json: schema: type: object properties: probes: type: array items: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /api/v1/canonical/run` [#post-apiv1canonicalrun] Trigger canonical detection run * Auth: bearer * Params: `None` * operationId: `canonicalRun` ```yaml post: operationId: canonicalRun summary: Trigger canonical detection run tags: - Canonical parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Canonical run initiated content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /api/v1/canonical/sources` [#get-apiv1canonicalsources] List canonical sources * Auth: bearer * Params: `None` * operationId: `listCanonicalSources` ```yaml get: operationId: listCanonicalSources summary: List canonical sources tags: - Canonical parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Source list content: application/json: schema: type: object properties: sources: type: array items: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ## Documents [#documents] ### `POST /documents` [#post-documents] Ingest a document — Create or update a document in a collection. Supports quality gate evaluation, schema packs, auto-linking, and temporal metadata. Requires X-Tenant-ID. * Auth: bearer * Params: `None` * Body: object( `collection`\* (string), `path`\* (string), `title` (string), `content`\* (string), `content_type` (string), `confidence` (number), `quality_score` (number), `metadata` (object( )), `user_id` (string), `run_id` (string), `event_at` (string), `event_type` (string) ) * operationId: `ingestDocument` ```yaml post: operationId: ingestDocument summary: Ingest a document description: 'Create or update a document in a collection. Supports quality gate evaluation, schema packs, auto-linking, and temporal metadata. Requires X-Tenant-ID. ' tags: - Documents parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - collection - path - content properties: collection: type: string description: Collection name path: type: string description: Unique document path within the collection title: type: string content: type: string maxLength: 1000000 description: Document body (max 1MB) content_type: type: string default: note confidence: type: number minimum: 0 maximum: 1 default: 0.5 quality_score: type: number minimum: 0 maximum: 1 default: 0.5 metadata: type: object additionalProperties: true user_id: type: string run_id: type: string event_at: type: string format: date-time event_type: type: string responses: '200': description: Document ingested content: application/json: schema: type: object properties: ok: type: boolean id: type: integer path: type: string hash: type: string embed_state: type: string gate_verdict: type: object properties: shouldIndex: type: boolean reason: type: string '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /documents` [#get-documents] List documents — List documents with optional filtering by collection. * Auth: bearer * Params: `None`, `collection`, `limit`, `offset` * operationId: `listDocuments` ```yaml get: operationId: listDocuments summary: List documents description: List documents with optional filtering by collection. tags: - Documents parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: collection in: query schema: type: string - name: limit in: query schema: type: integer default: 50 - name: offset in: query schema: type: integer default: 0 responses: '200': description: List of documents content: application/json: schema: type: object properties: documents: type: array items: $ref: '#/components/schemas/Document' total: type: integer '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /documents/{id}` [#get-documentsid] Get a document by ID or hash * Auth: bearer * Params: `None`, `id`\* * operationId: `getDocument` ```yaml get: operationId: getDocument summary: Get a document by ID or hash tags: - Documents parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string description: Document ID or hash responses: '200': description: Document details content: application/json: schema: $ref: '#/components/schemas/Document' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' ``` ### `PATCH /documents/{id}/visibility` [#patch-documentsidvisibility] Update document visibility * Auth: bearer * Params: `None`, `id`\* * Body: object( `visibility`\* (string) ) * operationId: `patchDocumentVisibility` ```yaml patch: operationId: patchDocumentVisibility summary: Update document visibility tags: - Documents parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object required: - visibility properties: visibility: type: string responses: '200': description: Visibility updated content: application/json: schema: type: object properties: ok: type: boolean '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' ``` ### `POST /documents/{id}/pin` [#post-documentsidpin] Pin a document for permanent prioritization * Auth: bearer * Params: `None`, `id`\* * operationId: `pinDocument` ```yaml post: operationId: pinDocument summary: Pin a document for permanent prioritization tags: - Documents parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string responses: '200': description: Document pinned content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /documents/{id}/snooze` [#post-documentsidsnooze] Temporarily hide a document from context * Auth: bearer * Params: `None`, `id`\* * Body: object( `until` (string) ) * operationId: `snoozeDocument` ```yaml post: operationId: snoozeDocument summary: Temporarily hide a document from context tags: - Documents parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string requestBody: content: application/json: schema: type: object properties: until: type: string format: date-time responses: '200': description: Document snoozed content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /documents/{id}/forget` [#post-documentsidforget] Permanently deactivate a document * Auth: bearer * Params: `None`, `id`\* * operationId: `forgetDocument` ```yaml post: operationId: forgetDocument summary: Permanently deactivate a document tags: - Documents parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string responses: '200': description: Document forgotten content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /documents/{id}/feedback` [#post-documentsidfeedback] Submit relevance feedback for a document * Auth: bearer * Params: `None`, `id`\* * Body: object( `relevance`\* (enum(positive, negative)) ) * operationId: `documentFeedback` ```yaml post: operationId: documentFeedback summary: Submit relevance feedback for a document tags: - Documents parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object required: - relevance properties: relevance: type: string enum: - positive - negative responses: '200': description: Feedback recorded content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' ``` ### `DELETE /documents/purge` [#delete-documentspurge] Purge documents by collection — Delete all documents in a collection (exact or prefix match). Cleans up vectors, triples, and orphan records. Requires X-Tenant-ID. * Auth: bearer * Params: `None`, `collection`, `collection_prefix` * operationId: `purgeDocuments` ```yaml delete: operationId: purgeDocuments summary: Purge documents by collection description: 'Delete all documents in a collection (exact or prefix match). Cleans up vectors, triples, and orphan records. Requires X-Tenant-ID. ' tags: - Documents parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: collection in: query schema: type: string description: Exact collection name - name: collection_prefix in: query schema: type: string description: Collection name prefix (LIKE match) responses: '200': description: Purge result content: application/json: schema: type: object properties: purged: type: integer orphan_vectors_cleaned: type: integer orphan_triples_cleaned: type: integer '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /timeline/{id}` [#get-timelineid] Temporal neighborhood around a document * Auth: bearer * Params: `None`, `id`\*, `before`, `after` * operationId: `timeline` ```yaml get: operationId: timeline summary: Temporal neighborhood around a document tags: - Documents parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string - name: before in: query schema: type: integer default: 5 - name: after in: query schema: type: integer default: 5 responses: '200': description: Timeline context content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /sessions` [#get-sessions] List recent sessions * Auth: bearer * Params: `None` * operationId: `listSessions` ```yaml get: operationId: listSessions summary: List recent sessions tags: - Documents parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Session list content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /collections` [#get-collections] List all collections * Auth: bearer * Params: `None` * operationId: `listCollections` ```yaml get: operationId: listCollections summary: List all collections tags: - Documents parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Collection list content: application/json: schema: type: object properties: collections: type: array items: type: object properties: name: type: string count: type: integer '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /profile` [#get-profile] Get current tenant/user profile * Auth: bearer * Params: `None` * operationId: `getProfile` ```yaml get: operationId: getProfile summary: Get current tenant/user profile tags: - Documents parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Profile data content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /export` [#get-export] Export documents * Auth: bearer * Params: `None`, `collection`, `format` * operationId: `exportData` ```yaml get: operationId: exportData summary: Export documents tags: - Documents parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: collection in: query schema: type: string - name: format in: query schema: type: string enum: - json - markdown default: json responses: '200': description: Exported data content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ## Entity [#entity] ### `GET /api/v1/entities/{name}/card` [#get-apiv1entitiesnamecard] Get entity card by name * Auth: bearer * Params: `None`, `name`\* * operationId: `getEntityCard` ```yaml get: operationId: getEntityCard summary: Get entity card by name tags: - Entity parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: name in: path required: true schema: type: string description: Entity name responses: '200': description: Entity card content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' ``` ### `POST /api/v1/entities/{name}/card` [#post-apiv1entitiesnamecard] Create or update an entity card * Auth: bearer * Params: `None`, `name`\* * Body: object( `summary` (string), `aliases` (array\[string]), `metadata` (object( )) ) * operationId: `upsertEntityCard` ```yaml post: operationId: upsertEntityCard summary: Create or update an entity card tags: - Entity parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: name in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object properties: summary: type: string aliases: type: array items: type: string metadata: type: object additionalProperties: true responses: '200': description: Entity card upserted content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /api/v1/triples` [#post-apiv1triples] Create an SPO triple — Create a subject-predicate-object triple. Resolves entity names to IDs. * Auth: bearer * Params: `None` * Body: object( `subject`\* (string), `predicate`\* (string), `object`\* (string), `confidence` (number) ) * operationId: `createTriple` ```yaml post: operationId: createTriple summary: Create an SPO triple description: Create a subject-predicate-object triple. Resolves entity names to IDs. tags: - Entity parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - subject - predicate - object properties: subject: type: string predicate: type: string object: type: string confidence: type: number default: 0.8 responses: '200': description: Triple created content: application/json: schema: type: object properties: ok: type: boolean triple: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ## Foundations [#foundations] ### `GET /foundations` [#get-foundations] Get Tier-0 foundation context * Auth: bearer * Params: `None` * operationId: `getFoundations` ```yaml get: operationId: getFoundations summary: Get Tier-0 foundation context tags: - Foundations parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Foundation documents content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /api/v1/state` [#get-apiv1state] Get structured engine state * Auth: bearer * Params: `None` * operationId: `getState` ```yaml get: operationId: getState summary: Get structured engine state tags: - Foundations parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Structured state content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /api/v1/foundations` [#post-apiv1foundations] Create a foundation document * Auth: bearer * Params: `None` * Body: object( `path`\* (string), `content`\* (string), `title` (string), `layer` (string) ) * operationId: `createFoundation` ```yaml post: operationId: createFoundation summary: Create a foundation document tags: - Foundations parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - path - content properties: path: type: string content: type: string title: type: string layer: type: string responses: '200': description: Foundation created content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' ``` ### `PUT /api/v1/foundations/{id}` [#put-apiv1foundationsid] Update a foundation document * Auth: bearer * Params: `None`, `id`\* * Body: object( `content` (string), `title` (string) ) * operationId: `updateFoundation` ```yaml put: operationId: updateFoundation summary: Update a foundation document tags: - Foundations parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object properties: content: type: string title: type: string responses: '200': description: Foundation updated content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' ``` ### `DELETE /api/v1/foundations/{id}` [#delete-apiv1foundationsid] Delete a foundation document * Auth: bearer * Params: `None`, `id`\* * operationId: `deleteFoundation` ```yaml delete: operationId: deleteFoundation summary: Delete a foundation document tags: - Foundations parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string responses: '200': description: Foundation deleted content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' ``` ### `POST /api/v1/foundations/{id}/promote` [#post-apiv1foundationsidpromote] Promote a foundation to a higher layer * Auth: bearer * Params: `None`, `id`\* * operationId: `promoteFoundation` ```yaml post: operationId: promoteFoundation summary: Promote a foundation to a higher layer tags: - Foundations parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string responses: '200': description: Foundation promoted content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' ``` ## Graph [#graph] ### `GET /graph/causal/{id}` [#get-graphcausalid] Get causal links for a document * Auth: bearer * Params: `None`, `id`\*, `direction`, `depth` * operationId: `getCausalLinks` ```yaml get: operationId: getCausalLinks summary: Get causal links for a document tags: - Graph parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string - name: direction in: query schema: type: string enum: - causes - caused_by - both default: both - name: depth in: query schema: type: integer default: 5 minimum: 1 maximum: 10 responses: '200': description: Causal link graph content: application/json: schema: type: object properties: links: type: array items: type: object properties: docid: type: string direction: type: string depth: type: integer reasoning: type: string '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /graph/similar/{id}` [#get-graphsimilarid] Find semantically similar documents * Auth: bearer * Params: `None`, `id`\*, `limit` * operationId: `getSimilar` ```yaml get: operationId: getSimilar summary: Find semantically similar documents tags: - Graph parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string - name: limit in: query schema: type: integer default: 5 responses: '200': description: Similar documents content: application/json: schema: type: object properties: similar: type: array items: $ref: '#/components/schemas/SearchResult' '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /graph/evolution/{id}` [#get-graphevolutionid] Get memory evolution timeline for a document * Auth: bearer * Params: `None`, `id`\*, `limit` * operationId: `getEvolution` ```yaml get: operationId: getEvolution summary: Get memory evolution timeline for a document tags: - Graph parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string - name: limit in: query schema: type: integer default: 10 responses: '200': description: Evolution timeline content: application/json: schema: type: object properties: evolution: type: array items: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ## Health [#health] ### `GET /healthz` [#get-healthz] Public liveness probe — Returns 200 if the process is up. No auth, no store dependency. * Auth: none * operationId: `healthz` ```yaml get: operationId: healthz summary: Public liveness probe description: Returns 200 if the process is up. No auth, no store dependency. tags: - Health security: [] responses: '200': description: Process is alive content: application/json: schema: type: object required: - status - service - timestamp properties: status: type: string enum: - ok service: type: string timestamp: type: string format: date-time ``` ### `GET /health` [#get-health] Health check with database status — Returns service status, document counts, vector index state, and request context. * Auth: none * operationId: `health` ```yaml get: operationId: health summary: Health check with database status description: Returns service status, document counts, vector index state, and request context. tags: - Health security: [] responses: '200': description: Service health content: application/json: schema: type: object required: - status - service properties: status: type: string service: type: string version: type: string database: type: string documents: type: integer needsEmbedding: type: integer hasVectors: type: boolean request: $ref: '#/components/schemas/RequestContext' ``` ### `GET /health/deep` [#get-healthdeep] Deep health check with per-component probes — Probes database, documents, LLM config, and embed worker. Used by uptime monitors. * Auth: none * operationId: `healthDeep` ```yaml get: operationId: healthDeep summary: Deep health check with per-component probes description: Probes database, documents, LLM config, and embed worker. Used by uptime monitors. tags: - Health security: [] responses: '200': description: Component-level health content: application/json: schema: type: object required: - checks properties: checks: type: object additionalProperties: type: object required: - ok properties: ok: type: boolean latency_ms: type: integer detail: type: string error: type: string latency_ms: type: integer ``` ### `GET /state` [#get-state] Engine state summary * Auth: bearer * operationId: `state` ```yaml get: operationId: state summary: Engine state summary tags: - Health responses: '200': description: State object content: application/json: schema: type: object ``` ### `GET /stats` [#get-stats] Index statistics and health * Auth: bearer * operationId: `stats` ```yaml get: operationId: stats summary: Index statistics and health tags: - Health responses: '200': description: Stats including document counts, collections, and health content: application/json: schema: type: object properties: documents: type: integer totalDocuments: type: integer needsEmbedding: type: integer collections: type: array items: type: object health: type: object ``` ### `GET /reports/memory` [#get-reportsmemory] Memory usage report — Tenant-scoped memory report. Requires X-Tenant-ID. * Auth: bearer * Params: `None` * operationId: `reportsMemory` ```yaml get: operationId: reportsMemory summary: Memory usage report description: Tenant-scoped memory report. Requires X-Tenant-ID. tags: - Health parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Memory report content: application/json: schema: type: object '400': $ref: '#/components/responses/BadRequest' ``` ### `GET /openapi.json` [#get-openapijson] OpenAPI 3.1 specification (JSON) — Returns the full API specification as JSON. * Auth: none * operationId: `openapiSpec` ```yaml get: operationId: openapiSpec summary: OpenAPI 3.1 specification (JSON) description: Returns the full API specification as JSON. tags: - Health security: [] responses: '200': description: OpenAPI specification content: application/json: schema: type: object ``` ## Identity [#identity] ### `GET /api/v1/identity` [#get-apiv1identity] Get current identity * Auth: bearer * Params: `None` * operationId: `getIdentity` ```yaml get: operationId: getIdentity summary: Get current identity tags: - Identity parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Identity profile content: application/json: schema: type: object properties: id: type: string name: type: string email: type: string tenant_id: type: string '401': $ref: '#/components/responses/Unauthorized' ``` ### `PUT /api/v1/identity` [#put-apiv1identity] Update current identity * Auth: bearer * Params: `None` * Body: object( `name` (string), `email` (string), `preferences` (object( )) ) * operationId: `updateIdentity` ```yaml put: operationId: updateIdentity summary: Update current identity tags: - Identity parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object properties: name: type: string email: type: string preferences: type: object responses: '200': description: Identity updated content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ## Lifecycle [#lifecycle] ### `GET /lifecycle/status` [#get-lifecyclestatus] Document lifecycle status * Auth: bearer * Params: `None` * operationId: `lifecycleStatus` ```yaml get: operationId: lifecycleStatus summary: Document lifecycle status tags: - Lifecycle parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Lifecycle statistics content: application/json: schema: type: object properties: active: type: integer archived: type: integer forgotten: type: integer pinned: type: integer snoozed: type: integer '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /lifecycle/sweep` [#post-lifecyclesweep] Run lifecycle sweep — Archive stale docs, optionally purge old archives. Defaults to dry run. * Auth: bearer * Params: `None` * Body: object( `dry_run` (boolean) ) * operationId: `lifecycleSweep` ```yaml post: operationId: lifecycleSweep summary: Run lifecycle sweep description: Archive stale docs, optionally purge old archives. Defaults to dry run. tags: - Lifecycle parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: content: application/json: schema: type: object properties: dry_run: type: boolean default: true responses: '200': description: Sweep result content: application/json: schema: type: object properties: dry_run: type: boolean to_archive: type: integer to_purge: type: integer '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /lifecycle/restore` [#post-lifecyclerestore] Restore archived documents * Auth: bearer * Params: `None` * Body: object( `query` (string), `collection` (string), `all` (boolean) ) * operationId: `lifecycleRestore` ```yaml post: operationId: lifecycleRestore summary: Restore archived documents tags: - Lifecycle parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: content: application/json: schema: type: object properties: query: type: string collection: type: string all: type: boolean default: false responses: '200': description: Restore result content: application/json: schema: type: object properties: restored: type: integer '401': $ref: '#/components/responses/Unauthorized' ``` ## MCP Tokens [#mcp-tokens] ### `GET /api/v1/mcp/tokens` [#get-apiv1mcptokens] List MCP API tokens * Auth: bearer * Params: `None` * operationId: `listMcpTokens` ```yaml get: operationId: listMcpTokens summary: List MCP API tokens tags: - MCP Tokens parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Token list content: application/json: schema: type: object properties: tokens: type: array items: type: object properties: id: type: string name: type: string prefix: type: string is_active: type: boolean created_at: type: string format: date-time '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /api/v1/mcp/tokens` [#post-apiv1mcptokens] Create an MCP API token * Auth: bearer * Params: `None` * Body: object( `name`\* (string), `expires_at` (string) ) * operationId: `createMcpToken` ```yaml post: operationId: createMcpToken summary: Create an MCP API token tags: - MCP Tokens parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - name properties: name: type: string expires_at: type: string format: date-time responses: '200': description: Token created (full key returned only once) content: application/json: schema: type: object properties: ok: type: boolean id: type: string key: type: string description: Full API key (shown only at creation) '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /api/v1/mcp/tokens/{tokenId}` [#get-apiv1mcptokenstokenid] Get MCP token details * Auth: bearer * Params: `None`, `tokenId`\* * operationId: `getMcpToken` ```yaml get: operationId: getMcpToken summary: Get MCP token details tags: - MCP Tokens parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: tokenId in: path required: true schema: type: string responses: '200': description: Token details content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' ``` ### `PUT /api/v1/mcp/tokens/{tokenId}` [#put-apiv1mcptokenstokenid] Update MCP token * Auth: bearer * Params: `None`, `tokenId`\* * Body: object( `name` (string), `is_active` (boolean) ) * operationId: `updateMcpToken` ```yaml put: operationId: updateMcpToken summary: Update MCP token tags: - MCP Tokens parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: tokenId in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object properties: name: type: string is_active: type: boolean responses: '200': description: Token updated content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' ``` ### `DELETE /api/v1/mcp/tokens/{tokenId}` [#delete-apiv1mcptokenstokenid] Delete MCP token * Auth: bearer * Params: `None`, `tokenId`\* * operationId: `deleteMcpToken` ```yaml delete: operationId: deleteMcpToken summary: Delete MCP token tags: - MCP Tokens parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: tokenId in: path required: true schema: type: string responses: '200': description: Token deleted content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' ``` ## Maintenance [#maintenance] ### `POST /reindex` [#post-reindex] Trigger full reindex — Re-scan all collections, detect new/changed/deleted documents. * Auth: bearer * Params: `None` * operationId: `reindex` ```yaml post: operationId: reindex summary: Trigger full reindex description: Re-scan all collections, detect new/changed/deleted documents. tags: - Maintenance parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Reindex initiated content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /graphs/build` [#post-graphsbuild] Build temporal and semantic graphs * Auth: bearer * Params: `None` * Body: object( `graph_types` (array\[enum(temporal, semantic, all)]) ) * operationId: `buildGraphs` ```yaml post: operationId: buildGraphs summary: Build temporal and semantic graphs tags: - Maintenance parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: content: application/json: schema: type: object properties: graph_types: type: array items: type: string enum: - temporal - semantic - all semantic_threshold: type: number default: 0.7 responses: '200': description: Graph build initiated content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /api/v1/collection-settings` [#get-apiv1collection-settings] List all collection settings * Auth: bearer * Params: `None` * operationId: `listCollectionSettings` ```yaml get: operationId: listCollectionSettings summary: List all collection settings tags: - Maintenance parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Settings list content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /api/v1/collection-settings/reindex` [#get-apiv1collection-settingsreindex] Re-evaluate documents against quality gate rules * Auth: bearer * Params: `None` * operationId: `reindexCollectionSettings` ```yaml get: operationId: reindexCollectionSettings summary: Re-evaluate documents against quality gate rules tags: - Maintenance parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Reindex result content: application/json: schema: type: object properties: ok: type: boolean collection: type: string dry_run: type: boolean total_docs: type: integer to_skip: type: integer to_index: type: integer '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /api/v1/collection-settings/reindex` [#post-apiv1collection-settingsreindex] Re-evaluate documents against quality gate rules (POST) * Auth: bearer * Params: `None` * Body: object( `collection`\* (string), `dry_run` (boolean) ) * operationId: `reindexCollectionSettingsPost` ```yaml post: operationId: reindexCollectionSettingsPost summary: Re-evaluate documents against quality gate rules (POST) tags: - Maintenance parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - collection properties: collection: type: string dry_run: type: boolean default: false responses: '200': description: Reindex result content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /api/v1/collection-settings/{collection}` [#get-apiv1collection-settingscollection] Get settings for a collection * Auth: bearer * Params: `None`, `collection`\* * operationId: `getCollectionSettings` ```yaml get: operationId: getCollectionSettings summary: Get settings for a collection tags: - Maintenance parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: collection in: path required: true schema: type: string responses: '200': description: Collection settings content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' ``` ### `PUT /api/v1/collection-settings/{collection}` [#put-apiv1collection-settingscollection] Set settings for a collection * Auth: bearer * Params: `None`, `collection`\* * Body: object( `max_doc_size` (integer), `skip_patterns` (array\[string]), `min_quality_score` (number) ) * operationId: `setCollectionSettings` ```yaml put: operationId: setCollectionSettings summary: Set settings for a collection tags: - Maintenance parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: collection in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object properties: max_doc_size: type: integer skip_patterns: type: array items: type: string min_quality_score: type: number responses: '200': description: Settings updated content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' ``` ### `DELETE /api/v1/collection-settings/{collection}` [#delete-apiv1collection-settingscollection] Delete settings for a collection * Auth: bearer * Params: `None`, `collection`\* * operationId: `deleteCollectionSettings` ```yaml delete: operationId: deleteCollectionSettings summary: Delete settings for a collection tags: - Maintenance parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: collection in: path required: true schema: type: string responses: '200': description: Settings deleted content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /generate` [#post-generate] LLM text generation (benchmark only) — Exposes the engine's local LLM as a simple text generation API. Benchmark tooling only. * Auth: bearer * Body: object( `prompt`\* (string), `maxTokens` (integer), `temperature` (number) ) * operationId: `generate` ```yaml post: operationId: generate summary: LLM text generation (benchmark only) description: Exposes the engine's local LLM as a simple text generation API. Benchmark tooling only. tags: - Maintenance requestBody: required: true content: application/json: schema: type: object required: - prompt properties: prompt: type: string maxTokens: type: integer default: 512 maximum: 2048 temperature: type: number minimum: 0 maximum: 2 responses: '200': description: Generated text content: application/json: schema: type: object properties: text: type: string model: type: string tokens: type: integer '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /skills` [#get-skills] List registered skills * Auth: bearer * operationId: `listSkills` ```yaml get: operationId: listSkills summary: List registered skills tags: - Maintenance responses: '200': description: Skill list content: application/json: schema: type: object properties: skills: type: array items: type: object ``` ### `POST /skills` [#post-skills] Register a new skill * Auth: bearer * Body: object( `name`\* (string), `description` (string), `handler` (string) ) * operationId: `addSkill` ```yaml post: operationId: addSkill summary: Register a new skill tags: - Maintenance requestBody: required: true content: application/json: schema: type: object required: - name properties: name: type: string description: type: string handler: type: string responses: '200': description: Skill registered content: application/json: schema: type: object properties: ok: type: boolean ``` ### `GET /skills/{skillId}` [#get-skillsskillid] Get skill details * Auth: bearer * Params: `skillId`\* * operationId: `getSkill` ```yaml get: operationId: getSkill summary: Get skill details tags: - Maintenance parameters: - name: skillId in: path required: true schema: type: string responses: '200': description: Skill details content: application/json: schema: type: object '404': $ref: '#/components/responses/NotFound' ``` ### `GET /setup/instructions` [#get-setupinstructions] Get setup instructions (public) * Auth: none * operationId: `setupInstructions` ```yaml get: operationId: setupInstructions summary: Get setup instructions (public) tags: - Maintenance security: [] responses: '200': description: Setup instructions content: application/json: schema: type: object ``` ## OAuth [#oauth] ### `GET /.well-known/oauth-authorization-server` [#get-well-knownoauth-authorization-server] OAuth authorization server metadata — Public discovery endpoint per RFC 9414. * Auth: none * operationId: `oauthAsMetadata` ```yaml get: operationId: oauthAsMetadata summary: OAuth authorization server metadata description: Public discovery endpoint per RFC 9414. tags: - OAuth security: [] responses: '200': description: Authorization server metadata content: application/json: schema: type: object ``` ### `GET /.well-known/oauth-protected-resource` [#get-well-knownoauth-protected-resource] OAuth protected resource metadata — Public discovery endpoint per RFC 9728. * Auth: none * operationId: `oauthRsMetadata` ```yaml get: operationId: oauthRsMetadata summary: OAuth protected resource metadata description: Public discovery endpoint per RFC 9728. tags: - OAuth security: [] responses: '200': description: Protected resource metadata content: application/json: schema: type: object ``` ### `POST /oauth/register` [#post-oauthregister] Dynamic client registration * Auth: none * Body: object( `client_name` (string), `redirect_uris` (array\[string]), `grant_types` (array\[string]) ) * operationId: `oauthRegister` ```yaml post: operationId: oauthRegister summary: Dynamic client registration tags: - OAuth security: [] requestBody: required: true content: application/json: schema: type: object properties: client_name: type: string redirect_uris: type: array items: type: string grant_types: type: array items: type: string responses: '201': description: Client registered content: application/json: schema: type: object properties: client_id: type: string client_secret: type: string '400': $ref: '#/components/responses/BadRequest' ``` ### `GET /oauth/authorize` [#get-oauthauthorize] OAuth authorization endpoint — Redirects to consent page. * Auth: none * Params: `response_type`*, `client_id`*, `redirect_uri`, `scope`, `state` * operationId: `oauthAuthorize` ```yaml get: operationId: oauthAuthorize summary: OAuth authorization endpoint description: Redirects to consent page. tags: - OAuth security: [] parameters: - name: response_type in: query required: true schema: type: string - name: client_id in: query required: true schema: type: string - name: redirect_uri in: query schema: type: string - name: scope in: query schema: type: string - name: state in: query schema: type: string responses: '302': description: Redirect to consent page '400': $ref: '#/components/responses/BadRequest' ``` ### `GET /oauth/consent` [#get-oauthconsent] OAuth consent page * Auth: none * operationId: `oauthConsentPage` ```yaml get: operationId: oauthConsentPage summary: OAuth consent page tags: - OAuth security: [] responses: '200': description: HTML consent form ``` ### `POST /oauth/consent` [#post-oauthconsent] Submit OAuth consent * Auth: none * operationId: `oauthConsentSubmit` ```yaml post: operationId: oauthConsentSubmit summary: Submit OAuth consent tags: - OAuth security: [] requestBody: required: true content: application/x-www-form-urlencoded: schema: type: object responses: '302': description: Redirect back to client ``` ### `POST /oauth/token` [#post-oauthtoken] OAuth token exchange * Auth: none * operationId: `oauthToken` ```yaml post: operationId: oauthToken summary: OAuth token exchange tags: - OAuth security: [] requestBody: required: true content: application/x-www-form-urlencoded: schema: type: object required: - grant_type properties: grant_type: type: string code: type: string client_id: type: string client_secret: type: string redirect_uri: type: string responses: '200': description: Token response content: application/json: schema: type: object properties: access_token: type: string token_type: type: string expires_in: type: integer refresh_token: type: string '400': $ref: '#/components/responses/BadRequest' ``` ### `POST /oauth/revoke` [#post-oauthrevoke] Revoke an OAuth token * Auth: none * operationId: `oauthRevoke` ```yaml post: operationId: oauthRevoke summary: Revoke an OAuth token tags: - OAuth security: [] requestBody: required: true content: application/x-www-form-urlencoded: schema: type: object required: - token properties: token: type: string responses: '200': description: Token revoked ``` ## Observability [#observability] ### `GET /metrics` [#get-metrics] Prometheus metrics — Public endpoint for Prometheus scraping. Low cardinality. * Auth: none * operationId: `metrics` ```yaml get: operationId: metrics summary: Prometheus metrics description: Public endpoint for Prometheus scraping. Low cardinality. tags: - Observability security: [] responses: '200': description: Prometheus text format metrics content: text/plain: schema: type: string ``` ### `GET /api/v1/trajectories` [#get-apiv1trajectories] List retrieval trajectories * Auth: bearer * Params: `None` * operationId: `listTrajectories` ```yaml get: operationId: listTrajectories summary: List retrieval trajectories tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Trajectory list content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /api/v1/roi` [#get-apiv1roi] Get ROI metrics * Auth: bearer * Params: `None` * operationId: `getROI` ```yaml get: operationId: getROI summary: Get ROI metrics tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: ROI data content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /api/v1/digest/send` [#post-apiv1digestsend] Send email digest * Auth: bearer * Params: `None` * operationId: `sendDigest` ```yaml post: operationId: sendDigest summary: Send email digest tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Digest sent content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /api/v1/features` [#get-apiv1features] List feature flags * Auth: bearer * Params: `None` * operationId: `listFeatures` ```yaml get: operationId: listFeatures summary: List feature flags tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Feature flags content: application/json: schema: type: object properties: features: type: object additionalProperties: type: boolean '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /api/v1/features` [#post-apiv1features] Set a feature flag * Auth: bearer * Params: `None` * Body: object( `name`\* (string), `enabled`\* (boolean) ) * operationId: `setFeature` ```yaml post: operationId: setFeature summary: Set a feature flag tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - name - enabled properties: name: type: string enabled: type: boolean responses: '200': description: Feature flag updated content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /api/v1/config` [#get-apiv1config] Get tenant configuration * Auth: bearer * Params: `None` * operationId: `getTenantConfig` ```yaml get: operationId: getTenantConfig summary: Get tenant configuration tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Tenant config content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `PUT /api/v1/config/{key}` [#put-apiv1configkey] Set a tenant configuration key * Auth: bearer * Params: `None`, `key`\* * Body: object( ) * operationId: `setTenantConfigKey` ```yaml put: operationId: setTenantConfigKey summary: Set a tenant configuration key tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: key in: path required: true schema: type: string pattern: ^[a-zA-Z][a-zA-Z0-9_]*$ requestBody: required: true content: application/json: schema: type: object responses: '200': description: Config key updated content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /api/v1/criteria` [#get-apiv1criteria] Get retrieval criteria * Auth: bearer * Params: `None` * operationId: `getCriteria` ```yaml get: operationId: getCriteria summary: Get retrieval criteria tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Criteria list content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `PUT /api/v1/criteria` [#put-apiv1criteria] Set retrieval criteria * Auth: bearer * Params: `None` * Body: object( ) * operationId: `setCriteria` ```yaml put: operationId: setCriteria summary: Set retrieval criteria tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object responses: '200': description: Criteria updated content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /api/v1/benchmark/run` [#post-apiv1benchmarkrun] Run a benchmark * Auth: bearer * Params: `None` * Body: object( `queries` (array\[string]), `expected` (array\[object( )]) ) * operationId: `benchmarkRun` ```yaml post: operationId: benchmarkRun summary: Run a benchmark tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object properties: queries: type: array items: type: string expected: type: array items: type: object responses: '200': description: Benchmark results content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /api/v1/benchmark/runs` [#get-apiv1benchmarkruns] List benchmark runs * Auth: bearer * Params: `None` * operationId: `benchmarkListRuns` ```yaml get: operationId: benchmarkListRuns summary: List benchmark runs tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Benchmark run list content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /api/v1/benchmark/compare` [#get-apiv1benchmarkcompare] Compare benchmark runs * Auth: bearer * Params: `None`, `run_a`, `run_b` * operationId: `benchmarkCompare` ```yaml get: operationId: benchmarkCompare summary: Compare benchmark runs tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: run_a in: query schema: type: string - name: run_b in: query schema: type: string responses: '200': description: Comparison results content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /api/v1/memory/recall` [#post-apiv1memoryrecall] Token-budgeted memory recall — Pull category-ranked memory in a fixed token budget (mem0-style). * Auth: bearer * Params: `None` * Body: object( `query` (string), `budget` (integer), `format` (enum(json, markdown)) ) * operationId: `memoryRecall` ```yaml post: operationId: memoryRecall summary: Token-budgeted memory recall description: Pull category-ranked memory in a fixed token budget (mem0-style). tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object properties: query: type: string budget: type: integer default: 1500 format: type: string enum: - json - markdown default: markdown responses: '200': description: Budgeted memory recall content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /api/v1/memory/used` [#post-apiv1memoryused] Declare which memories an answer actually used (quality loop) — REST mirror of the MCP `memory_used` tool. The agent declares the docids ('#ab12cd' hex prefixes) or paths of the memories it relied on; optionally a verdict ("confirmed"/"corrected") when the user reacted to what the memory said. Feeds usage coverage, ranking signals and the trust loop. Infra agents excluded downstream. * Auth: bearer * Params: `None` * Body: object( `docids`\* (array\[string]), `verdict` (enum(confirmed, corrected)), `note` (string) ) * operationId: `memoryUsed` ```yaml post: operationId: memoryUsed summary: Declare which memories an answer actually used (quality loop) description: 'REST mirror of the MCP `memory_used` tool. The agent declares the docids (''#ab12cd'' hex prefixes) or paths of the memories it relied on; optionally a verdict ("confirmed"/"corrected") when the user reacted to what the memory said. Feeds usage coverage, ranking signals and the trust loop. Infra agents excluded downstream. ' tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - docids properties: docids: type: array items: type: string minItems: 1 description: Docids ('#ab12cd') or document paths verdict: type: string enum: - confirmed - corrected description: User confirmed or corrected what the memory said (V5) note: type: string description: Why the memories were useful responses: '200': description: Declaration recorded content: application/json: schema: type: object properties: declared: type: integer marked: type: integer unresolved: type: array items: type: string '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' ``` ### `GET /api/v1/tenant/value-summary` [#get-apiv1tenantvalue-summary] Counted value by usage family for the Impact home and digest — Hero numbers (searches served, contexts delivered, memories recorded), usage families, quality coverage (sessions with declared memory\_used over sessions with delivered context), active agents, knowledge timeline and per-operation breakdown. Completed days are served from the pre-computed value\_daily table; the current day aggregates live; days the nightly job missed fall back to live aggregation and are reported in stale\_days. Infra agents excluded from every family. * Auth: bearer * Params: `None`, `period` * operationId: `tenantValueSummary` ```yaml get: operationId: tenantValueSummary summary: Counted value by usage family for the Impact home and digest description: 'Hero numbers (searches served, contexts delivered, memories recorded), usage families, quality coverage (sessions with declared memory_used over sessions with delivered context), active agents, knowledge timeline and per-operation breakdown. Completed days are served from the pre-computed value_daily table; the current day aggregates live; days the nightly job missed fall back to live aggregation and are reported in stale_days. Infra agents excluded from every family. ' tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: period in: query schema: type: string enum: - today - yesterday - 7d - 30d default: 7d description: Window (UTC days); yesterday is the closed digest day responses: '200': description: Value summary content: application/json: schema: type: object '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /api/v1/memory/health` [#get-apiv1memoryhealth] Memory health diagnostics * Auth: bearer * Params: `None` * operationId: `memoryHealth` ```yaml get: operationId: memoryHealth summary: Memory health diagnostics tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Health diagnostics content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /api/v1/privacy/preview` [#post-apiv1privacypreview] Preview privacy extraction * Auth: bearer * Params: `None` * Body: object( `content`\* (string) ) * operationId: `privacyPreview` ```yaml post: operationId: privacyPreview summary: Preview privacy extraction tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - content properties: content: type: string responses: '200': description: Privacy preview content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /api/v1/privacy/sanitize` [#post-apiv1privacysanitize] Sanitize PII from content * Auth: bearer * Params: `None` * Body: object( `content`\* (string) ) * operationId: `privacySanitize` ```yaml post: operationId: privacySanitize summary: Sanitize PII from content tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - content properties: content: type: string responses: '200': description: Sanitized content content: application/json: schema: type: object properties: sanitized: type: string '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /api/v1/privacy/restore` [#post-apiv1privacyrestore] Restore sanitized content * Auth: bearer * Params: `None` * Body: object( `content`\* (string), `tokens`\* (array\[object( )]) ) * operationId: `privacyRestore` ```yaml post: operationId: privacyRestore summary: Restore sanitized content tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - content - tokens properties: content: type: string tokens: type: array items: type: object responses: '200': description: Restored content content: application/json: schema: type: object properties: restored: type: string '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /api/v1/foresights` [#get-apiv1foresights] List foresight predictions * Auth: bearer * Params: `None` * operationId: `listForesights` ```yaml get: operationId: listForesights summary: List foresight predictions tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Foresight list content: application/json: schema: type: object properties: foresights: type: array items: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /api/v1/foresights/sweep` [#post-apiv1foresightssweep] Trigger foresight sweep * Auth: bearer * Params: `None` * operationId: `sweepForesights` ```yaml post: operationId: sweepForesights summary: Trigger foresight sweep tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Sweep initiated content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /api/v1/foresights/{id}` [#get-apiv1foresightsid] Get a specific foresight * Auth: bearer * Params: `None`, `id`\* * operationId: `getForesight` ```yaml get: operationId: getForesight summary: Get a specific foresight tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string responses: '200': description: Foresight details content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' ``` ### `PATCH /api/v1/foresights/{id}` [#patch-apiv1foresightsid] Update a foresight * Auth: bearer * Params: `None`, `id`\* * Body: object( ) * operationId: `patchForesight` ```yaml patch: operationId: patchForesight summary: Update a foresight tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object responses: '200': description: Foresight updated content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' ``` ### `DELETE /api/v1/foresights/{id}` [#delete-apiv1foresightsid] Delete a foresight * Auth: bearer * Params: `None`, `id`\* * operationId: `deleteForesight` ```yaml delete: operationId: deleteForesight summary: Delete a foresight tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string responses: '200': description: Foresight deleted content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' ``` ## Runtime [#runtime] ### `PATCH /api/v1/entities/{name}/card` [#patch-apiv1entitiesnamecard] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_PATCH__api_v1_entities_name_card` ```yaml patch: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_PATCH__api_v1_entities_name_card x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `DELETE /api/v1/entities/{name}/card` [#delete-apiv1entitiesnamecard] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_DELETE__api_v1_entities_name_card` ```yaml delete: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_DELETE__api_v1_entities_name_card x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /openapi.yaml` [#get-openapiyaml] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__openapi_yaml` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__openapi_yaml x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /health/admin` [#get-healthadmin] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__health_admin` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__health_admin x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /reports/usage` [#get-reportsusage] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__reports_usage` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__reports_usage x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/memory/team-activity` [#get-apiv1memoryteam-activity] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_memory_team_activity` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_memory_team_activity x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /dashboard` [#get-dashboard] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__dashboard` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__dashboard x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /memory-map` [#get-memory-map] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__memory_map` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__memory_map x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/knowledge-gaps` [#get-apiv1knowledge-gaps] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_knowledge_gaps` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_knowledge_gaps x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `POST /api/v1/knowledge-gaps/{id}/resolve` [#post-apiv1knowledge-gapsidresolve] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_POST__api_v1_knowledge_gaps_id_resolve` ```yaml post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_knowledge_gaps_id_resolve x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `POST /conversations` [#post-conversations] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_POST__conversations` ```yaml post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__conversations x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /contradictions` [#get-contradictions] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__contradictions` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__contradictions x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /documents/changes` [#get-documentschanges] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__documents_changes` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__documents_changes x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /documents/{id}/chain` [#get-documentsidchain] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__documents_id_chain` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__documents_id_chain x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `PATCH /documents/{id}/veracity` [#patch-documentsidveracity] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_PATCH__documents_id_veracity` ```yaml patch: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_PATCH__documents_id_veracity x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `PATCH /api/v1/documents/{id}/veracity` [#patch-apiv1documentsidveracity] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_PATCH__api_v1_documents_id_veracity` ```yaml patch: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_PATCH__api_v1_documents_id_veracity x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `PATCH /documents/veracity/bulk` [#patch-documentsveracitybulk] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_PATCH__documents_veracity_bulk` ```yaml patch: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_PATCH__documents_veracity_bulk x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `PATCH /api/v1/documents/veracity/bulk` [#patch-apiv1documentsveracitybulk] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_PATCH__api_v1_documents_veracity_bulk` ```yaml patch: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_PATCH__api_v1_documents_veracity_bulk x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /collections/health` [#get-collectionshealth] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__collections_health` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__collections_health x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `POST /collections/{id}/lifecycle` [#post-collectionsidlifecycle] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_POST__collections_id_lifecycle` ```yaml post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__collections_id_lifecycle x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/memory/working-context` [#get-apiv1memoryworking-context] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_memory_working_context` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_memory_working_context x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /memory/working-context` [#get-memoryworking-context] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__memory_working_context` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__memory_working_context x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/scratchpad` [#get-apiv1scratchpad] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_scratchpad` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_scratchpad x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `PUT /api/v1/scratchpad` [#put-apiv1scratchpad] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_PUT__api_v1_scratchpad` ```yaml put: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_PUT__api_v1_scratchpad x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `POST /api/v1/scratchpad` [#post-apiv1scratchpad] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_POST__api_v1_scratchpad` ```yaml post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_scratchpad x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `DELETE /api/v1/scratchpad` [#delete-apiv1scratchpad] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_DELETE__api_v1_scratchpad` ```yaml delete: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_DELETE__api_v1_scratchpad x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /scratchpad` [#get-scratchpad] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__scratchpad` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__scratchpad x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `PUT /scratchpad` [#put-scratchpad] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_PUT__scratchpad` ```yaml put: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_PUT__scratchpad x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `POST /scratchpad` [#post-scratchpad] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_POST__scratchpad` ```yaml post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__scratchpad x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `DELETE /scratchpad` [#delete-scratchpad] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_DELETE__scratchpad` ```yaml delete: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_DELETE__scratchpad x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /setup/artifacts` [#get-setupartifacts] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__setup_artifacts` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__setup_artifacts x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/entity-cards` [#get-apiv1entity-cards] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_entity_cards` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_entity_cards x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/pins` [#get-apiv1pins] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_pins` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_pins x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `POST /api/v1/pins` [#post-apiv1pins] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_POST__api_v1_pins` ```yaml post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_pins x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/pins/{id}` [#get-apiv1pinsid] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_pins_id_` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_pins_id_ x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `PATCH /api/v1/pins/{id}` [#patch-apiv1pinsid] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_PATCH__api_v1_pins_id_` ```yaml patch: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_PATCH__api_v1_pins_id_ x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `DELETE /api/v1/pins/{id}` [#delete-apiv1pinsid] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_DELETE__api_v1_pins_id_` ```yaml delete: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_DELETE__api_v1_pins_id_ x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `POST /api/v1/session-handoffs` [#post-apiv1session-handoffs] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_POST__api_v1_session_handoffs` ```yaml post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_session_handoffs x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/session-handoffs` [#get-apiv1session-handoffs] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_session_handoffs` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_session_handoffs x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/team/members` [#get-apiv1teammembers] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_team_members` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_team_members x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `POST /api/v1/team/messages` [#post-apiv1teammessages] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_POST__api_v1_team_messages` ```yaml post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_team_messages x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/team/inbox` [#get-apiv1teaminbox] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_team_inbox` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_team_inbox x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `POST /api/v1/team/handoffs` [#post-apiv1teamhandoffs] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_POST__api_v1_team_handoffs` ```yaml post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_team_handoffs x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/team/handoffs` [#get-apiv1teamhandoffs] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_team_handoffs` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_team_handoffs x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/team/briefing` [#get-apiv1teambriefing] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_team_briefing` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_team_briefing x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/team/stream` [#get-apiv1teamstream] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_team_stream` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_team_stream x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/memory/episodes` [#get-apiv1memoryepisodes] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_memory_episodes` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_memory_episodes x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/memory/episodes/{id}` [#get-apiv1memoryepisodesid] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_memory_episodes_id_` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_memory_episodes_id_ x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /admin/queues` [#get-adminqueues] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__admin_queues` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__admin_queues x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `POST /admin/queues` [#post-adminqueues] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_POST__admin_queues` ```yaml post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__admin_queues x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `POST /api/v1/admin/tenants/{id}/api-tokens` [#post-apiv1admintenantsidapi-tokens] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_POST__api_v1_admin_tenants_id_api_tokens` ```yaml post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_admin_tenants_id_api_tokens x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/admin/tenants/{id}/api-tokens` [#get-apiv1admintenantsidapi-tokens] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_admin_tenants_id_api_tokens` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_admin_tenants_id_api_tokens x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `DELETE /api/v1/admin/tenants/{id}/api-tokens/{id2}` [#delete-apiv1admintenantsidapi-tokensid2] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_DELETE__api_v1_admin_tenants_id_api_tokens_id2_` ```yaml delete: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_DELETE__api_v1_admin_tenants_id_api_tokens_id2_ x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `POST /api/v1/memory/refine` [#post-apiv1memoryrefine] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_POST__api_v1_memory_refine` ```yaml post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_memory_refine x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `POST /api/v1/runtimes/register` [#post-apiv1runtimesregister] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_POST__api_v1_runtimes_register` ```yaml post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_runtimes_register x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `POST /api/v1/runtimes/heartbeat` [#post-apiv1runtimesheartbeat] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_POST__api_v1_runtimes_heartbeat` ```yaml post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_runtimes_heartbeat x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/runtimes` [#get-apiv1runtimes] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_runtimes` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_runtimes x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/kg/explore` [#get-apiv1kgexplore] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_kg_explore` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_kg_explore x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/kg/entity-documents` [#get-apiv1kgentity-documents] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_kg_entity_documents` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_kg_entity_documents x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `POST /api/v1/memory/store` [#post-apiv1memorystore] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_POST__api_v1_memory_store` ```yaml post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_memory_store x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/memory/confirm-sample` [#get-apiv1memoryconfirm-sample] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_memory_confirm_sample` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_memory_confirm_sample x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/tenant/trust-summary` [#get-apiv1tenanttrust-summary] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_tenant_trust_summary` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_tenant_trust_summary x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/tenant/perf-summary` [#get-apiv1tenantperf-summary] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_tenant_perf_summary` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_tenant_perf_summary x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/tenant/impact` [#get-apiv1tenantimpact] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_tenant_impact` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_tenant_impact x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `POST /api/v1/users/resolve-caller` [#post-apiv1usersresolve-caller] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_POST__api_v1_users_resolve_caller` ```yaml post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_users_resolve_caller x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/users/channel-identities` [#get-apiv1userschannel-identities] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_users_channel_identities` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_users_channel_identities x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `POST /api/v1/users/channel-identities` [#post-apiv1userschannel-identities] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_POST__api_v1_users_channel_identities` ```yaml post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_users_channel_identities x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/lessons` [#get-apiv1lessons] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_lessons` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_lessons x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `POST /api/v1/lessons/record` [#post-apiv1lessonsrecord] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_POST__api_v1_lessons_record` ```yaml post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_lessons_record x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `POST /api/v1/lessons/feedback` [#post-apiv1lessonsfeedback] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_POST__api_v1_lessons_feedback` ```yaml post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_lessons_feedback x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/arcs` [#get-apiv1arcs] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_arcs` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_arcs x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `POST /api/v1/arcs` [#post-apiv1arcs] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_POST__api_v1_arcs` ```yaml post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_arcs x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/keyed-facts/as-of` [#get-apiv1keyed-factsas-of] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_keyed_facts_as_of` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_keyed_facts_as_of x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `POST /api/v1/keyed-facts` [#post-apiv1keyed-facts] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_POST__api_v1_keyed_facts` ```yaml post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_keyed_facts x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `POST /api/v1/keyed-facts/correct` [#post-apiv1keyed-factscorrect] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_POST__api_v1_keyed_facts_correct` ```yaml post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_keyed_facts_correct x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `POST /api/v1/memory/prepare` [#post-apiv1memoryprepare] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_POST__api_v1_memory_prepare` ```yaml post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_memory_prepare x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/kg/quarantine` [#get-apiv1kgquarantine] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_kg_quarantine` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_kg_quarantine x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/kg/entity-resolve/report` [#get-apiv1kgentity-resolvereport] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_kg_entity_resolve_report` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_kg_entity_resolve_report x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `POST /api/v1/kg/rag-retrieve` [#post-apiv1kgrag-retrieve] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_POST__api_v1_kg_rag_retrieve` ```yaml post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_kg_rag_retrieve x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/usage/answers` [#get-apiv1usageanswers] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_usage_answers` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_usage_answers x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/credits/summary` [#get-apiv1creditssummary] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_credits_summary` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_credits_summary x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `POST /api/v1/session-bootstrap` [#post-apiv1session-bootstrap] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_POST__api_v1_session_bootstrap` ```yaml post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_session_bootstrap x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `POST /api/v1/decisions` [#post-apiv1decisions] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_POST__api_v1_decisions` ```yaml post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_decisions x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/decisions` [#get-apiv1decisions] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_decisions` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_decisions x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `POST /api/v1/decisions/relations` [#post-apiv1decisionsrelations] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_POST__api_v1_decisions_relations` ```yaml post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_decisions_relations x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/decisions/chain` [#get-apiv1decisionschain] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_decisions_chain` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_decisions_chain x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/decisions/similar` [#get-apiv1decisionssimilar] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_decisions_similar` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_decisions_similar x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/decisions/impact` [#get-apiv1decisionsimpact] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_decisions_impact` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_decisions_impact x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `POST /api/v1/provenance` [#post-apiv1provenance] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_POST__api_v1_provenance` ```yaml post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_provenance x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/provenance/lineage` [#get-apiv1provenancelineage] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_provenance_lineage` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_provenance_lineage x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/provenance/export` [#get-apiv1provenanceexport] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_provenance_export` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_provenance_export x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/provenance/verify` [#get-apiv1provenanceverify] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_provenance_verify` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_provenance_verify x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `POST /api/v1/conflicts/detect` [#post-apiv1conflictsdetect] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_POST__api_v1_conflicts_detect` ```yaml post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_conflicts_detect x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/fact-conflicts` [#get-apiv1fact-conflicts] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_fact_conflicts` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_fact_conflicts x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `POST /api/v1/conflicts/resolve` [#post-apiv1conflictsresolve] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_POST__api_v1_conflicts_resolve` ```yaml post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_conflicts_resolve x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `GET /api/v1/contradictions` [#get-apiv1contradictions] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_GET__api_v1_contradictions` ```yaml get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_contradictions x-valorbrain-live: true responses: '200': description: See the running handler ``` ### `POST /api/v1/contradictions/{n}/resolve` [#post-apiv1contradictionsnresolve] Registered on this process; not yet in docs/reference/openapi.yaml * Auth: bearer * operationId: `live_POST__api_v1_contradictions_n_resolve` ```yaml post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_contradictions_n_resolve x-valorbrain-live: true responses: '200': description: See the running handler ``` ## Search [#search] ### `POST /search` [#post-search] Hybrid search (BM25 + vector + rerank) — Full hybrid search with optional HyDE expansion, self-correct retrieval, MMR diversity, and personalized graph ranking. * Auth: bearer * Params: `None` * Body: object( `q`\* (string), `collection` (string), `limit` (integer), `offset` (integer), `expand` (boolean), `mode` (enum(auto, keyword, semantic, causal, hybrid)), `diverse` (boolean) ) * operationId: `search` ```yaml post: operationId: search summary: Hybrid search (BM25 + vector + rerank) description: 'Full hybrid search with optional HyDE expansion, self-correct retrieval, MMR diversity, and personalized graph ranking. ' tags: - Search parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - q properties: q: type: string description: Search query collection: type: string description: Filter to collection limit: type: integer default: 10 offset: type: integer default: 0 expand: type: boolean description: Force HyDE expansion on/off mode: type: string enum: - auto - keyword - semantic - causal - hybrid diverse: type: boolean default: true description: Apply MMR diversity filter responses: '200': description: Search results content: application/json: schema: type: object properties: results: type: array items: $ref: '#/components/schemas/SearchResult' query: type: string mode: type: string '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /search/temporal` [#post-searchtemporal] Temporal search with time-aware filtering * Auth: bearer * Params: `None` * Body: object( `q`\* (string), `collection` (string), `limit` (integer), `from` (string), `to` (string) ) * operationId: `temporalSearch` ```yaml post: operationId: temporalSearch summary: Temporal search with time-aware filtering tags: - Search parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - q properties: q: type: string collection: type: string limit: type: integer from: type: string format: date-time to: type: string format: date-time responses: '200': description: Temporally filtered results content: application/json: schema: type: object properties: results: type: array items: $ref: '#/components/schemas/SearchResult' '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /search/hierarchical` [#post-searchhierarchical] Hierarchical search across memory layers * Auth: bearer * Params: `None` * Body: object( `q`\* (string), `limit` (integer) ) * operationId: `hierarchicalSearch` ```yaml post: operationId: hierarchicalSearch summary: Hierarchical search across memory layers tags: - Search parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - q properties: q: type: string limit: type: integer responses: '200': description: Hierarchical results content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /retrieve` [#post-retrieve] Unified retrieval with auto-routing — Auto-classifies query intent and routes to optimal search backend. * Auth: bearer * Params: `None` * Body: object( `q`\* (string), `mode` (enum(auto, keyword, semantic, causal, timeline, discovery, complex, hybrid)), `limit` (integer), `collection` (string) ) * operationId: `retrieve` ```yaml post: operationId: retrieve summary: Unified retrieval with auto-routing description: Auto-classifies query intent and routes to optimal search backend. tags: - Search parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - q properties: q: type: string mode: type: string enum: - auto - keyword - semantic - causal - timeline - discovery - complex - hybrid limit: type: integer collection: type: string responses: '200': description: Retrieved results content: application/json: schema: type: object properties: results: type: array items: $ref: '#/components/schemas/SearchResult' mode: type: string '401': $ref: '#/components/responses/Unauthorized' ``` ## Users [#users] ### `GET /api/v1/users` [#get-apiv1users] List users in tenant * Auth: bearer * Params: `None` * operationId: `listUsers` ```yaml get: operationId: listUsers summary: List users in tenant tags: - Users parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: User list content: application/json: schema: type: object properties: users: type: array items: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /api/v1/users` [#post-apiv1users] Create a user * Auth: bearer * Params: `None` * Body: object( `email`\* (string), `name` (string), `role` (string) ) * operationId: `createUser` ```yaml post: operationId: createUser summary: Create a user tags: - Users parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - email properties: email: type: string format: email name: type: string role: type: string responses: '200': description: User created content: application/json: schema: type: object '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' ``` ### `PUT /api/v1/users/{userId}` [#put-apiv1usersuserid] Update a user * Auth: bearer * Params: `None`, `userId`\* * Body: object( `name` (string), `role` (string), `metadata` (object( )) ) * operationId: `updateUser` ```yaml put: operationId: updateUser summary: Update a user tags: - Users parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: userId in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object properties: name: type: string role: type: string metadata: type: object responses: '200': description: User updated content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' ``` ## Workspace [#workspace] ### `GET /api/v1/workspace/focus` [#get-apiv1workspacefocus] List current workspace focus items * Auth: bearer * Params: `None` * operationId: `listFocus` ```yaml get: operationId: listFocus summary: List current workspace focus items tags: - Workspace parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Focus items content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `POST /api/v1/workspace/focus` [#post-apiv1workspacefocus] Set workspace focus * Auth: bearer * Params: `None` * Body: object( `items` (array\[object( )]) ) * operationId: `setFocus` ```yaml post: operationId: setFocus summary: Set workspace focus tags: - Workspace parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object properties: items: type: array items: type: object responses: '200': description: Focus updated content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /api/v1/workspace/sessions` [#get-apiv1workspacesessions] List workspace sessions * Auth: bearer * Params: `None` * operationId: `listWorkspaceSessions` ```yaml get: operationId: listWorkspaceSessions summary: List workspace sessions tags: - Workspace parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Session list content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /api/v1/workspace/handoffs` [#get-apiv1workspacehandoffs] List workspace handoffs * Auth: bearer * Params: `None` * operationId: `listHandoffs` ```yaml get: operationId: listHandoffs summary: List workspace handoffs tags: - Workspace parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Handoff list content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` ### `GET /api/v1/workspace/state` [#get-apiv1workspacestate] Get workspace state document * Auth: bearer * Params: `None` * operationId: `getWorkspaceState` ```yaml get: operationId: getWorkspaceState summary: Get workspace state document tags: - Workspace parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Workspace state content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' ``` # OpenAPI (engine, servers rewritten) ``` openapi: 3.1.0 info: title: ValorBrain Engine API description: 'REST interface for ValorBrain''s memory engine — search, retrieval, document lifecycle, RAG chat, knowledge graph, and multi-tenant management. ' version: 0.2.0 contact: name: Valor Digital url: https://valor.digital license: name: Proprietary x-valorbrain-generated-at: '2026-09-25T19:16:23.544Z' x-valorbrain-public-url: https://valorbrain-api.valor.digital x-valorbrain-yaml-operations: 144 x-valorbrain-live-operations: 231 x-valorbrain-missing-from-yaml: - GET /openapi.yaml - GET /health/admin - GET /reports/usage - GET /api/v1/memory/team-activity - GET /dashboard - GET /memory-map - GET /api/v1/knowledge-gaps - POST /api/v1/knowledge-gaps/{id}/resolve - POST /conversations - GET /harness-coverage - GET /contradictions - GET /documents/changes - GET /documents/{id}/chain - PATCH /documents/{id}/veracity - PATCH /api/v1/documents/{id}/veracity - PATCH /documents/veracity/bulk - PATCH /api/v1/documents/veracity/bulk - GET /collections/health - POST /collections/{id}/lifecycle - GET /api/v1/memory/working-context - GET /memory/working-context - GET /api/v1/scratchpad - PUT /api/v1/scratchpad - POST /api/v1/scratchpad - DELETE /api/v1/scratchpad - GET /scratchpad - PUT /scratchpad - POST /scratchpad - DELETE /scratchpad - GET /setup/artifacts - GET /api/v1/entity-cards - POST /api/v1/feedback - GET /api/v1/secrets - POST /api/v1/secrets - PATCH /api/v1/entities/{name}/card - DELETE /api/v1/entities/{name}/card - GET /api/v1/pins - POST /api/v1/pins - GET /api/v1/pins/{id} - PATCH /api/v1/pins/{id} - DELETE /api/v1/pins/{id} - POST /api/v1/session-handoffs - GET /api/v1/session-handoffs - GET /api/v1/team/members - GET /api/v1/team/overview - GET /api/v1/task-state - POST /api/v1/team/messages - GET /api/v1/team/inbox - POST /api/v1/team/handoffs - GET /api/v1/team/handoffs - GET /api/v1/team/briefing - GET /api/v1/team/stream - GET /api/v1/memory/episodes - GET /api/v1/memory/episodes/{id} - GET /admin/queues - POST /admin/queues - POST /api/v1/admin/tenants/{id}/api-tokens - GET /api/v1/admin/tenants/{id}/api-tokens - DELETE /api/v1/admin/tenants/{id}/api-tokens/{id2} - PATCH /api/v1/admin/tenants/{id}/status - POST /api/v1/memory/refine - POST /api/v1/runtimes/register - POST /api/v1/runtimes/heartbeat - GET /api/v1/runtimes - GET /api/v1/kg/explore - GET /api/v1/kg/entity-documents - POST /api/v1/memory/store - GET /api/v1/memory/confirm-sample - GET /api/v1/tenant/trust-summary - GET /api/v1/tenant/perf-summary - GET /api/v1/tenant/impact - POST /api/v1/users/resolve-caller - GET /api/v1/users/channel-identities - POST /api/v1/users/channel-identities - GET /api/v1/audit/pubkey - GET /api/v1/audit/bundle - GET /api/v1/audit/status - GET /api/v1/audit/recent - GET /api/v1/read-log/summary - GET /api/v1/lessons - POST /api/v1/lessons/record - POST /api/v1/lessons/feedback - GET /api/v1/arcs - POST /api/v1/arcs - GET /api/v1/keyed-facts/as-of - POST /api/v1/keyed-facts - POST /api/v1/keyed-facts/correct - POST /api/v1/authority/mandates - GET /api/v1/authority/mandates - POST /api/v1/harness-integrations - GET /api/v1/harness-integrations - POST /api/v1/memory/prepare - GET /api/v1/kg/quarantine - GET /api/v1/kg/entity-resolve/report - POST /api/v1/kg/rag-retrieve - GET /api/v1/usage/answers - GET /api/v1/credits/summary - POST /api/v1/session-bootstrap - POST /api/v1/hooks/run - POST /api/v1/decisions - POST /api/v1/decisions/relations - GET /api/v1/decisions/chain - GET /api/v1/decisions/similar - GET /api/v1/decisions/impact - GET /api/v1/decisions - POST /api/v1/provenance - GET /api/v1/provenance/lineage - GET /api/v1/provenance/export - GET /api/v1/provenance/verify - POST /api/v1/conflicts/detect - GET /api/v1/fact-conflicts - POST /api/v1/conflicts/resolve - GET /api/v1/contradictions - POST /api/v1/contradictions/{n}/resolve servers: - url: https://valorbrain-api.valor.digital description: Hosted engine REST - url: http://localhost:7438 description: Local engine (self-hosted) security: - bearerAuth: [] tags: - name: Health description: Liveness, readiness, and system diagnostics - name: Documents description: Document CRUD, ingest, and mutations - name: Search description: Hybrid search, temporal, hierarchical, and retrieve - name: Ask description: RAG chat with LLM answer and source citations - name: Graph description: Causal links, similarity, and memory evolution - name: Entity description: Entity cards and SPO triples - name: Foundations description: Knowledge OS Tier-0 context and foundation management - name: Agents description: Agent signup, identify, claim, and verify - name: Workspace description: 'Cross-agent workspace: focus, sessions, handoffs' - name: Users description: User management - name: Identity description: Agent/user identity profile - name: Billing description: Credits, pricing, subscriptions, and plans - name: Admin description: Tenant management, error logging (requires ENGINE_ADMIN_SECRET) - name: OAuth description: OAuth 2.1 authorization server and protected resource - name: MCP Tokens description: MCP API token CRUD - name: Observability description: Metrics, traces, ROI, and feature flags - name: Canonical description: Canonical tracking, conflicts, proposals, and probes - name: Lifecycle description: 'Document lifecycle: status, sweep, restore' - name: Maintenance description: Reindex, graph build, and collection settings paths: /healthz: get: operationId: healthz summary: Public liveness probe description: Returns 200 if the process is up. No auth, no store dependency. tags: - Health security: [] responses: '200': description: Process is alive content: application/json: schema: type: object required: - status - service - timestamp properties: status: type: string enum: - ok service: type: string timestamp: type: string format: date-time /health: get: operationId: health summary: Health check with database status description: Returns service status, document counts, vector index state, and request context. tags: - Health security: [] responses: '200': description: Service health content: application/json: schema: type: object required: - status - service properties: status: type: string service: type: string version: type: string database: type: string documents: type: integer needsEmbedding: type: integer hasVectors: type: boolean request: $ref: '#/components/schemas/RequestContext' /health/deep: get: operationId: healthDeep summary: Deep health check with per-component probes description: Probes database, documents, LLM config, and embed worker. Used by uptime monitors. tags: - Health security: [] responses: '200': description: Component-level health content: application/json: schema: type: object required: - checks properties: checks: type: object additionalProperties: type: object required: - ok properties: ok: type: boolean latency_ms: type: integer detail: type: string error: type: string latency_ms: type: integer /state: get: operationId: state summary: Engine state summary tags: - Health responses: '200': description: State object content: application/json: schema: type: object /stats: get: operationId: stats summary: Index statistics and health tags: - Health responses: '200': description: Stats including document counts, collections, and health content: application/json: schema: type: object properties: documents: type: integer totalDocuments: type: integer needsEmbedding: type: integer collections: type: array items: type: object health: type: object /reports/memory: get: operationId: reportsMemory summary: Memory usage report description: Tenant-scoped memory report. Requires X-Tenant-ID. tags: - Health parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Memory report content: application/json: schema: type: object '400': $ref: '#/components/responses/BadRequest' /documents: post: operationId: ingestDocument summary: Ingest a document description: 'Create or update a document in a collection. Supports quality gate evaluation, schema packs, auto-linking, and temporal metadata. Requires X-Tenant-ID. ' tags: - Documents parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - collection - path - content properties: collection: type: string description: Collection name path: type: string description: Unique document path within the collection title: type: string content: type: string maxLength: 1000000 description: Document body (max 1MB) content_type: type: string default: note confidence: type: number minimum: 0 maximum: 1 default: 0.5 quality_score: type: number minimum: 0 maximum: 1 default: 0.5 metadata: type: object additionalProperties: true user_id: type: string run_id: type: string event_at: type: string format: date-time event_type: type: string responses: '200': description: Document ingested content: application/json: schema: type: object properties: ok: type: boolean id: type: integer path: type: string hash: type: string embed_state: type: string gate_verdict: type: object properties: shouldIndex: type: boolean reason: type: string '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' get: operationId: listDocuments summary: List documents description: List documents with optional filtering by collection. tags: - Documents parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: collection in: query schema: type: string - name: limit in: query schema: type: integer default: 50 - name: offset in: query schema: type: integer default: 0 responses: '200': description: List of documents content: application/json: schema: type: object properties: documents: type: array items: $ref: '#/components/schemas/Document' total: type: integer '401': $ref: '#/components/responses/Unauthorized' /documents/{id}: get: operationId: getDocument summary: Get a document by ID or hash tags: - Documents parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string description: Document ID or hash responses: '200': description: Document details content: application/json: schema: $ref: '#/components/schemas/Document' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' /documents/{id}/visibility: patch: operationId: patchDocumentVisibility summary: Update document visibility tags: - Documents parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object required: - visibility properties: visibility: type: string responses: '200': description: Visibility updated content: application/json: schema: type: object properties: ok: type: boolean '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' /documents/{id}/pin: post: operationId: pinDocument summary: Pin a document for permanent prioritization tags: - Documents parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string responses: '200': description: Document pinned content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' /documents/{id}/snooze: post: operationId: snoozeDocument summary: Temporarily hide a document from context tags: - Documents parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string requestBody: content: application/json: schema: type: object properties: until: type: string format: date-time responses: '200': description: Document snoozed content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' /documents/{id}/forget: post: operationId: forgetDocument summary: Permanently deactivate a document tags: - Documents parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string responses: '200': description: Document forgotten content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' /documents/{id}/feedback: post: operationId: documentFeedback summary: Submit relevance feedback for a document tags: - Documents parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object required: - relevance properties: relevance: type: string enum: - positive - negative responses: '200': description: Feedback recorded content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' /documents/purge: delete: operationId: purgeDocuments summary: Purge documents by collection description: 'Delete all documents in a collection (exact or prefix match). Cleans up vectors, triples, and orphan records. Requires X-Tenant-ID. ' tags: - Documents parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: collection in: query schema: type: string description: Exact collection name - name: collection_prefix in: query schema: type: string description: Collection name prefix (LIKE match) responses: '200': description: Purge result content: application/json: schema: type: object properties: purged: type: integer orphan_vectors_cleaned: type: integer orphan_triples_cleaned: type: integer '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' /api/v1/documents/{id}/canonical: post: operationId: setCanonical summary: Mark a document as canonical tags: - Canonical parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object properties: canonical: type: boolean responses: '200': description: Canonical status set content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/documents/{id}/suggest-filters: post: operationId: suggestFilters summary: Suggest retrieval filters for a document tags: - Canonical parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string responses: '200': description: Suggested filters content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/documents/{id}/probes: post: operationId: registerProbe summary: Register a validation probe for a document tags: - Canonical parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string responses: '200': description: Probe registered content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /search: post: operationId: search summary: Hybrid search (BM25 + vector + rerank) description: 'Full hybrid search with optional HyDE expansion, self-correct retrieval, MMR diversity, and personalized graph ranking. ' tags: - Search parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - q properties: q: type: string description: Search query collection: type: string description: Filter to collection limit: type: integer default: 10 offset: type: integer default: 0 expand: type: boolean description: Force HyDE expansion on/off mode: type: string enum: - auto - keyword - semantic - causal - hybrid diverse: type: boolean default: true description: Apply MMR diversity filter responses: '200': description: Search results content: application/json: schema: type: object properties: results: type: array items: $ref: '#/components/schemas/SearchResult' query: type: string mode: type: string '401': $ref: '#/components/responses/Unauthorized' /search/temporal: post: operationId: temporalSearch summary: Temporal search with time-aware filtering tags: - Search parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - q properties: q: type: string collection: type: string limit: type: integer from: type: string format: date-time to: type: string format: date-time responses: '200': description: Temporally filtered results content: application/json: schema: type: object properties: results: type: array items: $ref: '#/components/schemas/SearchResult' '401': $ref: '#/components/responses/Unauthorized' /search/hierarchical: post: operationId: hierarchicalSearch summary: Hierarchical search across memory layers tags: - Search parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - q properties: q: type: string limit: type: integer responses: '200': description: Hierarchical results content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /retrieve: post: operationId: retrieve summary: Unified retrieval with auto-routing description: Auto-classifies query intent and routes to optimal search backend. tags: - Search parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - q properties: q: type: string mode: type: string enum: - auto - keyword - semantic - causal - timeline - discovery - complex - hybrid limit: type: integer collection: type: string responses: '200': description: Retrieved results content: application/json: schema: type: object properties: results: type: array items: $ref: '#/components/schemas/SearchResult' mode: type: string '401': $ref: '#/components/responses/Unauthorized' /ask: post: operationId: ask summary: RAG chat with LLM answer and source citations description: 'Retrieve relevant context, run through LLM reasoning, and return a grounded answer with source citations. Supports streaming (SSE). ' tags: - Ask parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - q properties: q: type: string description: User question collection: type: string stream: type: boolean default: false description: Enable SSE streaming language: type: string enum: - pt-BR - en default: pt-BR limit: type: integer default: 5 description: Max source documents to retrieve responses: '200': description: 'RAG answer. When stream=false, returns JSON with answer and sources. When stream=true, returns text/event-stream. ' content: application/json: schema: type: object properties: answer: type: string sources: type: array items: $ref: '#/components/schemas/SearchResult' trace_id: type: string text/event-stream: schema: type: string description: SSE stream of answer chunks '401': $ref: '#/components/responses/Unauthorized' /api/v1/traces: get: operationId: listTraces summary: List recent ask traces tags: - Ask parameters: - name: limit in: query schema: type: integer default: 50 - name: offset in: query schema: type: integer default: 0 responses: '200': description: Trace log entries content: application/json: schema: type: object properties: traces: type: array items: type: object count: type: integer /timeline/{id}: get: operationId: timeline summary: Temporal neighborhood around a document tags: - Documents parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string - name: before in: query schema: type: integer default: 5 - name: after in: query schema: type: integer default: 5 responses: '200': description: Timeline context content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /sessions: get: operationId: listSessions summary: List recent sessions tags: - Documents parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Session list content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /collections: get: operationId: listCollections summary: List all collections tags: - Documents parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Collection list content: application/json: schema: type: object properties: collections: type: array items: type: object properties: name: type: string count: type: integer '401': $ref: '#/components/responses/Unauthorized' /profile: get: operationId: getProfile summary: Get current tenant/user profile tags: - Documents parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Profile data content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /graph/causal/{id}: get: operationId: getCausalLinks summary: Get causal links for a document tags: - Graph parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string - name: direction in: query schema: type: string enum: - causes - caused_by - both default: both - name: depth in: query schema: type: integer default: 5 minimum: 1 maximum: 10 responses: '200': description: Causal link graph content: application/json: schema: type: object properties: links: type: array items: type: object properties: docid: type: string direction: type: string depth: type: integer reasoning: type: string '401': $ref: '#/components/responses/Unauthorized' /graph/similar/{id}: get: operationId: getSimilar summary: Find semantically similar documents tags: - Graph parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string - name: limit in: query schema: type: integer default: 5 responses: '200': description: Similar documents content: application/json: schema: type: object properties: similar: type: array items: $ref: '#/components/schemas/SearchResult' '401': $ref: '#/components/responses/Unauthorized' /graph/evolution/{id}: get: operationId: getEvolution summary: Get memory evolution timeline for a document tags: - Graph parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string - name: limit in: query schema: type: integer default: 10 responses: '200': description: Evolution timeline content: application/json: schema: type: object properties: evolution: type: array items: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/entities/{name}/card: get: operationId: getEntityCard summary: Get entity card by name tags: - Entity parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: name in: path required: true schema: type: string description: Entity name responses: '200': description: Entity card content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' post: operationId: upsertEntityCard summary: Create or update an entity card tags: - Entity parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: name in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object properties: summary: type: string aliases: type: array items: type: string metadata: type: object additionalProperties: true responses: '200': description: Entity card upserted content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' patch: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_PATCH__api_v1_entities_name_card x-valorbrain-live: true responses: '200': description: See the running handler delete: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_DELETE__api_v1_entities_name_card x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/triples: post: operationId: createTriple summary: Create an SPO triple description: Create a subject-predicate-object triple. Resolves entity names to IDs. tags: - Entity parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - subject - predicate - object properties: subject: type: string predicate: type: string object: type: string confidence: type: number default: 0.8 responses: '200': description: Triple created content: application/json: schema: type: object properties: ok: type: boolean triple: type: object '401': $ref: '#/components/responses/Unauthorized' /foundations: get: operationId: getFoundations summary: Get Tier-0 foundation context tags: - Foundations parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Foundation documents content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/state: get: operationId: getState summary: Get structured engine state tags: - Foundations parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Structured state content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/foundations: post: operationId: createFoundation summary: Create a foundation document tags: - Foundations parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - path - content properties: path: type: string content: type: string title: type: string layer: type: string responses: '200': description: Foundation created content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' /api/v1/foundations/{id}: put: operationId: updateFoundation summary: Update a foundation document tags: - Foundations parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object properties: content: type: string title: type: string responses: '200': description: Foundation updated content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' delete: operationId: deleteFoundation summary: Delete a foundation document tags: - Foundations parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string responses: '200': description: Foundation deleted content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' /api/v1/foundations/{id}/promote: post: operationId: promoteFoundation summary: Promote a foundation to a higher layer tags: - Foundations parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string responses: '200': description: Foundation promoted content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' /api/v1/agents/signup: post: operationId: agentSignup summary: Register a new agent (public) description: 'Public endpoint — no auth required. Creates a shadow tenant and returns an API key. ' tags: - Agents security: [] requestBody: required: true content: application/json: schema: type: object required: - agent_name properties: agent_name: type: string capabilities: type: array items: type: string metadata: type: object additionalProperties: true responses: '200': description: Agent registered with API key content: application/json: schema: type: object properties: ok: type: boolean tenant_id: type: string api_key: type: string '400': $ref: '#/components/responses/BadRequest' /api/v1/agents/identify: post: operationId: agentIdentify summary: Identify an agent by API key tags: - Agents security: [] requestBody: required: true content: application/json: schema: type: object required: - key properties: key: type: string responses: '200': description: Agent identity content: application/json: schema: type: object properties: agent_name: type: string tenant_id: type: string '401': $ref: '#/components/responses/Unauthorized' /api/v1/agents/claim: post: operationId: agentClaim summary: Request ownership claim for an agent tags: - Agents security: [] requestBody: required: true content: application/json: schema: type: object required: - agent_name - email properties: agent_name: type: string email: type: string format: email responses: '200': description: Claim request initiated content: application/json: schema: type: object '400': $ref: '#/components/responses/BadRequest' /api/v1/agents/claim/verify: post: operationId: agentClaimVerify summary: Verify an agent ownership claim tags: - Agents security: [] requestBody: required: true content: application/json: schema: type: object required: - token properties: token: type: string responses: '200': description: Claim verified content: application/json: schema: type: object properties: ok: type: boolean api_key: type: string '400': $ref: '#/components/responses/BadRequest' /api/v1/workspace/focus: get: operationId: listFocus summary: List current workspace focus items tags: - Workspace parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Focus items content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' post: operationId: setFocus summary: Set workspace focus tags: - Workspace parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object properties: items: type: array items: type: object responses: '200': description: Focus updated content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/workspace/sessions: get: operationId: listWorkspaceSessions summary: List workspace sessions tags: - Workspace parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Session list content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/workspace/handoffs: get: operationId: listHandoffs summary: List workspace handoffs tags: - Workspace parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Handoff list content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/workspace/state: get: operationId: getWorkspaceState summary: Get workspace state document tags: - Workspace parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Workspace state content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/users: get: operationId: listUsers summary: List users in tenant tags: - Users parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: User list content: application/json: schema: type: object properties: users: type: array items: type: object '401': $ref: '#/components/responses/Unauthorized' post: operationId: createUser summary: Create a user tags: - Users parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - email properties: email: type: string format: email name: type: string role: type: string responses: '200': description: User created content: application/json: schema: type: object '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' /api/v1/users/{userId}: put: operationId: updateUser summary: Update a user tags: - Users parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: userId in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object properties: name: type: string role: type: string metadata: type: object responses: '200': description: User updated content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' /api/v1/identity: get: operationId: getIdentity summary: Get current identity tags: - Identity parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Identity profile content: application/json: schema: type: object properties: id: type: string name: type: string email: type: string tenant_id: type: string '401': $ref: '#/components/responses/Unauthorized' put: operationId: updateIdentity summary: Update current identity tags: - Identity parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object properties: name: type: string email: type: string preferences: type: object responses: '200': description: Identity updated content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/credits/balance: get: operationId: getCreditsBalance summary: Get credit balance tags: - Billing parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Credit balance content: application/json: schema: $ref: '#/components/schemas/CreditBalance' '401': $ref: '#/components/responses/Unauthorized' /api/v1/credits/transactions: get: operationId: getCreditsTransactions summary: Get credit transaction history tags: - Billing parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: limit in: query schema: type: integer default: 50 responses: '200': description: Transaction list content: application/json: schema: type: object properties: transactions: type: array items: type: object properties: id: type: string amount: type: number action: type: string created_at: type: string format: date-time '401': $ref: '#/components/responses/Unauthorized' /api/v1/credits/grant: post: operationId: grantCredits summary: Grant credits to tenant description: Repeatable manual operator adjustment; the required reason is recorded in the credit ledger. tags: - Billing security: - moneyAdminAuth: [] parameters: - $ref: '#/components/parameters/MoneyTenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - amount - reason properties: amount: type: number exclusiveMinimum: 0 reason: type: string minLength: 1 metadata: type: object additionalProperties: true responses: '200': description: Credits granted content: application/json: schema: type: object required: - ok - balance_after properties: ok: type: boolean balance_after: type: number '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' /api/v1/pricing/actions: get: operationId: listPricingActions summary: List pricing actions tags: - Billing parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Pricing action list content: application/json: schema: type: object properties: actions: type: array items: type: object properties: action: type: string cost: type: number currency: type: string '401': $ref: '#/components/responses/Unauthorized' /api/v1/pricing/actions/{action}: put: operationId: setPricingAction summary: Set pricing for an action tags: - Billing security: - moneyAdminAuth: [] parameters: - $ref: '#/components/parameters/MoneyTenantIdHeader' - name: action in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object required: - cost properties: cost: type: number responses: '200': description: Pricing updated content: application/json: schema: type: object '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' /api/v1/plans: get: operationId: listPlans summary: List available subscription plans tags: - Billing responses: '200': description: Plan list content: application/json: schema: type: object properties: plans: type: array items: type: object properties: id: type: string name: type: string credits: type: number price: type: number /api/v1/subscription: get: operationId: getSubscription summary: Get current subscription tags: - Billing parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Subscription details content: application/json: schema: type: object properties: plan_id: type: string status: type: string current_period_end: type: string format: date-time '401': $ref: '#/components/responses/Unauthorized' put: operationId: updateSubscription summary: Update subscription plan tags: - Billing security: - moneyAdminAuth: [] parameters: - $ref: '#/components/parameters/MoneyTenantIdHeader' requestBody: required: true content: application/json: schema: type: object properties: plan_id: type: string responses: '200': description: Subscription updated content: application/json: schema: type: object '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' /api/v1/subscription/grant: post: operationId: grantSubscriptionCredits summary: Grant legacy Stripe invoice credits idempotently description: 'Compatibility endpoint for older Stripe contracts with monthly credits. Writes a credit_grant event with source stripe:invoice and source_id equal to invoice_id. It does not activate or change the subscription itself. ' tags: - Billing security: - moneyAdminAuth: [] parameters: - $ref: '#/components/parameters/MoneyTenantIdHeader' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/SubscriptionCreditGrantRequest' responses: '200': description: Credits granted once, or an identical invoice replay skipped content: application/json: schema: $ref: '#/components/schemas/SubscriptionCreditGrantResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/BillingConflict' '422': $ref: '#/components/responses/BillingUnprocessable' /api/v1/billing/events/apply: post: operationId: applyBillingEvent summary: Apply a verified billing event idempotently description: 'Applies an externally verified billing effect in one tenant-scoped transaction. The tenant row is locked before replay lookup and before any subscription lock. Subscription events update entitlement/quota; credit_grant updates only balance and ledger and returns subscription null. Older periods are journaled as immutable stale no-ops. The final non-null result is inserted once with the event after all effects are built; a global source-key or settlement-proof conflict rolls back every effect. Payment verification and private signing material stay outside this API. ' tags: - Billing security: - moneyAdminAuth: [] parameters: - $ref: '#/components/parameters/MoneyTenantIdHeader' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/BillingEventApplyRequest' responses: '200': description: Event applied once or returned as an identical replay content: application/json: schema: $ref: '#/components/schemas/BillingEventApplyResult' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/BillingConflict' '422': $ref: '#/components/responses/BillingUnprocessable' /api/v1/billing/events: get: operationId: findBillingEvents summary: Find tenant billing events for reconciliation description: 'Admin-only, tenant-scoped journal lookup. Supply event_id, the complete source/source_id pair, or provider_subscription_id. Combined selectors use AND. Results are ordered by created_at descending and never expose another tenant''s event. ' tags: - Billing security: - moneyAdminAuth: [] parameters: - $ref: '#/components/parameters/MoneyTenantIdHeader' - name: event_id in: query schema: type: string format: uuid - name: source in: query description: Must be supplied together with source_id. schema: type: string maxLength: 128 - name: source_id in: query description: Must be supplied together with source. schema: type: string maxLength: 512 - name: provider_subscription_id in: query schema: type: string maxLength: 512 - name: limit in: query schema: type: integer minimum: 1 maximum: 50 default: 20 responses: '200': description: Matching tenant billing events content: application/json: schema: $ref: '#/components/schemas/BillingEventsResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' /api/v1/admin/tenants: post: operationId: adminCreateTenant summary: Create a tenant (admin only) tags: - Admin security: - adminSecret: [] requestBody: required: true content: application/json: schema: type: object required: - name properties: name: type: string metadata: type: object additionalProperties: true responses: '200': description: Tenant created content: application/json: schema: type: object properties: ok: type: boolean tenant_id: type: string '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' /api/v1/admin/tenants/{tenantId}/users: post: operationId: adminCreateUser summary: Create a user in a tenant (admin only) tags: - Admin security: - adminSecret: [] parameters: - name: tenantId in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object required: - email properties: email: type: string format: email name: type: string role: type: string responses: '200': description: User created content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' /api/v1/admin/tenants/{tenantId}: delete: operationId: adminDeleteTenant summary: Delete a tenant (admin only) tags: - Admin security: - adminSecret: [] parameters: - name: tenantId in: path required: true schema: type: string responses: '200': description: Tenant deleted content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' /api/v1/admin/errors: get: operationId: adminListErrors summary: List error log (admin only) tags: - Admin security: - adminSecret: [] parameters: - name: limit in: query schema: type: integer default: 50 - name: unresolved_only in: query schema: type: boolean default: true responses: '200': description: Error list content: application/json: schema: type: object properties: errors: type: array items: type: object '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' /api/v1/admin/errors/{errorId}/resolve: post: operationId: adminResolveError summary: Resolve an error (admin only) tags: - Admin security: - adminSecret: [] parameters: - name: errorId in: path required: true schema: type: integer responses: '200': description: Error resolved content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' /api/v1/admin/test-error: get: operationId: adminTestError summary: Trigger a test error (admin only) tags: - Admin security: - adminSecret: [] responses: '200': description: Test error triggered content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' /.well-known/oauth-authorization-server: get: operationId: oauthAsMetadata summary: OAuth authorization server metadata description: Public discovery endpoint per RFC 9414. tags: - OAuth security: [] responses: '200': description: Authorization server metadata content: application/json: schema: type: object /.well-known/oauth-protected-resource: get: operationId: oauthRsMetadata summary: OAuth protected resource metadata description: Public discovery endpoint per RFC 9728. tags: - OAuth security: [] responses: '200': description: Protected resource metadata content: application/json: schema: type: object /oauth/register: post: operationId: oauthRegister summary: Dynamic client registration tags: - OAuth security: [] requestBody: required: true content: application/json: schema: type: object properties: client_name: type: string redirect_uris: type: array items: type: string grant_types: type: array items: type: string responses: '201': description: Client registered content: application/json: schema: type: object properties: client_id: type: string client_secret: type: string '400': $ref: '#/components/responses/BadRequest' /oauth/authorize: get: operationId: oauthAuthorize summary: OAuth authorization endpoint description: Redirects to consent page. tags: - OAuth security: [] parameters: - name: response_type in: query required: true schema: type: string - name: client_id in: query required: true schema: type: string - name: redirect_uri in: query schema: type: string - name: scope in: query schema: type: string - name: state in: query schema: type: string responses: '302': description: Redirect to consent page '400': $ref: '#/components/responses/BadRequest' /oauth/consent: get: operationId: oauthConsentPage summary: OAuth consent page tags: - OAuth security: [] responses: '200': description: HTML consent form post: operationId: oauthConsentSubmit summary: Submit OAuth consent tags: - OAuth security: [] requestBody: required: true content: application/x-www-form-urlencoded: schema: type: object responses: '302': description: Redirect back to client /oauth/token: post: operationId: oauthToken summary: OAuth token exchange tags: - OAuth security: [] requestBody: required: true content: application/x-www-form-urlencoded: schema: type: object required: - grant_type properties: grant_type: type: string code: type: string client_id: type: string client_secret: type: string redirect_uri: type: string responses: '200': description: Token response content: application/json: schema: type: object properties: access_token: type: string token_type: type: string expires_in: type: integer refresh_token: type: string '400': $ref: '#/components/responses/BadRequest' /oauth/revoke: post: operationId: oauthRevoke summary: Revoke an OAuth token tags: - OAuth security: [] requestBody: required: true content: application/x-www-form-urlencoded: schema: type: object required: - token properties: token: type: string responses: '200': description: Token revoked /api/v1/mcp/tokens: get: operationId: listMcpTokens summary: List MCP API tokens tags: - MCP Tokens parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Token list content: application/json: schema: type: object properties: tokens: type: array items: type: object properties: id: type: string name: type: string prefix: type: string is_active: type: boolean created_at: type: string format: date-time '401': $ref: '#/components/responses/Unauthorized' post: operationId: createMcpToken summary: Create an MCP API token tags: - MCP Tokens parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - name properties: name: type: string expires_at: type: string format: date-time responses: '200': description: Token created (full key returned only once) content: application/json: schema: type: object properties: ok: type: boolean id: type: string key: type: string description: Full API key (shown only at creation) '401': $ref: '#/components/responses/Unauthorized' /api/v1/mcp/tokens/{tokenId}: get: operationId: getMcpToken summary: Get MCP token details tags: - MCP Tokens parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: tokenId in: path required: true schema: type: string responses: '200': description: Token details content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' put: operationId: updateMcpToken summary: Update MCP token tags: - MCP Tokens parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: tokenId in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object properties: name: type: string is_active: type: boolean responses: '200': description: Token updated content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' delete: operationId: deleteMcpToken summary: Delete MCP token tags: - MCP Tokens parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: tokenId in: path required: true schema: type: string responses: '200': description: Token deleted content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' /api/v1/acl/me: get: operationId: aclMe summary: Effective source-ACL domains of the caller (the "why" trace) description: 'Union of user + role + agent grants with the provenance of each grant (who granted, reason, temporal validity). Feeds the permission trace of the governance simulator. Requires a caller identity (bound user or agent persona); 401 otherwise, with no regime structure leaked. ' tags: - Governance parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: ACL trace for the caller content: application/json: schema: type: object properties: tenant_id: type: string identity: type: object properties: user_id: type: - string - 'null' role: type: - string - 'null' agent: type: - string - 'null' acl: type: object properties: active: type: boolean state: type: string allowed_domains: type: array items: type: string denied_domains: type: array items: type: string known_domains: type: array items: type: string hidden_documents: type: integer grants: type: array items: type: object trace: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/acl/grants: get: operationId: listAclGrants summary: List source-ACL grants (ADMIN) tags: - Governance parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: subject_kind in: query schema: type: string enum: - user - role - agent - name: subject_id in: query schema: type: string - name: domain in: query schema: type: string responses: '200': description: Grant list + domain mappings content: application/json: schema: type: object properties: grants: type: array items: type: object domains: type: array items: type: object '403': $ref: '#/components/responses/Unauthorized' post: operationId: createAclGrant summary: Create a source-ACL grant (ADMIN; reason required) tags: - Governance parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - subject_kind - subject_id - domain - reason properties: subject_kind: type: string enum: - user - role - agent subject_id: type: string domain: type: string reason: type: string valid_from: type: string format: date-time nullable: true valid_to: type: string format: date-time nullable: true responses: '201': description: Grant created '409': description: Grant already exists /api/v1/acl/grants/{grantId}: delete: operationId: revokeAclGrant summary: Revoke a source-ACL grant (ADMIN) tags: - Governance parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: grantId in: path required: true schema: type: string responses: '200': description: Grant revoked '404': $ref: '#/components/responses/NotFound' /api/v1/acl/domains: get: operationId: listAclDomains summary: The collection→domain regime (ADMIN) description: Collections without a mapping sit outside the ACL regime — readable by everyone, even with the flag on. tags: - Governance parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Domain mappings '403': $ref: '#/components/responses/Forbidden' post: operationId: upsertAclDomain summary: Upsert one collection→domain mapping (ADMIN) tags: - Governance parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - collection - domain properties: collection: type: string domain: type: string description: lowercase business-domain slug (gtm finance: null …): null responses: '201': description: Mapping upserted (applies on the next request) '400': $ref: '#/components/responses/BadRequest' '403': $ref: '#/components/responses/Forbidden' /api/v1/acl/domains/{collection}: delete: operationId: removeAclDomain summary: Remove a mapping — the collection leaves the ACL regime (ADMIN) tags: - Governance parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: collection in: path required: true schema: type: string responses: '200': description: Mapping removed '404': $ref: '#/components/responses/NotFound' /api/v1/read-log: get: operationId: queryReadLog summary: The query read-log — "who read which version" (LGPD tier) description: 'One row per retrieval query (governance spec 2026-09-24 §2.2): identity in the secret_access_log pattern (actor user/agent/harness, token prefix, session), channel/operation, the query as a HASH (the text is never stored — LGPD) and docs_touched, the (doc_hash, revision_count) pairs frozen at read time (cap 20). Retention: 90 hot days plus the read_log_monthly anonymous rollup. Access is privileged: persona (vbm_) tokens need the handler-scoped `read_log:read` scope (legacy `read` and scopeless tokens do NOT cover it); workspace credentials need the SaaS-resolved ADMIN role. Every query of this log is itself audited in mutation_audit as `read_log.query`. ' tags: - Governance parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: doc in: query schema: type: string description: Doc hash (full or prefix) — who read THIS document - name: actor in: query schema: type: string description: Actor user id — what THIS person read - name: channel in: query schema: type: string enum: - mcp - rest - hook - cli - name: operation in: query schema: type: string - name: from in: query schema: type: string format: date-time - name: to in: query schema: type: string format: date-time - name: limit in: query schema: type: integer minimum: 1 maximum: 200 default: 50 responses: '200': description: Read-log entries (hashes only — no query text, no document content) content: application/json: schema: type: object properties: tenant_id: type: string total: type: integer entries: type: array items: type: object properties: id: type: string created_at: type: string actor_user_id: type: - string - 'null' actor_agent: type: - string - 'null' actor_harness: type: - string - 'null' token_prefix: type: - string - 'null' session_id: type: - string - 'null' channel: type: string operation: type: string query_hash: type: - string - 'null' result_count: type: integer docs_touched: type: - array - 'null' description: Up to 20 {h, v} (doc hash, revision) pairs frozen at read time items: type: object properties: h: type: string v: type: - number - 'null' '400': $ref: '#/components/responses/BadRequest' '403': $ref: '#/components/responses/Forbidden' /api/v1/read-log/erase: post: operationId: eraseReadLogActor summary: LGPD erasure of a data subject's identity in the read-log description: 'Rights of the holder (governance spec 2026-09-24 §2.7): anonymizes the actor (actor_user_id → ''erased'') on every read-log row of the tenant via the SECURITY DEFINER function from migration 0223 — the only mutation the append-only table admits. The access facts (which documents, which versions, when) stay; the identity is gone, so the remaining rows no longer identify the person; the anonymous read_log_monthly rollup is preserved. Tier: persona tokens need explicit `read_log:write`; workspace credentials need the SaaS-resolved ADMIN role. Audited in mutation_audit as `read_log.erase`. ' tags: - Governance parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - actor_user_id properties: actor_user_id: type: string format: uuid responses: '200': description: Actor anonymized (anonymized = rows affected) '400': $ref: '#/components/responses/BadRequest' '403': $ref: '#/components/responses/Forbidden' /metrics: get: operationId: metrics summary: Prometheus metrics description: Public endpoint for Prometheus scraping. Low cardinality. tags: - Observability security: [] responses: '200': description: Prometheus text format metrics content: text/plain: schema: type: string /api/v1/trajectories: get: operationId: listTrajectories summary: List retrieval trajectories tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Trajectory list content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/roi: get: operationId: getROI summary: Get ROI metrics tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: ROI data content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/digest/send: post: operationId: sendDigest summary: Send email digest tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Digest sent content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' /api/v1/features: get: operationId: listFeatures summary: List feature flags tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Feature flags content: application/json: schema: type: object properties: features: type: object additionalProperties: type: boolean '401': $ref: '#/components/responses/Unauthorized' post: operationId: setFeature summary: Set a feature flag tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - name - enabled properties: name: type: string enabled: type: boolean responses: '200': description: Feature flag updated content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/config: get: operationId: getTenantConfig summary: Get tenant configuration tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Tenant config content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/config/{key}: put: operationId: setTenantConfigKey summary: Set a tenant configuration key tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: key in: path required: true schema: type: string pattern: ^[a-zA-Z][a-zA-Z0-9_]*$ requestBody: required: true content: application/json: schema: type: object responses: '200': description: Config key updated content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/criteria: get: operationId: getCriteria summary: Get retrieval criteria tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Criteria list content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' put: operationId: setCriteria summary: Set retrieval criteria tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object responses: '200': description: Criteria updated content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/benchmark/run: post: operationId: benchmarkRun summary: Run a benchmark tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object properties: queries: type: array items: type: string expected: type: array items: type: object responses: '200': description: Benchmark results content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/benchmark/runs: get: operationId: benchmarkListRuns summary: List benchmark runs tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Benchmark run list content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/benchmark/compare: get: operationId: benchmarkCompare summary: Compare benchmark runs tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: run_a in: query schema: type: string - name: run_b in: query schema: type: string responses: '200': description: Comparison results content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/memory/recall: post: operationId: memoryRecall summary: Token-budgeted memory recall description: Pull category-ranked memory in a fixed token budget (mem0-style). tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object properties: query: type: string budget: type: integer default: 1500 format: type: string enum: - json - markdown default: markdown responses: '200': description: Budgeted memory recall content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/memory/used: post: operationId: memoryUsed summary: Declare which memories an answer actually used (quality loop) description: 'REST mirror of the MCP `memory_used` tool. The agent declares the docids (''#ab12cd'' hex prefixes) or paths of the memories it relied on; optionally a verdict ("confirmed"/"corrected") when the user reacted to what the memory said. Feeds usage coverage, ranking signals and the trust loop. Infra agents excluded downstream. ' tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - docids properties: docids: type: array items: type: string minItems: 1 description: Docids ('#ab12cd') or document paths verdict: type: string enum: - confirmed - corrected description: User confirmed or corrected what the memory said (V5) note: type: string description: Why the memories were useful responses: '200': description: Declaration recorded content: application/json: schema: type: object properties: declared: type: integer marked: type: integer unresolved: type: array items: type: string '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' /api/v1/tenant/value-summary: get: operationId: tenantValueSummary summary: Counted value by usage family for the Impact home and digest description: 'Hero numbers (searches served, contexts delivered, memories recorded), usage families, quality coverage (sessions with declared memory_used over sessions with delivered context), active agents, knowledge timeline and per-operation breakdown. Completed days are served from the pre-computed value_daily table; the current day aggregates live; days the nightly job missed fall back to live aggregation and are reported in stale_days. Infra agents excluded from every family. ' tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: period in: query schema: type: string enum: - today - yesterday - 7d - 30d default: 7d description: Window (UTC days); yesterday is the closed digest day responses: '200': description: Value summary content: application/json: schema: type: object '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' /api/v1/memory/health: get: operationId: memoryHealth summary: Memory health diagnostics tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Health diagnostics content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/privacy/preview: post: operationId: privacyPreview summary: Preview privacy extraction tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - content properties: content: type: string responses: '200': description: Privacy preview content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/privacy/sanitize: post: operationId: privacySanitize summary: Sanitize PII from content tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - content properties: content: type: string responses: '200': description: Sanitized content content: application/json: schema: type: object properties: sanitized: type: string '401': $ref: '#/components/responses/Unauthorized' /api/v1/privacy/restore: post: operationId: privacyRestore summary: Restore sanitized content tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - content - tokens properties: content: type: string tokens: type: array items: type: object responses: '200': description: Restored content content: application/json: schema: type: object properties: restored: type: string '401': $ref: '#/components/responses/Unauthorized' /api/v1/foresights: get: operationId: listForesights summary: List foresight predictions tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Foresight list content: application/json: schema: type: object properties: foresights: type: array items: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/foresights/sweep: post: operationId: sweepForesights summary: Trigger foresight sweep tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Sweep initiated content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/foresights/{id}: get: operationId: getForesight summary: Get a specific foresight tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string responses: '200': description: Foresight details content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' patch: operationId: patchForesight summary: Update a foresight tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object responses: '200': description: Foresight updated content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' delete: operationId: deleteForesight summary: Delete a foresight tags: - Observability parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string responses: '200': description: Foresight deleted content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' /api/v1/conflicts: get: operationId: listConflicts summary: List canonical conflicts tags: - Canonical parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Conflict list content: application/json: schema: type: object properties: conflicts: type: array items: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/proposals: get: operationId: listProposals summary: List update proposals tags: - Canonical parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Proposal list content: application/json: schema: type: object properties: proposals: type: array items: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/proposals/{id}/pick: post: operationId: pickProposal summary: Pick a proposal variant tags: - Canonical parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object properties: variant: type: string responses: '200': description: Proposal picked content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/proposals/{id}/resolve: post: operationId: resolveProposal summary: Resolve a proposal tags: - Canonical parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: id in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object properties: status: type: string responses: '200': description: Proposal resolved content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/probes: get: operationId: listProbes summary: List validation probes tags: - Canonical parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Probe list content: application/json: schema: type: object properties: probes: type: array items: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/canonical/run: post: operationId: canonicalRun summary: Trigger canonical detection run tags: - Canonical parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Canonical run initiated content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' /api/v1/canonical/sources: get: operationId: listCanonicalSources summary: List canonical sources tags: - Canonical parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Source list content: application/json: schema: type: object properties: sources: type: array items: type: object '401': $ref: '#/components/responses/Unauthorized' /lifecycle/status: get: operationId: lifecycleStatus summary: Document lifecycle status tags: - Lifecycle parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Lifecycle statistics content: application/json: schema: type: object properties: active: type: integer archived: type: integer forgotten: type: integer pinned: type: integer snoozed: type: integer '401': $ref: '#/components/responses/Unauthorized' /lifecycle/sweep: post: operationId: lifecycleSweep summary: Run lifecycle sweep description: Archive stale docs, optionally purge old archives. Defaults to dry run. tags: - Lifecycle parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: content: application/json: schema: type: object properties: dry_run: type: boolean default: true responses: '200': description: Sweep result content: application/json: schema: type: object properties: dry_run: type: boolean to_archive: type: integer to_purge: type: integer '401': $ref: '#/components/responses/Unauthorized' /lifecycle/restore: post: operationId: lifecycleRestore summary: Restore archived documents tags: - Lifecycle parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: content: application/json: schema: type: object properties: query: type: string collection: type: string all: type: boolean default: false responses: '200': description: Restore result content: application/json: schema: type: object properties: restored: type: integer '401': $ref: '#/components/responses/Unauthorized' /reindex: post: operationId: reindex summary: Trigger full reindex description: Re-scan all collections, detect new/changed/deleted documents. tags: - Maintenance parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Reindex initiated content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' /graphs/build: post: operationId: buildGraphs summary: Build temporal and semantic graphs tags: - Maintenance parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: content: application/json: schema: type: object properties: graph_types: type: array items: type: string enum: - temporal - semantic - all semantic_threshold: type: number default: 0.7 responses: '200': description: Graph build initiated content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' /api/v1/collection-settings: get: operationId: listCollectionSettings summary: List all collection settings tags: - Maintenance parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Settings list content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/collection-settings/reindex: get: operationId: reindexCollectionSettings summary: Re-evaluate documents against quality gate rules tags: - Maintenance parameters: - $ref: '#/components/parameters/TenantIdHeader' responses: '200': description: Reindex result content: application/json: schema: type: object properties: ok: type: boolean collection: type: string dry_run: type: boolean total_docs: type: integer to_skip: type: integer to_index: type: integer '401': $ref: '#/components/responses/Unauthorized' post: operationId: reindexCollectionSettingsPost summary: Re-evaluate documents against quality gate rules (POST) tags: - Maintenance parameters: - $ref: '#/components/parameters/TenantIdHeader' requestBody: required: true content: application/json: schema: type: object required: - collection properties: collection: type: string dry_run: type: boolean default: false responses: '200': description: Reindex result content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /api/v1/collection-settings/{collection}: get: operationId: getCollectionSettings summary: Get settings for a collection tags: - Maintenance parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: collection in: path required: true schema: type: string responses: '200': description: Collection settings content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' put: operationId: setCollectionSettings summary: Set settings for a collection tags: - Maintenance parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: collection in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object properties: max_doc_size: type: integer skip_patterns: type: array items: type: string min_quality_score: type: number responses: '200': description: Settings updated content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' delete: operationId: deleteCollectionSettings summary: Delete settings for a collection tags: - Maintenance parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: collection in: path required: true schema: type: string responses: '200': description: Settings deleted content: application/json: schema: type: object properties: ok: type: boolean '401': $ref: '#/components/responses/Unauthorized' /generate: post: operationId: generate summary: LLM text generation (benchmark only) description: Exposes the engine's local LLM as a simple text generation API. Benchmark tooling only. tags: - Maintenance requestBody: required: true content: application/json: schema: type: object required: - prompt properties: prompt: type: string maxTokens: type: integer default: 512 maximum: 2048 temperature: type: number minimum: 0 maximum: 2 responses: '200': description: Generated text content: application/json: schema: type: object properties: text: type: string model: type: string tokens: type: integer '401': $ref: '#/components/responses/Unauthorized' /skills: get: operationId: listSkills summary: List registered skills tags: - Maintenance responses: '200': description: Skill list content: application/json: schema: type: object properties: skills: type: array items: type: object post: operationId: addSkill summary: Register a new skill tags: - Maintenance requestBody: required: true content: application/json: schema: type: object required: - name properties: name: type: string description: type: string handler: type: string responses: '200': description: Skill registered content: application/json: schema: type: object properties: ok: type: boolean /skills/{skillId}: get: operationId: getSkill summary: Get skill details tags: - Maintenance parameters: - name: skillId in: path required: true schema: type: string responses: '200': description: Skill details content: application/json: schema: type: object '404': $ref: '#/components/responses/NotFound' /setup/instructions: get: operationId: setupInstructions summary: Get setup instructions (public) tags: - Maintenance security: [] responses: '200': description: Setup instructions content: application/json: schema: type: object /admin/l0-l1/run: post: operationId: l0l1Run summary: Trigger L0/L1 generation tags: - Admin responses: '200': description: L0/L1 generation initiated content: application/json: schema: type: object properties: ok: type: boolean /export: get: operationId: exportData summary: Export documents tags: - Documents parameters: - $ref: '#/components/parameters/TenantIdHeader' - name: collection in: query schema: type: string - name: format in: query schema: type: string enum: - json - markdown default: json responses: '200': description: Exported data content: application/json: schema: type: object '401': $ref: '#/components/responses/Unauthorized' /openapi.json: get: operationId: openapiSpec summary: OpenAPI 3.1 specification (JSON) description: Returns the full API specification as JSON. tags: - Health security: [] responses: '200': description: OpenAPI specification content: application/json: schema: type: object /openapi.yaml: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__openapi_yaml x-valorbrain-live: true responses: '200': description: See the running handler /health/admin: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__health_admin x-valorbrain-live: true responses: '200': description: See the running handler /reports/usage: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__reports_usage x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/memory/team-activity: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_memory_team_activity x-valorbrain-live: true responses: '200': description: See the running handler /dashboard: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__dashboard x-valorbrain-live: true responses: '200': description: See the running handler /memory-map: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__memory_map x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/knowledge-gaps: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_knowledge_gaps x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/knowledge-gaps/{id}/resolve: post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_knowledge_gaps_id_resolve x-valorbrain-live: true responses: '200': description: See the running handler /conversations: post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__conversations x-valorbrain-live: true responses: '200': description: See the running handler /harness-coverage: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__harness_coverage x-valorbrain-live: true responses: '200': description: See the running handler /contradictions: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__contradictions x-valorbrain-live: true responses: '200': description: See the running handler /documents/changes: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__documents_changes x-valorbrain-live: true responses: '200': description: See the running handler /documents/{id}/chain: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__documents_id_chain x-valorbrain-live: true responses: '200': description: See the running handler /documents/{id}/veracity: patch: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_PATCH__documents_id_veracity x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/documents/{id}/veracity: patch: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_PATCH__api_v1_documents_id_veracity x-valorbrain-live: true responses: '200': description: See the running handler /documents/veracity/bulk: patch: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_PATCH__documents_veracity_bulk x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/documents/veracity/bulk: patch: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_PATCH__api_v1_documents_veracity_bulk x-valorbrain-live: true responses: '200': description: See the running handler /collections/health: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__collections_health x-valorbrain-live: true responses: '200': description: See the running handler /collections/{id}/lifecycle: post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__collections_id_lifecycle x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/memory/working-context: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_memory_working_context x-valorbrain-live: true responses: '200': description: See the running handler /memory/working-context: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__memory_working_context x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/scratchpad: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_scratchpad x-valorbrain-live: true responses: '200': description: See the running handler put: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_PUT__api_v1_scratchpad x-valorbrain-live: true responses: '200': description: See the running handler post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_scratchpad x-valorbrain-live: true responses: '200': description: See the running handler delete: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_DELETE__api_v1_scratchpad x-valorbrain-live: true responses: '200': description: See the running handler /scratchpad: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__scratchpad x-valorbrain-live: true responses: '200': description: See the running handler put: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_PUT__scratchpad x-valorbrain-live: true responses: '200': description: See the running handler post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__scratchpad x-valorbrain-live: true responses: '200': description: See the running handler delete: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_DELETE__scratchpad x-valorbrain-live: true responses: '200': description: See the running handler /setup/artifacts: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__setup_artifacts x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/entity-cards: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_entity_cards x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/feedback: post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_feedback x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/secrets: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_secrets x-valorbrain-live: true responses: '200': description: See the running handler post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_secrets x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/pins: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_pins x-valorbrain-live: true responses: '200': description: See the running handler post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_pins x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/pins/{id}: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_pins_id_ x-valorbrain-live: true responses: '200': description: See the running handler patch: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_PATCH__api_v1_pins_id_ x-valorbrain-live: true responses: '200': description: See the running handler delete: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_DELETE__api_v1_pins_id_ x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/session-handoffs: post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_session_handoffs x-valorbrain-live: true responses: '200': description: See the running handler get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_session_handoffs x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/team/members: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_team_members x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/team/overview: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_team_overview x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/task-state: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_task_state x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/team/messages: post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_team_messages x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/team/inbox: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_team_inbox x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/team/handoffs: post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_team_handoffs x-valorbrain-live: true responses: '200': description: See the running handler get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_team_handoffs x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/team/briefing: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_team_briefing x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/team/stream: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_team_stream x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/memory/episodes: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_memory_episodes x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/memory/episodes/{id}: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_memory_episodes_id_ x-valorbrain-live: true responses: '200': description: See the running handler /admin/queues: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__admin_queues x-valorbrain-live: true responses: '200': description: See the running handler post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__admin_queues x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/admin/tenants/{id}/api-tokens: post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_admin_tenants_id_api_tokens x-valorbrain-live: true responses: '200': description: See the running handler get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_admin_tenants_id_api_tokens x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/admin/tenants/{id}/api-tokens/{id2}: delete: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_DELETE__api_v1_admin_tenants_id_api_tokens_id2_ x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/admin/tenants/{id}/status: patch: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_PATCH__api_v1_admin_tenants_id_status x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/memory/refine: post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_memory_refine x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/runtimes/register: post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_runtimes_register x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/runtimes/heartbeat: post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_runtimes_heartbeat x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/runtimes: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_runtimes x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/kg/explore: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_kg_explore x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/kg/entity-documents: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_kg_entity_documents x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/memory/store: post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_memory_store x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/memory/confirm-sample: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_memory_confirm_sample x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/tenant/trust-summary: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_tenant_trust_summary x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/tenant/perf-summary: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_tenant_perf_summary x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/tenant/impact: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_tenant_impact x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/users/resolve-caller: post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_users_resolve_caller x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/users/channel-identities: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_users_channel_identities x-valorbrain-live: true responses: '200': description: See the running handler post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_users_channel_identities x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/audit/pubkey: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_audit_pubkey x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/audit/bundle: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_audit_bundle x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/audit/status: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_audit_status x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/audit/recent: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_audit_recent x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/read-log/summary: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_read_log_summary x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/lessons: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_lessons x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/lessons/record: post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_lessons_record x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/lessons/feedback: post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_lessons_feedback x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/arcs: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_arcs x-valorbrain-live: true responses: '200': description: See the running handler post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_arcs x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/keyed-facts/as-of: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_keyed_facts_as_of x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/keyed-facts: post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_keyed_facts x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/keyed-facts/correct: post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_keyed_facts_correct x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/authority/mandates: post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_authority_mandates x-valorbrain-live: true responses: '200': description: See the running handler get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_authority_mandates x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/harness-integrations: post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_harness_integrations x-valorbrain-live: true responses: '200': description: See the running handler get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_harness_integrations x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/memory/prepare: post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_memory_prepare x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/kg/quarantine: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_kg_quarantine x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/kg/entity-resolve/report: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_kg_entity_resolve_report x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/kg/rag-retrieve: post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_kg_rag_retrieve x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/usage/answers: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_usage_answers x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/credits/summary: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_credits_summary x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/session-bootstrap: post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_session_bootstrap x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/hooks/run: post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_hooks_run x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/decisions: post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_decisions x-valorbrain-live: true responses: '200': description: See the running handler get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_decisions x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/decisions/relations: post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_decisions_relations x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/decisions/chain: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_decisions_chain x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/decisions/similar: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_decisions_similar x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/decisions/impact: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_decisions_impact x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/provenance: post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_provenance x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/provenance/lineage: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_provenance_lineage x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/provenance/export: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_provenance_export x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/provenance/verify: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_provenance_verify x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/conflicts/detect: post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_conflicts_detect x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/fact-conflicts: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_fact_conflicts x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/conflicts/resolve: post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_conflicts_resolve x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/contradictions: get: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_GET__api_v1_contradictions x-valorbrain-live: true responses: '200': description: See the running handler /api/v1/contradictions/{n}/resolve: post: tags: - Runtime summary: Registered on this process; not yet in docs/reference/openapi.yaml operationId: live_POST__api_v1_contradictions_n_resolve x-valorbrain-live: true responses: '200': description: See the running handler components: securitySchemes: bearerAuth: type: http scheme: bearer description: VALORBRAIN_API_TOKEN or shadow tenant API key (vb_*) adminSecret: type: apiKey in: header name: Authorization description: ENGINE_ADMIN_SECRET as Bearer token moneyAdminAuth: type: http scheme: bearer bearerFormat: VALORBRAIN_API_TOKEN or ENGINE_ADMIN_SECRET description: 'Money-route credential. Accepts the engine master token or ENGINE_ADMIN_SECRET. Tenant API and MCP persona tokens are rejected. ' parameters: TenantIdHeader: name: X-Tenant-ID in: header required: false description: 'Tenant UUID for multi-tenant operations. Required when VALORBRAIN_DEFAULT_TENANT_ID is not set. Some endpoints (like ingest) always require it. ' schema: type: string format: uuid MoneyTenantIdHeader: name: X-Tenant-ID in: header required: true description: 'Explicit target tenant UUID for a money operation. The tenant is never accepted from the JSON body. ' schema: type: string format: uuid responses: BadRequest: description: Invalid request parameters or body content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' Unauthorized: description: Missing or invalid authentication content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' Forbidden: description: Insufficient permissions (admin required) content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' NotFound: description: Resource not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' BillingConflict: description: 'Source idempotency, settlement proof, provider identity, or subscription period/state conflict. Cross-tenant ownership is never disclosed. ' content: application/json: schema: $ref: '#/components/schemas/BillingEventErrorResponse' BillingUnprocessable: description: Recognized billing event that cannot be applied content: application/json: schema: $ref: '#/components/schemas/BillingEventErrorResponse' schemas: Document: type: object properties: id: type: integer description: Internal document ID hash: type: string description: Content hash (SHA-256) collection: type: string path: type: string title: type: string content_type: type: string page_type: type: string visibility: type: string enum: - private - tenant - public embed_state: type: string enum: - pending - indexed - skipped - error is_pinned: type: integer created_at: type: string format: date-time updated_at: type: string format: date-time SearchResult: type: object properties: docid: type: string filepath: type: string title: type: string score: type: number snippet: type: string body: type: string ErrorResponse: type: object required: - error properties: error: type: string CreditBalance: type: object properties: balance: type: number currency: type: string RequestContext: type: object properties: tenantId: type: string nullable: true sourceAgent: type: string nullable: true sourceSystem: type: string nullable: true sessionId: type: string nullable: true BillingEventKind: type: string enum: - subscription_activation - subscription_renewal - subscription_payment_failed - subscription_cancelled - credit_grant - refund - reversal BillingEventApplyRequest: type: object additionalProperties: false required: - source - source_id - event_kind description: 'All four subscription events require provider_subscription_id, period_start, and period_end. Activation and renewal additionally require plan_id and the complete settlement bundle. Their paid period is compared by PostgreSQL without JavaScript timestamp rounding. credit_amount must be zero for every event except credit_grant, where it must be positive. Refund and reversal are recognized but return unsupported_billing_event (422). ' allOf: - oneOf: - properties: period_start: type: 'null' period_end: type: 'null' - required: - period_start - period_end properties: period_start: type: string format: date-time period_end: type: string format: date-time - oneOf: - properties: settlement_asset: type: 'null' settlement_network: type: 'null' settlement_amount_atomic: type: 'null' settlement_decimals: type: 'null' settlement_reference: type: 'null' - required: - settlement_asset - settlement_network - settlement_amount_atomic - settlement_decimals - settlement_reference properties: settlement_asset: type: string minLength: 1 settlement_network: type: string minLength: 1 settlement_amount_atomic: oneOf: - type: string pattern: ^[0-9]{1,38}$ - type: integer minimum: 0 maximum: 9007199254740991 settlement_decimals: type: integer minimum: 0 maximum: 18 settlement_reference: type: string minLength: 1 - if: properties: event_kind: enum: - subscription_activation - subscription_renewal - subscription_payment_failed - subscription_cancelled required: - event_kind then: required: - provider_subscription_id - period_start - period_end properties: provider_subscription_id: type: string minLength: 1 period_start: type: string format: date-time period_end: type: string format: date-time - if: properties: event_kind: enum: - subscription_activation - subscription_renewal required: - event_kind then: required: - plan_id - settlement_asset - settlement_network - settlement_amount_atomic - settlement_decimals - settlement_reference properties: plan_id: type: string minLength: 1 settlement_asset: type: string minLength: 1 settlement_network: type: string minLength: 1 settlement_amount_atomic: oneOf: - type: string pattern: ^[0-9]{1,38}$ - type: integer minimum: 0 maximum: 9007199254740991 settlement_decimals: type: integer minimum: 0 maximum: 18 settlement_reference: type: string minLength: 1 - if: properties: event_kind: const: credit_grant required: - event_kind then: required: - credit_amount properties: credit_amount: type: number exclusiveMinimum: 0 else: properties: credit_amount: type: number maximum: 0 properties: source: type: string minLength: 1 maxLength: 128 pattern: ^[A-Za-z0-9:_-]+$ description: 'Provider-qualified source. Subscription events use stripe:*, solana:mpp:*, or manual_contract:*. ' source_id: type: string minLength: 1 maxLength: 512 description: Globally stable provider event identity. event_kind: $ref: '#/components/schemas/BillingEventKind' plan_id: type: - string - 'null' maxLength: 64 provider_subscription_id: type: - string - 'null' maxLength: 512 period_start: type: - string - 'null' format: date-time description: 'RFC3339 with an explicit timezone. Original text is preserved in canonical hashing and final event results. ' period_end: type: - string - 'null' format: date-time description: 'RFC3339 with an explicit timezone and later than period_start. ' settlement_asset: type: - string - 'null' maxLength: 16 description: Normalized to uppercase. settlement_network: type: - string - 'null' maxLength: 128 description: Normalized to lowercase before hashing and proof uniqueness checks. settlement_amount_atomic: oneOf: - type: string pattern: ^[0-9]{1,38}$ - type: integer minimum: 0 maximum: 9007199254740991 - type: 'null' settlement_decimals: type: - integer - 'null' minimum: 0 maximum: 18 settlement_reference: type: - string - 'null' maxLength: 512 description: 'Globally unique together with lowercase settlement_network when present, regardless of source or tenant. ' credit_amount: type: number minimum: 0 maximum: 1000000000 multipleOf: 1.0e-08 default: 0 provider_metadata: type: object additionalProperties: true description: 'Small public provider references only. Secret, private, credential, token, mandate, authorization, and signature keys are rejected. ' metadata: type: object additionalProperties: true description: 'Non-sensitive metadata copied to the credit ledger when applicable. The same secret/private/token/mandate/signature key filter applies. ' BillingSubscriptionSnapshot: type: object required: - plan_id - status - billing_provider - provider_subscription_id - current_period_start - current_period_end - grace_until properties: plan_id: type: string status: type: string enum: - free - incomplete - active - past_due - cancelled - expired billing_provider: type: - string - 'null' enum: - stripe - solana_mpp - manual_contract - null provider_subscription_id: type: - string - 'null' current_period_start: type: - string - 'null' format: date-time current_period_end: type: - string - 'null' format: date-time grace_until: type: - string - 'null' format: date-time BillingCreditResult: type: object required: - granted - balance_after properties: granted: type: number balance_after: type: number BillingEventApplyResult: type: object required: - event_id - applied - replay - subscription description: 'Subscription is null for pure credit_grant events. Ignored events keep applied false and include a stable ignored_reason. An identical source replay sets replay true and applied false while preserving the stored subscription, credit, ignored_reason, and event id. ' properties: event_id: type: string format: uuid applied: type: boolean replay: type: boolean subscription: oneOf: - $ref: '#/components/schemas/BillingSubscriptionSnapshot' - type: 'null' ignored_reason: type: string enum: - stale_period - subscription_cancelled - grace_elapsed credit: $ref: '#/components/schemas/BillingCreditResult' BillingEventRecord: type: object required: - id - tenant_id - source - source_id - event_kind - request_hash - credit_amount - result - created_at properties: id: type: string format: uuid tenant_id: type: string format: uuid source: type: string source_id: type: string event_kind: $ref: '#/components/schemas/BillingEventKind' request_hash: type: string pattern: ^[0-9a-f]{64}$ plan_id: type: - string - 'null' provider_subscription_id: type: - string - 'null' period_start: type: - string - 'null' format: date-time period_end: type: - string - 'null' format: date-time settlement_asset: type: - string - 'null' settlement_network: type: - string - 'null' description: Lowercase canonical network identifier. settlement_amount_atomic: type: - string - 'null' pattern: ^[0-9]+$ settlement_decimals: type: - integer - 'null' settlement_reference: type: - string - 'null' credit_amount: type: string description: PostgreSQL numeric serialized without precision loss. result: $ref: '#/components/schemas/BillingEventApplyResult' created_at: type: string format: date-time BillingEventsResponse: type: object required: - events properties: events: type: array items: $ref: '#/components/schemas/BillingEventRecord' SubscriptionCreditGrantRequest: type: object additionalProperties: false required: - invoice_id - subscription_id - plan_id - amount description: 'Legacy Stripe invoice credit. It is journaled as credit_grant and never creates, reads, or mutates tenant_subscriptions. ' properties: invoice_id: type: string minLength: 1 maxLength: 512 subscription_id: type: string minLength: 1 maxLength: 512 plan_id: type: string minLength: 1 maxLength: 64 amount: type: number exclusiveMinimum: 0 maximum: 1000000000 multipleOf: 1.0e-08 period_start: type: - string - 'null' format: date-time period_end: type: - string - 'null' format: date-time SubscriptionCreditGrantResponse: type: object required: - ok - balance_after - granted properties: ok: type: boolean enum: - true balance_after: type: number description: Zero on an identical legacy invoice replay. granted: type: number description: Zero on an identical legacy invoice replay. idempotent_skip: type: boolean BillingEventErrorResponse: type: object required: - error properties: error: type: string description: 'Includes idempotency_conflict, settlement_proof_conflict, subscription_provider_conflict, subscription_period_conflict, invalid_subscription_transition, and unsupported_billing_event. ' message: type: string description: Present for validation errors; omitted for conflicts and higher statuses. ``` # CLI help --json (published package) ``` { "name": "@valorbrain/cli", "version": "0.1.1", "config": "~/.valorbrain/config.json", "default_rest_base_url": "https://valorbrain-api.valor.digital", "default_mcp_url": "https://mcpbrain.valor.digital/mcp", "global_flags": [ { "flag": "--json", "aliases": [ "--agent" ], "description": "machine-readable output" }, { "flag": "--key", "description": "API key override" }, { "flag": "--url", "description": "REST base URL override" } ], "commands": [ { "name": "init", "usage": "init --agent [--agent-caller ] | init --email
[--otp ]", "description": "create an agent account or claim it with an email" }, { "name": "identify", "usage": "identify ", "description": "idempotent agent_caller backfill" }, { "name": "add", "usage": "add [--file ] [--collection ] [--title ] [--type ]", "description": "store a memory" }, { "name": "search", "usage": "search [--collection ] [--mode auto|keyword|semantic|hybrid]", "description": "search memories" }, { "name": "list", "usage": "list", "description": "list collections" }, { "name": "status", "usage": "status", "description": "local config + remote health" }, { "name": "mcp", "usage": "mcp [--token vbm_…] [--url ]", "description": "stdio ⇄ HTTP MCP proxy" }, { "name": "help", "usage": "help [--json]", "description": "this surface, machine-readable with --json" } ] } ``` # MCP tool schemas (registerTool metadata) # MCP tool schemas Generated from `/opt/valorbrain/src/mcp-tools.ts`. 100 registerTool() calls. This is the description and input shape the MCP server advertises. ## memory_retrieve Unified memory retrieval — one call is enough for most questions (server expands/fuses queries). Prefer a SINGLE well-formed query; do not fire 5 near-duplicate retrieves. Auto-routing: why→causal, last session→timeline, related→neighbors, general→hybrid. Params: - limit / max_results: how many hits to return (default 12; try 15–20 for broad topics). - expand: server-side query expansion + score fusion (default true). - snippet_chars: chars of body preview per hit (default 200) so you often skip get(). - budget: TOKEN budget for category-ranked recall mode (different from max_results). After search: multi_get only for full bodies when snippet is insufficient. ``` z.object({ query: z.string().describe("Your question or search query (one clear query; avoid spamming variants)"), mode: z.enum(["auto", "keyword", "semantic", "causal", "timeline", "discovery", "complex", "hybrid"]).optional().default("auto"), limit: z.number().optional().default(12).describe("Max ranked results to return (alias: max_results)"), max_results: z.number().optional().describe("Alias for limit — max ranked results (FB-0022)"), compact: z.boolean().optional().default(true), vault: z.string().optional(), expand: z.boolean().optional().describe("Server-side expansion + RRF fusion. Default: auto (server decides based on corpus size). Set true to force, false for fastest response."), snippet_chars: z.number().optional().default(200).describe("Snippet length in compact mode (default 200)"), budget: z.number().optional().describe("TOKEN budget for category-ranked recall (not result count). Prefer limit/max_results for hit count."), recall_format: z.enum(["json", "markdown"]).optional(), min_score: z.number().optional().describe("Descarta resultados com composite score abaixo deste valor (0-1)"), }), } ``` ## memory_recent Answer "what did agent X do recently?" — author+recency scoped list of work-product docs (decision/milestone/handoff/lesson/problem/observation) by documents.source_agent, newest first. Use it to evaluate or continue another agent's recent work: memory_retrieve is topic-based and titles do not carry the author, so topic search cannot answer author questions. agent: author slug (e.g. 'zcode', 'kiro-cli', 'hermes-plugin'); omit for any author. hours (default 24) or since (ISO date, overrides hours; window capped at 30 days). types: content_type allowlist (pass ['note'] to include transcripts). query: optional — keep only docs matching at least one query term (title/path/body preview). ``` z.object({ agent: z.string().optional().describe("Author slug — documents.source_agent. Omit for any author."), hours: z.number().optional().default(24).describe("Recency window in hours (default 24, max 720)"), since: z.string().optional().describe("ISO date/datetime lower bound on created_at (overrides hours)"), types: z.array(z.string()).optional().describe("content_type allowlist (default: work-product types)"), limit: z.number().optional().default(12).describe("Max items (default 12, max 40)"), query: z.string().optional().describe("Optional topic filter over title/path/body preview"), vault: z.string().optional(), }), } ``` ## memory_store We decided to use PostgreSQL instead of MongoDBThe API rate limit is 100/minRoot cause: missing FOR UPDATE in the queryDeployed v2.0 to production ``` z.object({ type: z.union([ z.enum(['decision', 'observation', 'problem', 'milestone', 'handoff', 'lesson', 'note']), z.string(), ]).describe("Memory type: decision | observation | problem | milestone | handoff | lesson | note. Near-misses (insight, fact, info, issue, bug, learning, task, plurals, any case) are auto-mapped; anything else is rejected with the allowed list."), title: z.string().min(5).max(200).describe("Short title (5-200 chars). Will appear in search results and dashboard."), content: z.string().min(20).describe("Full memory content in markdown. Include context, reasoning, and evidence."), collection: z.string().optional().describe("Collection name (default: '_valorbrain'). Use a custom name to group related memories."), tags: z.array(z.string()).optional().describe("Optional tags for categorization."), confidence: z.number().min(0).max(1).optional().describe("Confidence score 0-1 (default: 0.8 for decisions, 0.6 for observations)."), visibility: z.enum(['tenant', 'private']) .optional() .default('tenant') .describe("Who can read this memory. 'tenant' (default) = everyone in the company sees it, with you as the author. 'private' = only you. Company memory is the product default — go private only for personal or sensitive notes."), }), } ``` ## task_state The working state of the current task, persisted and cross-session. goal sets what done means (appears in __goals__ of every memory_prepare); progress records milestones (__progress__, 48h); read returns goal + ledger + recent progress. ledger is the five-line J-Space discipline with SERVER-ENFORCED epistemic rules: ledger_open requires goal+next; ledger_checkpoint requires verified_by WITH stated coverage ('verified without coverage is a mood, not a result'); ledger_open_question requires settled_by (the cheapest test that could refute it); next is never empty. Open a goal when starting long-horizon work; checkpoint at each verified step; re-read after compaction or session boundaries. ``` z.object({ action: z.enum(["goal", "progress", "ledger_open", "ledger_checkpoint", "ledger_open_question", "ledger_next", "read"]), slug: z.string().min(2).max(60).optional().describe("goal: short stable identifier, e.g. 'ship-v2-release'"), description: z.string().min(10).max(500).optional().describe("goal/ledger_open: what done means; progress: the milestone title"), status: z.string().optional().default("active").describe("goal: active, paused, complete"), detail: z.string().optional().describe("progress: additional context, blockers, next steps"), session: z.string().optional().describe("ledger/read: session key (defaults to the MCP token session)"), what: z.string().optional().describe("ledger_checkpoint: what now holds"), verified_by: z.string().optional().describe("ledger_checkpoint: what verified it AND what the verification covered (e.g. 'full suite, 2 passes, all files')"), question: z.string().optional().describe("ledger_open_question: the unsettled question"), settled_by: z.string().optional().describe("ledger_open_question: the cheapest test that could refute it"), next: z.string().optional().describe("ledger_open/ledger_next: the single next action"), }), } ``` ## set_goal DEPRECATED — use task_state with action goal. Create or update an active goal. Goals persist across sessions and are delivered to any agent via the __goals__ block in memory_prepare. ``` z.object({ slug: z.string().min(2).max(60).describe("Short stable identifier, e.g. 'ship-v2-release'"), description: z.string().min(10).max(500).describe("What the goal is, current status, next steps"), status: z.string().optional().default("active").describe("Goal status: active, paused, complete"), }), } ``` ## report_progress DEPRECATED — use task_state with action progress. Record a progress milestone. Appears in the __progress__ block of memory_prepare for the next 48 hours. ``` z.object({ title: z.string().min(5).max(200).describe("What was accomplished, e.g. 'Completed API migration, 60% of release done'"), detail: z.string().optional().describe("Additional context, blockers, or next steps"), }), } ``` ## memory_forget Remove a memory. Prefer path or docid for precise deletion. Query does fuzzy match (less safe). ``` z.object({ query: z.string().optional().describe("What to forget — fuzzy search for closest match (less precise)"), path: z.string().optional().describe("Exact collection/path to deactivate (e.g. 'gbrain_full_2026_06_20_companies/companies/vitru.md'). Safe — no fuzzy matching."), docid: z.string().optional().describe("Exact doc ID (e.g. '#cbde70' or '850559'). Safe — no fuzzy matching."), confirm: z.boolean().optional().default(true).describe("If true, deactivates. If false, previews what would be forgotten."), vault: z.string().optional().describe("Named vault (omit for default vault)"), }), } ``` ## profile Get the current user profile (static facts + dynamic context). Rebuild if stale. ``` z.object({ rebuild: z.boolean().optional().default(false).describe("Force rebuild the profile"), rollback: z.boolean().optional().describe("Revert the profile to the previous snapshot (prime-agent /refine pattern)"), rollback_hash: z.string().optional().describe("Roll back to a specific content hash (defaults to the most recent history entry)"), vault: z.string().optional().describe("Named vault (omit for default vault)"), }), } ``` ## working_context One-shot stable facts + recent decisions/how-tos + optional session scratchpad. Prefer this at session start. ``` z.object({ session_id: z.string().optional().describe("Session id for scratchpad slice"), format: z.enum(["markdown", "json"]).optional().default("markdown"), vault: z.string().optional(), }), } ``` ## scratchpad Read/write/clear ephemeral reasoning notes for this session. Not indexed in hybrid search. ``` z.object({ action: z.enum(["read", "write", "clear", "append"]).describe("Operation"), session_id: z.string().describe("Session id (required)"), text: z.string().optional().describe("Body for write/append"), vault: z.string().optional(), }), } ``` ## get USE THIS for reading a file. Returns the document content by path or docid with optional line range. If you only need a snippet, set fromLine/maxLines. ``` z.object({ file: z.string().describe("File path or docid (#abc123)"), fromLine: z.number().optional(), maxLines: z.number().optional(), lineNumbers: z.boolean().optional().default(false), vault: z.string().optional().describe("Named vault (omit for default vault)"), }), } ``` ## multi_get Retrieve multiple documents by glob pattern or comma-separated list. ``` z.object({ pattern: z.string().describe("Glob pattern or comma-separated paths"), maxLines: z.number().optional(), maxBytes: z.number().optional().default(10240), lineNumbers: z.boolean().optional().default(false), vault: z.string().optional().describe("Named vault (omit for default vault)"), }), } ``` ## find_similar USE THIS for 'what else relates to X', 'show me similar docs'. Finds k-NN vector neighbors of a reference document — discovers connections beyond keyword overlap that search/query cannot find. ``` z.object({ file: z.string().describe("Path of reference document"), limit: z.number().optional().default(5), vault: z.string().optional().describe("Named vault (omit for default vault)"), }), } ``` ## reindex Refresh all collections from the database. Detects stale embeddings and re-embeds documents that need it. Also cleans up orphaned FTS entries. ``` z.object({ vault: z.string().optional().describe("Named vault (omit for default vault)"), }), } ``` ## operations Long operations submitted with run_async=true. status checks a handle (wait_ms long-polls instead of spinning); list shows recent operations in the tenant, newest first — find a lost handle or see whether a reindex is already running; cancel asks a runner to stop cooperatively at its next checkpoint. ``` z.object({ action: z.enum(["status", "list", "cancel"]).describe("Operation verb"), handle: z.string().optional().describe("status/cancel: operation handle (op_...)"), wait_ms: z.number().optional().describe("status: block up to this long (max 60000)"), status: z.enum(["queued", "running", "succeeded", "failed", "cancelled"]).optional().describe("list: filter"), operation: z.string().optional().describe("list: filter by tool name"), limit: z.number().optional().describe("list: default 20, max 100"), vault: z.string().optional(), }), } ``` ## operation_status DEPRECATED — use operations with action status. Check a long operation submitted with run_async=true. Returns status, progress and, once finished, the result. Pass wait_ms to long-poll instead of spinning on it. ``` z.object({ handle: z.string().describe("Operation handle (op_...)"), wait_ms: z.number().optional().describe("Block up to this long waiting for it to finish (max 60000)"), vault: z.string().optional(), }), } ``` ## operation_list DEPRECATED — use operations with action list. Recent long operations in this tenant, newest first. Use to find a handle you lost, or to see whether somebody else already has a reindex running. ``` z.object({ status: z.enum(["queued", "running", "succeeded", "failed", "cancelled"]).optional(), operation: z.string().optional().describe("Filter by tool name"), limit: z.number().optional().describe("Default 20, max 100"), vault: z.string().optional(), }), } ``` ## operation_cancel DEPRECATED — use operations with action cancel. Ask a running operation to stop. Cooperative: the runner stops at its next checkpoint, so a half-written reindex is not left behind. ``` z.object({ handle: z.string().describe("Operation handle (op_...)"), vault: z.string().optional(), }), } ``` ## memory_used Declare quais memórias você realmente usou na resposta (docids como '#ab12cd', ou caminhos) — declare o conjunto COMPLETO do working set, não só as mais óbvias. Uma linha no seu prompt de sistema chamando esta ferramenta antes da resposta final registra uso declarado separado de recuperação. Para um comprovante antes da resposta final, envie receipt:{task_id,result} e note explicando a contribuição. Opcional (contabilidade honesta, graft-style): saved_tokens (economia estimada de tokens/contexto), waste_avoided (descreva O QUE foi evitado em linguagem humana, sem usar a palavra 'evitado' — ex.: '240 perguntas de benchmark desperdiçadas (protocolo errado)') e discounted (consultas que não geraram ganho). O receipt.summary estima tokens do conteúdo consultado e conta memórias criadas hoje que foram reutilizadas; economia aparece rotulada (declarada). Retorna receipt.summary sem LLM adicional; uso declarado, não prova causalidade. docids:[] com receipt declara ausência de uso. ``` z.object({ docids: z .array(z.string()) .min(0) .describe("Docids ('#ab12cd') ou caminhos das memórias efetivamente usadas"), verdict: z .enum(["confirmed", "corrected"], { error: "verdict must be 'confirmed' or 'corrected'" }) .optional() .describe("V5: o usuário CONFIRMOU o que a memória dizia ('confirmed') ou CORRIGIU/contradisse ('corrected') nesta resposta. Declare junto com os docids."), outcome: z .enum(["success", "failure", "partial"], { error: "outcome must be 'success', 'failure' or 'partial'" }) .optional() .describe("Eixo outcome: agir sobre estas memórias FUNCIONOU ('success'), FALHOU ('failure') ou ajudou em parte ('partial')? Distinto do verdict — uma memória pode ser verdadeira e ainda assim não resolver a tarefa. Falha não é punida: é o sinal que alimenta a próxima correção."), query: z .string() .max(2000) .optional() .describe("A pergunta/mensagem que motivou este uso — vira o lado esquerdo do par (query → memória) que treina o reranker de utilidade e alimenta o eixo de confiabilidade de produtor. Envie sempre que fizer sentido (a mensagem do usuário da resposta atual)."), note: z.string().optional().describe("Por que serviu (opcional, entra no registro)"), receipt: ContributionReceiptRequestSchema.optional(), saved_tokens: z.number().int().min(1).max(100_000_000).optional() .describe("Economia estimada de tokens/contexto (declarada, exibida rotulada como declarada)"), waste_avoided: z.string().max(120).optional() .describe("Uma linha do desperdício evitado (letras/números/pontuação básica). Ex.: 'run de 240 perguntas de LLM evitado'"), discounted: z.number().int().min(0).max(50).optional() .describe("Consultas que não geraram ganho — o desconto honesto"), vault: z.string().optional(), }).refine((input) => input.docids.length > 0 || input.receipt !== undefined, "docids must not be empty unless receipt is requested"), } ``` ## memory_grep Busca por expressão regular no texto cru das memórias, devolvendo caminho e número de linha. Use quando a pergunta é exata e não aproximada: um valor, uma chave, um identificador, uma data, o que mudou entre duas versões. `memory_retrieve` acha o que é parecido; este acha o que é igual, e devolve só a linha — o que custa muito menos token que um trecho inteiro. Sintaxe do Postgres (ARE): \\d, \\y e classes funcionam, lookahead não. ``` z.object({ pattern: z.string().describe("Expressão regular (sintaxe POSIX do Postgres)"), collection: z.string().optional().describe("Restringe a uma coleção"), since: z.string().optional().describe("Só documentos modificados desde esta data (ISO)"), path: z.string().optional().describe("Restringe a um caminho exato (collection/path ou path)"), docid: z.string().optional().describe("Restringe ao documento do docid (#abc123)"), timeout_ms: z.number().optional().describe("Teto de tempo da varredura em ms (1000-30000; default do servidor)"), context: z .boolean() .optional() .describe("Inclui a linha anterior e a seguinte de cada acerto"), case_sensitive: z.boolean().optional().describe("Diferencia maiúscula (padrão: não)"), limit: z.number().optional().describe("Teto de linhas (padrão 40, máx 200)"), doc_limit: z.number().optional().describe("Teto de documentos varridos (padrão 200)"), vault: z.string().optional(), }), } ``` ## usage_report Uso medido deste tenant: operações por canal (MCP, REST, hook), por ferramenta, por pessoa/agente, latência p50/p95, resultados devolvidos e série diária. Use para responder 'quantas consultas fizemos este mês' e para dimensionar valor entregue. Contagem direta do ledger — sem estimativa. ``` z.object({ period: z .enum(["today", "week", "month", "quarter"]) .optional() .describe("Janela do relatório (padrão: month = 30 dias)"), vault: z.string().optional(), }), } ``` ## harness_coverage Cobertura de entrega dos harnesses/agentes deste tenant: cruza atividade (uso de ferramentas) com ingestão (sessões entregues). Um agente listado como SILENT consulta a memória mas nunca entrega sessões — configurado pela metade. Use quando o usuário perguntar se a integração está completa/saudável, ou periodicamente: a saída traz o conserto exato para levar ao usuário. ``` z.object({ days: z.number().int().min(1).max(90).optional() .describe("Janela em dias (padrão 7)"), min_activity: z.number().int().min(1).optional() .describe("Mínimo de chamadas para contar como ativo (padrão 10)"), vault: z.string().optional(), }), } ``` ## index_stats Detailed index statistics with content type distribution, staleness info, and memory health. ``` z.object({ vault: z.string().optional().describe("Named vault (omit for default vault)"), }), } ``` ## beads_sync Sync Beads issues from Dolt backend (bd CLI) into ValorBrain search index. Queries live Dolt database — no stale JSONL dependency. ``` z.object({ project_path: z.string().optional().describe("Path to project with .beads/ directory (default: cwd)"), vault: z.string().optional().describe("Named vault (omit for default vault)"), }), } ``` ## build_graphs Build temporal and semantic graphs for MAGMA multi-graph memory. Run after indexing documents. ``` z.object({ graph_types: z.array(z.enum(['temporal', 'semantic', 'all'])).optional().default(['all']), semantic_threshold: z.number().optional().default(0.7).describe("Similarity threshold for semantic edges (0.0-1.0)"), vault: z.string().optional().describe("Named vault (omit for default vault)"), }), } ``` ## find_causal_links USE THIS to trace decision chains: 'what led to X', 'trace how we got from A to B'. Follow up intent_search with this tool on a top result to walk the full causal chain. Returns depth-annotated links with reasoning. ``` z.object({ docid: z.string().describe("Document ID (e.g., '#123' or path)"), direction: z.enum(['causes', 'caused_by', 'both']).optional().default('both').describe("Direction: 'causes' (outbound), 'caused_by' (inbound), or 'both'"), depth: z.number().optional().default(5).describe("Maximum traversal depth (1-10)"), vault: z.string().optional().describe("Named vault (omit for default vault)"), }), } ``` ## kg_query Query the knowledge graph for an entity's relationships. Supports multihop traversal (2-3 hops) via pg_ripple SPARQL when VALORBRAIN_KG_ENGINE=hybrid|ripple. Returns structured facts with temporal validity (valid_from/valid_to). Use for 'what does X relate to?', 'what was true about X on date Y?', 'who/what is connected to X?'. Accepts an entity name (e.g. 'ValorBrain') OR a canonical entity ID in the form 'vault:type:slug' (e.g. 'default:service:valorbrain'). ``` z.object({ entity: z.string().describe("Entity name or canonical ID ('vault:type:slug') to query"), as_of: z.string().optional().describe("Date filter (YYYY-MM-DD) — only facts valid at this date"), direction: z.enum(["outgoing", "incoming", "both"]).optional().default("both").describe("Relationship direction"), max_hops: z.number().int().min(1).max(4).optional().describe("Graph traversal depth (1=star only, 2-3=multihop). Default from VALORBRAIN_KG_MAX_HOPS (2)."), vault: z.string().optional().describe("Named vault (omit for default vault)"), }), } ``` ## kg_explain Explain why a KG fact holds, including Datalog inference proof trees when pg_ripple.record_derivations is enabled. Pass entity names/IDs for subject and object (or object_literal for literal facts). ``` z.object({ subject: z.string().describe("Subject entity name or canonical ID"), predicate: z.string().describe("Predicate (e.g. depends_on, runs_on)"), object: z.string().optional().describe("Object entity name or canonical ID"), object_literal: z.string().optional().describe("Object literal value (mutually exclusive with object)"), vault: z.string().optional().describe("Named vault (omit for default vault)"), }), } ``` ## memory_evolution_status Get the evolution timeline for a memory document, showing how its keywords and context have changed over time based on new evidence. ``` z.object({ docid: z.string().describe("Document ID (e.g., '#123' or path)"), limit: z.number().optional().default(10).describe("Maximum number of evolution entries to return (1-100)"), vault: z.string().optional().describe("Named vault (omit for default vault)"), }), } ``` ## timeline Show the temporal neighborhood around a document — what was created/modified before and after it. Token-efficient progressive disclosure: search → timeline (context) → get (full content). Use after finding a document via search to understand what happened around it. ``` z.object({ docid: z.string().describe("Document ID (e.g., '#123' or short hash)"), before: z.number().optional().default(5).describe("Number of documents to show before the focus (1-20)"), after: z.number().optional().default(5).describe("Number of documents to show after the focus (1-20)"), same_collection: z.boolean().optional().default(false).describe("Constrain to same collection (like session scoping)"), vault: z.string().optional().describe("Named vault (omit for default vault)"), }), } ``` ## memory_curate Curate a memory's surfacing: pin for permanent prioritization (+0.3 boost), unpin, snooze to hide for N days, or unsnooze. USE PROACTIVELY: pin when the user states a persistent constraint, makes an architecture decision, or corrects a misconception; snooze when vault-context repeatedly surfaces irrelevant content (30 days by default). Resolves by docid (#abc123, exact), path, or search query. A search query needs at least one term in common with the target (path/title) — otherwise nothing is curated. ``` z.object({ action: z.enum(["pin", "unpin", "snooze", "unsnooze"]).describe("Curate verb"), query: z.string().optional().describe("Target: path or search query (required when docid is absent)"), docid: z.string().optional().describe("Exact document id (#abc123) — takes precedence over query"), until: z.string().optional().describe("snooze only: ISO date to snooze until (default 30 days)"), vault: z.string().optional().describe("Named vault (omit for default vault)"), }), } ``` ## memory_pin DEPRECATED — use memory_curate with action pin/unpin. Pin a memory for permanent prioritization (+0.3 boost). USE PROACTIVELY when: user states a persistent constraint, makes an architecture decision, or corrects a misconception. Don't wait for curator — pin critical decisions immediately. ``` z.object({ query: z.string().describe("Search query to find the memory to pin/unpin"), unpin: z.boolean().optional().default(false).describe("Set true to unpin"), vault: z.string().optional().describe("Named vault (omit for default vault)"), }), } ``` ## memory_snooze DEPRECATED — use memory_curate with action snooze/unsnooze. Temporarily hide a memory from context surfacing. USE PROACTIVELY when vault-context repeatedly surfaces irrelevant content — snooze it for 30 days instead of ignoring it. Reduces noise for future sessions. ``` z.object({ query: z.string().describe("Search query to find the memory to snooze"), until: z.string().optional().describe("ISO date to snooze until (e.g. 2026-03-01). Omit to unsnooze."), vault: z.string().optional().describe("Named vault (omit for default vault)"), }), } ``` ## lifecycle_status Show document lifecycle statistics: active, archived, forgotten, pinned, snoozed counts and policy summary. Also lists the pin/snooze CANDIDATES with docid/path and metrics (FB-0028) so they can be acted on with memory_curate. ``` z.object({ vault: z.string().optional().describe("Named vault (omit for default vault)"), candidates_limit: z.number().optional().default(10).describe("how many pin/snooze candidates to list (0 = counts only, max 100)"), }), } ``` ## ripple_rag_retrieve Neuro-symbolic RAG via pg_ripple.rag_retrieve with 500ms budget (VB-3203). Returns entity context JSON for LLM grounding. ``` z.object({ question: z.string().describe("Natural language question"), k: z.number().optional().default(5), budget_ms: z.number().optional().default(500), sparql_filter: z.string().optional(), vault: z.string().optional(), }), } ``` ## entity_cards Entity surface in one place. action=list: stable identity cards do tenant (filtros entity_type, min_mentions/max_mentions, name_contains, quarantined=only para auditar). action=alias_propose: sugere fusões de entidades que são a MESMA coisa (nome curto prefixo de nome longo, co-ocorrendo em >= 3 docs) e marca AMBÍGUO quando o prenome tem vários candidatos. action=alias_merge: funde (decisão do tenant — nada é automático); action=alias_reject: registra que NÃO são a mesma pessoa/coisa (a sugestão não volta). ``` z.object({ action: z.enum(["list", "alias_propose", "alias_merge", "alias_reject"]).optional().default("list"), limit: z.number().optional().default(50), offset: z.number().optional().default(0), entity_type: z.string().optional().describe("list: canonical type (person, org, project, service, tool, concept, product, agent, location)"), min_mentions: z.number().optional().describe("list: minimum document mentions (evidence of the entity node)"), max_mentions: z.number().optional().describe("list: maximum document mentions"), name_contains: z.string().optional().describe("list: entity name or card text contains"), quarantined: z.enum(["exclude", "include", "only"]).optional().default("exclude").describe("list: quarantine view: exclude (default), include, only (audit)"), canonical: z.string().optional().describe("alias_merge: nome ou entity_id da canônica que fica"), alias: z.string().optional().describe("alias_merge/reject: nome ou entity_id que vira apelido (merge aceita lista por vírgula)"), longo: z.string().optional().describe("alias_reject: candidato rejeitado (omita para rejeitar o prenome inteiro)"), vault: z.string().optional(), }), } ``` ## list_entity_cards DEPRECATED — use entity_cards com action=list (a curadoria de apelido também vive lá). ``` z.object({ limit: z.number().optional().default(50), offset: z.number().optional().default(0), entity_type: z.string().optional(), min_mentions: z.number().optional(), max_mentions: z.number().optional(), name_contains: z.string().optional(), quarantined: z.enum(["exclude", "include", "only"]).optional().default("exclude"), vault: z.string().optional(), }), } ``` ## append_entity_card Append IDENTITY/ATTRIBUTE/RELATIONSHIP/INSTRUCTION entries to an entity card. ``` z.object({ entity_id: z.string(), entries: z.array(z.string()), vault: z.string().optional(), }), } ``` ## episodes Bounded dialogue episodes (MemCell summaries) for episodic retrieval. list shows recent episodes (optionally by user); get fetches one by UUID. ``` z.object({ action: z.enum(["list", "get"]).describe("Episode verb"), limit: z.number().optional().default(20).describe("list: max episodes"), user_id: z.string().optional().describe("list: filter by user"), episode_id: z.string().optional().describe("get: episode UUID"), vault: z.string().optional(), }), } ``` ## list_memory_episodes DEPRECATED — use episodes with action list. List bounded dialogue episodes (MemCell summaries) for episodic retrieval. ``` z.object({ limit: z.number().optional().default(20), user_id: z.string().optional(), vault: z.string().optional(), }), } ``` ## get_memory_episode DEPRECATED — use episodes with action get. Fetch a single memory episode by UUID. ``` z.object({ episode_id: z.string(), vault: z.string().optional(), }), } ``` ## kg_quarantine Triples rejected by the SHACL pre-check awaiting human review. list shows the queue; approve re-validates and persists a triple into entity_triples; reject discards it permanently. Curator surface. ``` z.object({ action: z.enum(["list", "approve", "reject"]).describe("Quarantine verb"), quarantine_id: z.string().uuid().optional().describe("approve/reject: the quarantine entry id"), limit: z.number().optional().default(50).describe("list: max entries"), vault: z.string().optional(), }), } ``` ## list_kg_quarantine DEPRECATED — use kg_quarantine with action list. List triples rejected by SHACL pre-check awaiting human review. ``` z.object({ limit: z.number().optional().default(50), vault: z.string().optional(), }), } ``` ## approve_kg_quarantine DEPRECATED — use kg_quarantine with action approve. Re-validate and persist an approved quarantined triple into entity_triples. ``` z.object({ quarantine_id: z.string().uuid(), vault: z.string().optional(), }), } ``` ## reject_kg_quarantine DEPRECATED — use kg_quarantine with action reject. Permanently discard a quarantined triple candidate. ``` z.object({ quarantine_id: z.string().uuid(), vault: z.string().optional(), }), } ``` ## kg_entity_resolve_report VB-3306 dedup report: eval-suite hit rate + near-duplicate entity pairs. ``` z.object({ vault: z.string().optional() }), } ``` ## memory_prepare PMB-style single-call context assembly: recall + vault-facts + foresights + funnel (episodes, lessons, keyed facts, top docs). ``` z.object({ message: z.string().describe("User message or query to prepare context for"), surface_id: z.string().optional().describe("Surface for lesson filtering"), collection: z.string().optional().describe("Collection scope for funnel search"), episode_id: z.string().optional().describe("Episode UUID for scoped hybrid retrieval"), recall_budget: z.number().optional().default(600), fast_mode: z.boolean().optional().default(false).describe( "Skip funnel document retrieval (embedding + hybrid search). " + "Recall still covers docs by category. Use for low-latency hooks." ), vault: z.string().optional(), }), } ``` ## record_lesson Record or verify a procedural lesson for a surface (PMB-style follow-through). Dedupes on surface_id + content; set verify=true to bump follow-through score. Pass approve_lesson_id to approve a pending candidate filed by an outcome=failure report (content optionally refines the lesson text); re-recording the same surface_id+content also activates a pending twin. ``` z.object({ surface_id: z.string().describe("Surface or workflow this lesson applies to"), content: z.string().describe("Lesson text (what to do / avoid)"), evidence: z.string().optional().describe("Supporting evidence or citation"), episode_id: z.string().optional().describe("Linked episode UUID"), verify: z.boolean().optional().default(false).describe("Bump verification count"), approve_lesson_id: z.string().optional().describe("Approve this pending lesson candidate (from outcome=failure reports); content becomes the refined lesson text"), vault: z.string().optional().describe("Named vault (omit for default vault)"), }), } ``` ## list_lessons List procedural lessons for the tenant, optionally filtered by surface or min follow-through score. Defaults to ACTIVE lessons only — pass status="pending" to triage outcome=failure candidates. ``` z.object({ surface_id: z.string().optional().describe("Filter by surface"), min_score: z.number().optional().describe("Minimum follow_through_score (0–1)"), status: z.enum(["pending", "active", "superseded", "invalidated", "archived"]).optional().describe("Filter by status (default: active)"), since: z.string().optional().describe("Só lições criadas a partir desta data (ISO)"), until: z.string().optional().describe("Só lições criadas até esta data (ISO)"), content_chars: z.number().optional().default(0).describe("Trunca content/evidence em N chars (0 = completo); use com limit alto para não estourar tokens"), limit: z.number().optional().default(20), vault: z.string().optional(), }), } ``` ## memory_arcs Narrative memory arcs — threads linking episodes and goals. create opens an arc around a goal; list filters arcs by episode, status (active/completed/paused) or recency. ``` z.object({ action: z.enum(["create", "list"]).describe("Arc verb"), title: z.string().optional().describe("create: arc title"), summary: z.string().optional().describe("create: arc summary"), goal: z.string().optional().describe("create: the goal this arc tracks"), episode_ids: z.array(z.string()).optional().describe("create: episodes to link"), episode_id: z.string().optional().describe("list: filter arcs containing this episode"), status: z.enum(["active", "completed", "paused"]).optional().describe("list: filter by status"), limit: z.number().optional().default(20).describe("list: max arcs"), vault: z.string().optional(), }), } ``` ## list_memory_arcs DEPRECATED — use memory_arcs with action list. List narrative memory arcs (threads linking episodes and goals). ``` z.object({ episode_id: z.string().optional().describe("Filter arcs containing this episode"), status: z.enum(["active", "completed", "paused"]).optional(), limit: z.number().optional().default(20), vault: z.string().optional(), }), } ``` ## create_memory_arc DEPRECATED — use memory_arcs with action create. Create a narrative arc linking episodes and a goal. ``` z.object({ title: z.string().describe("Arc title"), summary: z.string().optional(), goal: z.string().optional(), episode_ids: z.array(z.string()).optional(), vault: z.string().optional(), }), } ``` ## keyed_facts_as_of Time-travel query: latest value per fact_key where as_of <= date (YYYY-MM-DD). ``` z.object({ as_of: z.string().describe("Query date YYYY-MM-DD"), keys: z.array(z.string()).optional().describe("Restrict to these keys"), vault: z.string().optional(), }), } ``` ## upsert_keyed_fact Insert or update a temporal keyed fact snapshot (tenant, key, as_of unique). Runs the same authority policy as corrections: a weaker caller over a protected winner becomes a pending proposal instead of a write. ``` z.object({ fact_key: z.string(), fact_value: z.string(), as_of: z.string().describe("Snapshot date YYYY-MM-DD"), evidence: z.string().optional(), authority: z.enum(["human", "designated", "agent", "import"]).optional(), vault: z.string().optional(), }), } ``` ## assert_authority_correction Correctability (3C): persist a durable keyed fact with authority, mark prior values for the same key as superseded (non-winning), and soft-invalidate free-form docs that still assert the old value without the new one. Pass losing_values when the wrong value only lived in prose (never as a keyed fact). Currency formats (R$20K vs 20000) are normalized. FB-0092: by default losing_values only demotes docs that ALSO mention the fact_key's entity (account.softville.* → 'softville'); pass losing_values_scope='tenant' to opt into the tenant-wide literal sweep, and dry_run=true to preview the blast radius (count + sample) without writing anything. Demotions exceeding 25 docs are held and returned as a preview — re-run with confirm_prose_demotion=true after reviewing. Undo with authority_restore_demotion. MCP-sourced authority is capped at 'agent' (human/designated require REST admin auth). Tenant-scoped; no hardcoded accounts. ``` z.object({ fact_key: z.string().describe("Stable key, e.g. account.alpha.received_brl"), fact_value: z.string().describe("Correct value"), as_of: z.string().describe("Snapshot date YYYY-MM-DD"), authority: z .enum(["human", "designated", "agent", "import"]) .describe("human > designated > import > agent"), confirmed_by_user: z.boolean().optional().describe( "Set true only when the current authenticated human explicitly stated or approved this exact fact. The server derives identity from the token.", ), evidence: z.string().optional(), losing_values: z .array(z.string()) .optional() .describe("Wrong prior values to demote in prose (e.g. ['20000','20k'] when correcting to 30000)"), losing_values_scope: z .enum(["fact_key", "tenant"]) .optional() .describe( "fact_key (default): only docs also mentioning the fact_key's entity get demoted. tenant: literal sweep across the whole tenant (the behavior that caused FB-0092 — explicit opt-in).", ), dry_run: z .boolean() .optional() .describe( "Preview only: count + sample of docs the losing_values sweep would demote. Writes nothing.", ), confirm_prose_demotion: z .boolean() .optional() .describe( "Set true to proceed after reviewing a held preview (>25 docs would be demoted).", ), vault: z.string().optional(), }), } ``` ## authority_restore_demotion Correctability (3C) undo: reverse the prose demotion caused by one authority correction — restores each document's confidence to its pre-demotion value, un-hides docs invalidated by that demotion, and cancels any pending demotion work for the key. Identify the correction by demotion_work_id (returned by assert_authority_correction) or by fact_key. Does NOT alter the keyed fact itself; docs demoted before the audit columns existed are reported as unrecoverable. Tenant-scoped. ``` z.object({ demotion_work_id: z.string().uuid().optional().describe( "Work item id returned by assert_authority_correction", ), fact_key: z.string().optional().describe( "Alternative to demotion_work_id: restore every doc demoted for this key", ), confirm: z.boolean().optional().describe( "Required (true) when the current winner for the fact_key has human/designated authority — explicit acknowledgment that you are undoing the prose propagation of a stronger correction.", ), vault: z.string().optional(), }), } ``` ## list_arcs DEPRECATED — use memory_arcs with action list. List narrative arcs (goal-oriented threads linked to episodes). Optional status filter. ``` z.object({ status: z.enum(["active", "completed", "paused"]).optional().describe("Filter by status: active | completed | paused"), vault: z.string().optional().describe("Named vault (omit for default vault)"), }), } ``` ## lifecycle_sweep Run lifecycle policies: archive stale docs, optionally purge old archives. Defaults to dry_run (preview only). ``` z.object({ dry_run: z.boolean().optional().default(true).describe("Preview what would be archived/purged without acting"), vault: z.string().optional().describe("Named vault (omit for default vault)"), }), } ``` ## lifecycle_restore Restore documents that were auto-archived by lifecycle policies. Does NOT restore manually forgotten documents. ``` z.object({ query: z.string().optional().describe("Search archived docs by keyword to find what to restore"), collection: z.string().optional().describe("Restore all archived docs from a specific collection"), all: z.boolean().optional().default(false).describe("Restore ALL archived documents"), vault: z.string().optional().describe("Named vault (omit for default vault)"), }), } ``` ## list_vaults Show all configured vault names and their SQLite paths. Returns empty if running in single-vault mode (default). ``` z.object({}), } ``` ## vault_sync Index markdown documents from a directory into a named vault. Use to populate a vault with content from a specific path. ``` z.object({ vault: z.string().describe("Target vault name (must be configured in config.yaml or VALORBRAIN_VAULTS)"), content_root: z.string().describe("Directory path to index markdown files from"), pattern: z.string().optional().default("**/*.md").describe("Glob pattern (default: **/*.md)"), collection_name: z.string().optional().describe("Collection name in the vault. Defaults to vault name."), }), } ``` ## diary The agent's observational diary. WRITE to record events, decisions or context worth reviewing later (entries become searchable memories — useful where no hook support exists). READ recent entries to review past observations. ``` z.object({ action: z.enum(["read", "write"]).describe("Diary verb"), entry: z.string().optional().describe("write: diary entry text"), topic: z.string().optional().describe("write: topic tag (e.g., 'technical', 'user_facts', 'session')"), agent: z.string().optional().describe("write: agent name; read: filter by agent name"), last_n: z.number().optional().describe("read: number of recent entries (default 10)"), vault: z.string().optional().describe("Named vault (omit for default vault)"), }), } ``` ## diary_write DEPRECATED — use diary with action write. Write to the agent's diary. Use for recording important events, decisions, or observations in environments without hook support. Entries are stored as memories and are searchable. ``` z.object({ entry: z.string().describe("Diary entry text"), topic: z.string().optional().default("general").describe("Topic tag (e.g., 'technical', 'user_facts', 'session')"), agent: z.string().optional().default("agent").describe("Agent name writing the entry"), vault: z.string().optional().describe("Named vault (omit for default vault)"), }), } ``` ## diary_read DEPRECATED — use diary with action read. Read recent diary entries. Use to review past observations and events recorded by the agent. ``` z.object({ last_n: z.number().optional().default(10).describe("Number of recent entries to return"), agent: z.string().optional().describe("Filter by agent name"), vault: z.string().optional().describe("Named vault (omit for default vault)"), }), } ``` ## whoami Returns who THIS MCP connection is: tenant, user, agent slug (from token), team member if any, and the tenant identity summary. Call after connect to verify multi-user setup. No extra headers needed — the Bearer token already identifies you. ``` z.object({}), } ``` ## memory_health Returns open proposal/conflict counts, high-priority items, and canonical sources with drift. Call at end of substantive sessions. ``` z.object({ entity: z.string().optional().describe("Filter proposals by path/title/summary substring"), limit: z.number().optional().describe("Max high-priority proposals (default 3)"), }), } ``` ## list_proposals Returns proposals for canonical docs that may need updating. Agents (Hermes/Claude/etc) consume these to execute write-back. ``` z.object({ limit: z.number().optional().describe("Max proposals (default 20)"), }), } ``` ## store Stores a markdown document in the tenant's memory. Use for explicit notes, decisions, or facts that the agent wants persisted. ``` z.object({ path: z.string().describe("Logical path/identifier (e.g. 'decisions/2026-05.md')"), content: z.string().describe("Markdown content"), title: z.string().optional().describe("Optional title for retrieval"), collection: z.string().optional().describe("Collection name (default: 'memories')"), }), } ``` ## export_docs Export documents from a collection to a JSON array. Useful for backup, migration, or cross-instance transfer. ``` z.object({ collection: z.string().optional().describe("Collection to export (omit for all)"), limit: z.number().optional().default(1000).describe("Max documents to export"), format: z.enum(["json", "ndjson"]).optional().default("json").describe("Output format: json (array) or ndjson (one-per-line)"), }), } ``` ## import_docs Import documents from a JSON array. Each object needs collection, path, title, and body. Supports upsert (existing docs with same collection+path get updated). ``` z.object({ documents: z.string().describe("JSON string: array of {collection, path, title, body, content_type?, tags?, confidence?}"), on_conflict: z.enum(["upsert", "skip", "error"]).optional().default("upsert").describe("How to handle existing docs with same collection+path"), }), } ``` ## feedback Channel to the ValorBrain product team (not end-user CRM). submit files a bug/feature/question/praise — returns FB-XXXX; check tracks status and team response by id or 'all'. WHEN TO CALL (agents): **ValorBrain** tool/MCP errors (a bug in YOUR harness/CLI/editor — herdr, omp, codex, kiro, cursor, … — belongs to that project, not here); empty or wrong memory_retrieve when knowledge should exist; ranking noise; missing capability; verified fix (praise). WHEN NOT TO: normal successful domain work, chat without a product defect, secrets in the body. One FB per distinct issue. ``` z.object({ action: z.enum(["submit", "check"]).describe("Feedback verb"), title: z.string().min(5).max(200).optional().describe("submit: short title — what is this about?"), description: z.string().min(10).max(5000).optional().describe("submit: what happened / expected / steps, or what you want and why"), category: z.enum(["bug", "feature", "question", "improvement", "praise", "feedback"]).optional().default("feedback").describe("submit: type of feedback"), priority: z.enum(["low", "normal", "high", "critical"]).optional().default("normal").describe("submit: suggested priority (team may adjust)"), tags: z.array(z.string()).optional().describe("submit: optional tags"), feedback_id: z.string().optional().describe("check: FB-XXXX or 'all' to list recent"), vault: z.string().optional(), }), } ``` ## feedback_submit DEPRECATED — use feedback with action submit. Submit a bug report, feature request, question, praise, or improvement to the ValorBrain product team (not end-user CRM). Returns FB-XXXX for tracking via feedback action check. WHEN TO CALL (agents): ValorBrain tool/MCP errors (not bugs in your harness/CLI/editor — those belong to their projects); empty or wrong memory_retrieve when knowledge should exist; ranking noise; missing capability blocking work; verified fix (category=praise). WHEN NOT TO: normal successful domain work, chat without a product defect, secrets in the body. One FB per distinct issue. Human ops triage at ValorBrain Ops /feedback. ``` z.object({ title: z.string().min(5).max(200).describe("Short title — what is this about?"), description: z.string().min(10).max(5000).describe("Detailed description. For bugs: what happened, what you expected, steps to reproduce. For features: what you want and why."), category: z.enum(["bug", "feature", "question", "improvement", "praise", "feedback"]).default("feedback").describe("Type of feedback"), priority: z.enum(["low", "normal", "high", "critical"]).default("normal").describe("Suggested priority (team may adjust)"), tags: z.array(z.string()).optional().describe("Optional tags for categorization"), vault: z.string().optional(), }), } ``` ## secrets Cofre de segredos do tenant. A memória guarda a referência `secret://`; o valor mora aqui e só sai por get (auditado). put cria/atualiza (write); get resolve o valor (read); list devolve só metadados (read); rotate re-embrulha a chave do tenant (write); delete remove (write). get aceita nome aproximado em linguagem natural: get name='senha da cloudflare' resolve para 'cloudflare-password' quando o candidato é único. QUANDO USAR: o usuário falou uma credencial (senha, token, chave) → put com um nome curto e estável (ex.: 'cloudflare-password'); o usuário perguntou uma credencial → get. Nunca escreva o valor em documento/memória: a memória só carrega a referência. Exige escopo 'secrets:read' (get/list) ou 'secrets:write' (put/rotate/delete) — 'read'/'write' legados não cobrem. Nunca é injetado em retrieval. ``` z.object({ action: z.enum(["put", "get", "list", "rotate", "delete"]).describe("Cofre: verbo"), name: z.string().optional().describe("put/get/delete: nome do segredo (vira secret://)"), value: z.string().optional().describe("put: valor — nunca é devolvido por list"), description: z.string().optional().describe("put: para que serve"), expires_at: z.string().optional().describe("put: validade ISO (opcional)"), vault: z.string().optional(), }), } ``` ## acl_me Domínios efetivos do chamador no source ACL (governança por pessoa e por fonte): união user+role+agent, com a fonte de cada grant (quem concedeu, reason, validade) e o contador de documentos ocultos. É o trace real que o simulador de governança renderiza (inherit(user=marina): gtm, support · finance ✗). Herança: o agente herda o acesso de quem o usa; grants de persona SOMAM. Sem identidade (nem user nem persona) devolve erro limpo — sem vazar estrutura do regime. USE QUANDO: precisar explicar por que um domínio aparece ou não no retrieval; antes de reclamar de 'o ValorBrain não acha' — a ausência pode ser permissão de fonte, não falha de busca. ``` z.object({}), } ``` ## acl_grants Administra os grants ALLOW do source ACL do tenant (user|role|agent → domínio de negócio, com validade temporal). list devolve grants + mapeamentos collection→domain (coleção sem mapeamento está FORA do regime — sempre legível); create exige reason (todo grant precisa dizer por quê) e aceita valid_from/valid_to ISO; revoke remove por id. Criar/revogar limpa o cache de resolução (60s) — vale no próximo request — e grava no mutation_audit. Exige escopo 'acl_grants:read' (list) ou 'acl_grants:write' (create/revoke) — legado read/write e token sem escopo não cobrem. Espelho REST: GET/POST/DELETE /api/v1/acl/grants (ADMIN do tenant). ``` z.object({ action: z.enum(["list", "create", "revoke"]).describe("Acl grants: verbo"), subject_kind: z.enum(["user", "role", "agent"]).optional().describe("create: tipo do sujeito"), subject_id: z.string().optional().describe("create: users.id (UUID) | 'STAFF' | persona slug"), domain: z.string().optional().describe("create/list: domínio de negócio ('gtm', 'finance'…)"), reason: z.string().optional().describe("create: OBRIGATÓRIO — por que este acesso existe"), valid_from: z.string().optional().describe("create: ISO timestamp (opcional)"), valid_to: z.string().optional().describe("create: ISO timestamp (opcional)"), id: z.string().optional().describe("revoke: id do grant (UUID)"), vault: z.string().optional(), }), } ``` ## read_log Trilha de leitura do tenant (governança): quem leu, por meio de qual agente/canal, qual versão de cada documento entrou no contexto e quando. 1 linha por consulta; query é gravada como hash (nunca texto — LGPD); retenção 90 dias quentes + agregado. Filtros: doc (hash, prefixo ok), actor (user id), channel (mcp|rest|hook), operation, from/to ISO, limit (<=200). Toda consulta a esta trilha é registrada em mutation_audit (read_log.query). Exige escopo explícito 'read_log:read' — legado read/write e token sem escopo não cobrem. Espelho REST: GET /api/v1/read-log. ``` z.object({ doc: z.string().optional().describe("Filtrar por hash de documento (prefixo ok) — 'quem leu ESTE documento'"), actor: z.string().optional().describe("Filtrar por user id do titular — 'o que ESTA pessoa leu'"), channel: z.enum(["mcp", "rest", "hook", "cli"]).optional().describe("Filtrar por canal"), operation: z.string().optional().describe("Filtrar por operação (ex.: memory_retrieve, 'POST /search', 'hook:context-surfacing')"), from: z.string().optional().describe("ISO timestamp inicial (inclusive)"), to: z.string().optional().describe("ISO timestamp final (inclusive)"), limit: z.number().optional().describe("Máximo de linhas (default 50, teto 200)"), vault: z.string().optional(), }), } ``` ## feedback_check DEPRECATED — use feedback with action check. Check the status and response of submitted feedback. Use the feedback ID (FB-XXXX) or 'all' to list recent. ``` z.object({ feedback_id: z.string().describe("Feedback ID (e.g. FB-0001) or 'all' to list recent"), vault: z.string().optional(), }), } ``` ## notifications Your notification inbox for team and system messages: feedback responses, announcements, alerts. check returns unread count + recent items ('all' includes read; an N-XXXX id fetches one). mark_read dismisses by id or 'all'. ``` z.object({ action: z.enum(["check", "mark_read"]).describe("Inbox verb"), filter: z.string().optional().describe("check: 'unread' (default), 'all', or a notification ID (N-XXXX)"), notification_id: z.string().optional().describe("mark_read: notification ID (N-XXXX) or 'all'"), vault: z.string().optional(), }), } ``` ## notifications_check DEPRECATED — use notifications with action check. Check your notification inbox for unread messages from the team or system. Includes feedback responses, announcements, and alerts. Returns unread count + recent items. Use 'all' to include read items, or a specific notification ID. ``` z.object({ filter: z.string().optional().describe("'unread' (default), 'all', or a notification ID (N-XXXX)"), vault: z.string().optional(), }), } ``` ## notifications_mark_read DEPRECATED — use notifications with action mark_read. Mark a notification as read/dismissed. Use the notification ID (N-XXXX) or 'all' to mark everything read. ``` z.object({ notification_id: z.string().describe("Notification ID (N-XXXX) or 'all'"), vault: z.string().optional(), }), } ``` ## team_message Send an async message to a teammate (human or agent). They'll see it in their inbox on their next briefing or inbox check. For questions, context, or coordination that doesn't need an immediate reply. ``` z.object({ to: z.string().describe("Recipient: a teammate's name or member id"), title: z.string().min(3).max(200).describe("Short subject"), body: z.string().optional().describe("Message content"), category: z.enum(["message", "request", "decision", "alert"]).default("message").describe("message = chat, request = asks for action, decision = record a choice, alert = needs attention"), priority: z.enum(["low", "normal", "high", "critical"]).default("normal"), vault: z.string().optional(), }), } ``` ## team_handoff Durable async work assignment in the shared brain. create hands work to a teammate with context — the recipient should DO something with it (open questions, files changed); shows in their briefing until consumed; status=blocked_on_human parks it waiting on a human (anti-loop). consume marks a handoff done after finishing the work or closing a duplicate/resolved loop — prevents briefing clutter. ``` z.object({ action: z.enum(["create", "consume"]).optional().default("create").describe("Handoff verb (default create)"), to: z.string().optional().describe("create: recipient teammate name or id"), summary: z.string().min(5).max(500).optional().describe("create: what this handoff is about / what needs doing"), open_questions: z.array(z.string()).optional().describe("create: questions for the recipient to resolve"), files_changed: z.array(z.string()).optional().describe("create: files involved"), priority: z.enum(["low", "normal", "high", "critical"]).optional().default("normal"), status: z.enum(["pending", "blocked_on_human"]).optional().default("pending") .describe("create: pending=actionable work; blocked_on_human=parked waiting on human (do not re-escalate)"), handoff_id: z.union([z.string(), z.number()]).optional().describe("consume: handoff #id (from team_briefing) or its summary"), note: z.string().max(500).optional().describe("consume: optional completion note"), vault: z.string().optional(), }), } ``` ## team_handoff_consume DEPRECATED — use team_handoff with action consume. Mark a team handoff as consumed (done). Use after finishing the work or when closing a duplicate/resolved loop. Prevents briefing clutter from stale pending handoffs. ``` z.object({ handoff_id: z.union([z.string(), z.number()]).describe("Handoff id to consume"), note: z.string().max(500).optional().describe("Optional completion note"), vault: z.string().optional(), }), } ``` ## team_inbox Check messages sent to you by teammates. Returns unread count and recent messages. Mark read with notifications_mark_read once handled. ``` z.object({ unread_only: z.boolean().default(true).describe("If false, include already-read messages"), vault: z.string().optional(), }), } ``` ## team_briefing Get oriented when starting work: your unread inbox, pending handoffs, the team's shared mission (foundations), and recent activity across the team. Call this at the start of a session to understand what needs attention and stay aligned with company direction. ``` z.object({ vault: z.string().optional(), }), } ``` ## team_roster List who's on the team (humans and agents), their roles, and how to reach them. Use before messaging to know who handles what. ``` z.object({ vault: z.string().optional(), }), } ``` ## team_notify_human Pull a human teammate into a conversation NOW via their messaging channel (Telegram/Discord/etc.). Use when you need a decision, approval, or unblock that only a human can make and it can't wait for them to check their inbox. The message is ALSO saved to their ValorBrain inbox. Resolve the human by name or role; 'manager'/'lead'/'human' match any human in your team. Reserve for things that genuinely need human attention — don't spam. ``` z.object({ to: z.string().describe("Human teammate name, role, or 'manager'/'lead'/'human' to reach any human on the team"), title: z.string().min(3).max(200).describe("What you need — short, action-oriented"), body: z.string().optional().describe("Context: why you need them, what decision/approval"), priority: z.enum(["normal", "high", "critical"]).default("normal"), vault: z.string().optional(), }), } ``` ## decisions First-class, auditable decision records. record creates a hash-chained node (category/scenario/reasoning/outcome/confidence); relate links two decisions causally (caused/influenced/precedent_for); trace walks the causal chain up or downstream; similar finds precedents for a scenario; list filters by category/date/confidence. Use similar BEFORE deciding, record AFTER. ``` z.object({ action: z.enum(["record", "relate", "trace", "similar", "list"]).describe("Decision verb"), category: z.string().min(2).max(100).optional().describe("record/list: decision category, e.g. 'architecture'"), scenario: z.string().min(10).optional().describe("record: what triggered this decision"), reasoning: z.string().optional().describe("record/relate: the rationale"), outcome: z.string().min(3).optional().describe("record: what was decided / the result"), confidence: z.number().min(0).max(1).optional().describe("record/relate: confidence 0-1"), decision_maker: z.string().optional().describe("record: who or what made the decision"), valid_from: z.string().optional().describe("record: valid from (YYYY-MM-DD)"), valid_until: z.string().optional().describe("record: expires/superseded (YYYY-MM-DD)"), source_doc_ids: z.array(z.string()).optional().describe("record: document refs that informed this decision — UUID, #docid, or collection/path"), source_decision_id: z.string().optional().describe("relate: UUID of the upstream decision"), target_decision_id: z.string().optional().describe("relate: UUID of the downstream decision"), relationship_type: z.enum(["caused", "influenced", "precedent_for"]).optional().describe("relate: how source relates to target"), decision_id: z.string().optional().describe("trace: UUID of the decision to trace from"), direction: z.enum(["causes", "caused_by", "both"]).optional().default("both").describe("trace: direction"), max_depth: z.number().min(1).max(10).optional().default(5).describe("trace: max depth (1-10)"), query: z.string().min(5).optional().describe("similar: scenario to find precedents for"), start_date: z.string().optional().describe("list: from date (YYYY-MM-DD)"), end_date: z.string().optional().describe("list: to date (YYYY-MM-DD)"), min_confidence: z.number().min(0).max(1).optional().describe("list: minimum confidence"), limit: z.number().min(1).max(100).optional().default(20).describe("similar/list: max results"), }), } ``` ## record_decision DEPRECATED — use decisions with action record. Record a structured decision with category, scenario, reasoning, outcome, and confidence. Creates a first-class, queryable, auditable decision node with a hash-chained trace entry. Follow up with decisions action relate to build causal links. ``` z.object({ category: z.string().min(2).max(100).describe("Decision category, e.g. 'architecture', 'vendor_selection', 'budget'"), scenario: z.string().min(10).describe("What was the situation that triggered this decision"), reasoning: z.string().optional().describe("Why this decision was made — the rationale"), outcome: z.string().min(3).describe("What was decided / the result"), confidence: z.number().min(0).max(1).optional().describe("Confidence score 0-1 (default 0.8)"), decision_maker: z.string().optional().describe("Who or what made the decision"), valid_from: z.string().optional().describe("When the decision becomes valid (YYYY-MM-DD)"), valid_until: z.string().optional().describe("When the decision expires/superseded (YYYY-MM-DD)"), source_doc_ids: z.array(z.string()).optional().describe("Document IDs that informed this decision"), }), } ``` ## add_decision_relation DEPRECATED — use decisions with action relate. Link two decisions with a causal relationship (caused / influenced / precedent_for). Builds auditable causal chains. ``` z.object({ source_decision_id: z.string().describe("UUID of the source (earlier/upstream) decision"), target_decision_id: z.string().describe("UUID of the target (later/downstream) decision"), relationship_type: z.enum(["caused", "influenced", "precedent_for"]).describe("How source relates to target"), reasoning: z.string().optional().describe("Why this causal link exists"), confidence: z.number().min(0).max(1).optional().describe("Link confidence 0-1 (default 0.7)"), }), } ``` ## trace_decision_chain DEPRECATED — use decisions with action trace. Trace the full causal ancestry or downstream impact of a decision. Direction 'caused_by' = what led to this decision (upstream), 'causes' = what this decision led to (downstream). ``` z.object({ decision_id: z.string().describe("UUID of the decision to trace from"), direction: z.enum(["causes", "caused_by", "both"]).optional().default("both").describe("Direction to trace"), max_depth: z.number().min(1).max(10).optional().default(5).describe("Maximum traversal depth (1-10)"), }), } ``` ## find_similar_decisions DEPRECATED — use decisions with action similar. Semantic precedent search across past decisions. Given a scenario description, finds decisions with similar category, scenario, or outcome. Use before making a decision to find relevant precedents. ``` z.object({ query: z.string().min(5).describe("Scenario or question to find precedents for"), limit: z.number().min(1).max(50).optional().default(10).describe("Max results (default 10)"), }), } ``` ## list_decisions DEPRECATED — use decisions with action list. List decisions with optional filters (category, date range, min confidence). Ordered by most recent first. ``` z.object({ category: z.string().optional().describe("Filter by category"), start_date: z.string().optional().describe("Filter from date (YYYY-MM-DD)"), end_date: z.string().optional().describe("Filter to date (YYYY-MM-DD)"), min_confidence: z.number().min(0).max(1).optional().describe("Minimum confidence threshold"), limit: z.number().min(1).max(100).optional().default(20).describe("Max results (default 20)"), }), } ``` ## provenance W3C PROV-O lineage of an entity. trace walks parent/used edges — where a fact came from (upstream) and what depends on it (downstream); export emits the full audit trail as RDF Turtle with hash-chain integrity metadata (regulator-ready). ``` z.object({ action: z.enum(["trace", "export"]).describe("Provenance verb"), entity_id: z.string().describe("The entity (document hash, triple ID, keyed_fact key)"), direction: z.enum(["upstream", "downstream", "both"]).optional().default("both").describe("trace only: upstream = where it came from, downstream = what derived from it"), max_depth: z.number().min(1).max(10).optional().default(5).describe("trace only: maximum traversal depth (1-10)"), }), } ``` ## trace_lineage DEPRECATED — use provenance with action trace. Trace the full W3C PROV-O lineage of an entity — where it came from (upstream) or what was derived from it (downstream). Answers 'where did this fact come from?' and 'what depends on this?' ``` z.object({ entity_id: z.string().describe("The entity to trace (document hash, triple ID, keyed_fact key)"), direction: z.enum(["upstream", "downstream", "both"]).optional().default("both").describe("upstream = where it came from, downstream = what derived from it"), max_depth: z.number().min(1).max(10).optional().default(5).describe("Maximum traversal depth (1-10)"), }), } ``` ## export_provenance DEPRECATED — use provenance with action export. Export the full W3C PROV-O provenance of an entity as RDF Turtle — regulator-ready audit trail with hash-chain integrity metadata. ``` z.object({ entity_id: z.string().describe("Entity to export provenance for"), }), } ``` ## conflicts Contradictions across the tenant's knowledge. detect scans for value/temporal/relationship conflicts (also auto-detected by the consolidation tick); list shows them filtered by status/type/severity; resolve picks a strategy and winner. Curator surface. ``` z.object({ action: z.enum(["detect", "list", "resolve"]).describe("Conflict verb"), status: z.enum(["detected", "reviewing", "resolved", "ignored"]).optional().describe("list: filter by status"), conflict_type: z.enum(["value", "type", "relationship", "temporal", "logical"]).optional().describe("list: filter by conflict type"), severity: z.enum(["critical", "high", "medium", "low"]).optional().describe("list: filter by severity"), limit: z.number().min(1).max(100).optional().default(20).describe("list: max results"), conflict_id: z.string().optional().describe("resolve: UUID of the conflict to resolve"), resolution_strategy: z.enum(["voting", "credibility_weighted", "most_recent", "first_seen", "highest_confidence", "authority", "manual_review"]).optional().describe("resolve: how the conflict was resolved"), resolved_value: z.string().optional().describe("resolve: the chosen value"), resolved_source: z.enum(["source_a", "source_b", "merged", "custom"]).optional().describe("resolve: which source won"), resolution_note: z.string().optional().describe("resolve: optional note explaining the resolution"), apply_canonical: z.boolean().optional().describe("resolve: apply a verified human decision to the canonical fact atomically"), expected_revision: z.string().optional().describe("resolve: revision returned by conflicts list"), as_of: z.string().optional().describe("resolve: effective date YYYY-MM-DD for canonical correction"), human_confirmation: z.string().optional().describe("resolve: class-A act-bound envelope supplied by an enrolled harness; never invent this proof"), confirmed_by_user: z.boolean().optional().describe("resolve: true only when the current authenticated human explicitly chose this value; makes canonical application the default"), }), } ``` ## detect_conflicts DEPRECATED — use conflicts with action detect. Scan for contradictions across the tenant's knowledge: value conflicts (same fact_key, different values), temporal conflicts (valid_until < as_of), and relationship conflicts (contradictory triples). Returns detected conflicts with severity. ``` z.object({}), } ``` ## list_conflicts DEPRECATED — use conflicts with action list. List detected fact conflicts with optional filters (status, type, severity). Ordered by severity (critical first) then detection date. ``` z.object({ status: z.enum(["detected", "reviewing", "resolved", "ignored"]).optional().describe("Filter by status"), conflict_type: z.enum(["value", "type", "relationship", "temporal", "logical"]).optional().describe("Filter by conflict type"), severity: z.enum(["critical", "high", "medium", "low"]).optional().describe("Filter by severity"), limit: z.number().min(1).max(100).optional().default(20).describe("Max results (default 20)"), }), } ``` ## resolve_conflict DEPRECATED — use conflicts with action resolve. Resolve a detected fact conflict by choosing a resolution strategy and winner. Strategies: voting, credibility_weighted, most_recent, first_seen, highest_confidence, authority, manual_review. ``` z.object({ conflict_id: z.string().describe("UUID of the conflict to resolve"), resolution_strategy: z.enum(["voting", "credibility_weighted", "most_recent", "first_seen", "highest_confidence", "authority", "manual_review"]).describe("How the conflict was resolved"), resolved_value: z.string().describe("The chosen value"), resolved_source: z.enum(["source_a", "source_b", "merged", "custom"]).describe("Which source won"), resolution_note: z.string().optional().describe("Optional note explaining the resolution"), apply_canonical: z.boolean().optional(), expected_revision: z.string().optional(), as_of: z.string().optional(), human_confirmation: z.string().optional(), confirmed_by_user: z.boolean().optional(), }), } ```