langchain-core only: context_runnable() places the context in the prompt’s messages, NiadraCallbackHandler records the turns and history_tools() hands over the kit as StructuredTools. In JavaScript, @niadra/sdk/langchain brings niadraContext(), withNiadraContext() for LangGraph.js nodes, NiadraCallbackHandler and niadraTools().
Install
@niadra/sdk on npm.
The five primitives
Minimal example
examples/langchain_chain.py and examples/langgraph.ts. For LangGraph agents in Python, see LangGraph.
Agent memory
In Python,history_tools(conversation, agent_memory=...) adds the agent memory tools, and agent_memory=True (or {"write": True, "max_tokens": 300, "tags": [...]}) on the runnable puts the agent’s own notes right before the customer’s context, in the same system message. See Agent memory.
Turn records
With theturns feature on in the space (it ships on), NiadraCallbackHandler(conversation, turns=True) in Python and new NiadraCallbackHandler(convo, { turns: true }) in JavaScript record each top-level run as a turn record, with the tool calls by the provider’s call ids and the model calls with their tokens. A function wrapped with Niadra.tool() inside a LangChain tool takes over the call the handler already recorded, so each call is recorded once. In a replay, a tool passed through replayable() (Python) or recordTools() (JavaScript) answers from the record, and any other is refused with ReplayRefusedError (NiadraReplayRefusedError) instead of running live. A turn never waits for Niadra and never repeats the conversation’s text.
Limits
- No
BaseChatMessageHistoryorBaseStoreof its own: Niadra is not the state store of the chain or the graph, and the checkpointer never stores a pack. - Nothing here fails the chain: with Niadra slow or down, the messages go to the model as they came.
- Tested against
langchain-core1.6 and@langchain/core1.2 with a fake chat model and Niadra on the emulator.
Next steps
LangGraph
the middleware for
create_agent in Python.History navigation
the three tools the agent receives.

