make existing snippets testable (#4010)

This commit is contained in:
Naomi Pentrel
2026-05-15 11:03:51 +02:00
committed by GitHub
parent 065969b91a
commit ca4ed8df63
49 changed files with 1654 additions and 384 deletions
+1
View File
@@ -117,6 +117,7 @@ jobs:
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
LANGSMITH_API_KEY: ${{ secrets.LANGSMITH_API_KEY }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
POSTGRES_URI: postgresql://postgres:postgres@127.0.0.1:5432/postgres?sslmode=disable
TAVILY_API_KEY: ${{ secrets.TAVILY_API_KEY }}
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
+1
View File
@@ -22,6 +22,7 @@ dependencies = [
"langchain-google-genai>=2.0.0",
"langchain-daytona>=0.0.5",
"daytona>=0.100.0",
"langchain-quickjs>=0.1.2",
]
@@ -0,0 +1,23 @@
// :snippet-start: backend-composite-js
import {
createDeepAgent,
CompositeBackend,
StateBackend,
StoreBackend,
} from "deepagents";
import { InMemoryStore } from "@langchain/langgraph";
const store = new InMemoryStore();
// KEEP MODEL
const agent = createDeepAgent({
model: "google_genai:gemini-3.1-pro-preview",
backend: new CompositeBackend(new StateBackend(), {
"/memories/": new StoreBackend(),
}),
store,
});
// :snippet-end:
// :remove-start:
if (!agent) throw new Error("agent not created");
// :remove-end:
@@ -0,0 +1,13 @@
// :snippet-start: backend-filesystem-js
import { createDeepAgent, FilesystemBackend } from "deepagents";
// KEEP MODEL
const agent = createDeepAgent({
model: "google_genai:gemini-3.1-pro-preview",
backend: new FilesystemBackend({ rootDir: ".", virtualMode: true }),
});
// :snippet-end:
// :remove-start:
if (!agent) throw new Error("agent not created");
// :remove-end:
@@ -0,0 +1,14 @@
// :snippet-start: backend-local-shell-js
import { createDeepAgent, LocalShellBackend } from "deepagents";
const backend = new LocalShellBackend({ workingDirectory: "." });
// KEEP MODEL
const agent = createDeepAgent({
model: "google_genai:gemini-3.1-pro-preview",
backend,
});
// :snippet-end:
// :remove-start:
if (!agent) throw new Error("agent not created");
// :remove-end:
@@ -0,0 +1,15 @@
// :snippet-start: backend-state-js
import { createDeepAgent, StateBackend } from "deepagents";
// By default we provide a StateBackend
const agent = createDeepAgent();
// Under the hood, it looks like
const agent2 = createDeepAgent({
backend: new StateBackend(),
});
// :snippet-end:
// :remove-start:
if (!agent || !agent2) throw new Error("agents not created");
// :remove-end:
@@ -0,0 +1,18 @@
// :snippet-start: backend-store-js
import { createDeepAgent, StoreBackend } from "deepagents";
import { InMemoryStore } from "@langchain/langgraph";
const store = new InMemoryStore(); // Good for local dev; omit for LangSmith Deployment
// KEEP MODEL
const agent = createDeepAgent({
model: "google_genai:gemini-3.1-pro-preview",
backend: new StoreBackend({
namespace: (ctx) => [ctx.runtime.context.userId],
}),
store,
});
// :snippet-end:
// :remove-start:
if (!agent) throw new Error("agent not created");
// :remove-end:
@@ -0,0 +1,88 @@
"""Customization: virtual filesystem backend examples."""
# :snippet-start: backend-state-py
from deepagents import create_deep_agent
from deepagents.backends import StateBackend
# By default we provide a StateBackend
# KEEP MODEL
agent = create_deep_agent(model="google_genai:gemini-3.1-pro-preview")
# Under the hood, it looks like
# KEEP MODEL
agent2 = create_deep_agent(
model="google_genai:gemini-3.1-pro-preview",
backend=StateBackend(),
)
# :snippet-end:
# :snippet-start: backend-filesystem-py
from deepagents import create_deep_agent
from deepagents.backends import FilesystemBackend
# KEEP MODEL
agent = create_deep_agent(
model="google_genai:gemini-3.1-pro-preview",
backend=FilesystemBackend(root_dir=".", virtual_mode=True),
)
# :snippet-end:
# :snippet-start: backend-local-shell-py
from deepagents import create_deep_agent
from deepagents.backends import LocalShellBackend
# KEEP MODEL
agent = create_deep_agent(
model="google_genai:gemini-3.1-pro-preview",
backend=LocalShellBackend(root_dir=".", virtual_mode=True, env={"PATH": "/usr/bin:/bin"}),
)
# :snippet-end:
# :snippet-start: backend-store-py
from deepagents import create_deep_agent
from deepagents.backends import StoreBackend
from langgraph.store.memory import InMemoryStore
# KEEP MODEL
agent = create_deep_agent(
model="google_genai:gemini-3.1-pro-preview",
backend=StoreBackend(
namespace=lambda ctx: (ctx.runtime.context.user_id,),
),
store=InMemoryStore(), # Good for local dev; omit for LangSmith Deployment
)
# :snippet-end:
# :snippet-start: backend-context-hub-py
from deepagents import create_deep_agent
from deepagents.backends import ContextHubBackend
# KEEP MODEL
agent = create_deep_agent(
model="google_genai:gemini-3.1-pro-preview",
backend=ContextHubBackend("my-agent"),
)
# :snippet-end:
# :snippet-start: backend-composite-py
from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend
from langgraph.store.memory import InMemoryStore
# KEEP MODEL
agent = create_deep_agent(
model="google_genai:gemini-3.1-pro-preview",
backend=CompositeBackend(
default=StateBackend(),
routes={
"/memories/": StoreBackend(),
},
),
store=InMemoryStore(), # Store passed to create_deep_agent, not backend
)
# :snippet-end:
# :remove-start:
assert agent is not None
assert agent2 is not None
# :remove-end:
@@ -0,0 +1,45 @@
"""Customization: human-in-the-loop interrupt_on example."""
# :snippet-start: hitl-basic-config-py
from langchain.tools import tool
from deepagents import create_deep_agent
from langgraph.checkpoint.memory import MemorySaver
@tool
def remove_file(path: str) -> str:
"""Delete a file from the filesystem."""
return f"Deleted {path}"
@tool
def fetch_file(path: str) -> str:
"""Read a file from the filesystem."""
return f"Contents of {path}"
@tool
def notify_email(to: str, subject: str, body: str) -> str:
"""Send an email."""
return f"Sent email to {to}"
# Checkpointer is REQUIRED for human-in-the-loop
checkpointer = MemorySaver()
# KEEP MODEL
agent = create_deep_agent(
model="google_genai:gemini-3.1-pro-preview",
tools=[remove_file, fetch_file, notify_email],
interrupt_on={
"remove_file": True, # Default: approve, edit, reject, respond
"fetch_file": False, # No interrupts needed
"notify_email": {"allowed_decisions": ["approve", "reject"]}, # No editing
},
checkpointer=checkpointer, # Required!
)
# :snippet-end:
# :remove-start:
assert agent is not None
# :remove-end:
@@ -0,0 +1,74 @@
// :snippet-start: hitl-basic-config-js
import { tool } from "langchain";
import { createDeepAgent } from "deepagents";
import { MemorySaver } from "@langchain/langgraph";
import { z } from "zod";
const removeFile = tool(
async ({ path }: { path: string }) => {
return `Deleted ${path}`;
},
{
name: "remove_file",
description: "Delete a file from the filesystem.",
schema: z.object({
path: z.string(),
}),
},
);
const fetchFile = tool(
async ({ path }: { path: string }) => {
return `Contents of ${path}`;
},
{
name: "fetch_file",
description: "Read a file from the filesystem.",
schema: z.object({
path: z.string(),
}),
},
);
const notifyEmail = tool(
async ({
to,
subject,
body,
}: {
to: string;
subject: string;
body: string;
}) => {
return `Sent email to ${to}`;
},
{
name: "notify_email",
description: "Send an email.",
schema: z.object({
to: z.string(),
subject: z.string(),
body: z.string(),
}),
},
);
// Checkpointer is REQUIRED for human-in-the-loop
const checkpointer = new MemorySaver();
// KEEP MODEL
const agent = createDeepAgent({
model: "google_genai:gemini-3.1-pro-preview",
tools: [removeFile, fetchFile, notifyEmail],
interruptOn: {
remove_file: true, // Default: approve, edit, reject, respond
fetch_file: false, // No interrupts needed
notify_email: { allowedDecisions: ["approve", "reject"] }, // No editing
},
checkpointer, // Required!
});
// :snippet-end:
// :remove-start:
if (!agent) throw new Error("agent not created");
// :remove-end:
@@ -0,0 +1,33 @@
// :snippet-start: skills-usage-filesystem-js
import { createCodeInterpreterMiddleware } from "@langchain/quickjs";
import { createDeepAgent, FilesystemBackend } from "deepagents";
import { MemorySaver } from "@langchain/langgraph";
const checkpointer = new MemorySaver();
const backend = new FilesystemBackend({ rootDir: process.cwd() });
// KEEP MODEL
const agent = await createDeepAgent({
model: "google-genai:gemini-3.1-pro-preview",
backend,
skills: ["./examples/skills/"],
interruptOn: {
read_file: true,
write_file: true,
delete_file: true,
},
checkpointer, // Required!
middleware: [createCodeInterpreterMiddleware({ skillsBackend: backend })],
});
const config = { configurable: { thread_id: `thread-${Date.now()}` } };
const result = await agent.invoke(
{ messages: [{ role: "user", content: "what is langraph?" }] },
config,
);
// :snippet-end:
// :remove-start:
if (!agent) throw new Error("agent not created");
if (!result) throw new Error("result empty");
// :remove-end:
@@ -0,0 +1,56 @@
import { readFile } from "node:fs/promises";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
// :snippet-start: skills-usage-state-js
import { createCodeInterpreterMiddleware } from "@langchain/quickjs";
import { createDeepAgent, StateBackend, type FileData } from "deepagents";
import { MemorySaver } from "@langchain/langgraph";
const checkpointer = new MemorySaver();
const backend = new StateBackend();
// :remove-start:
const __dirname = dirname(fileURLToPath(import.meta.url));
// :remove-end:
function createFileData(content: string): FileData {
const now = new Date().toISOString();
return {
content: content.split("\n"),
created_at: now,
modified_at: now,
};
}
const skillsFiles: Record<string, FileData> = {};
const skillUrl =
"https://raw.githubusercontent.com/langchain-ai/deepagentsjs/refs/heads/main/examples/skills/langgraph-docs/SKILL.md";
const response = await fetch(skillUrl);
const skillContent = await response.text();
skillsFiles["/skills/langgraph-docs/SKILL.md"] = createFileData(skillContent);
// KEEP MODEL
const agent = await createDeepAgent({
model: "google-genai:gemini-3.1-pro-preview",
backend,
checkpointer, // Required !
// IMPORTANT: deepagents skill source paths are virtual (POSIX) paths relative to the backend root.
skills: ["/skills/"],
middleware: [createCodeInterpreterMiddleware({ skillsBackend: backend })],
});
const config = { configurable: { thread_id: `thread-${Date.now()}` } };
const result = await agent.invoke(
{
messages: [{ role: "user", content: "what is langraph?" }],
files: skillsFiles,
},
config,
);
// :snippet-end:
// :remove-start:
if (!agent) throw new Error("agent not created");
if (!result) throw new Error("result not created");
// :remove-end:
@@ -0,0 +1,52 @@
// :snippet-start: skills-usage-store-js
import { createCodeInterpreterMiddleware } from "@langchain/quickjs";
import { createDeepAgent, StoreBackend, type FileData } from "deepagents";
import { InMemoryStore, MemorySaver } from "@langchain/langgraph";
const checkpointer = new MemorySaver();
const store = new InMemoryStore();
const backend = new StoreBackend();
function createFileData(content: string): FileData {
const now = new Date().toISOString();
return {
content: content.split("\n"),
created_at: now,
modified_at: now,
};
}
const skillUrl =
"https://raw.githubusercontent.com/langchain-ai/deepagentsjs/refs/heads/main/examples/skills/langgraph-docs/SKILL.md";
const response = await fetch(skillUrl);
const skillContent = await response.text();
const fileData = createFileData(skillContent);
await store.put(["filesystem"], "/skills/langgraph-docs/SKILL.md", fileData);
// KEEP MODEL
const agent = await createDeepAgent({
model: "google-genai:gemini-3.1-pro-preview",
backend,
store,
checkpointer,
// IMPORTANT: deepagents skill source paths are virtual (POSIX) paths relative to the backend root.
skills: ["/skills/"],
middleware: [createCodeInterpreterMiddleware({ skillsBackend: backend })],
});
const config = {
recursionLimit: 50,
configurable: { thread_id: `thread-${Date.now()}` },
};
const result = await agent.invoke(
{ messages: [{ role: "user", content: "what is langraph?" }] },
config,
);
// :snippet-end:
// :remove-start:
if (!agent) throw new Error("agent not created");
if (!result) throw new Error("result empty");
// :remove-end:
@@ -0,0 +1,117 @@
"""Customization: wiring skills with different backends."""
# :snippet-start: skills-usage-state-py
from urllib.request import urlopen
from deepagents import create_deep_agent
from deepagents.backends import StateBackend
from deepagents.backends.utils import create_file_data
from langchain_quickjs import CodeInterpreterMiddleware
from langgraph.checkpoint.memory import MemorySaver
checkpointer = MemorySaver()
backend = StateBackend()
skill_url = "https://raw.githubusercontent.com/langchain-ai/deepagents/refs/heads/main/libs/cli/examples/skills/langgraph-docs/SKILL.md"
with urlopen(skill_url) as response:
skill_content = response.read().decode('utf-8')
skills_files = {
"/skills/langgraph-docs/SKILL.md": create_file_data(skill_content),
}
agent = create_deep_agent(
model="anthropic:claude-sonnet-4-6",
backend=backend,
skills=["/skills/"],
checkpointer=checkpointer,
middleware=[CodeInterpreterMiddleware(skills_backend=backend)], # for interpreter skills
)
result = agent.invoke(
{
"messages": [{"role": "user", "content": "What is langgraph?"}],
# Seed the default StateBackend's in-state filesystem (virtual paths must start with "/").
"files": skills_files,
},
config={"configurable": {"thread_id": "12345"}},
)
# :snippet-end:
assert result is not None
# :snippet-start: skills-usage-store-py
from urllib.request import urlopen
from deepagents import create_deep_agent
from deepagents.backends import StoreBackend
from deepagents.backends.utils import create_file_data
from langchain_quickjs import CodeInterpreterMiddleware
from langgraph.store.memory import InMemoryStore
store = InMemoryStore()
backend = StoreBackend()
skill_url = "https://raw.githubusercontent.com/langchain-ai/deepagents/refs/heads/main/libs/cli/examples/skills/langgraph-docs/SKILL.md"
with urlopen(skill_url) as response:
skill_content = response.read().decode('utf-8')
store.put(
namespace=("filesystem",),
key="/skills/langgraph-docs/SKILL.md",
value=create_file_data(skill_content),
)
# KEEP MODEL
agent = create_deep_agent(
model="google_genai:gemini-3.1-pro-preview",
backend=backend,
store=store,
skills=["/skills/"],
middleware=[CodeInterpreterMiddleware(skills_backend=backend)],
)
result = agent.invoke(
{"messages": [{"role": "user", "content": "What is langgraph?"}]},
config={"configurable": {"thread_id": "12345"}},
)
# :snippet-end:
from pathlib import Path
# :snippet-start: skills-usage-filesystem-py
from deepagents import create_deep_agent
from deepagents.backends.filesystem import FilesystemBackend
from langchain_quickjs import CodeInterpreterMiddleware
from langgraph.checkpoint.memory import MemorySaver
# Checkpointer is REQUIRED for human-in-the-loop
checkpointer = MemorySaver()
root_dir = "/Users/user/{project}"
backend = FilesystemBackend(root_dir=root_dir)
# :remove-start:
# Test harness: make test-code-samples runs from the repo root.
example_dir = (Path.cwd() / "src/code-samples/deepagents").resolve()
root_dir = str(example_dir)
backend = FilesystemBackend(root_dir=root_dir, virtual_mode=True)
# :remove-end:
# KEEP MODEL
agent = create_deep_agent(
model="google_genai:gemini-3.1-pro-preview",
backend=backend,
skills=[str(Path(root_dir) / "skills")],
interrupt_on={
"write_file": True,
"read_file": False,
"edit_file": True,
},
checkpointer=checkpointer, # Required!
middleware=[CodeInterpreterMiddleware(skills_backend=backend)], # for interpreter skills
)
result = agent.invoke(
{"messages": [{"role": "user", "content": "What is langgraph?"}]},
config={"configurable": {"thread_id": "12345"}},
)
# :snippet-end:
# :remove-start:
assert agent is not None
# :remove-end:
@@ -0,0 +1,46 @@
"""Customization: subagent configuration example."""
# :snippet-start: subagent-basic-py
import os
from typing import Literal
from deepagents import create_deep_agent
from tavily import TavilyClient
tavily_client = TavilyClient(api_key=os.environ["TAVILY_API_KEY"])
def internet_search(
query: str,
max_results: int = 5,
topic: Literal["general", "news", "finance"] = "general",
include_raw_content: bool = False,
):
"""Run a web search"""
return tavily_client.search(
query,
max_results=max_results,
include_raw_content=include_raw_content,
topic=topic,
)
research_subagent = {
"name": "research-agent",
"description": "Used to research more in depth questions",
"system_prompt": "You are a great researcher",
"tools": [internet_search],
"model": "openai:gpt-5.4", # Optional override, defaults to main agent model
}
subagents = [research_subagent]
# KEEP MODEL
agent = create_deep_agent(
model="google_genai:gemini-3.1-pro-preview",
subagents=subagents,
)
# :snippet-end:
# :remove-start:
assert agent is not None
# :remove-end:
@@ -1,4 +1,4 @@
```typescript
// :snippet-start: subagent-basic-js
import { tool } from "langchain";
import { TavilySearch } from "@langchain/tavily";
import { createDeepAgent, type SubAgent } from "deepagents";
@@ -44,12 +44,17 @@ const researchSubagent: SubAgent = {
description: "Used to research more in depth questions",
systemPrompt: "You are a great researcher",
tools: [internetSearch],
model: "openai:gpt-5.4", // Optional override, defaults to main agent model
model: "openai:gpt-5.4", // Optional override, defaults to main agent model
};
const subagents = [researchSubagent];
// KEEP MODEL
const agent = createDeepAgent({
model: "claude-sonnet-4-6",
model: "google_genai:gemini-3.1-pro-preview",
subagents,
});
```
// :snippet-end:
// :remove-start:
if (!agent) throw new Error("agent not created");
// :remove-end:
@@ -0,0 +1,28 @@
---
name: langgraph-docs
description: Fetches and references LangGraph Python documentation to build stateful agents, create multi-agent workflows, and implement human-in-the-loop patterns. Use when the user asks about LangGraph, graph agents, state machines, agent orchestration, LangGraph API, or needs LangGraph implementation guidance.
---
# langgraph-docs
## Workflow
### 1. Fetch the Documentation Index
Use `fetch_url` to read: https://docs.langchain.com/llms.txt
This returns a structured list of all available documentation with descriptions.
### 2. Select Relevant Documentation
Identify 2-4 most relevant URLs from the index. Prioritize:
- **Implementation questions** — specific how-to guides
- **Conceptual questions** — core concept pages
- **End-to-end examples** — tutorials
- **API details** — reference docs
### 3. Fetch and Apply
Use `fetch_url` on the selected URLs, then complete the user's request using the documentation content.
If `fetch_url` fails or returns empty content, retry once. If it fails again, inform the user and suggest checking https://langchain-ai.github.io/langgraph/ directly.
+35
View File
@@ -11,6 +11,7 @@
"dependencies": {
"@langchain/anthropic": "^1.3.22",
"@langchain/daytona": "^0.2.0",
"@langchain/google-genai": "^2.1.30",
"@langchain/langgraph-checkpoint-postgres": "^1.0.1",
"@langchain/openai": "^1.2.12",
"@langchain/quickjs": "^0.4.0",
@@ -268,6 +269,7 @@
"resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.1032.0.tgz",
"integrity": "sha512-A1wjVhV3IgsZ5td2l4AWgK03EjZ+ldwbiorxuO1hPf7RHJtSdr6oq/gKzyUwP7Tm7ma/M2xS/tplg5C8XB8RWg==",
"license": "Apache-2.0",
"peer": true,
"dependencies": {
"@aws-crypto/sha1-browser": "5.2.0",
"@aws-crypto/sha256-browser": "5.2.0",
@@ -1440,6 +1442,15 @@
"node": ">=18"
}
},
"node_modules/@google/generative-ai": {
"version": "0.24.1",
"resolved": "https://registry.npmjs.org/@google/generative-ai/-/generative-ai-0.24.1.tgz",
"integrity": "sha512-MqO+MLfM6kjxcKoy0p1wRzG3b4ZZXtPI+z2IE26UogS2Cm/XHO+7gGRBh6gcJsOiIVoH93UwKvW4HdgiOZCy9Q==",
"license": "Apache-2.0",
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@grpc/grpc-js": {
"version": "1.14.3",
"resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.14.3.tgz",
@@ -1583,6 +1594,7 @@
"resolved": "https://registry.npmjs.org/@langchain/core/-/core-1.1.46.tgz",
"integrity": "sha512-i8rDC83BpItxChCw4Lf+6tAr+k+OUcbirc5ZkrhI9ywYWmvxegUljLGOGYvtJNTbEAIFkhYIODPE5QRqyjF6sA==",
"license": "MIT",
"peer": true,
"dependencies": {
"@cfworker/json-schema": "^4.0.2",
"@standard-schema/spec": "^1.1.0",
@@ -1608,6 +1620,21 @@
"deepagents": ">=1.6.0"
}
},
"node_modules/@langchain/google-genai": {
"version": "2.1.30",
"resolved": "https://registry.npmjs.org/@langchain/google-genai/-/google-genai-2.1.30.tgz",
"integrity": "sha512-0wKgy1NvV89fw5MwYiOOhh18SnUEH20z6MZrPV6Tj2hMAA3jAHVSLlIcCQ2mDRJo2r1aHLV8MDXhzkvD1tEHoQ==",
"license": "MIT",
"dependencies": {
"@google/generative-ai": "^0.24.0"
},
"engines": {
"node": ">=20"
},
"peerDependencies": {
"@langchain/core": "^1.1.43"
}
},
"node_modules/@langchain/langgraph": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@langchain/langgraph/-/langgraph-1.3.0.tgz",
@@ -1639,6 +1666,7 @@
"resolved": "https://registry.npmjs.org/@langchain/langgraph-checkpoint/-/langgraph-checkpoint-1.0.2.tgz",
"integrity": "sha512-F4E5Tr0nt8FGghgdscJtHw+ABzChOHeI80R7Y1pjIHdiJom6c2ieo76vL+FWiny80JmoGqhrVAEIWrw0cXKPxg==",
"license": "MIT",
"peer": true,
"dependencies": {
"uuid": "^10.0.0"
},
@@ -1869,6 +1897,7 @@
"resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.1.tgz",
"integrity": "sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==",
"license": "Apache-2.0",
"peer": true,
"engines": {
"node": ">=8.0.0"
}
@@ -3372,6 +3401,7 @@
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
"integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
"license": "MIT",
"peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -3587,6 +3617,7 @@
"resolved": "https://registry.npmjs.org/deepagents/-/deepagents-1.10.2.tgz",
"integrity": "sha512-Ptp+t/FgIvMhDbVK0ml3IHcNx3gog3Cbqx+s88H4Hz8ieHG7svuR+/4Mawc/g14FY7mCls7Y8gCcrGb0i3Mi4w==",
"license": "MIT",
"peer": true,
"dependencies": {
"@langchain/core": "^1.1.44",
"@langchain/langgraph": "^1.3.0",
@@ -4235,6 +4266,7 @@
"resolved": "https://registry.npmjs.org/langsmith/-/langsmith-0.6.3.tgz",
"integrity": "sha512-pXrQ4/4myQvjFFOAUmt5pWRrLEZR20gzIJD7MNdUH+5/S5nLI4ZRBo/SYKC6coaYj9pYTfQdBIzcs+3kfJ5uDA==",
"license": "MIT",
"peer": true,
"dependencies": {
"p-queue": "6.6.2"
},
@@ -4501,6 +4533,7 @@
"resolved": "https://registry.npmjs.org/pg/-/pg-8.20.0.tgz",
"integrity": "sha512-ldhMxz2r8fl/6QkXnBD3CR9/xg694oT6DZQ2s6c/RI28OjtSOpxnPrUCGOBJ46RCUxcWdx3p6kw/xnDHjKvaRA==",
"license": "MIT",
"peer": true,
"dependencies": {
"pg-connection-string": "^2.12.0",
"pg-pool": "^3.13.0",
@@ -4968,6 +5001,7 @@
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=12"
},
@@ -5187,6 +5221,7 @@
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
"license": "MIT",
"peer": true,
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
+1
View File
@@ -12,6 +12,7 @@
"dependencies": {
"@langchain/anthropic": "^1.3.22",
"@langchain/daytona": "^0.2.0",
"@langchain/google-genai": "^2.1.30",
"@langchain/langgraph-checkpoint-postgres": "^1.0.1",
"@langchain/openai": "^1.2.12",
"@langchain/quickjs": "^0.4.0",
+15 -11
View File
@@ -3,17 +3,17 @@ title: Backends
description: Choose and configure filesystem backends for Deep Agents. You can specify routes to different backends, implement virtual filesystems, and enforce policies.
---
import BackendStatePy from '/snippets/backend-state-py.mdx';
import BackendStateJs from '/snippets/backend-state-js.mdx';
import BackendFilesystemPy from '/snippets/backend-filesystem-py.mdx';
import BackendFilesystemJs from '/snippets/backend-filesystem-js.mdx';
import BackendLocalShellPy from '/snippets/backend-local-shell-py.mdx';
import BackendLocalShellJs from '/snippets/backend-local-shell-js.mdx';
import BackendStorePy from '/snippets/backend-store-py.mdx';
import BackendStoreJs from '/snippets/backend-store-js.mdx';
import BackendContextHubPy from '/snippets/backend-context-hub-py.mdx';
import BackendCompositePy from '/snippets/backend-composite-py.mdx';
import BackendCompositeJs from '/snippets/backend-composite-js.mdx';
import BackendStatePy from '/snippets/code-samples/backend-state-py.mdx';
import BackendStateJs from '/snippets/code-samples/backend-state-js.mdx';
import BackendFilesystemPy from '/snippets/code-samples/backend-filesystem-py.mdx';
import BackendFilesystemJs from '/snippets/code-samples/backend-filesystem-js.mdx';
import BackendLocalShellPy from '/snippets/code-samples/backend-local-shell-py.mdx';
import BackendLocalShellJs from '/snippets/code-samples/backend-local-shell-js.mdx';
import BackendStorePy from '/snippets/code-samples/backend-store-py.mdx';
import BackendStoreJs from '/snippets/code-samples/backend-store-js.mdx';
import BackendContextHubPy from '/snippets/code-samples/backend-context-hub-py.mdx';
import BackendCompositePy from '/snippets/code-samples/backend-composite-py.mdx';
import BackendCompositeJs from '/snippets/code-samples/backend-composite-js.mdx';
Deep Agents expose a filesystem surface to the agent via tools like `ls`, `read_file`, `write_file`, `edit_file`, `glob`, and `grep`. These tools operate through a pluggable backend. The `read_file` tool natively supports image files (`.png`, `.jpg`, `.jpeg`, `.gif`, `.webp`) across all backends, returning them as multimodal content blocks.
@@ -218,6 +218,10 @@ Use with extreme caution and only in appropriate environments.
<BackendStoreJs />
:::
<Note>
When deploying to [LangSmith Deployment](/langsmith/deployment), omit the `store` parameter. The platform automatically provisions a store for your agent.
</Note>
<Tip>
The `namespace` parameter controls data isolation. For multi-user deployments, always set a [namespace factory](/oss/deepagents/backends#namespace-factories) to isolate data per user or tenant.
</Tip>
+19 -15
View File
@@ -6,23 +6,23 @@ description: Learn how to customize Deep Agents with system prompts, tools, suba
import ChatModelTabsDaPy from '/snippets/chat-model-tabs-da.mdx';
import ChatModelTabsDaJs from '/snippets/chat-model-tabs-da-js.mdx';
import HitlBasicConfigPy from '/snippets/hitl-basic-config-py.mdx';
import HitlBasicConfigJs from '/snippets/hitl-basic-config-js.mdx';
import HitlBasicConfigPy from '/snippets/code-samples/hitl-basic-config-py.mdx';
import HitlBasicConfigJs from '/snippets/code-samples/hitl-basic-config-js.mdx';
import SkillsUsageTabsPy from '/snippets/skills-usage-tabs-py.mdx';
import SkillsUsageTabsJs from '/snippets/skills-usage-tabs-js.mdx';
import BackendStatePy from '/snippets/backend-state-py.mdx';
import BackendStateJs from '/snippets/backend-state-js.mdx';
import BackendFilesystemPy from '/snippets/backend-filesystem-py.mdx';
import BackendFilesystemJs from '/snippets/backend-filesystem-js.mdx';
import BackendLocalShellPy from '/snippets/backend-local-shell-py.mdx';
import BackendLocalShellJs from '/snippets/backend-local-shell-js.mdx';
import BackendStorePy from '/snippets/backend-store-py.mdx';
import BackendStoreJs from '/snippets/backend-store-js.mdx';
import BackendContextHubPy from '/snippets/backend-context-hub-py.mdx';
import BackendCompositePy from '/snippets/backend-composite-py.mdx';
import BackendCompositeJs from '/snippets/backend-composite-js.mdx';
import SubagentBasicPy from '/snippets/subagent-basic-py.mdx';
import SubagentBasicJs from '/snippets/subagent-basic-js.mdx';
import BackendStatePy from '/snippets/code-samples/backend-state-py.mdx';
import BackendStateJs from '/snippets/code-samples/backend-state-js.mdx';
import BackendFilesystemPy from '/snippets/code-samples/backend-filesystem-py.mdx';
import BackendFilesystemJs from '/snippets/code-samples/backend-filesystem-js.mdx';
import BackendLocalShellPy from '/snippets/code-samples/backend-local-shell-py.mdx';
import BackendLocalShellJs from '/snippets/code-samples/backend-local-shell-js.mdx';
import BackendStorePy from '/snippets/code-samples/backend-store-py.mdx';
import BackendStoreJs from '/snippets/code-samples/backend-store-js.mdx';
import BackendContextHubPy from '/snippets/code-samples/backend-context-hub-py.mdx';
import BackendCompositePy from '/snippets/code-samples/backend-composite-py.mdx';
import BackendCompositeJs from '/snippets/code-samples/backend-composite-js.mdx';
import SubagentBasicPy from '/snippets/code-samples/subagent-basic-py.mdx';
import SubagentBasicJs from '/snippets/code-samples/subagent-basic-js.mdx';
import SandboxBasicPy from '/snippets/deepagents-sandbox-basic-py.mdx';
import SandboxBasicJs from '/snippets/deepagents-sandbox-basic-js.mdx';
import CreateDeepAgentConfigOptionsPy from '/snippets/create-deep-agent-config-options-py.mdx';
@@ -406,6 +406,10 @@ If you are using [skills](#skills) or [memory](#memory), you must add the expect
<BackendStoreJs />
:::
<Note>
When deploying to [LangSmith Deployment](/langsmith/deployment), omit the `store` parameter. The platform automatically provisions a store for your agent.
</Note>
<Tip>
The `namespace` parameter controls data isolation. For multi-user deployments, always set a [namespace factory](/oss/deepagents/backends#namespace-factories) to isolate data per user or tenant.
</Tip>
+2 -2
View File
@@ -3,8 +3,8 @@ title: Human-in-the-loop
description: Learn how to configure human approval for sensitive tool operations
---
import HitlBasicConfigPy from '/snippets/hitl-basic-config-py.mdx';
import HitlBasicConfigJs from '/snippets/hitl-basic-config-js.mdx';
import HitlBasicConfigPy from '/snippets/code-samples/hitl-basic-config-py.mdx';
import HitlBasicConfigJs from '/snippets/code-samples/hitl-basic-config-js.mdx';
Some tool operations may be sensitive and require human approval before execution. Deep Agents support human-in-the-loop workflows through LangGraph's interrupt capabilities. You can configure which tools require approval using the `interrupt_on` parameter.
+2 -2
View File
@@ -3,8 +3,8 @@ title: Subagents
description: Learn how to use subagents to delegate work and keep context clean
---
import SubagentBasicPy from '/snippets/subagent-basic-py.mdx';
import SubagentBasicJs from '/snippets/subagent-basic-js.mdx';
import SubagentBasicPy from '/snippets/code-samples/subagent-basic-py.mdx';
import SubagentBasicJs from '/snippets/code-samples/subagent-basic-js.mdx';
A deep agent can create subagents to delegate work. You can specify custom subagents in the `subagents` parameter. Subagents are useful for [context quarantine](https://www.dbreunig.com/2025/06/26/how-to-fix-your-context.html#context-quarantine) (keeping the main agent's context clean) and for providing specialized instructions.
-15
View File
@@ -1,15 +0,0 @@
```typescript
import { createDeepAgent, CompositeBackend, StateBackend, StoreBackend } from "deepagents";
import { InMemoryStore } from "@langchain/langgraph";
const store = new InMemoryStore();
const agent = createDeepAgent({
backend: new CompositeBackend(
new StateBackend(),
{
"/memories/": new StoreBackend(),
}
),
store,
});
```
-16
View File
@@ -1,16 +0,0 @@
```typescript
import { createDeepAgent, StoreBackend } from "deepagents";
import { InMemoryStore } from "@langchain/langgraph";
const store = new InMemoryStore(); // Good for local dev; omit for LangSmith Deployment
const agent = createDeepAgent({
backend: new StoreBackend({
namespace: (ctx) => [ctx.runtime.context.userId],
}),
store
});
```
<Note>
When deploying to [LangSmith Deployment](/langsmith/deployment), omit the `store` parameter. The platform automatically provisions a store for your agent.
</Note>
@@ -0,0 +1,18 @@
```ts
import {
createDeepAgent,
CompositeBackend,
StateBackend,
StoreBackend,
} from "deepagents";
import { InMemoryStore } from "@langchain/langgraph";
const store = new InMemoryStore();
const agent = createDeepAgent({
model: "google_genai:gemini-3.1-pro-preview",
backend: new CompositeBackend(new StateBackend(), {
"/memories/": new StoreBackend(),
}),
store,
});
```
@@ -9,8 +9,8 @@ agent = create_deep_agent(
default=StateBackend(),
routes={
"/memories/": StoreBackend(),
}
},
),
store=InMemoryStore() # Store passed to create_deep_agent, not backend
store=InMemoryStore(), # Store passed to create_deep_agent, not backend
)
```
@@ -1,8 +1,9 @@
```python
from deepagents import create_deep_agent
from deepagents.backends import ContextHubBackend
agent = create_deep_agent(
model="google_genai:gemini-3.1-pro-preview",
backend=ContextHubBackend("my-agent")
backend=ContextHubBackend("my-agent"),
)
```
@@ -1,7 +1,8 @@
```typescript
```ts
import { createDeepAgent, FilesystemBackend } from "deepagents";
const agent = createDeepAgent({
model: "google_genai:gemini-3.1-pro-preview",
backend: new FilesystemBackend({ rootDir: ".", virtualMode: true }),
});
```
@@ -1,8 +1,9 @@
```python
from deepagents import create_deep_agent
from deepagents.backends import FilesystemBackend
agent = create_deep_agent(
model="google_genai:gemini-3.1-pro-preview",
backend=FilesystemBackend(root_dir=".", virtual_mode=True)
backend=FilesystemBackend(root_dir=".", virtual_mode=True),
)
```
@@ -1,6 +1,9 @@
```typescript
```ts
import { createDeepAgent, LocalShellBackend } from "deepagents";
const backend = new LocalShellBackend({ workingDirectory: "." });
const agent = createDeepAgent({ backend });
const agent = createDeepAgent({
model: "google_genai:gemini-3.1-pro-preview",
backend,
});
```
@@ -1,8 +1,9 @@
```python
from deepagents import create_deep_agent
from deepagents.backends import LocalShellBackend
agent = create_deep_agent(
model="google_genai:gemini-3.1-pro-preview",
backend=LocalShellBackend(root_dir=".", env={"PATH": "/usr/bin:/bin"})
backend=LocalShellBackend(root_dir=".", virtual_mode=True, env={"PATH": "/usr/bin:/bin"}),
)
```
@@ -1,4 +1,4 @@
```typescript
```ts
import { createDeepAgent, StateBackend } from "deepagents";
// By default we provide a StateBackend
@@ -1,12 +1,13 @@
```python
from deepagents import create_deep_agent
from deepagents.backends import StateBackend
# By default we provide a StateBackend
agent = create_deep_agent(model="google_genai:gemini-3.1-pro-preview")
# Under the hood, it looks like
from deepagents.backends import StateBackend
agent = create_deep_agent(
agent2 = create_deep_agent(
model="google_genai:gemini-3.1-pro-preview",
backend=StateBackend()
backend=StateBackend(),
)
```
@@ -0,0 +1,13 @@
```ts
import { createDeepAgent, StoreBackend } from "deepagents";
import { InMemoryStore } from "@langchain/langgraph";
const store = new InMemoryStore(); // Good for local dev; omit for LangSmith Deployment
const agent = createDeepAgent({
model: "google_genai:gemini-3.1-pro-preview",
backend: new StoreBackend({
namespace: (ctx) => [ctx.runtime.context.userId],
}),
store,
});
```
@@ -1,16 +1,13 @@
```python
from langgraph.store.memory import InMemoryStore
from deepagents import create_deep_agent
from deepagents.backends import StoreBackend
from langgraph.store.memory import InMemoryStore
agent = create_deep_agent(
model="google_genai:gemini-3.1-pro-preview",
backend=StoreBackend(
namespace=lambda ctx: (ctx.runtime.context.user_id,),
),
store=InMemoryStore() # Good for local dev; omit for LangSmith Deployment
store=InMemoryStore(), # Good for local dev; omit for LangSmith Deployment
)
```
<Note>
When deploying to [LangSmith Deployment](/langsmith/deployment), omit the `store` parameter. The platform automatically provisions a store for your agent.
</Note>
@@ -1,15 +1,15 @@
```typescript
```ts
import { tool } from "langchain";
import { createDeepAgent } from "deepagents";
import { MemorySaver } from "@langchain/langgraph";
import { z } from "zod";
const deleteFile = tool(
const removeFile = tool(
async ({ path }: { path: string }) => {
return `Deleted ${path}`;
},
{
name: "delete_file",
name: "remove_file",
description: "Delete a file from the filesystem.",
schema: z.object({
path: z.string(),
@@ -17,12 +17,12 @@ const deleteFile = tool(
},
);
const readFile = tool(
const fetchFile = tool(
async ({ path }: { path: string }) => {
return `Contents of ${path}`;
},
{
name: "read_file",
name: "fetch_file",
description: "Read a file from the filesystem.",
schema: z.object({
path: z.string(),
@@ -30,12 +30,20 @@ const readFile = tool(
},
);
const sendEmail = tool(
async ({ to, subject, body }: { to: string; subject: string; body: string }) => {
const notifyEmail = tool(
async ({
to,
subject,
body,
}: {
to: string;
subject: string;
body: string;
}) => {
return `Sent email to ${to}`;
},
{
name: "send_email",
name: "notify_email",
description: "Send an email.",
schema: z.object({
to: z.string(),
@@ -50,12 +58,12 @@ const checkpointer = new MemorySaver();
const agent = createDeepAgent({
model: "google_genai:gemini-3.1-pro-preview",
tools: [deleteFile, readFile, sendEmail],
tools: [removeFile, fetchFile, notifyEmail],
interruptOn: {
delete_file: true, // Default: approve, edit, reject, respond
read_file: false, // No interrupts needed
send_email: { allowedDecisions: ["approve", "reject"] }, // No editing
remove_file: true, // Default: approve, edit, reject, respond
fetch_file: false, // No interrupts needed
notify_email: { allowedDecisions: ["approve", "reject"] }, // No editing
},
checkpointer, // Required!
checkpointer, // Required!
});
```
@@ -3,32 +3,36 @@ from langchain.tools import tool
from deepagents import create_deep_agent
from langgraph.checkpoint.memory import MemorySaver
@tool
def delete_file(path: str) -> str:
def remove_file(path: str) -> str:
"""Delete a file from the filesystem."""
return f"Deleted {path}"
@tool
def read_file(path: str) -> str:
def fetch_file(path: str) -> str:
"""Read a file from the filesystem."""
return f"Contents of {path}"
@tool
def send_email(to: str, subject: str, body: str) -> str:
def notify_email(to: str, subject: str, body: str) -> str:
"""Send an email."""
return f"Sent email to {to}"
# Checkpointer is REQUIRED for human-in-the-loop
checkpointer = MemorySaver()
agent = create_deep_agent(
model="google_genai:gemini-3.1-pro-preview",
tools=[delete_file, read_file, send_email],
tools=[remove_file, fetch_file, notify_email],
interrupt_on={
"delete_file": True, # Default: approve, edit, reject, respond
"read_file": False, # No interrupts needed
"send_email": {"allowed_decisions": ["approve", "reject"]}, # No editing
"remove_file": True, # Default: approve, edit, reject, respond
"fetch_file": False, # No interrupts needed
"notify_email": {"allowed_decisions": ["approve", "reject"]}, # No editing
},
checkpointer=checkpointer # Required!
checkpointer=checkpointer, # Required!
)
```
@@ -0,0 +1,27 @@
```ts
import { createCodeInterpreterMiddleware } from "@langchain/quickjs";
import { createDeepAgent, FilesystemBackend } from "deepagents";
import { MemorySaver } from "@langchain/langgraph";
const checkpointer = new MemorySaver();
const backend = new FilesystemBackend({ rootDir: process.cwd() });
const agent = await createDeepAgent({
model: "google-genai:gemini-3.1-pro-preview",
backend,
skills: ["./examples/skills/"],
interruptOn: {
read_file: true,
write_file: true,
delete_file: true,
},
checkpointer, // Required!
middleware: [createCodeInterpreterMiddleware({ skillsBackend: backend })],
});
const config = { configurable: { thread_id: `thread-${Date.now()}` } };
const result = await agent.invoke(
{ messages: [{ role: "user", content: "what is langraph?" }] },
config,
);
```
@@ -0,0 +1,29 @@
```python
from deepagents import create_deep_agent
from deepagents.backends.filesystem import FilesystemBackend
from langchain_quickjs import CodeInterpreterMiddleware
from langgraph.checkpoint.memory import MemorySaver
# Checkpointer is REQUIRED for human-in-the-loop
checkpointer = MemorySaver()
root_dir = "/Users/user/{project}"
backend = FilesystemBackend(root_dir=root_dir)
agent = create_deep_agent(
model="google_genai:gemini-3.1-pro-preview",
backend=backend,
skills=[str(Path(root_dir) / "skills")],
interrupt_on={
"write_file": True,
"read_file": False,
"edit_file": True,
},
checkpointer=checkpointer, # Required!
middleware=[CodeInterpreterMiddleware(skills_backend=backend)], # for interpreter skills
)
result = agent.invoke(
{"messages": [{"role": "user", "content": "What is langgraph?"}]},
config={"configurable": {"thread_id": "12345"}},
)
```
@@ -0,0 +1,43 @@
```ts
import { createCodeInterpreterMiddleware } from "@langchain/quickjs";
import { createDeepAgent, StateBackend, type FileData } from "deepagents";
import { MemorySaver } from "@langchain/langgraph";
const checkpointer = new MemorySaver();
const backend = new StateBackend();
function createFileData(content: string): FileData {
const now = new Date().toISOString();
return {
content: content.split("\n"),
created_at: now,
modified_at: now,
};
}
const skillsFiles: Record<string, FileData> = {};
const skillUrl =
"https://raw.githubusercontent.com/langchain-ai/deepagentsjs/refs/heads/main/examples/skills/langgraph-docs/SKILL.md";
const response = await fetch(skillUrl);
const skillContent = await response.text();
skillsFiles["/skills/langgraph-docs/SKILL.md"] = createFileData(skillContent);
const agent = await createDeepAgent({
model: "google-genai:gemini-3.1-pro-preview",
backend,
checkpointer, // Required !
// IMPORTANT: deepagents skill source paths are virtual (POSIX) paths relative to the backend root.
skills: ["/skills/"],
middleware: [createCodeInterpreterMiddleware({ skillsBackend: backend })],
});
const config = { configurable: { thread_id: `thread-${Date.now()}` } };
const result = await agent.invoke(
{
messages: [{ role: "user", content: "what is langraph?" }],
files: skillsFiles,
},
config,
);
```
@@ -0,0 +1,260 @@
<CodeGroup>
```python Google
from urllib.request import urlopen
from deepagents import create_deep_agent
from deepagents.backends import StateBackend
from deepagents.backends.utils import create_file_data
from langchain_quickjs import CodeInterpreterMiddleware
from langgraph.checkpoint.memory import MemorySaver
checkpointer = MemorySaver()
backend = StateBackend()
skill_url = "https://raw.githubusercontent.com/langchain-ai/deepagents/refs/heads/main/libs/cli/examples/skills/langgraph-docs/SKILL.md"
with urlopen(skill_url) as response:
skill_content = response.read().decode('utf-8')
skills_files = {
"/skills/langgraph-docs/SKILL.md": create_file_data(skill_content),
}
agent = create_deep_agent(
model="google_genai:gemini-3.1-pro-preview",
backend=backend,
skills=["/skills/"],
checkpointer=checkpointer,
middleware=[CodeInterpreterMiddleware(skills_backend=backend)], # for interpreter skills
)
result = agent.invoke(
{
"messages": [{"role": "user", "content": "What is langgraph?"}],
# Seed the default StateBackend's in-state filesystem (virtual paths must start with "/").
"files": skills_files,
},
config={"configurable": {"thread_id": "12345"}},
)
```
```python OpenAI
from urllib.request import urlopen
from deepagents import create_deep_agent
from deepagents.backends import StateBackend
from deepagents.backends.utils import create_file_data
from langchain_quickjs import CodeInterpreterMiddleware
from langgraph.checkpoint.memory import MemorySaver
checkpointer = MemorySaver()
backend = StateBackend()
skill_url = "https://raw.githubusercontent.com/langchain-ai/deepagents/refs/heads/main/libs/cli/examples/skills/langgraph-docs/SKILL.md"
with urlopen(skill_url) as response:
skill_content = response.read().decode('utf-8')
skills_files = {
"/skills/langgraph-docs/SKILL.md": create_file_data(skill_content),
}
agent = create_deep_agent(
model="openai:gpt-5.4",
backend=backend,
skills=["/skills/"],
checkpointer=checkpointer,
middleware=[CodeInterpreterMiddleware(skills_backend=backend)], # for interpreter skills
)
result = agent.invoke(
{
"messages": [{"role": "user", "content": "What is langgraph?"}],
# Seed the default StateBackend's in-state filesystem (virtual paths must start with "/").
"files": skills_files,
},
config={"configurable": {"thread_id": "12345"}},
)
```
```python Anthropic
from urllib.request import urlopen
from deepagents import create_deep_agent
from deepagents.backends import StateBackend
from deepagents.backends.utils import create_file_data
from langchain_quickjs import CodeInterpreterMiddleware
from langgraph.checkpoint.memory import MemorySaver
checkpointer = MemorySaver()
backend = StateBackend()
skill_url = "https://raw.githubusercontent.com/langchain-ai/deepagents/refs/heads/main/libs/cli/examples/skills/langgraph-docs/SKILL.md"
with urlopen(skill_url) as response:
skill_content = response.read().decode('utf-8')
skills_files = {
"/skills/langgraph-docs/SKILL.md": create_file_data(skill_content),
}
agent = create_deep_agent(
model="anthropic:claude-sonnet-4-6",
backend=backend,
skills=["/skills/"],
checkpointer=checkpointer,
middleware=[CodeInterpreterMiddleware(skills_backend=backend)], # for interpreter skills
)
result = agent.invoke(
{
"messages": [{"role": "user", "content": "What is langgraph?"}],
# Seed the default StateBackend's in-state filesystem (virtual paths must start with "/").
"files": skills_files,
},
config={"configurable": {"thread_id": "12345"}},
)
```
```python OpenRouter
from urllib.request import urlopen
from deepagents import create_deep_agent
from deepagents.backends import StateBackend
from deepagents.backends.utils import create_file_data
from langchain_quickjs import CodeInterpreterMiddleware
from langgraph.checkpoint.memory import MemorySaver
checkpointer = MemorySaver()
backend = StateBackend()
skill_url = "https://raw.githubusercontent.com/langchain-ai/deepagents/refs/heads/main/libs/cli/examples/skills/langgraph-docs/SKILL.md"
with urlopen(skill_url) as response:
skill_content = response.read().decode('utf-8')
skills_files = {
"/skills/langgraph-docs/SKILL.md": create_file_data(skill_content),
}
agent = create_deep_agent(
model="openrouter:anthropic/claude-sonnet-4-6",
backend=backend,
skills=["/skills/"],
checkpointer=checkpointer,
middleware=[CodeInterpreterMiddleware(skills_backend=backend)], # for interpreter skills
)
result = agent.invoke(
{
"messages": [{"role": "user", "content": "What is langgraph?"}],
# Seed the default StateBackend's in-state filesystem (virtual paths must start with "/").
"files": skills_files,
},
config={"configurable": {"thread_id": "12345"}},
)
```
```python Fireworks
from urllib.request import urlopen
from deepagents import create_deep_agent
from deepagents.backends import StateBackend
from deepagents.backends.utils import create_file_data
from langchain_quickjs import CodeInterpreterMiddleware
from langgraph.checkpoint.memory import MemorySaver
checkpointer = MemorySaver()
backend = StateBackend()
skill_url = "https://raw.githubusercontent.com/langchain-ai/deepagents/refs/heads/main/libs/cli/examples/skills/langgraph-docs/SKILL.md"
with urlopen(skill_url) as response:
skill_content = response.read().decode('utf-8')
skills_files = {
"/skills/langgraph-docs/SKILL.md": create_file_data(skill_content),
}
agent = create_deep_agent(
model="fireworks:accounts/fireworks/models/qwen3p5-397b-a17b",
backend=backend,
skills=["/skills/"],
checkpointer=checkpointer,
middleware=[CodeInterpreterMiddleware(skills_backend=backend)], # for interpreter skills
)
result = agent.invoke(
{
"messages": [{"role": "user", "content": "What is langgraph?"}],
# Seed the default StateBackend's in-state filesystem (virtual paths must start with "/").
"files": skills_files,
},
config={"configurable": {"thread_id": "12345"}},
)
```
```python Baseten
from urllib.request import urlopen
from deepagents import create_deep_agent
from deepagents.backends import StateBackend
from deepagents.backends.utils import create_file_data
from langchain_quickjs import CodeInterpreterMiddleware
from langgraph.checkpoint.memory import MemorySaver
checkpointer = MemorySaver()
backend = StateBackend()
skill_url = "https://raw.githubusercontent.com/langchain-ai/deepagents/refs/heads/main/libs/cli/examples/skills/langgraph-docs/SKILL.md"
with urlopen(skill_url) as response:
skill_content = response.read().decode('utf-8')
skills_files = {
"/skills/langgraph-docs/SKILL.md": create_file_data(skill_content),
}
agent = create_deep_agent(
model="baseten:zai-org/GLM-5",
backend=backend,
skills=["/skills/"],
checkpointer=checkpointer,
middleware=[CodeInterpreterMiddleware(skills_backend=backend)], # for interpreter skills
)
result = agent.invoke(
{
"messages": [{"role": "user", "content": "What is langgraph?"}],
# Seed the default StateBackend's in-state filesystem (virtual paths must start with "/").
"files": skills_files,
},
config={"configurable": {"thread_id": "12345"}},
)
```
```python Ollama
from urllib.request import urlopen
from deepagents import create_deep_agent
from deepagents.backends import StateBackend
from deepagents.backends.utils import create_file_data
from langchain_quickjs import CodeInterpreterMiddleware
from langgraph.checkpoint.memory import MemorySaver
checkpointer = MemorySaver()
backend = StateBackend()
skill_url = "https://raw.githubusercontent.com/langchain-ai/deepagents/refs/heads/main/libs/cli/examples/skills/langgraph-docs/SKILL.md"
with urlopen(skill_url) as response:
skill_content = response.read().decode('utf-8')
skills_files = {
"/skills/langgraph-docs/SKILL.md": create_file_data(skill_content),
}
agent = create_deep_agent(
model="ollama:devstral-2",
backend=backend,
skills=["/skills/"],
checkpointer=checkpointer,
middleware=[CodeInterpreterMiddleware(skills_backend=backend)], # for interpreter skills
)
result = agent.invoke(
{
"messages": [{"role": "user", "content": "What is langgraph?"}],
# Seed the default StateBackend's in-state filesystem (virtual paths must start with "/").
"files": skills_files,
},
config={"configurable": {"thread_id": "12345"}},
)
```
</CodeGroup>
@@ -0,0 +1,46 @@
```ts
import { createCodeInterpreterMiddleware } from "@langchain/quickjs";
import { createDeepAgent, StoreBackend, type FileData } from "deepagents";
import { InMemoryStore, MemorySaver } from "@langchain/langgraph";
const checkpointer = new MemorySaver();
const store = new InMemoryStore();
const backend = new StoreBackend();
function createFileData(content: string): FileData {
const now = new Date().toISOString();
return {
content: content.split("\n"),
created_at: now,
modified_at: now,
};
}
const skillUrl =
"https://raw.githubusercontent.com/langchain-ai/deepagentsjs/refs/heads/main/examples/skills/langgraph-docs/SKILL.md";
const response = await fetch(skillUrl);
const skillContent = await response.text();
const fileData = createFileData(skillContent);
await store.put(["filesystem"], "/skills/langgraph-docs/SKILL.md", fileData);
const agent = await createDeepAgent({
model: "google-genai:gemini-3.1-pro-preview",
backend,
store,
checkpointer,
// IMPORTANT: deepagents skill source paths are virtual (POSIX) paths relative to the backend root.
skills: ["/skills/"],
middleware: [createCodeInterpreterMiddleware({ skillsBackend: backend })],
});
const config = {
recursionLimit: 50,
configurable: { thread_id: `thread-${Date.now()}` },
};
const result = await agent.invoke(
{ messages: [{ role: "user", content: "what is langraph?" }] },
config,
);
```
@@ -0,0 +1,34 @@
```python
from urllib.request import urlopen
from deepagents import create_deep_agent
from deepagents.backends import StoreBackend
from deepagents.backends.utils import create_file_data
from langchain_quickjs import CodeInterpreterMiddleware
from langgraph.store.memory import InMemoryStore
store = InMemoryStore()
backend = StoreBackend()
skill_url = "https://raw.githubusercontent.com/langchain-ai/deepagents/refs/heads/main/libs/cli/examples/skills/langgraph-docs/SKILL.md"
with urlopen(skill_url) as response:
skill_content = response.read().decode('utf-8')
store.put(
namespace=("filesystem",),
key="/skills/langgraph-docs/SKILL.md",
value=create_file_data(skill_content),
)
agent = create_deep_agent(
model="google_genai:gemini-3.1-pro-preview",
backend=backend,
store=store,
skills=["/skills/"],
middleware=[CodeInterpreterMiddleware(skills_backend=backend)],
)
result = agent.invoke(
{"messages": [{"role": "user", "content": "What is langgraph?"}]},
config={"configurable": {"thread_id": "12345"}},
)
```
@@ -0,0 +1,393 @@
<CodeGroup>
```ts Google
import { tool } from "langchain";
import { TavilySearch } from "@langchain/tavily";
import { createDeepAgent, type SubAgent } from "deepagents";
import { z } from "zod";
const internetSearch = tool(
async ({
query,
maxResults = 5,
topic = "general",
includeRawContent = false,
}: {
query: string;
maxResults?: number;
topic?: "general" | "news" | "finance";
includeRawContent?: boolean;
}) => {
const tavilySearch = new TavilySearch({
maxResults,
tavilyApiKey: process.env.TAVILY_API_KEY,
includeRawContent,
topic,
});
return await tavilySearch._call({ query });
},
{
name: "internet_search",
description: "Run a web search",
schema: z.object({
query: z.string().describe("The search query"),
maxResults: z.number().optional().default(5),
topic: z
.enum(["general", "news", "finance"])
.optional()
.default("general"),
includeRawContent: z.boolean().optional().default(false),
}),
},
);
const researchSubagent: SubAgent = {
name: "research-agent",
description: "Used to research more in depth questions",
systemPrompt: "You are a great researcher",
tools: [internetSearch],
model: "google-genai:gemini-3.1-pro-preview", // Optional override, defaults to main agent model
};
const subagents = [researchSubagent];
const agent = createDeepAgent({
model: "google_genai:gemini-3.1-pro-preview",
subagents,
});
```
```ts OpenAI
import { tool } from "langchain";
import { TavilySearch } from "@langchain/tavily";
import { createDeepAgent, type SubAgent } from "deepagents";
import { z } from "zod";
const internetSearch = tool(
async ({
query,
maxResults = 5,
topic = "general",
includeRawContent = false,
}: {
query: string;
maxResults?: number;
topic?: "general" | "news" | "finance";
includeRawContent?: boolean;
}) => {
const tavilySearch = new TavilySearch({
maxResults,
tavilyApiKey: process.env.TAVILY_API_KEY,
includeRawContent,
topic,
});
return await tavilySearch._call({ query });
},
{
name: "internet_search",
description: "Run a web search",
schema: z.object({
query: z.string().describe("The search query"),
maxResults: z.number().optional().default(5),
topic: z
.enum(["general", "news", "finance"])
.optional()
.default("general"),
includeRawContent: z.boolean().optional().default(false),
}),
},
);
const researchSubagent: SubAgent = {
name: "research-agent",
description: "Used to research more in depth questions",
systemPrompt: "You are a great researcher",
tools: [internetSearch],
model: "openai:gpt-5.4", // Optional override, defaults to main agent model
};
const subagents = [researchSubagent];
const agent = createDeepAgent({
model: "google_genai:gemini-3.1-pro-preview",
subagents,
});
```
```ts Anthropic
import { tool } from "langchain";
import { TavilySearch } from "@langchain/tavily";
import { createDeepAgent, type SubAgent } from "deepagents";
import { z } from "zod";
const internetSearch = tool(
async ({
query,
maxResults = 5,
topic = "general",
includeRawContent = false,
}: {
query: string;
maxResults?: number;
topic?: "general" | "news" | "finance";
includeRawContent?: boolean;
}) => {
const tavilySearch = new TavilySearch({
maxResults,
tavilyApiKey: process.env.TAVILY_API_KEY,
includeRawContent,
topic,
});
return await tavilySearch._call({ query });
},
{
name: "internet_search",
description: "Run a web search",
schema: z.object({
query: z.string().describe("The search query"),
maxResults: z.number().optional().default(5),
topic: z
.enum(["general", "news", "finance"])
.optional()
.default("general"),
includeRawContent: z.boolean().optional().default(false),
}),
},
);
const researchSubagent: SubAgent = {
name: "research-agent",
description: "Used to research more in depth questions",
systemPrompt: "You are a great researcher",
tools: [internetSearch],
model: "anthropic:claude-sonnet-4-6", // Optional override, defaults to main agent model
};
const subagents = [researchSubagent];
const agent = createDeepAgent({
model: "google_genai:gemini-3.1-pro-preview",
subagents,
});
```
```ts OpenRouter
import { tool } from "langchain";
import { TavilySearch } from "@langchain/tavily";
import { createDeepAgent, type SubAgent } from "deepagents";
import { z } from "zod";
const internetSearch = tool(
async ({
query,
maxResults = 5,
topic = "general",
includeRawContent = false,
}: {
query: string;
maxResults?: number;
topic?: "general" | "news" | "finance";
includeRawContent?: boolean;
}) => {
const tavilySearch = new TavilySearch({
maxResults,
tavilyApiKey: process.env.TAVILY_API_KEY,
includeRawContent,
topic,
});
return await tavilySearch._call({ query });
},
{
name: "internet_search",
description: "Run a web search",
schema: z.object({
query: z.string().describe("The search query"),
maxResults: z.number().optional().default(5),
topic: z
.enum(["general", "news", "finance"])
.optional()
.default("general"),
includeRawContent: z.boolean().optional().default(false),
}),
},
);
const researchSubagent: SubAgent = {
name: "research-agent",
description: "Used to research more in depth questions",
systemPrompt: "You are a great researcher",
tools: [internetSearch],
model: "openrouter:anthropic/claude-sonnet-4-6", // Optional override, defaults to main agent model
};
const subagents = [researchSubagent];
const agent = createDeepAgent({
model: "google_genai:gemini-3.1-pro-preview",
subagents,
});
```
```ts Fireworks
import { tool } from "langchain";
import { TavilySearch } from "@langchain/tavily";
import { createDeepAgent, type SubAgent } from "deepagents";
import { z } from "zod";
const internetSearch = tool(
async ({
query,
maxResults = 5,
topic = "general",
includeRawContent = false,
}: {
query: string;
maxResults?: number;
topic?: "general" | "news" | "finance";
includeRawContent?: boolean;
}) => {
const tavilySearch = new TavilySearch({
maxResults,
tavilyApiKey: process.env.TAVILY_API_KEY,
includeRawContent,
topic,
});
return await tavilySearch._call({ query });
},
{
name: "internet_search",
description: "Run a web search",
schema: z.object({
query: z.string().describe("The search query"),
maxResults: z.number().optional().default(5),
topic: z
.enum(["general", "news", "finance"])
.optional()
.default("general"),
includeRawContent: z.boolean().optional().default(false),
}),
},
);
const researchSubagent: SubAgent = {
name: "research-agent",
description: "Used to research more in depth questions",
systemPrompt: "You are a great researcher",
tools: [internetSearch],
model: "fireworks:accounts/fireworks/models/qwen3p5-397b-a17b", // Optional override, defaults to main agent model
};
const subagents = [researchSubagent];
const agent = createDeepAgent({
model: "google_genai:gemini-3.1-pro-preview",
subagents,
});
```
```ts Baseten
import { tool } from "langchain";
import { TavilySearch } from "@langchain/tavily";
import { createDeepAgent, type SubAgent } from "deepagents";
import { z } from "zod";
const internetSearch = tool(
async ({
query,
maxResults = 5,
topic = "general",
includeRawContent = false,
}: {
query: string;
maxResults?: number;
topic?: "general" | "news" | "finance";
includeRawContent?: boolean;
}) => {
const tavilySearch = new TavilySearch({
maxResults,
tavilyApiKey: process.env.TAVILY_API_KEY,
includeRawContent,
topic,
});
return await tavilySearch._call({ query });
},
{
name: "internet_search",
description: "Run a web search",
schema: z.object({
query: z.string().describe("The search query"),
maxResults: z.number().optional().default(5),
topic: z
.enum(["general", "news", "finance"])
.optional()
.default("general"),
includeRawContent: z.boolean().optional().default(false),
}),
},
);
const researchSubagent: SubAgent = {
name: "research-agent",
description: "Used to research more in depth questions",
systemPrompt: "You are a great researcher",
tools: [internetSearch],
model: "baseten:zai-org/GLM-5", // Optional override, defaults to main agent model
};
const subagents = [researchSubagent];
const agent = createDeepAgent({
model: "google_genai:gemini-3.1-pro-preview",
subagents,
});
```
```ts Ollama
import { tool } from "langchain";
import { TavilySearch } from "@langchain/tavily";
import { createDeepAgent, type SubAgent } from "deepagents";
import { z } from "zod";
const internetSearch = tool(
async ({
query,
maxResults = 5,
topic = "general",
includeRawContent = false,
}: {
query: string;
maxResults?: number;
topic?: "general" | "news" | "finance";
includeRawContent?: boolean;
}) => {
const tavilySearch = new TavilySearch({
maxResults,
tavilyApiKey: process.env.TAVILY_API_KEY,
includeRawContent,
topic,
});
return await tavilySearch._call({ query });
},
{
name: "internet_search",
description: "Run a web search",
schema: z.object({
query: z.string().describe("The search query"),
maxResults: z.number().optional().default(5),
topic: z
.enum(["general", "news", "finance"])
.optional()
.default("general"),
includeRawContent: z.boolean().optional().default(false),
}),
},
);
const researchSubagent: SubAgent = {
name: "research-agent",
description: "Used to research more in depth questions",
systemPrompt: "You are a great researcher",
tools: [internetSearch],
model: "ollama:devstral-2", // Optional override, defaults to main agent model
};
const subagents = [researchSubagent];
const agent = createDeepAgent({
model: "google_genai:gemini-3.1-pro-preview",
subagents,
});
```
</CodeGroup>
@@ -1,11 +1,13 @@
```python
import os
from typing import Literal
from tavily import TavilyClient
from deepagents import create_deep_agent
from tavily import TavilyClient
tavily_client = TavilyClient(api_key=os.environ["TAVILY_API_KEY"])
def internet_search(
query: str,
max_results: int = 5,
@@ -20,6 +22,7 @@ def internet_search(
topic=topic,
)
research_subagent = {
"name": "research-agent",
"description": "Used to research more in depth questions",
@@ -29,8 +32,9 @@ research_subagent = {
}
subagents = [research_subagent]
agent = create_deep_agent(
model="claude-sonnet-4-6",
subagents=subagents
model="google_genai:gemini-3.1-pro-preview",
subagents=subagents,
)
```
+7 -158
View File
@@ -1,166 +1,15 @@
import SkillsUsageStateJs from '/snippets/code-samples/skills-usage-state-js.mdx';
import SkillsUsageStoreJs from '/snippets/code-samples/skills-usage-store-js.mdx';
import SkillsUsageFilesystemJs from '/snippets/code-samples/skills-usage-filesystem-js.mdx';
<Tabs>
<Tab title="StateBackend">
```typescript
import { createDeepAgent, StateBackend, type FileData } from "deepagents";
import { MemorySaver } from "@langchain/langgraph";
import { createCodeInterpreterMiddleware } from "@langchain/quickjs";
const checkpointer = new MemorySaver();
const backend = new StateBackend();
function createFileData(content: string): FileData {
const now = new Date().toISOString();
return {
content: content.split("\n"),
created_at: now,
modified_at: now,
};
}
const skillsFiles: Record<string, FileData> = {};
const skillUrl =
"https://raw.githubusercontent.com/langchain-ai/deepagentsjs/refs/heads/main/examples/skills/langgraph-docs/SKILL.md";
const response = await fetch(skillUrl);
const skillContent = await response.text();
skillsFiles["/skills/langgraph-docs/SKILL.md"] = createFileData(skillContent);
const agent = await createDeepAgent({
model: "openai:gpt-5.4",
backend,
checkpointer,
// IMPORTANT: deepagents skill source paths are virtual (POSIX) paths relative to the backend root.
skills: ["/skills/"],
middleware: [createCodeInterpreterMiddleware({ skillsBackend: backend })],
});
const config = {
configurable: {
thread_id: `thread-${Date.now()}`,
},
};
const result = await agent.invoke(
{
messages: [
{
role: "user",
content: "what is langraph? Use the langgraph-docs skill if available.",
},
],
files: skillsFiles,
},
config,
);
```
<SkillsUsageStateJs />
</Tab>
<Tab title="StoreBackend">
```typescript
import { createDeepAgent, StoreBackend, type FileData } from "deepagents";
import {
InMemoryStore,
MemorySaver,
} from "@langchain/langgraph";
import { createCodeInterpreterMiddleware } from "@langchain/quickjs";
const checkpointer = new MemorySaver();
const store = new InMemoryStore();
const backend = new StoreBackend();
function createFileData(content: string): FileData {
const now = new Date().toISOString();
return {
content: content.split("\n"),
created_at: now,
modified_at: now,
};
}
const skillUrl =
"https://raw.githubusercontent.com/langchain-ai/deepagentsjs/refs/heads/main/examples/skills/langgraph-docs/SKILL.md";
const response = await fetch(skillUrl);
const skillContent = await response.text();
const fileData = createFileData(skillContent);
await store.put(["filesystem"], "/skills/langgraph-docs/SKILL.md", fileData);
const agent = await createDeepAgent({
model: "openai:gpt-5.4",
backend,
store: store,
checkpointer,
// IMPORTANT: deepagents skill source paths are virtual (POSIX) paths relative to the backend root.
skills: ["/skills/"],
middleware: [createCodeInterpreterMiddleware({ skillsBackend: backend })],
});
const config = {
recursionLimit: 50,
configurable: {
thread_id: `thread-${Date.now()}`,
},
};
const result = await agent.invoke(
{
messages: [
{
role: "user",
content: "what is langraph? Use the langgraph-docs skill if available.",
},
],
},
config,
);
```
<SkillsUsageStoreJs />
</Tab>
<Tab title="FilesystemBackend">
```typescript
import { createDeepAgent, FilesystemBackend } from "deepagents";
import { MemorySaver } from "@langchain/langgraph";
import { createCodeInterpreterMiddleware } from "@langchain/quickjs";
const checkpointer = new MemorySaver();
const backend = new FilesystemBackend({ rootDir: process.cwd() });
const agent = await createDeepAgent({
model: "openai:gpt-5.4",
backend,
skills: ["./examples/skills/"],
interruptOn: {
read_file: true,
write_file: true,
delete_file: true,
},
checkpointer, // Required!
middleware: [createCodeInterpreterMiddleware({ skillsBackend: backend })],
});
const config = {
configurable: {
thread_id: `thread-${Date.now()}`,
},
};
const result = await agent.invoke(
{
messages: [
{
role: "user",
content: "what is langraph? Use the langgraph-docs skill if available.",
},
],
},
config,
);
```
<SkillsUsageFilesystemJs />
</Tab>
</Tabs>
+7 -118
View File
@@ -1,126 +1,15 @@
import SkillsUsageStatePy from '/snippets/code-samples/skills-usage-state-py.mdx';
import SkillsUsageStorePy from '/snippets/code-samples/skills-usage-store-py.mdx';
import SkillsUsageFilesystemPy from '/snippets/code-samples/skills-usage-filesystem-py.mdx';
<Tabs>
<Tab title="StateBackend">
```python
from urllib.request import urlopen
from deepagents import create_deep_agent
from deepagents.backends.utils import create_file_data
from langgraph.checkpoint.memory import MemorySaver
from deepagents.backends import StateBackend
from langchain_quickjs import CodeInterpreterMiddleware
checkpointer = MemorySaver()
backend = StateBackend()
skill_url = "https://raw.githubusercontent.com/langchain-ai/deepagents/refs/heads/main/libs/cli/examples/skills/langgraph-docs/SKILL.md"
with urlopen(skill_url) as response:
skill_content = response.read().decode('utf-8')
skills_files = {
"/skills/langgraph-docs/SKILL.md": create_file_data(skill_content)
}
agent = create_deep_agent(
model="google_genai:gemini-3.1-pro-preview",
backend=backend,
skills=["/skills/"],
checkpointer=checkpointer,
middleware=[CodeInterpreterMiddleware(skills_backend=backend)] # for interpreter skills
)
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "What is langgraph?",
}
],
# Seed the default StateBackend's in-state filesystem (virtual paths must start with "/").
"files": skills_files
},
config={"configurable": {"thread_id": "12345"}},
)
```
<SkillsUsageStatePy />
</Tab>
<Tab title="StoreBackend">
```python
from urllib.request import urlopen
from deepagents import create_deep_agent
from deepagents.backends import StoreBackend
from deepagents.backends.utils import create_file_data
from langgraph.store.memory import InMemoryStore
from langchain_quickjs import CodeInterpreterMiddleware
store = InMemoryStore()
backend = StoreBackend()
skill_url = "https://raw.githubusercontent.com/langchain-ai/deepagents/refs/heads/main/libs/cli/examples/skills/langgraph-docs/SKILL.md"
with urlopen(skill_url) as response:
skill_content = response.read().decode('utf-8')
store.put(
namespace=("filesystem",),
key="/skills/langgraph-docs/SKILL.md",
value=create_file_data(skill_content)
)
agent = create_deep_agent(
model="google_genai:gemini-3.1-pro-preview",
backend=backend,
store=store,
skills=["/skills/"],
middleware=[CodeInterpreterMiddleware(skills_backend=backend)] # for interpreter skills
)
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "What is langgraph?",
}
]
},
config={"configurable": {"thread_id": "12345"}},
)
```
<SkillsUsageStorePy />
</Tab>
<Tab title="FilesystemBackend">
```python
from deepagents import create_deep_agent
from langgraph.checkpoint.memory import MemorySaver
from deepagents.backends.filesystem import FilesystemBackend
from langchain_quickjs import CodeInterpreterMiddleware
# Checkpointer is REQUIRED for human-in-the-loop
checkpointer = MemorySaver()
backend = FilesystemBackend(root_dir="/Users/user/{project}")
agent = create_deep_agent(
model="google_genai:gemini-3.1-pro-preview",
backend=,
skills=["/Users/user/{project}/skills/"],
interrupt_on={
"write_file": True, # Default: approve, edit, reject
"read_file": False, # No interrupts needed
"edit_file": True # Default: approve, edit, reject
},
checkpointer=checkpointer, # Required!
middleware=[CodeInterpreterMiddleware(skills_backend=backend)] # for interpreter skills
)
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "What is langgraph?",
}
]
},
config={"configurable": {"thread_id": "12345"}},
)
```
<SkillsUsageFilesystemPy />
</Tab>
</Tabs>
Generated
+6
View File
@@ -1,6 +1,10 @@
version = 1
revision = 3
requires-python = ">=3.13.0, <4.0.0"
resolution-markers = [
"python_full_version >= '3.14'",
"python_full_version < '3.14'",
]
[manifest]
overrides = [{ name = "pytest-codspeed", specifier = ">=3.1.0,<4.0.0" }]
@@ -589,6 +593,7 @@ dependencies = [
{ name = "langchain-daytona" },
{ name = "langchain-google-genai" },
{ name = "langchain-openai" },
{ name = "langchain-quickjs" },
{ name = "langgraph-checkpoint-postgres" },
{ name = "markdownify" },
{ name = "nbconvert" },
@@ -625,6 +630,7 @@ requires-dist = [
{ name = "langchain-daytona", specifier = ">=0.0.5" },
{ name = "langchain-google-genai", specifier = ">=2.0.0" },
{ name = "langchain-openai", specifier = ">=1.1.14" },
{ name = "langchain-quickjs", specifier = ">=0.1.2" },
{ name = "langgraph-checkpoint-postgres" },
{ name = "markdownify", specifier = ">=0.13.0" },
{ name = "nbconvert", specifier = ">=7.17.1" },