--- title: "Memory for the Claude Agent SDK" description: "The Claude Agent SDK tracks session state. Add durable, temporal user history through the past.dev API." canonical: https://past.dev/integrations/claude-agent-sdk last-updated: 2026-10-15 --- # Add memory to the Claude Agent SDK Source: https://past.dev/integrations/claude-agent-sdk The Claude Agent SDK manages context, tools and state for an agent run. File-based memory is available inside the sandbox. Applications that need shared memory across users, sessions and machines require an external service. past.dev provides ingestion and recall through HTTP calls from an SDK tool. Recall returns ranked documents with dates and source excerpts. ## Claude Agent SDK memory scope The [Claude Agent SDK](https://platform.claude.com/docs/en/agent-sdk/overview) runs an agent loop with tools, hooks, subagents and session management. Within a session, context is handled for you. Anthropic's memory tool persists notes as files the agent reads and writes. Both are scoped to the agent's own working environment. - Session state ends with the session unless you resume it; there is no cross-user memory model. - File-based memory stores unstructured prose. It has no built-in entity resolution, validity dates, or change queries. - File notes do not include a standard validity model for distinguishing current and superseded facts. Files can retain one developer's coding context. The [claude-mem](/compare/claude-mem) plugin uses this pattern. A product with many users and changing facts may require shared memory through a service. ## The integration: one tool, two endpoints Define SDK tools that call past.dev. Store observations with their original timestamps, then call recall when the agent needs history. A custom tool is an `@tool` handler in an in-process MCP server built with `create_sdk_mcp_server` ([custom tools](https://code.claude.com/docs/en/agent-sdk/custom-tools)). The [API reference](/docs/memory-api/api-reference) documents all public operations. ```python import os from typing import Any import httpx from claude_agent_sdk import ClaudeAgentOptions, create_sdk_mcp_server, tool BASE = "https://api.past.dev/api/v1" HEADERS = {"Authorization": f"Bearer {os.environ['PAST_API_KEY']}"} async def post(path: str, body: dict[str, Any]) -> dict[str, Any]: async with httpx.AsyncClient() as client: r = await client.post(f"{BASE}/{path}", headers=HEADERS, json=body) return {"content": [{"type": "text", "text": r.text}]} def make_past_server(user_id: str): """Build the memory tools for one signed-in user. The model never sees user_id.""" @tool("remember", "Store timestamped source text, readable by the whole project, authored by the current user.", {"content": str, "happened_at": str}) async def remember(args: dict[str, Any]) -> dict[str, Any]: return await post("ingest", { "content": args["content"], "timestamp": args["happened_at"], "identity": user_id, }) @tool("recall", "Return ranked documents with dates and source excerpts for the current user.", {"query": str}) async def recall(args: dict[str, Any]) -> dict[str, Any]: return await post("recall", {"query": args["query"], "identity": user_id}) return create_sdk_mcp_server(name="memory", version="1.0.0", tools=[remember, recall]) options = ClaudeAgentOptions( mcp_servers={"memory": make_past_server("demo-user")}, # the signed-in user's id allowed_tools=["mcp__memory__*"], ) ``` A handler receives only its validated arguments, so `make_past_server` closes over the signed-in user's id. Build the options for each user's request, and describe in the system prompt when to use the tools: remember durable facts about the user or the work, recall before answering questions that depend on history. > **Identity** > > The application sets the identity. The model never chooses it. Recall returns what the identity in the request may read, so take the identity from the signed-in user in code, and keep it out of every value that the model fills. ## Or connect the MCP server The Agent SDK connects to a remote MCP server listed in `mcp_servers` with `"type": "http"`. MCP tools need explicit permission, and `allowed_tools` with the wildcard `mcp__past__*` approves every tool of the server ([MCP guide](https://code.claude.com/docs/en/agent-sdk/mcp)). The project's end-user MCP server then gives the agent `recall`, `answer` and `who_am_i`, plus `remember` while the project's write toggle is on, with no tool code to write. 1. Turn on the project's end-user MCP server on **Build › MCP server** in the console. 2. Mint an access link there, or with the account server's `create_mcp_access_link` tool. The link has the form `https://api.past.dev/mcp//link/`. It is one URL that is one identity, and the server answers it with no sign-in step. 3. Keep the link in a secret store, such as the `PAST_MCP_URL` environment variable that the code below reads. The secret in its path is the credential. ```python import asyncio, os from claude_agent_sdk import ClaudeAgentOptions, ResultMessage, query options = ClaudeAgentOptions( mcp_servers={ "past": {"type": "http", "url": os.environ["PAST_MCP_URL"]}, }, allowed_tools=["mcp__past__*"], ) async def main(): async for message in query(prompt="What did we decide about the Q4 budget?", options=options): if isinstance(message, ResultMessage) and message.subtype == "success": print(message.result) asyncio.run(main()) ``` Every call through the link runs as its identity, with that identity's audiences. Mint one link per install, so that a revoked link stops one agent only. When the agent serves several people, mint one link per end user, and connect each request with the link of the user who makes it. Never share one link between users. `remember` writes to the identity's own private audience, and only that identity recalls it. Send data that the whole project must recall through the ingest call. The [end-user server documentation](/docs/mcp/serving-your-own-users) describes the tools, the links and revocation. ## How an SDK agent uses recall results Recall returns ranked documents with dates and source excerpts. The application decides whether those documents support an answer, contain a disagreement, or are insufficient; HTTP failures are handled separately. Define application behavior for the returned documents. Cite source excerpts that support an answer, present documents that disagree, and decline to answer when the material does not meet the application's sufficiency policy. ## Claude Code and team memory Claude Code can call the same endpoints through a hook or MCP tool. Agents using the same project key can query shared, dated records for decisions, incidents and conventions. Start with the [quickstart](/docs/memory-api/quickstart), which shows how to ingest, wait until ingestion completes, and recall. For how recall quality is measured, see the [benchmarks](/benchmarks). ## Frequently asked questions ### Does this replace the SDK's built-in memory tool? No. Keep file memory for the agent's private working notes. Use past.dev for durable facts that must survive sessions, be shared across agents and users, carry dates and sources, and support historical questions. ### Can multiple agents share one memory? Yes. Memory lives behind the API, so every agent, SDK-based or not, reads the same graph with the same key scoping. That is the difference between memory as a file and memory as infrastructure. ## Related - [Memory for OpenClaw](https://past.dev/integrations/openclaw) - [past.dev and claude-mem](https://past.dev/compare/claude-mem) - [Memory for LangGraph](https://past.dev/integrations/langgraph) - [What is agent memory?](https://past.dev/what-is-agent-memory) - [Quickstart](https://past.dev/docs/memory-api/quickstart)