Help us improve
Share bugs, ideas, or general feedback.
From langchain-skills
Creates, deploys, runs, and operates Managed Deep Agents in LangSmith. Covers CLI, Python/TypeScript SDKs, React useStream, REST fallbacks, MCP tools, interrupts, and backends.
npx claudepluginhub langchain-ai/langchain-skills --plugin langchain-skillsHow this skill is triggered — by the user, by Claude, or both
Slash command
/langchain-skills:managed-deep-agentsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Managed Deep Agents is a hosted runtime for creating, running, and operating Deep Agents in LangSmith. It packages the operational layer around the open-source Deep Agents harness: a versioned Context Hub agent repo, durable threads, streamed runs, MCP credential storage, managed files, and optional LangSmith sandboxes.
Implements agents using the Deep Agents library: create_deep_agent, backends, subagents, middleware, and human-in-the-loop workflows.
Builds Deep Agents applications using create_deep_agent(), harness architecture with middleware for task planning, context management, subagents, memory, and human-in-the-loop.
Guides developers to create new AgentCore agent projects on AWS: framework selection (Strands, LangGraph), project scaffolding, first deploy, and invocation. For beginners or 'agentcore create'.
Share bugs, ideas, or general feedback.
Managed Deep Agents is a hosted runtime for creating, running, and operating Deep Agents in LangSmith. It packages the operational layer around the open-source Deep Agents harness: a versioned Context Hub agent repo, durable threads, streamed runs, MCP credential storage, managed files, and optional LangSmith sandboxes.
Use the Managed Deep Agents path when the user wants LangSmith to host and operate the agent. For self-hosted deployments, custom application routes, or the full Agent Server API surface, use a standard LangSmith Deployment via [[langgraph-cli]] instead.
Use this skill when the user wants to:
@langchain/react useStream.uv tool install "deepagents-cli>=0.2.2"
pip install managed-deepagents
npm install @langchain/managed-deepagents @langchain/react
Set the API key in the shell or server environment:
export LANGSMITH_API_KEY="<LANGSMITH_API_KEY>"
The SDKs default to https://api.smith.langchain.com/v1/deepagents. To use a different compatible endpoint, set LANGSMITH_ENDPOINT or pass api_url / apiUrl in the client.
For direct REST examples, set:
export DEEPAGENTS_BASE_URL="https://api.smith.langchain.com/v1/deepagents"
All REST requests authenticate with:
X-Api-Key: <LANGSMITH_API_KEY>
Never expose a long-lived LangSmith API key in browser code. For browser apps, route requests through your own backend or provide a custom fetch implementation that proxies requests server-side.
| Interface | Use for |
|---|---|
deepagents-cli>=0.2.2 | Normal project-file workflow: scaffold, edit files, deploy, manage MCP servers. |
Python SDK managed-deepagents | Server-side Python automation, tests, scripts, services, and streaming. |
TypeScript SDK @langchain/managed-deepagents | Server-side TypeScript automation and LangGraph-compatible streaming. |
React useStream | Chat UIs that should let LangGraph own thread/run/projection state. |
REST /v1/deepagents | Low-level fallback when a client does not expose a field yet. |
Prefer the CLI for local agent projects. Prefer the SDKs for application code. Use REST only when you need exact request control.
| Group | Purpose |
|---|---|
| Agents | Create, list, get, update, clone, delete, and health-check Managed Deep Agents. |
| Threads | Create, list, search, count, inspect, update, and delete durable thread state. |
| Runs | Start and stream runs on a thread. |
| MCP servers | Register, list, update, delete, and connect MCP servers. |
| MCP tools | List tools exposed by a registered MCP server for tools.json. |
| Auth sessions | Start and inspect OAuth authorization sessions. |
The CLI uses a local project directory and deploys it into the managed Context Hub agent repo.
my-agent/
agent.json
AGENTS.md
tools.json
skills/<name>/SKILL.md
subagents/<name>/agent.json
subagents/<name>/AGENTS.md
subagents/<name>/tools.json
| File / directory | Purpose |
|---|---|
agent.json | Agent name, description, model, backend, permissions, and optional target agent_id. |
AGENTS.md | Main agent instructions. |
tools.json | MCP-backed tools plus interrupt_config. |
skills/ | Reusable instructions and files the agent can load. |
subagents/ | Delegated worker definitions and optional subagent-scoped tools. |
At runtime, the agent can read and write managed files, including memory files created by the Deep Agents harness.
New projects should use the canonical backend names from deepagents-cli>=0.2.2.
Use state when the agent does not need sandbox-specific backend behavior:
{
"backend": {
"type": "state"
}
}
Use sandbox when the agent needs a LangSmith sandbox for code execution, filesystem work, or long-running tasks:
{
"backend": {
"type": "sandbox",
"sandbox_config": {
"scope": "thread",
"policy_ids": ["policy-id"],
"idle_ttl_seconds": 900,
"delete_after_stop_seconds": 300
}
}
}
sandbox_config.scope must be thread or agent.
Use the CLI for most deploy workflows.
deepagents init research-assistant
cd research-assistant
Edit agent.json:
{
"name": "research-assistant",
"description": "Research assistant that can search the web and summarize sources.",
"model": "openai:gpt-5.5",
"backend": {
"type": "state"
}
}
Edit AGENTS.md with the main instructions, then deploy:
deepagents deploy
Useful CLI commands:
| Command | Use |
|---|---|
deepagents --version | Confirm deepagents-cli>=0.2.2. |
deepagents deploy --dry-run | Print the agent payload and managed file tree without deploying. |
deepagents agents list | List Managed Deep Agents in the workspace. |
deepagents agents get <agent_id> --include-files | Inspect an agent and its managed files. |
deepagents mcp-servers add --url URL --name NAME | Register a static-header MCP server. |
deepagents mcp-servers add --url URL --auth-type oauth --connect | Register and connect an OAuth MCP server. |
| `deepagents mcp-servers tools <id | name |
| `deepagents mcp-servers connect <id | name |
For shared repositories, put the target agent_id in agent.json; the CLI asks for confirmation before updating that remote agent. Use --yes only when the target is intentional.
Tools are configured with a tools array and an interrupt_config map. The same shape is used in tools.json and inline SDK/REST create or update payloads.
{
"tools": [
{
"name": "read_url_content",
"mcp_server_url": "https://example.com/mcp",
"mcp_server_name": "my-tools",
"display_name": "read_url_content"
}
],
"interrupt_config": {
"https://example.com/mcp::read_url_content": false
}
}
tools[].mcp_server_url must match a registered workspace MCP server URL.tools[].name is the tool name exposed by the MCP server, not the workspace MCP-server display name.deepagents mcp-servers tools <server> or the SDK tool-listing methods to confirm exact tool names.interrupt_config keys use {mcp_server_url}::{tool_name}. Additional :: parts are accepted for compatibility, but do not rely on them for new configs.true to require human approval before the tool runs.Python SDK tool listing:
from managed_deepagents import Client
with Client() as client:
tools = client.mcp_servers.list_tools(
url="https://example.com/mcp",
force_refresh=True,
)
print(tools["tools"])
TypeScript SDK tool listing:
import { Client } from "@langchain/managed-deepagents";
const client = new Client({ apiKey: process.env.LANGSMITH_API_KEY });
const tools = await client.mcpServers.listTools({
url: "https://example.com/mcp",
forceRefresh: true,
});
console.log(tools.tools);
Use the Python SDK for server-side automation and streaming.
from managed_deepagents import Client
with Client() as client:
agent = client.agents.create(
name="research-assistant",
description="Research assistant that can search the web and summarize sources.",
model="openai:gpt-5.5",
backend={"type": "state"},
instructions=(
"You are a careful research assistant. Search for sources, "
"keep notes, and return concise answers with citations."
),
)
thread = client.threads.create(
agent_id=agent["id"],
options={
"test_run": False,
"skip_memory_write_protection": False,
},
)
for event in client.threads.stream(
thread["id"],
agent_id=agent["id"],
messages=[
{
"role": "user",
"content": "Research recent approaches to agent memory and summarize the main tradeoffs.",
}
],
stream_mode=["values", "updates", "messages-tuple"],
stream_subgraphs=True,
user_timezone="America/Los_Angeles",
):
print(event.event, event.data)
Async Python clients are available as AsyncClient with matching resource names.
Use the TypeScript SDK for server-side automation and LangGraph-compatible streaming.
import { Client } from "@langchain/managed-deepagents";
const client = new Client({
apiKey: process.env.LANGSMITH_API_KEY,
});
const agent = await client.agents.create({
name: "research-assistant",
description: "Research assistant that can search the web and summarize sources.",
model: "openai:gpt-5.5",
backend: { type: "state" },
instructions:
"You are a careful research assistant. Search for sources, keep notes, and return concise answers with citations.",
});
const thread = await client.threads.create({
agent_id: agent.id,
options: {
test_run: false,
skip_memory_write_protection: false,
},
});
const langGraphClient = client.getLangGraphClient({ agentId: agent.id });
const stream = langGraphClient.runs.stream(thread.id, agent.id, {
input: {
messages: [
{
role: "user",
content:
"Research recent approaches to agent memory and summarize the main tradeoffs.",
},
],
},
streamMode: ["values", "updates", "messages-tuple"],
streamSubgraphs: true,
});
for await (const event of stream) {
console.log(event.event, event.data);
}
The adapter translates LangGraph SDK request fields into Managed Deep Agents routes, headers, and payload fields.
useStreamFor React applications, use the TypeScript SDK's LangGraph client adapter with @langchain/react. useStream owns the thread, run, and state projection behavior while the Managed Deep Agents SDK handles auth, routes, and payload translation.
import { Client } from "@langchain/managed-deepagents";
import { useStream } from "@langchain/react";
const agentId = "<agent_id>";
const managedDeepAgents = new Client({
// Server-only or browser-safe proxy configuration.
// Do not ship LANGSMITH_API_KEY to browser clients.
apiKey: process.env.LANGSMITH_API_KEY,
});
const client = managedDeepAgents.getLangGraphClient({ agentId });
export function ManagedDeepAgentStream() {
const stream = useStream({
client,
assistantId: agentId,
fetchStateHistory: false,
});
return (
<section>
<button
type="button"
disabled={stream.isLoading}
onClick={() => {
void stream.submit({
messages: [
{ role: "user", content: "Write a short status update." },
],
});
}}
>
Run agent
</button>
{stream.messages.map((message, index) => (
<p key={message.id ?? index}>{String(message.content)}</p>
))}
</section>
);
}
stream.submit({ messages }) is the correct UI-level shape. The SDK adapter rewrites it to the Managed Deep Agents stream route as input.messages.
Use REST when a client does not expose a field yet or when debugging raw payloads. Prefer SDK helpers in normal application code.
Create an agent:
import os
import httpx
BASE_URL = os.environ["DEEPAGENTS_BASE_URL"]
HEADERS = {"X-Api-Key": os.environ["LANGSMITH_API_KEY"]}
response = httpx.post(
f"{BASE_URL}/agents",
headers=HEADERS,
json={
"name": "research-assistant",
"description": "Research assistant that can search the web and summarize sources.",
"runtime": {"model": {"model_id": "openai:gpt-5.5"}},
"backend": {"type": "state"},
"instructions": (
"You are a careful research assistant. Search for sources, "
"keep notes, and return concise answers with citations."
),
},
)
response.raise_for_status()
agent_id = response.json()["id"]
Create a thread:
response = httpx.post(
f"{BASE_URL}/threads",
headers=HEADERS,
json={
"agent_id": agent_id,
"options": {
"test_run": False,
"skip_memory_write_protection": False,
},
},
)
response.raise_for_status()
thread_id = response.json()["id"]
Stream a run:
payload = {
"agent_id": agent_id,
"input": {
"messages": [
{
"role": "user",
"content": "Research recent approaches to agent memory and summarize the main tradeoffs.",
}
]
},
"stream_mode": ["values", "updates", "messages-tuple"],
"stream_subgraphs": True,
"user_timezone": "America/Los_Angeles",
}
with httpx.stream(
"POST",
f"{BASE_URL}/threads/{thread_id}/runs/stream",
headers={**HEADERS, "Accept": "text/event-stream"},
json=payload,
timeout=None,
) as response:
response.raise_for_status()
for line in response.iter_lines():
if line:
print(line)
Set Accept: text/event-stream for raw REST streaming. stream_mode accepts LangGraph stream modes such as values, updates, and messages-tuple. stream_subgraphs: true emits subagent events as well as parent events.
When interrupt_config flags a tool with true, the run pauses before the tool executes and emits an interrupt payload inside a values or updates event:
{
"__interrupt__": [
{
"value": {
"action_requests": [
{
"name": "read_url_content",
"args": { "url": "https://example.com" },
"description": "Tool execution requires approval"
}
],
"review_configs": [
{
"action_name": "read_url_content",
"allowed_decisions": ["approve", "edit", "reject", "respond"]
}
]
},
"id": "interrupt-id"
}
]
}
The stream closes after the interrupt is emitted. To act on it, post a follow-up run with command.resume on the same thread.
Python SDK resume:
for event in client.threads.stream(
thread_id,
agent_id=agent_id,
messages=[{"role": "system", "content": ""}],
command={"resume": {"decisions": [{"type": "approve"}]}},
stream_mode=["values", "updates", "messages-tuple"],
stream_subgraphs=True,
):
print(event.event, event.data)
REST resume:
payload = {
"agent_id": agent_id,
"input": {"messages": [{"role": "system", "content": ""}]},
"command": {
"resume": {
"decisions": [{"type": "approve"}]
}
},
"stream_mode": ["values", "updates", "messages-tuple"],
"stream_subgraphs": True,
}
The resume value must be the HITL response object {"decisions": [...]}, not a bare decision list. Send exactly one decision per action_request, in the same order.
| Decision | Shape | Effect |
|---|---|---|
| Approve | {"type": "approve"} | Run the tool with the proposed args. |
| Edit | {"type": "edit", "edited_action": {"name": "...", "args": {...}}} | Run the tool with modified name/args. |
| Reject | {"type": "reject", "message": "..."} | Block the tool and return an error ToolMessage to the model. |
| Respond | {"type": "respond", "message": "..."} | Skip the tool and return a synthetic successful tool reply. |
Each decision type must be allowed by the matching review_configs[i].allowed_decisions.
POST /v1/deepagents/threads/{thread_id}/resolve-interrupt takes no body and returns 204. It terminates the paused run at the interrupt; it is not an approve shortcut. Use command.resume on /runs/stream for approve, edit, reject, or respond decisions.
Use a standard LangSmith Deployment via [[langgraph-cli]] (langgraph deploy) instead when you need:
deepagents-cli>=0.2.2 - older CLI versions generate stale backend names.state or sandbox with sandbox_config.scope.input.messages - SDK helpers accept messages and normalize the request body.fetch.PATCH can replace nested fields wholesale - when updating tools, pass the full desired tool set.tools[].name is wrong, the model will not see the tool.tools.json - use the CLI or SDK tool-listing methods to avoid name mismatches.command.resume = {"decisions": [...]} - a bare list is invalid.[ {"role": "system", "content": ""} ] as a no-op message when needed.resolve-interrupt cancels/finalizes - it does not approve a pending action.openai:gpt-5.5, not a bare model name./v1/deepagents is still evolving; prefer SDK and CLI surfaces for user-facing workflows.