---
title: Letta Agent SDK migration guide | Letta Docs
description: Migrate from the Claude Agent SDK to the Letta Agent SDK
---

The Claude Agent SDK is **query-based** and does not expose a persistent agent entity; state lives in a **session/thread** resumed by `session_id`. Letta Agent SDK is **agent-based** with persistent memory, and also supports multiple conversation threads per agent. The closest mental model depends on which Claude SDK interface you’re using.

## Claude Agent SDK V2 (preview)

V2 uses `createSession` / `resumeSession` with an explicit `send()` / `stream()` cycle per turn. This maps closely to Letta Agent SDK.

### High-level mapping (V2)

| Claude Agent SDK V2                     | Letta Agent SDK                 |
| --------------------------------------- | ------------------------------- |
| `unstable_v2_prompt(...)`               | `prompt(...)`                   |
| `unstable_v2_createSession(...)`        | `createSession(...)`            |
| `unstable_v2_resumeSession(session_id)` | `resumeSession(conversationId)` |
| `session.send(...)`                     | `session.send(...)`             |
| `session.stream()`                      | `session.stream()`              |

### Notes

- Claude `session_id` corresponds to Letta `conversationId`.
- Letta sessions are anchored to a persistent **agent**; Claude sessions are ephemeral unless you store the session ID.
- If you want stateless behavior, use `prompt(...)` or create a fresh agent per run.

## Claude Agent SDK V1 (query-based)

V1 streams results from a single `query(...)` async generator. In Letta Agent SDK, use `prompt(...)` for one-shots or `createSession(...).send()` + `stream()` for multi-turn flows.

### High-level mapping (V1)

| Claude Agent SDK V1          | Letta Agent SDK                                  |
| ---------------------------- | ------------------------------------------------ |
| `query({ prompt, options })` | `prompt(message)` or `createSession(...).send()` |

## Key differences

| Feature                | Claude Agent SDK          | Letta Agent SDK                   |
| ---------------------- | ------------------------- | --------------------------------- |
| Persistence model      | Session-based (ephemeral) | Agent-based (persistent)          |
| Memory                 | Session state only        | Persistent memory blocks          |
| Model support          | Claude only               | Claude, GPT, Gemini, local models |
| Multiple conversations | One per session           | Multiple per agent                |

## Permissions and interactive tools

If you used Claude’s permission/user-input handling, the closest Letta Agent SDK controls are:

- `canUseTool(toolName, toolInput)` for runtime approval decisions.
- `allowedTools` / `disallowedTools` for coarse allow/deny policy.
- `permissionMode` (`standard`, `acceptEdits`, `memory`, `unrestricted`) for global behavior.

In non-interactive headless flows, tools that require runtime user input (for example `AskUserQuestion`) should be handled in `canUseTool` or blocked with `disallowedTools`.

## Example migration

### Before (Claude Agent SDK V2)

```
import {
  unstable_v2_createSession,
  unstable_v2_resumeSession,
} from "@anthropic-ai/claude-agent-sdk";


// Create new session
await using session = unstable_v2_createSession({
  systemPrompt: "You are a helpful assistant.",
});


// Send message
await session.send("Hello!");
for await (const msg of session.stream()) {
  console.log(msg);
}


// Resume later
await using resumed = unstable_v2_resumeSession(session.sessionId);
```

### After (Letta Agent SDK)

```
import { createAgent, resumeSession } from "@letta-ai/letta-code-sdk";


// Create new agent (persistent)
const agentId = await createAgent({
  systemPrompt: "You are a helpful assistant.",
});


// Resume agent's default conversation
await using session = resumeSession(agentId);


// Send message
await session.send("Hello!");
for await (const msg of session.stream()) {
  console.log(msg);
}


// Resume later - just use the agentId
await using resumed = resumeSession(agentId);
```

> **Note:** In the Claude Agent SDK, you must save `sessionId` to resume. In Letta Agent SDK, the **agent** persists—just use `resumeSession(agentId)` to continue where you left off.
>
> For multiple concurrent conversations, use `createSession(agentId)` and `resumeSession(conversationId)`.
