Pydantic AI
Give a Pydantic AI agent a memory of each of your users. The user is the agent's dependency, so the same agent serves everyone: what is known goes in through dynamic instructions, or the agent looks it up with a tool, and each exchange is saved after the run.
Install
pip install "pydantic-ai-slim[anthropic]" geniffyuv add "pydantic-ai-slim[anthropic]" geniffySet ANTHROPIC_API_KEY, and GENIFFY_API_KEY from API keys in the Geniffy app. Any model Pydantic AI
supports works the same way. These examples use AsyncGeniffy, the same client with every method awaited.
Remember each user
from dataclasses import dataclass
from geniffy import AsyncGeniffy
from pydantic_ai import Agent, RunContext
geniffy = AsyncGeniffy() # reads GENIFFY_API_KEY
@dataclass
class User:
id: str
agent = Agent("anthropic:claude-opus-5-5", deps_type=User,
instructions="You are a helpful assistant.")
@agent.instructions
async def memory(ctx: RunContext[User]) -> str:
context = await geniffy.space(f"user_{ctx.deps.id}").context(str(ctx.prompt))
return f"<memory>\n{context}\n</memory>"
async def chat(user_id: str, message: str) -> str:
result = await agent.run(message, deps=User(id=user_id))
await geniffy.space(f"user_{user_id}").memories.add(messages=[
{"role": "user", "content": message},
{"role": "assistant", "content": result.output},
])
return result.outputCall it with the user from your own sign-in:
reply = await chat(user.id, "Who signs the Lumen renewal?")The agent sees what is known about this user, each line with where it came from. When nothing is known, the block says so in one sentence, so the agent says it doesn't know instead of guessing.
Let the agent look things up
To let the agent decide when to look something up, give it a recall tool. The tool reads the user from the
run's dependency, so the model never sees or chooses whose memory it reads.
from dataclasses import dataclass
from geniffy import AsyncGeniffy
from pydantic_ai import Agent, RunContext
geniffy = AsyncGeniffy()
INSTRUCTIONS = ("You are a helpful assistant. Use recall before answering anything "
"that depends on what the user said before.")
@dataclass
class User:
id: str
agent = Agent("anthropic:claude-opus-5-5", deps_type=User, instructions=INSTRUCTIONS)
@agent.tool
async def recall(ctx: RunContext[User], query: str) -> str:
"""Look up what is known about the user, with where it came from.
Args:
query: What to look up
"""
return await geniffy.space(f"user_{ctx.deps.id}").context(query)
async def chat(user_id: str, message: str) -> str:
result = await agent.run(message, deps=User(id=user_id))
await geniffy.space(f"user_{user_id}").memories.add(messages=[
{"role": "user", "content": message},
{"role": "assistant", "content": result.output},
])
return result.outputThe tool answers with context(), so the agent reads the same lines, with their sources, that the
instructions would hold, and the same sentence when nothing is known.