What Pydantic AI already keeps

Message history is passed between runs by your code, and dependencies carry per-request context. Long-term facts are not stored for you.

Where Auld fits

Put the user id and an HTTP client in the agent’s dependencies, and register a recall tool that reads them through RunContext. Typed deps make the identity boundary explicit.

ConcernPydantic AIAuld
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. Define deps

    A dataclass with user_id and an HTTP client.

  2. Register the tool

    Use @agent.tool so it receives the run context.

  3. Return structured text

    Format memories with state and dates.

  4. Ingest after the run

    Send the turn using the same deps.

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."
Pydantic AI wiring
from dataclasses import dataclass
from pydantic_ai import Agent, RunContext
from memory_client import auld_post

@dataclass
class Deps:
    user_id: str

agent = Agent("openai:gpt-4o", deps_type=Deps,
              system_prompt="Use recall_memory for anything about the user's past.")

@agent.tool
def recall_memory(ctx: RunContext[Deps], query: str) -> str:
    """Recall facts about the current user, newest first, with sources."""
    res = auld_post("recall", {"query": query, "viewer": ctx.deps.user_id, "maxTokens": 1500})
    return "\n".join(m["text"] for m in res["memories"]) or "nothing known"

# result = agent.run_sync("What did we agree last week?", deps=Deps(user_id="user_42"))

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

Or connect the MCP server

If your Pydantic AI 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 Pydantic AI’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

Why use deps instead of a global?

Each run gets its own user id, so concurrent requests can’t mix memory.

Can the output type include citations?

Yes — return source ids from the tool and ask for them in a structured output field.