# Memória para LangChain e LangGraph.js: um runnable de contexto, um callback e as ferramentas do histórico | Niadra

> Como dar memória de cliente a uma cadeia LangChain em Python e a um grafo LangGraph.js: context_runnable() põe o contexto nas mensagens do prompt, NiadraCallbackHandler registra os turnos e history_tools() entrega o kit como StructuredTool; em JavaScript, niadraContext(), withNiadraContext() e niadraTools(). Código do SDK e limites.

URL: https://niadra.com/integracoes/langchain

Integração · LangChain

# Memória para LangChain e LangGraph.js.

Em Python, com langchain-core só: context\_runnable() coloca o contexto nas mensagens do prompt, NiadraCallbackHandler registra os turnos e history\_tools() entrega o kit como StructuredTool. Em JavaScript, @niadra/sdk/langchain traz niadraContext() para cadeias LCEL, withNiadraContext() para nós de LangGraph.js, o callback handler e niadraTools().

[Pedir acesso antecipado](/enterprise)[Documentação do adaptador(abre docs.niadra.com)](https://docs.niadra.com/integrations/langchain)

A memória de conversa do LangChain é o histórico desta cadeia, numa sessão da sua aplicação. Ela não cruza fornecedor, não cruza canal e não sabe o que um sistema de registro mudou. Cada agente da empresa fica com a própria versão do cliente.

A Niadra entra como um runnable no meio da cadeia: as mensagens do prompt entram, e saem com o contexto da cliente como SystemMessage logo depois das mensagens de sistema e o turn\_block no fim. O callback registra o que o cliente disse e o que o modelo respondeu, com o usage\_metadata.

O exemplo mínimo, como está na documentação

```
pip install 'niadra[langchain]'   # langchain-core 1.6 or newer, below 2
```

```
"""An LCEL chain with the customer's context and the history tools."""

from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI

from niadra import Niadra, phone
from niadra.integrations.langchain import NiadraCallbackHandler, context_runnable, history_tools

niadra = Niadra(channel="chat")
prompt = ChatPromptTemplate.from_messages([("system", "You are Acme's agent."), ("human", "{question}")])

with niadra.conversation("thread-81", subject=phone("+5511912345678")) as conversation:
    model = ChatOpenAI(model="gpt-4.1").bind_tools(history_tools(conversation))
    chain = prompt | context_runnable(conversation) | model
    reply = chain.invoke(
        {"question": "Where is my replacement lid?"},
        config={"callbacks": [NiadraCallbackHandler(conversation)]},
    )
    print(reply.content)
```

```
npm install @niadra/sdk @langchain/core   # @langchain/core 1.x, as an optional peer dependency
```

```
// A LangGraph.js agent: the context goes into the model call inside the node (never into the
// graph's state), the history tools run through ToolNode, and the callback records the answers.
import { HumanMessage, SystemMessage } from "@langchain/core/messages";
import { END, MessagesAnnotation, START, StateGraph } from "@langchain/langgraph";
import { ToolNode, toolsCondition } from "@langchain/langgraph/prebuilt";
import { ChatOpenAI } from "@langchain/openai";
import { Niadra, handles } from "@niadra/sdk";
import { NiadraCallbackHandler, niadraTools, withNiadraContext } from "@niadra/sdk/langchain";

const niadra = new Niadra();

/** One customer message in; `userId` comes from your session, never from the model. */
export async function reply(userId: string, threadId: string, text: string): Promise<string> {
  const convo = niadra.conversation({ subject: handles.appUserId(userId), channel: "web_chat", conversation_id: threadId });
  const tools = niadraTools(convo);
  const model = new ChatOpenAI({ model: "gpt-4.1" }).bindTools(tools);

  const graph = new StateGraph(MessagesAnnotation)
    .addNode("agent", async (state) => ({ messages: [await model.invoke(await withNiadraContext(convo, state.messages))] }))
    .addNode("tools", new ToolNode(tools))
    .addEdge(START, "agent")
    .addConditionalEdges("agent", toolsCondition, ["tools", END])
    .addEdge("tools", "agent")
    .compile();

  const result = await graph.invoke(
    { messages: [new SystemMessage("You are Acme's support agent. Be brief."), new HumanMessage(text)] },
    { callbacks: [new NiadraCallbackHandler(convo)] },
  );
  return result.messages.at(-1)?.text ?? "";
}
```

-   Python
-   TypeScript

O mesmo código está em examples/langchain\_chain.py, examples/langgraph-js.ts nos repositórios dos SDKs, onde roda na CI contra os tipos reais do framework e o emulador da Niadra. Para testar sem a nuvem da Niadra, niadra-mock e NIADRA\_BASE\_URL=http://127.0.0.1:8765.

## Como o adaptador se liga

As cinco primitivas de toda integração da Niadra, nos pontos de extensão deste framework.

Contexto

Em Python, context\_runnable() recebe as mensagens do prompt, uma lista ou um PromptValue, e devolve com o contexto como SystemMessage logo depois das mensagens de sistema iniciais e o turn\_block como SystemMessage no fim; with\_context() e awith\_context() fazem o mesmo numa lista sua. Em JavaScript, niadraContext(session) é um runnable para cadeias LCEL (niadraContext(convo).pipe(model)); withNiadraContext(session, messages) faz o mesmo dentro de um nó do LangGraph.js, logo antes da chamada ao modelo, então nada entra no estado do grafo.

Turnos

NiadraCallbackHandler registra as mensagens do cliente quando um chat model começa, chaveadas pela posição, e a resposta do modelo com o usage\_metadata quando termina. Em JavaScript, registra as respostas com o usage\_metadata que o LangChain padroniza; respostas que só chamam ferramentas não registram nada.

Ferramentas

history\_tools(): StructuredTool com os nomes, descrições e esquemas do kit, amarradas ao cliente. Em JavaScript, niadraTools(session).

Verificação

conversation.verify() antes da chamada.

Transbordo

conversation.handoff() onde a cadeia transfere.

## O que o agente recebe

O contexto é compilado quando a memória muda e servido pronto, sem modelo de IA na leitura. O que outro canal disse durante a conversa chega como delta, no fim do prompt.

-   Quem é o cliente, pelo que a conversa já provou: o nível de verificação decide o que entra
-   Fatos, pendências e promessas, com a data e o canal de origem
-   O que outros agentes fizeram por dentro, confirmado pelo sistema de registro
-   Padrões calculados por regra, com as evidências e o prazo
-   As três ferramentas do histórico: buscar, linha do tempo e abrir um item, amarradas ao cliente no seu código
-   Comprovante de cada leitura, encadeado por SHA-256

[Ver o contexto por dentro](/produtos/contexto)

## O que o adaptador não faz

-   Sem BaseChatMessageHistory nem BaseStore próprios: a Niadra não é o armazenamento de estado da cadeia nem do grafo, e o checkpointer nunca guarda um contexto.
-   Nada aqui derruba a cadeia: com a Niadra lenta ou fora, as mensagens vão ao modelo como vieram.
-   Testado contra langchain-core 1.6 e @langchain/core 1.2 com um chat model falso e a Niadra no emulador.

## Perguntas frequentes

### Preciso de langchain inteiro ou só do core?

Em Python, só de langchain-core: o runnable, o callback e as ferramentas usam as interfaces do core. O exemplo usa langchain-openai para o modelo, mas qualquer chat model serve.

### A memória de conversa do LangChain continua funcionando?

Continua, e é sua. O histórico da cadeia é o que o modelo viu nesta sessão; a Niadra é o que a empresa sabe da pessoa, vindo de todos os canais e sistemas. O callback registra os turnos uma vez, pela posição, então o histórico repetido na próxima chamada não entra duas vezes.

### E numa cadeia que chama ferramentas várias vezes?

Em JavaScript, respostas que só chamam ferramentas não registram nada; o turno do agente é a resposta com texto. As ferramentas do histórico rodam pelo ToolNode, como qualquer outra, amarradas ao cliente que o seu código abriu.

### Preciso trocar de modelo, de prompt ou de fornecedor?

Não. O adaptador coloca o contexto depois das suas instruções e o delta no fim do prompt, nos pontos de extensão que o framework já tem. O seu modelo, o seu prompt e o seu fornecedor continuam os mesmos, e trocar qualquer um deles depois não apaga a memória.

### Onde ficam os dados e quanto custa?

Os dados ficam numa região só, informada no contrato, cifrados com AES-256-GCM e chave exclusiva por empresa, protegida em HSM FIPS 140-3. O preço é por conversa ou tarefa em que um agente leu a memória: de US$ 2 a 3 a cada mil, conforme o volume, com leituras, buscas e eventos de sistema incluídos. A Niadra está abrindo para empresas por pedido, antes do lançamento.

## Outras integrações

-   [LiveKit Agents](/integracoes/livekit)
-   [Pipecat](/integracoes/pipecat)
-   [Vapi](/integracoes/vapi)
-   [Retell AI](/integracoes/retell)
-   [ElevenLabs Agents Platform](/integracoes/elevenlabs)
-   [Twilio](/integracoes/twilio)
-   [WhatsApp Cloud API](/integracoes/whatsapp)
-   [OpenAI Agents SDK](/integracoes/openai-agents)
-   [LangGraph](/integracoes/langgraph)
-   [CrewAI](/integracoes/crewai)
-   [Vercel AI SDK](/integracoes/ai-sdk)
-   [n8n](/integracoes/n8n)
-   [As 36 integrações, na documentação(abre docs.niadra.com)](https://docs.niadra.com/integrations/overview)

## Conte o que você está construindo.

E-mail corporativo e duas linhas sobre os seus agentes bastam. Quem responde é quem escreve o código, com uma proposta de acesso antecipado para o seu caso.

[Prefere contar mais sobre a sua empresa? Use o formulário completo](/enterprise)
