# How to Migrate Agent Logic from the DeepAgents SDK to the CLI for Interactive Development

> Migrate agent logic from DeepAgents SDK to CLI using create_cli_agent for interactive development. Enjoy automatic middleware setup, interactive prompts, and Textual UI configuration.

- Repository: [LangChain/deepagents](https://github.com/langchain-ai/deepagents)
- Tags: migration-guide
- Published: 2026-03-17

---

**To migrate from the SDK to the CLI, replace `deepagents.graph.create_deep_agent` with `deepagents_cli.agent.create_cli_agent`, which automatically wires the full middleware stack, generates interactive system prompts, and configures the Textual UI while preserving all SDK arguments.**

The **DeepAgents** framework by LangChain provides a Python SDK for building agent graphs and a dedicated CLI for interactive development. When you need to transition from programmatic SDK usage to a terminal-based workflow with real-time streaming, human-in-the-loop approvals, and built-in memory, you must migrate your agent construction logic to use CLI-specific wrappers. This guide demonstrates the exact migration path using actual source implementations from the `langchain-ai/deepagents` repository.

## Why Use create_cli_agent Instead of create_deep_agent

When you migrate agent logic from the SDK to the CLI, you shift from manual graph assembly to an opinionated wrapper that handles the full interactive stack. The core difference lies in how middleware, system prompts, and UI components are assembled.

**`create_deep_agent`** (SDK) requires you to manually inject every middleware component and craft your own system prompt. You must separately handle token tracking, sandbox routing, and checkpoint persistence.

**`create_cli_agent`** (CLI) wraps the SDK function while automatically injecting the complete middleware stack—including `AskUserMiddleware`, `MemoryMiddleware`, `SkillsMiddleware`, and `SummarizationToolMiddleware`—plus UI-specific hooks for `SpinnerStatus` and token statistics. It generates an interactive system prompt from [`system_prompt.md`](https://github.com/langchain-ai/deepagents/blob/main/system_prompt.md) and handles local versus remote sandbox selection.

According to the source code in [`libs/cli/deepagents_cli/agent.py`](https://github.com/langchain-ai/deepagents/blob/main/libs/cli/deepagents_cli/agent.py) (lines 641–720), `create_cli_agent` accepts all SDK arguments but adds optional CLI-specific parameters like `interactive`, `auto_approve`, and `enable_memory`, making it future-proof against SDK updates.

## Step-by-Step Migration Guide

### 1. Identify Your Current SDK Implementation

Locate your existing SDK entry point. A typical SDK-based agent looks like this:

```python
from deepagents.graph import create_deep_agent

agent = create_deep_agent(
    model="gpt-4o-mini",
    tools=[my_tool],
    middleware=[my_middleware],
    system_prompt="You are a data-analysis bot...",
)

```

*Source: [`libs/deepagents/deepagents/graph.py`](https://github.com/langchain-ai/deepagents/blob/main/libs/deepagents/deepagents/graph.py) at line 82.*

### 2. Replace the Import Statement

Change your import to use the CLI wrapper:

```python
from deepagents_cli.agent import create_cli_agent

```

### 3. Migrate Core Arguments

Pass the same `model`, `tools`, and optional `system_prompt` to `create_cli_agent`. You should generally **remove** SDK-specific middleware that the CLI automatically provides—such as `AskUserMiddleware`, `MemoryMiddleware`, `SkillsMiddleware`, and `SummarizationToolMiddleware`—unless you require custom implementations.

```python
agent_graph, backend = create_cli_agent(
    model="gpt-4o-mini",
    assistant_id="my-assistant",
    tools=[my_tool],
    middleware=[my_custom_middleware],  # Only if you have custom middleware not in CLI defaults

)

```

### 4. Configure CLI-Specific Options

Set optional flags to control the interactive behavior:

- **`interactive=False`** – Enables headless mode without human-in-the-loop instructions.
- **`auto_approve=True`** – Skips the approval UI, useful for CI pipelines.
- **`sandbox_type`** – Set to `"modal"`, `"runloop"`, or `None` for local filesystem.
- **`enable_memory=False`** or **`enable_skills=False`** – Disable specific CLI features if not needed.
- **`cwd=Path("my/project")`** – Override the working directory shown in the system prompt.
- **`checkpointer=MyCheckpointSaver`** – Inject a custom checkpoint saver as with the SDK.

```python
agent_graph, backend = create_cli_agent(
    model="gpt-4o-mini",
    assistant_id="my-assistant",
    tools=[my_tool],
    sandbox_type="modal",
    interactive=True,
    auto_approve=False,
    enable_memory=True,
    enable_skills=True,
    cwd=Path.cwd(),
)

```

### 5. Execute the Graph

The CLI returns a **LangGraph Pregel** instance. For interactive use, wrap it with `TextualUIAdapter`:

```python
from deepagents_cli.textual_adapter import TextualUIAdapter

ui_adapter = TextualUIAdapter(agent_graph, backend)
ui_adapter.run()  # Blocks until TUI exits

```

For headless execution, invoke the graph directly:

```python
from langgraph.checkpoint.memory import MemorySaver

checkpoint = MemorySaver()
config = {"configurable": {"thread_id": "demo"}}
result = await agent_graph.ainvoke(
    {"messages": [{"role": "user", "content": "Explain recursion"}]},
    config=config,
    checkpoint=checkpoint,
)

```

### 6. Leverage Configuration Files

The CLI reads from [`deepagents/config.toml`](https://github.com/langchain-ai/deepagents/blob/main/deepagents/config.toml) or `~/.deepagents/config.toml` for model specifications. You can use `create_model` from `deepagents_cli.config` to respect environment variables:

```python
from deepagents_cli.config import create_model

model = create_model("gpt-4o-mini")  # Respects env vars and config files

```

### 7. Persist Customizations

The CLI automatically creates [`AGENTS.md`](https://github.com/langchain-ai/deepagents/blob/main/AGENTS.md) in the assistant’s directory (e.g., `~/.deepagents/<assistant_id>/AGENTS.md`). Add custom system prompt sections and skill aliases here; the CLI reloads these on every start. This persistence logic is implemented in [`libs/cli/deepagents_cli/agent.py`](https://github.com/langchain-ai/deepagents/blob/main/libs/cli/deepagents_cli/agent.py) (lines 21–27).

## Practical Code Examples

### Minimal Interactive CLI Agent

This example demonstrates the most basic migration path for launching the Textual TUI:

```python
from deepagents_cli.agent import create_cli_agent
from deepagents_cli.textual_adapter import TextualUIAdapter

# Build graph and backend with full CLI middleware

graph, backend = create_cli_agent(
    model="gpt-4o-mini",
    assistant_id="research-bot",
    tools=[],  # Add custom tools here

)

# Launch interactive terminal UI

ui = TextualUIAdapter(graph, backend)
ui.run()

```

### Headless CI Agent

For automated testing without UI interaction:

```python
from deepagents_cli.agent import create_cli_agent
from langgraph.checkpoint.memory import MemorySaver
import asyncio

graph, backend = create_cli_agent(
    model="gpt-4o-mini",
    assistant_id="ci-bot",
    interactive=False,  # Disables human-in-the-loop wording

    auto_approve=True,  # Skips approval UI

)

checkpoint = MemorySaver()
config = {"configurable": {"thread_id": "ci-run"}}

async def run_one_turn():
    result = await graph.ainvoke(
        {"messages": [{"role": "user", "content": "Summarize the latest LangChain release notes"}]},
        config=config,
        checkpoint=checkpoint,
    )
    print(result["messages"][-1].content)

asyncio.run(run_one_turn())

```

### Custom Middleware with CLI Defaults

Add your own middleware while retaining the CLI's default stack:

```python
from deepagents_cli.agent import create_cli_agent
from deepagents.middleware import MyAnalyticsMiddleware

graph, backend = create_cli_agent(
    model="gpt-4o-mini",
    assistant_id="analytics-bot",
    middleware=[MyAnalyticsMiddleware()],  # CLI still adds its own stack

)

```

### Remote Sandbox Configuration

Using Modal as a remote sandbox backend:

```python
from deepagents_cli.agent import create_cli_agent
from deepagents.backends.modal import ModalBackend

remote_backend = ModalBackend(
    modal_image="ghcr.io/langchain-ai/deepagents:latest",
    env={"OPENAI_API_KEY": "..."},
)

graph, backend = create_cli_agent(
    model="gpt-4o-mini",
    assistant_id="modal-bot",
    sandbox=remote_backend,
    sandbox_type="modal",
)

```

The CLI automatically routes large tool results through dedicated routes like `/large_tool_results/` and `/conversation_history/` when using remote sandboxes.

## Key Source Files Reference

Understanding these files ensures you can debug migration issues by referencing the actual implementation:

| File | Purpose |
|------|---------|
| [`libs/deepagents/deepagents/graph.py`](https://github.com/langchain-ai/deepagents/blob/main/libs/deepagents/deepagents/graph.py) | Core SDK function `create_deep_agent` that assembles the LangGraph Pregel graph. |
| [`libs/cli/deepagents_cli/agent.py`](https://github.com/langchain-ai/deepagents/blob/main/libs/cli/deepagents_cli/agent.py) | CLI wrapper `create_cli_agent`—builds middleware stack, selects backend, generates system prompt, and calls `create_deep_agent`. |
| [`libs/cli/deepagents_cli/system_prompt.md`](https://github.com/langchain-ai/deepagents/blob/main/libs/cli/deepagents_cli/system_prompt.md) | Template for interactive system prompts containing `{mode_description}`, `{model_identity_section}`, and `{interactive_preamble}` variables. |
| [`libs/cli/deepagents_cli/textual_adapter.py`](https://github.com/langchain-ai/deepagents/blob/main/libs/cli/deepagents_cli/textual_adapter.py) | Bridges the Pregel graph to the Textual UI, handling token statistics, spinners, and rendering. |
| [`libs/cli/deepagents_cli/config.py`](https://github.com/langchain-ai/deepagents/blob/main/libs/cli/deepagents_cli/config.py) | Settings loader for [`deepagents/config.toml`](https://github.com/langchain-ai/deepagents/blob/main/deepagents/config.toml), model detection, and environment handling. |

## Summary

- **`create_cli_agent`** wraps **`create_deep_agent`** while injecting CLI-specific middleware, system prompts, and UI hooks.
- Remove SDK-only middleware (like `AskUserMiddleware` and `MemoryMiddleware`) when migrating unless you need custom behavior, as the CLI adds these automatically.
- The **`assistant_id`** parameter is required for CLI persistence and directory creation under `~/.deepagents/<assistant_id>/`.
- Set **`interactive=False`** and **`auto_approve=True`** for headless CI usage, or keep defaults for the full Textual TUI experience.
- The CLI handles sandbox routing, token tracking, and checkpoint configuration while remaining compatible with all SDK arguments for future-proofing.

## Frequently Asked Questions

### Can I use custom middleware with the CLI wrapper?

Yes. Pass a list of custom middleware to the `middleware` parameter in `create_cli_agent`. The function appends your custom middleware to the CLI's default stack, so you retain features like memory and skills while adding your own analytics or logging layers.

### Do I need to rewrite my existing SDK tests after migration?

No. Existing unit tests continue to work because `create_cli_agent` forwards all SDK arguments to the underlying `create_deep_agent` function. For CLI-specific behavior—such as approval flows or UI rendering—add new tests under `libs/cli/tests/` that patch functions like `deepagents_cli.agent.get_system_prompt`.

### How does the CLI handle system prompts differently from the SDK?

The SDK requires you to manually provide a `system_prompt` string. The CLI generates one automatically from [`system_prompt.md`](https://github.com/langchain-ai/deepagents/blob/main/system_prompt.md), injecting dynamic variables like working directory, model identity, and skills path. You can override this by passing your own `system_prompt` argument or by editing the generated [`AGENTS.md`](https://github.com/langchain-ai/deepagents/blob/main/AGENTS.md) file in the assistant's directory.

### What is the difference between local and remote sandbox configuration?

When `sandbox_type` is `None` (default), the CLI uses the local filesystem. When set to `"modal"` or other remote providers, the CLI instantiates the specified backend (e.g., `ModalBackend`) and automatically routes large tool results and conversation history through dedicated API endpoints to avoid size limitations.