deepagents — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited deepagents (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
deepagents (LangChain Python)deepagents is a Python agent harness built on LangChain + LangGraph. Calling create_deep_agent(...) returns a compiled LangGraph graph that already knows how to plan, write to a virtual filesystem, spawn sub-agents, and manage its own context window. Your job, when writing code that uses it, is to wire the right capabilities together — not to reinvent them.
This skill is the navigation hub. It contains the mental model, the 80% patterns, the gotchas, and an index into deeper reference files. Load reference files only when needed — they exist to keep the top-level lean while still giving you authoritative depth on demand.
deepagents is (and isn't) the right fitReach for deepagents when all of these are true:
For simpler agents — single tool, one-shot answer, no planning needed — use langchain.agents.create_agent instead. For maximum control over graph topology, use raw LangGraph. deepagents sits on top of both and is the right pick when you'd otherwise be re-implementing planning + filesystem + sub-agents by hand.
Every deepagents application is built on these four pieces. Understand all four before writing code; the API only makes sense in this frame.
system_prompt= is prepended (not replaced).These map to four context-engineering strategies: offload (filesystem), isolate (subagents), summarize (auto-summarization middleware), quarantine (sandboxes for shell). Keep that vocabulary in your head — it's how the docs talk and how to reason about adding capabilities.
pip install deepagentsPlus the model provider package(s) you'll use:
pip install langchain-anthropic # default model is anthropic:claude-sonnet-4-6
# or langchain-openai, langchain-google-genai, langchain-ollama, "langchain[aws]", etc.API keys come from environment variables (ANTHROPIC_API_KEY, OPENAI_API_KEY, TAVILY_API_KEY, …). Python 3.10+.
For LangSmith tracing: LANGSMITH_TRACING=true and LANGSMITH_API_KEY.
from deepagents import create_deep_agent
def get_weather(city: str) -> str:
"""Get the weather in a city."""
return f"It's always sunny in {city}!"
agent = create_deep_agent(
model="anthropic:claude-sonnet-4-6",
tools=[get_weather],
system_prompt="You are a helpful weather assistant.",
)
result = agent.invoke({
"messages": [{"role": "user", "content": "what is the weather in sf"}]
})
print(result["messages"][-1].content)The agent already has write_todos, ls, read_file, write_file, edit_file, glob, grep, and task even though we passed only one custom tool. They are merged in by middleware automatically.
A complete, runnable version of this and six more end-to-end examples are in examples/ — see §10.
from deepagents import create_deep_agent # or async_create_deep_agent
create_deep_agent(
model: str | BaseChatModel | None = None, # "anthropic:claude-sonnet-4-6" by default
tools: Sequence[BaseTool | Callable | dict] | None = None,
*,
system_prompt: str | SystemMessage | None = None,
middleware: Sequence[AgentMiddleware] = (),
subagents: list[SubAgent | CompiledSubAgent | AsyncSubAgent] | None = None,
skills: list[str] | None = None,
memory: list[str] | None = None,
response_format: ResponseFormat | None = None,
context_schema: type[Any] | None = None,
checkpointer: Checkpointer | None = None,
store: BaseStore | None = None,
backend: BackendProtocol | BackendFactory | None = None,
interrupt_on: dict[str, bool | InterruptOnConfig] | None = None,
debug: bool = False,
name: str | None = None,
cache: BaseCache | None = None,
) -> CompiledStateGraphThe return value is a compiled LangGraph graph, which means you also get agent.invoke, agent.ainvoke, agent.stream, agent.astream, checkpointing, time travel, LangGraph Studio, and LangSmith tracing for free — without any extra adaptation code.
Always set `model=` and `system_prompt=` explicitly. The defaults exist for demos but real applications should pin both for reproducibility and to make intent obvious to readers.
For the full per-parameter reference (types, semantics, edge cases), load references/api-reference.md.
deepagents had a significant API rename between 0.0.x and the current 0.4.x line. Old code samples on the internet may use parameters that no longer exist. When generating code, always:
system_prompt= (not prompt= / not instructions=).SubAgent dicts, use the key system_prompt and always include `tools` and `model` — these are now required for declarative subagents (the factory raises if they're missing).anthropic:claude-sonnet-4-6. Older docs say claude-sonnet-4-5-20250929 or claude-sonnet-4-20250514 — these are stale.glob and grep are filesystem tools (added in 0.4); the execute shell tool is only available when the backend implements SandboxBackendProtocol. Without a sandbox backend, calling it returns an error.If the user's existing code uses old names, see references/migration-from-0.0.x.md before changing anything.
This is the index you should consult when a task involves more than the basics. Don't read all of these up front. Load them as the task demands.
| When the task involves… | Load this reference |
|---|---|
| Exact parameter semantics, types, return shape, edge cases | references/api-reference.md |
| Spawning sub-agents (declarative, compiled, or async/remote) | references/subagents.md |
| Choosing/configuring a filesystem backend, or running shell commands safely | references/backends-and-sandboxes.md |
| Adding custom middleware, summarization, prompt caching, rate limits | references/middleware.md |
Approval gates / interrupt_on / resuming after interrupts | references/human-in-the-loop.md |
Wiring MCP servers (langchain-mcp-adapters) into the agent | references/mcp-integration.md |
Loading AGENTS.md, sharing skills, cross-thread memory | references/skills-and-memory.md |
Streaming modes, sub-agent stream events, response_format Pydantic output | references/streaming-and-output.md |
| Deployment, tracing, cost/token control, security model | references/production.md |
| Migrating an existing 0.0.x codebase | references/migration-from-0.0.x.md |
These are the shapes most real deepagents apps take. Pick the closest one and adapt; full runnable code is in examples/.
A supervisor with a research-agent sub-agent. The supervisor plans, the sub-agent does the heavy retrieval, only a summary returns. See examples/02_research_agent.py.
from deepagents import create_deep_agent
from tavily import TavilyClient
tavily = TavilyClient()
def internet_search(query: str, max_results: int = 5, topic: str = "general") -> dict:
"""Search the web."""
return tavily.search(query=query, max_results=max_results, topic=topic)
research_subagent = {
"name": "research-agent",
"description": "Use for in-depth research on a single topic. Provide a clear, focused question.",
"system_prompt": "You are an expert researcher. Search thoroughly, then summarize.",
"tools": [internet_search], # ← required in 0.4.x
"model": "anthropic:claude-sonnet-4-6", # ← required in 0.4.x
}
agent = create_deep_agent(
model="anthropic:claude-sonnet-4-6",
tools=[internet_search],
system_prompt="You are a senior research lead. Plan, delegate research, then write a polished report.",
subagents=[research_subagent],
)Why this works: the supervisor's context stays small because each sub-agent's search noise is discarded after summary. Use write_file to stash drafts of the report between sub-agent calls.
Use a sandbox backend so the execute tool is real, and gate destructive filesystem writes with interrupt_on. See examples/03_coding_agent_with_sandbox.py.
Pick a sandbox by environment:
LocalShellBackend only for fully trusted local development — it's an unrestricted local shell.Use MultiServerMCPClient from langchain-mcp-adapters to load tools from any MCP server (filesystem, GitHub, Slack, Postgres, …) and pass them to async_create_deep_agent. MCP tools are async, so use the async factory. See examples/05_mcp_integration.py and references/mcp-integration.md.
Pair interrupt_on={"tool_name": True} with a checkpointer (mandatory). Resume with Command(resume=...). See examples/04_hitl_with_checkpointer.py and references/human-in-the-loop.md.
For sub-agents that run for minutes or hours (deep research, long compilation), wrap a remote LangGraph deployment in an AsyncSubAgent. The supervisor gets start_async_task / check_async_task / cancel_async_task tools and uses fire-and-forget semantics. See examples/07_async_subagents.py and the AsyncSubAgent section in references/subagents.md.
Pass a Pydantic model (or any create_agent-compatible schema) to response_format=. Read the typed result from result["structured_response"]. See examples/06_structured_output.py.
These are the issues you'll keep hitting. Skim them every time you start a new deepagents project.
system_prompt= in 0.4.x.StateBackend doesn't ship execute. Plug in ModalSandbox / LocalShellBackend / etc.checkpointer. interrupt_on without a checkpointer is silently a no-op.StateBackend working as designed (per-thread, ephemeral). Use StoreBackend (with store=) for cross-thread persistence, or FilesystemBackend for real disk.create_deep_agent to async_create_deep_agent and use agent.ainvoke / agent.astream.subgraphs=True and version="v2" to agent.stream(...). Check chunk["ns"] to identify which subgraph./. read_file("notes.md") fails; read_file("/notes.md") works.max_retries=10, set a timeout, and add RateLimitMiddleware for production. See references/production.md."general-purpose" in the subagents list.The examples/ directory contains seven progressively-more-complex working scripts. Treat these as the fastest path to a working application; copy one and adapt.
| File | Pattern shown |
|---|---|
examples/01_minimal.py | The tiniest possible agent (one tool, no subagents). |
examples/02_research_agent.py | Supervisor + research sub-agent + Tavily search. The canonical example. |
examples/03_coding_agent_with_sandbox.py | Sandbox backend + execute + HITL on destructive writes. |
examples/04_hitl_with_checkpointer.py | interrupt_on + MemorySaver + resume via Command(resume=...). |
examples/05_mcp_integration.py | async_create_deep_agent + MultiServerMCPClient. |
examples/06_structured_output.py | Pydantic response_format and reading structured_response. |
examples/07_async_subagents.py | AsyncSubAgent for long-running remote tasks. |
When writing deepagents code, follow these defaults so the output is consistent and easy to review:
model= and system_prompt= explicitly. Readers should see what model and what role the agent has without grepping for defaults.tools, subagents, the create_deep_agent call) into a single build_agent() factory function. Tests and notebooks call this; nothing else should construct the agent ad-hoc.@tool from langchain.tools — gives proper schemas and clear docstrings the model uses for routing.description field, in the imperative ("Use for…", "Use when…"). The supervisor reads only this to choose between sub-agents.checkpointer in the same expression as interrupt_on. Reviewers should never have to verify it was set somewhere else.name= so traces are readable in LangSmith.That's the skill. Start with §4, pick a pattern from §8, copy the matching examples/ file, and load reference files from §7 only when the task pushes past the basics.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.