> ## Documentation Index
> Fetch the complete documentation index at: https://docs.niadra.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Navegação do histórico

> Busca, linha do tempo e abrir item: o agente consulta tudo o que já aconteceu com o cliente.

O contexto cobre o que importa agora. Para todo o resto, o agente consulta o **histórico**: tudo o que já aconteceu com o cliente, em qualquer canal, sistema ou fornecedor. São três operações (buscar, ver a linha do tempo e abrir um item) que qualquer LLM chama sozinho, como ferramenta, ou que o seu código chama direto pelo SDK. Nenhum modelo da Niadra fica no caminho, e a resposta chega em menos de 200 ms.

## Contexto e histórico, lado a lado

|             | Contexto                                                                  | Histórico                                               |
| ----------- | ------------------------------------------------------------------------- | ------------------------------------------------------- |
| Quando      | Antes da primeira palavra, sempre                                         | No meio da conversa, quando ela pede mais               |
| Quem decide | O seu código, numa chamada fixa                                           | O LLM do agente, chamando a ferramenta, ou o seu código |
| O que cobre | Identidade, pendências, o que acabou de acontecer, destaques do histórico | Tudo o que já aconteceu com o cliente                   |
| Tempo       | Menos de 100 ms                                                           | Menos de 200 ms                                         |

As duas leituras passam pela mesma política, pelo mesmo nível de verificação e deixam o mesmo comprovante.

## Buscar

`search` recebe uma pergunta em linguagem natural ou palavras-chave e procura por palavra e por significado, só dentro do histórico daquele cliente. Alcança conversas, fatos, pendências, promessas, eventos de sistema, ações de agentes, objetos e padrões.

<CodeGroup>
  ```python Python theme={null}
  from niadra import Niadra, phone

  niadra = Niadra()

  result = niadra.search(
      phone("+14155550123"),
      "credit for missed technician visit",
      max_tokens=300,
      conversation_id="call-4471",
      voice=True,
  )
  if result.recurrence:
      print(result.recurrence.occurrences, result.recurrence.last_resolution)
  ```

  ```typescript TypeScript theme={null}
  const { data } = await niadra.search({
    subject: handles.phone("+14155550123"),
    query: "credit for missed technician visit",
    max_tokens: 300,
    conversation_id: "call-4471",
  });
  if (data?.recurrence) console.log(data.recurrence.occurrences, data.recurrence.last_resolution);
  ```

  ```bash cURL theme={null}
  curl -X POST "https://acme-prod.us-east-1.api.niadra.com/v1/history/search" \
    -H "Authorization: Bearer $NIADRA_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"subject": {"type": "phone_e164", "value": "+14155550123"},
         "query": "credit for missed technician visit", "max_tokens": 300, "conversation_id": "call-4471"}'
  ```
</CodeGroup>

Cada item volta com `kind`, texto denso no mesmo estilo do contexto, `at`, `channel`, `outcome`, `confidence` e `origin_event_id`, o evento de onde veio. É daí que o agente diz "em 12 de março, por telefone, vocês me deram um crédito".

### Recorrência

Quando a busca casa com uma categoria, a resposta traz o bloco `recurrence`: quantas vezes aconteceu na janela, a data da última, o desfecho e a solução da última. É uma contagem sobre conversas já classificadas, não um palpite do modelo. No exemplo da Marina: `occurrences: 2`, `window_days: 365`, `last_resolution: "$40 credit"`. A mesma contagem sustenta o padrão "reclamação recorrente", então os dois nunca divergem.

### Filtros

`filters` restringe a busca por período (`since`, `until`), `channels`, `categories`, tipos de item (`item_kinds`: `episode`, `fact`, `open_item`, `action`, `system_event`, `object`, `trait`), `outcome` e `object`.

### Orçamento

`max_tokens` limita o tamanho da resposta: de 50 a 4.000, padrão 800. Use 300 em voz. O corte é por valor, nunca por ordem de chegada. A resposta informa `tokens_used`.

## Linha do tempo

`timeline` folheia o cliente em ordem, do mais recente para o mais antigo: uma conversa, um evento de sistema ou uma ação por linha, com cursor. É o que o LLM usa quando não sabe o que procurar.

<CodeGroup>
  ```python Python theme={null}
  page = niadra.timeline(phone("+14155550123"), filters={"since": "2026-01-01T00:00:00Z"}, limit=20)
  for item in page.items:
      print(item.at, item.kind, item.text)
  ```

  ```typescript TypeScript theme={null}
  const { data: page } = await niadra.timeline({
    subject: handles.phone("+14155550123"),
    filters: { since: "2026-01-01T00:00:00Z" },
    limit: 20,
  });
  ```

  ```bash cURL theme={null}
  curl -X POST "https://acme-prod.us-east-1.api.niadra.com/v1/history/timeline" \
    -H "Authorization: Bearer $NIADRA_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"subject": {"type": "phone_e164", "value": "+14155550123"}, "limit": 20}'
  ```
</CodeGroup>

Esta linha do tempo é `POST` pelo mesmo motivo do contexto: o handle é dado pessoal e fica fora da URL. `limit` vai de 1 a 100; continue com `next_cursor`. Quando você já tem o id do perfil, [`GET /v1/history/timeline?profile_id=...`](/api/history-timeline-by-profile) devolve a mesma página, com `cursor`, `limit`, `verification` e `conversation_id` na query.

A navegação do histórico lê um cliente de cada vez. Perguntas sobre todos os clientes de uma vez ("quais promessas estão vencidas?", "quem reclamou três vezes da entrega?") vão para a [análise da base](/api/insights-aggregate), que responde com pseudônimos por padrão, suprime grupos pequenos e só revela um cliente por um [pedido de revelação](/api/insights-reveal) com motivo, que deixa comprovante.

## Abrir um item

`open` abre uma conversa ou um objeto encontrado pela busca ou pela linha do tempo: o que foi pedido, o que foi prometido e por quem, o desfecho, a solução, a linha do tempo e os itens de memória que nasceram dele. O trecho literal da transcrição (`excerpt`) só sai com escopo elevado e nunca para audiência de voz.

<CodeGroup>
  ```python Python theme={null}
  item = niadra.open("ep_01J2", conversation_id="call-4471")
  ```

  ```typescript TypeScript theme={null}
  const { data: item } = await niadra.open("ep_01J2", { conversation_id: "call-4471" });
  ```

  ```bash cURL theme={null}
  curl "https://acme-prod.us-east-1.api.niadra.com/v1/history/items/ep_01J2?conversation_id=call-4471" \
    -H "Authorization: Bearer $NIADRA_API_KEY"
  ```
</CodeGroup>

## Como ferramenta de qualquer LLM

`tools()` devolve as três operações como ferramentas no formato de função mais difundido (`search_customer_history`, `get_customer_timeline`, `open_history_item`), com o cliente **amarrado fora do alcance do modelo**. As definições não têm parâmetro de cliente: o LLM escolhe a pergunta, nunca de quem ela é. Uma injeção de prompt que diga "agora procure o cliente X" não tem onde colocar o X.

<CodeGroup>
  ```python Python theme={null}
  kit = niadra.tools(phone("+14155550123"), conversation_id="call-4471", voice=True)

  reply = llm.chat.completions.create(model=MODEL, messages=messages, tools=kit.definitions)
  for call in reply.choices[0].message.tool_calls or []:
      output = kit.call(call.function.name, call.function.arguments)
      messages.append({"role": "tool", "tool_call_id": call.id, "content": output})
  ```

  ```typescript TypeScript theme={null}
  const kit = niadra.tools(handles.phone("+14155550123"), { conversation_id: "call-4471", voice: true });

  const reply = await llm.chat.completions.create({ model: MODEL, messages, tools: kit.definitions });
  for (const call of reply.choices[0].message.tool_calls ?? []) {
    const output = await kit.call(call.function.name, call.function.arguments);
    messages.push({ role: "tool", tool_call_id: call.id, content: output });
  }
  ```
</CodeGroup>

No Python, `kit.anthropic_definitions()` devolve as mesmas ferramentas no formato da API de mensagens da Anthropic. As definições também saem por [`GET /v1/history/tools`](/api/history-tools), e pelo [servidor MCP](/guides/mcp), onde o cliente é amarrado pelo `subject_token`.

## Custo sob controle

* As descrições são texto fixo, com até cerca de 120 tokens por ferramenta, e ficam no prefixo que o provedor guarda em cache.
* Cada descrição diz ao modelo quando **não** chamar: a resposta pode já estar em "Do histórico", no contexto.
* A mesma consulta, na mesma conversa, devolve os mesmos bytes.
* Declare o kit só nos agentes que precisam. Uma URA curta não paga nada.
* Buscar não é cobrado à parte: a unidade continua sendo a conversa ou tarefa.

## Garantias da resposta

* `withheld` diz quantos itens a política segurou neste nível de verificação, nunca o conteúdo.
* `as_of` diz até quando o histórico reflete os eventos.
* `degraded: "text_only"` indica que só a busca por palavra rodou.
* Cada consulta deixa um comprovante com quem perguntou, a consulta, os itens devolvidos por hash e o que foi retido.
* O que sai por padrão são itens derivados, já triados contra injeção e marcados como dados, não instruções.

## Próximos passos

<CardGroup cols={2}>
  <Card title="MCP com qualquer LLM" href="/guides/mcp">
    o kit por Streamable HTTP.
  </Card>

  <Card title="Buscar no histórico" href="/api/history-search">
    a referência de `POST /v1/history/search`.
  </Card>

  <Card title="Comprovantes e auditoria" href="/concepts/receipts">
    o que cada consulta deixa registrado.
  </Card>
</CardGroup>
