#2404·instructor

feat: Add persistent memory cookbook with Dakera integration

Author: ferhimedamineCreated Jul 1, 2026Updated Aug 8, 2026

Summary

Proposes adding a cookbook recipe for persistent, cross-session memory using Dakera — a self-hosted, decay-weighted vector memory server.

The problem: Instructor is stateless between calls

Every client.create() call starts fresh. Applications that need cross-session memory must implement their own retrieval and injection logic. There's currently no memory example in the Instructor cookbook.

The integration

Instructor's hook system (client.on("completion:kwargs") / client.on("completion:response")) is the ideal native integration point — observed in the existing Langfuse tracing integration.

DakeraMemoryHook uses the same pattern:

python
import instructor
from examples.persistent_memory_dakera.dakera_memory import DakeraMemory, DakeraMemoryHook

client = instructor.from_provider("openai/gpt-4o-mini")
mem = DakeraMemory(base_url="http://localhost:3300", api_key="demo", agent_id="user-123")
hook = DakeraMemoryHook(mem)
hook.attach(client)  # 3 lines for persistent memory

class Reply(BaseModel):
    text: str

# Session 1
reply = client.create(messages=[{"role": "user", "content": "My name is Alex."}], response_model=Reply)

# Session 2 (new process — memories recalled from Dakera automatically)
reply = client.create(messages=[{"role": "user", "content": "What is my name?"}], response_model=Reply)
# reply.text → "Your name is Alex."

How it hooks in

  • completion:kwargs → searches Dakera for the top-K most relevant memories for the current prompt → prepends a system message with the recalled context
  • completion:response → stores the user prompt + model reply in Dakera after the call

Dakera errors are silently swallowed (non-fatal) — the hook never crashes an LLM call.

Structured extraction variant

The hook also works naturally with structured extraction pipelines:

python
class UserProfile(BaseModel):
    name: str
    preferences: list[str]

profile = client.create(
    messages=[{"role": "user", "content": "I'm Alex, I love Python and Rust."}],
    response_model=UserProfile,
)
# profile.name, profile.preferences are structured — and the conversation is persisted

What the PR adds

  • examples/persistent_memory_dakera/dakera_memory.py — integration helper (DakeraMemory, AsyncDakeraMemory, DakeraMemoryHook, build_context_messages)
  • examples/persistent_memory_dakera/run.py — four runnable scenarios
  • examples/persistent_memory_dakera/test_dakera_memory.py — 31 tests, all passing (fully mocked with unittest.mock, no live server needed)
  • docs/examples/persistent_memory_dakera.md — cookbook page
  • mkdocs.yml — one line added under Cookbook: alongside "Tracing with Langfuse"

Dakera

  • Docker: docker run -p 3300:3300 -e DAKERA_API_KEY=demo ghcr.io/dakera-ai/dakera:latest
  • REST API: POST /v1/memory/store, /v1/memory/search, /v1/memory/forget
  • Server-side embedding (no local model needed)
  • Decay-weighted importance (memories fade unless accessed)