> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sovseal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# OpenAI Agents SDK: Add Persistent Memory with sovseal

> Wrap sovseal-sdk's store/recall as function tools in OpenAI Agents SDK so every agent in a multi-agent handoff workflow shares persistent context.

<style>
  {`
      main, article, .prose {
        margin-left: 2.5cm !important;
        margin-right: 2.5cm !important;
      }
      `}
</style>

sovseal gives OpenAI Agents SDK a persistent memory layer that survives agent handoffs and multi-run workflows. The example below wraps `sovseal-sdk`'s `store`/`recall` methods as two `@function_tool`-decorated callables — named `search_memory` and `save_memory` here, but those are just this example's chosen wrapper names, not sovseal's own tool names. (sovseal's actual methods are `store`/`recall` on the SDK, or the `store_memory`/`recall_memory` MCP tools if you're going through an MCP client instead.) Any agent in your network — triage agents, specialists, or orchestrators — can read from and write to the same local zero-knowledge memory store this way. `store`/`recall` talk to the local ONEBRAIN engine over framed IPC, so memory retrieval adds no network round-trip to your runner loop.

## Installation

```bash theme={null}
pip install openai-agents sovseal-sdk python-dotenv
```

## Define memory-aware agents with handoffs

The example below creates a `triage_agent` that routes requests to either a `travel_agent` or a `health_agent`. All three agents share the same `search_memory`/`save_memory` tool wrappers, and the triage agent persists a summary of each session after the runner completes.

```python agents.py theme={null}
import os
import asyncio
from dotenv import load_dotenv
from agents import Agent, Runner, function_tool
from sovseal import AgentStateClient, EngineUnavailableError

load_dotenv()

# Shared client instance — reused across all tool calls in a session.
# store/recall need no endpoint/api_key; they talk to the local native host.
client = AgentStateClient()


# 1. Memory search tool — wraps sovseal-sdk's recall()
@function_tool
def search_memory(query: str) -> str:
    """Search through past conversations and stored preferences for the user."""
    try:
        hits = client.recall(query, top_k=3)
    except EngineUnavailableError as e:
        return f"Memory engine unavailable ({e.reason})."
    if hits:
        return "\n".join(f"- {h['text']}" for h in hits)
    return "No relevant memories found."


# 2. Memory save tool — wraps sovseal-sdk's store()
@function_tool
def save_memory(content: str) -> str:
    """Save an important fact or preference about the user to persistent memory."""
    try:
        client.store(content)
    except EngineUnavailableError as e:
        return f"Memory engine unavailable ({e.reason}) — not saved."
    return "Information saved successfully."


# 3. Specialist agents
travel_agent = Agent(
    name="Travel Planner",
    instructions=(
        "You are a travel planning specialist. Always call search_memory first "
        "to check for stored travel preferences or past destinations for the user."
    ),
    tools=[search_memory, save_memory],
    model="gpt-4o",
)

health_agent = Agent(
    name="Health Advisor",
    instructions=(
        "You are a health and wellness advisor. Call search_memory first "
        "to retrieve any dietary restrictions or health preferences for the user."
    ),
    tools=[search_memory, save_memory],
    model="gpt-4o",
)


# 4. Triage agent with handoffs
triage_agent = Agent(
    name="Personal Assistant",
    instructions=(
        "You are a triage assistant. Route the user to the Travel Planner or "
        "Health Advisor based on their request. "
        "Use the memory tools to personalise every interaction."
    ),
    handoffs=[travel_agent, health_agent],
    model="gpt-4o",
)


# 5. Run a session and persist the outcome
async def chat_session(user_input: str, user_id: str) -> str:
    result = await Runner.run_async(triage_agent, user_input, user_id=user_id)

    # Persist the session summary so future runs have context
    try:
        client.store(
            f"User '{user_id}' requested: '{user_input}'. "
            f"Agent responded: '{result.final_output}'"
        )
    except EngineUnavailableError:
        pass  # fail open — engine not installed/running

    return result.final_output


if __name__ == "__main__":
    response = asyncio.run(
        chat_session("Plan a healthy meal for my trip to Rome", "alice_12")
    )
    print("Assistant Response:", response)
```

## How memory flows through handoffs

When `triage_agent` hands off to `travel_agent`, the specialist immediately calls `search_memory` before generating any output. This means the specialist inherits the user's history without needing the triage agent to relay it explicitly — the memory store acts as a shared, always-available context layer across the entire agent network. Because `AgentStateClient` talks to the same on-device engine regardless of which agent calls it, this works with zero coordination code between agents.

<Note>
  Initialise `client` once at module level and reuse it across all tool calls, as shown above — the native-host subprocess is spawned lazily on first call and reused across calls, so creating a new `AgentStateClient` per tool invocation adds unnecessary overhead. Requires the native host launcher at `~/.sovseal/native-host/run.sh` (run `npx -y @sovseal/mcp-server` once to provision it — see [SDK Reference: Overview](/sdk-reference/overview)).
</Note>
