What LangGraph already keeps

Checkpointers save graph state so a thread can resume; stores hold key–value documents across threads. Both persist what you put in them, but reconciling a changed fact, keeping its history and attaching sources is left to your code.

Where Auld fits

Add a load_memory node at the start of the graph that recalls for the incoming message and writes the result into state, and a save_memory node after the response that ingests the turn. The checkpointer keeps the thread; Auld keeps the facts.

ConcernLangGraphAuld
Current conversationYesNot needed
Facts across sessions and channelsYour codeYes
Which fact is current after a changeYour codeYes, with history
What was true on a dateYour codeYes (asOf)
Who may see a memoryYour codeIdentities and audiences
Source for each statementYour codeReturned with every memory

Implementation sequence

  1. Extend the state

    Add a memory string field to your state schema.

  2. Recall in a node

    The first node calls recall with the latest user message and the user id from config.

  3. Use memory in the model node

    Prepend the recalled memories to the system message.

  4. Ingest after responding

    A final node sends the user turn as a record with its timestamp; it does not block the reply if you run it asynchronously.

Example

memory_client.py — shared helper
import os, requests

AULD = os.environ["AULD_API_BASE"]          # e.g. https://YOUR-AULD-HOST
HEADERS = {"Authorization": f"Bearer {os.environ['AULD_API_KEY']}"}

def auld_post(path: str, body: dict) -> dict:
    r = requests.post(f"{AULD}/v1/{path}", json=body, headers=HEADERS, timeout=30)
    r.raise_for_status()
    return r.json()

def remember(text: str, user_id: str, source_id: str, occurred_at: str) -> str:
    """Store a dated record for one user. Returns the job id."""
    return auld_post("records", {"sourceId": source_id, "text": text,
                                 "occurredAt": occurred_at, "author": user_id,
                                 "visibility": f"user:{user_id}"})["jobId"]

def recall(query: str, user_id: str, max_tokens: int = 2000) -> str:
    """Current memories with sources, formatted for a prompt."""
    res = auld_post("recall", {"query": query, "viewer": user_id, "maxTokens": max_tokens})
    return "\n".join(f"- {m['text']} ({m['sources'][0]['title']}, {m['sources'][0]['occurredAt'][:10]})"
                     for m in res["memories"]) or "No relevant memory."
LangGraph wiring
from typing import TypedDict
from datetime import datetime, timezone
from langgraph.graph import StateGraph, START, END
from memory_client import remember, recall

class State(TypedDict):
    user_id: str
    message: str
    memory: str
    reply: str

def load_memory(state: State) -> dict:
    return {"memory": recall(state["message"], state["user_id"])}

def respond(state: State) -> dict:
    prompt = f"Known context:\n{state['memory']}\n\nUser: {state['message']}"
    return {"reply": llm.invoke(prompt).content}

def save_memory(state: State) -> dict:
    now = datetime.now(timezone.utc).isoformat()
    remember(state["message"], state["user_id"], f"turn-{state['user_id']}-{now}", now)
    return {}

g = StateGraph(State)
g.add_node("load_memory", load_memory); g.add_node("respond", respond); g.add_node("save_memory", save_memory)
g.add_edge(START, "load_memory"); g.add_edge("load_memory", "respond")
g.add_edge("respond", "save_memory"); g.add_edge("save_memory", END)
graph = g.compile()

Illustrative example · standard HTTP · check the framework’s current docs for exact signatures

Or connect the MCP server

If your LangGraph setup can use MCP tools, point it at the Auld MCP endpoint instead of writing wrappers. The model gets remember, recall, forget and memory_status. Use wrappers when you need to inject the user id yourself or post-process results; use MCP for speed of setup.

Connect an MCP client →

Custom integration recipe using standard HTTP/MCP tools

  • This recipe wires LangGraph’s own tool interface to the Auld REST API or MCP server; there is nothing Auld-specific to install.
  • Bind the viewer id from your authentication layer, not from model output.
  • Ingestion is asynchronous — poll the job before depending on a just-sent fact in tests.
  • Recall returns up to your plan’s token limit (8,000 on Pay as you go and Flex).

Frequently asked questions

Fixed node or tool?

A fixed recall node guarantees context on every turn and is easier to test. A tool lets the model decide and saves calls on turns that don’t need history. Many graphs use a node for the first turn and a tool afterwards.

What about the LangGraph store?

It is a good place for agent configuration and scratch data. Use Auld when you need supersession, point-in-time questions and sources.