Try Live
Add Docs
Rankings
Pricing
Enterprise
Docs
Install
Theme
Install
Docs
Pricing
Enterprise
More...
More...
Try Live
Rankings
Create API Key
Add Docs
Deep Agents
https://github.com/langchain-ai/deepagentsjs
Admin
A TypeScript package for creating Deep Agents that overcome the limitations of simple LLM agents by
...
Tokens:
31,711
Snippets:
176
Trust Score:
9.2
Update:
2 weeks ago
Context
Skills
Chat
Benchmark
81.1
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# DeepAgents.js DeepAgents.js is a TypeScript library for building controllable AI agents with LangGraph. It provides a middleware-based architecture for creating sophisticated agents with built-in support for filesystem operations, subagent delegation, conversation summarization, skills management, and memory persistence. The library maintains 1:1 compatibility with the Python Deep Agents library while leveraging TypeScript's strong typing system. The core of the library is the `createDeepAgent` function which assembles agents with a comprehensive middleware stack. This includes todo list management, filesystem tools, subagent spawning capabilities, automatic conversation summarization when token limits are approached, and Anthropic prompt caching optimizations. The architecture supports multiple backend storage options (state-based, store-based, filesystem, and sandbox environments) making it flexible for various deployment scenarios. ## createDeepAgent - Create a Deep Agent with Middleware-Based Architecture The main entry point for creating AI agents. It configures the agent with model selection, tools, system prompts, middleware, subagents, and backend storage. The function automatically includes built-in middleware for todo management, filesystem operations, subagent delegation, summarization, and prompt caching. ```typescript import { createDeepAgent, FilesystemBackend, type SubAgent } from "deepagents"; import { tool } from "langchain"; import { z } from "zod"; import { HumanMessage } from "@langchain/core/messages"; // Define custom tools const searchTool = tool( (input) => `Search results for: ${input.query}`, { name: "search", description: "Search for information", schema: z.object({ query: z.string().describe("The search query"), }), } ); // Define a subagent for specialized tasks const researcherSubAgent: SubAgent = { name: "researcher", description: "Researches topics thoroughly using web search and analysis", systemPrompt: "You are a research specialist. Gather and analyze information.", tools: [searchTool], }; // Create the agent with full configuration const agent = createDeepAgent({ model: "claude-sonnet-4-5-20250929", // Default model, can use string or LanguageModelLike systemPrompt: "You are a helpful assistant with research capabilities.", tools: [searchTool], subagents: [researcherSubAgent], backend: new FilesystemBackend({ rootDir: "/workspace", virtualMode: true }), skills: ["/skills/user/", "/skills/project/"], // Skill directories to load memory: ["~/.deepagents/AGENTS.md"], // Memory files to inject into system prompt }); // Invoke the agent const result = await agent.invoke({ messages: [new HumanMessage("Research the latest AI developments")], }); console.log(result.messages[result.messages.length - 1].content); // Output: Detailed research findings about AI developments ``` ## StateBackend - Ephemeral File Storage in Agent State Backend that stores files in LangGraph agent state for ephemeral, within-conversation file operations. Files persist within a conversation thread but not across threads. State is automatically checkpointed after each agent step. ```typescript import { createDeepAgent, StateBackend } from "deepagents"; import { HumanMessage } from "@langchain/core/messages"; // StateBackend is the default when no backend is specified const agent = createDeepAgent({ systemPrompt: "You are a coding assistant that can create and edit files.", }); // Files are stored in agent state and can be passed in initial state const result = await agent.invoke({ messages: [new HumanMessage("Create a hello.py file that prints 'Hello World'")], files: { "/existing-file.txt": { content: "Initial content here", mimeType: "text/plain", created_at: new Date().toISOString(), modified_at: new Date().toISOString(), }, }, }); // Access the files from the result state console.log(result.files); // Output: { "/hello.py": { content: "print('Hello World')", ... }, "/existing-file.txt": {...} } // StateBackend operations return filesUpdate for LangGraph state management const stateAndStore = { state: { files: {} } }; const backend = new StateBackend(stateAndStore); const writeResult = backend.write("/newfile.txt", "Hello"); console.log(writeResult); // Output: { path: "/newfile.txt", filesUpdate: { "/newfile.txt": { content: "Hello", ... } } } const readResult = backend.read("/newfile.txt"); console.log(readResult); // Output: { content: "Hello", mimeType: "text/plain" } ``` ## FilesystemBackend - Direct Filesystem Access Backend that reads and writes files directly to the filesystem. Supports both absolute paths and virtual mode (sandboxed to a root directory). Includes security features like symlink prevention and path traversal protection. ```typescript import { createDeepAgent, FilesystemBackend } from "deepagents"; import { HumanMessage } from "@langchain/core/messages"; // Create filesystem backend with virtual mode for security const backend = new FilesystemBackend({ rootDir: "/project/workspace", virtualMode: true, // Paths are sandboxed to rootDir maxFileSizeMb: 10, // Maximum file size for grep operations }); // Use with createDeepAgent const agent = createDeepAgent({ systemPrompt: "You are a coding assistant with filesystem access.", backend: backend, }); const result = await agent.invoke({ messages: [new HumanMessage("List files in the current directory and read package.json")], }); // Direct backend operations const lsResult = await backend.ls("/"); console.log(lsResult); // Output: { files: [{ path: "/src/", is_dir: true, size: 0, modified_at: "..." }, ...] } const readResult = await backend.read("/package.json", 0, 100); console.log(readResult); // Output: { content: "{ \"name\": \"my-project\", ... }", mimeType: "application/json" } const grepResult = await backend.grep("import", "/src", "*.ts"); console.log(grepResult); // Output: { matches: [{ path: "/src/index.ts", line: 1, text: "import { foo } from 'bar'" }] } const globResult = await backend.glob("**/*.ts", "/src"); console.log(globResult); // Output: { files: [{ path: "/src/index.ts", is_dir: false, size: 1234, modified_at: "..." }] } ``` ## StoreBackend - Persistent Cross-Conversation Storage Backend that stores files in LangGraph's BaseStore for persistent storage across conversations. Files are organized via namespaces and persist across all threads. Supports custom namespace patterns for user-scoped or org-scoped isolation. ```typescript import { createDeepAgent, StoreBackend } from "deepagents"; import { InMemoryStore } from "@langchain/langgraph"; import { HumanMessage } from "@langchain/core/messages"; // Create a store instance const store = new InMemoryStore(); // Create StoreBackend with custom namespace for user isolation const stateAndStore = { state: {}, store: store, assistantId: "my-assistant", }; const backend = new StoreBackend(stateAndStore, { namespace: ["memories", "org-123", "user-456", "filesystem"], fileFormat: "v2", // Use v2 format with MIME types }); // Use with createDeepAgent via factory function const agent = createDeepAgent({ systemPrompt: "You are an assistant with persistent memory.", store: store, backend: (config) => new StoreBackend(config, { namespace: ["memories", "user-456", "filesystem"], }), }); const result = await agent.invoke({ messages: [new HumanMessage("Save my preferences to a file")], }); // Direct backend operations await backend.write("/preferences.json", JSON.stringify({ theme: "dark" })); const readResult = await backend.read("/preferences.json"); console.log(readResult); // Output: { content: "{ \"theme\": \"dark\" }", mimeType: "application/json" } // Files persist across conversations const lsResult = await backend.ls("/"); console.log(lsResult); // Output: { files: [{ path: "/preferences.json", is_dir: false, size: 18, ... }] } ``` ## BaseSandbox - Abstract Base for Sandbox Backends with Command Execution Abstract base class for creating sandbox backends that support shell command execution. Concrete implementations only need to implement `execute()`, `uploadFiles()`, and `downloadFiles()`. All other file operations are automatically implemented using POSIX shell commands. ```typescript import { createDeepAgent, BaseSandbox, type ExecuteResponse, type FileUploadResponse, type FileDownloadResponse, } from "deepagents"; import { HumanMessage } from "@langchain/core/messages"; import cp from "node:child_process"; import fs from "node:fs"; import path from "node:path"; // Create a concrete sandbox implementation class LocalShellSandbox extends BaseSandbox { readonly id: string; private workingDirectory: string; constructor(workingDirectory: string) { super(); this.workingDirectory = path.resolve(workingDirectory); this.id = `local-shell-${this.workingDirectory.replace(/[^a-zA-Z0-9]/g, "-")}`; if (!fs.existsSync(this.workingDirectory)) { fs.mkdirSync(this.workingDirectory, { recursive: true }); } } async execute(command: string): Promise<ExecuteResponse> { return new Promise((resolve) => { cp.exec(command, { cwd: this.workingDirectory }, (error, stdout, stderr) => { resolve({ output: stdout + stderr, exitCode: error ? error.code ?? 1 : 0, truncated: false, }); }); }); } async uploadFiles(files: Array<[string, Uint8Array]>): Promise<FileUploadResponse[]> { return files.map(([filePath, content]) => { const fullPath = path.join(this.workingDirectory, filePath); fs.mkdirSync(path.dirname(fullPath), { recursive: true }); fs.writeFileSync(fullPath, content); return { path: filePath, error: null }; }); } async downloadFiles(paths: string[]): Promise<FileDownloadResponse[]> { return paths.map((filePath) => { const fullPath = path.join(this.workingDirectory, filePath); if (!fs.existsSync(fullPath)) { return { path: filePath, content: null, error: "file_not_found" }; } return { path: filePath, content: fs.readFileSync(fullPath), error: null }; }); } } // Use sandbox with createDeepAgent const sandbox = new LocalShellSandbox("/tmp/sandbox-workspace"); const agent = createDeepAgent({ systemPrompt: "You are a coding assistant with shell access.", backend: sandbox, }); const result = await agent.invoke({ messages: [new HumanMessage("Create a Node.js project and run npm init -y")], }); // The agent can now use the execute tool to run shell commands console.log(result.messages[result.messages.length - 1].content); ``` ## createSubAgentMiddleware - Task Delegation to Specialized Subagents Creates middleware that provides a `task` tool for spawning and delegating work to specialized subagents. Supports both pre-compiled agents (CompiledSubAgent) and dynamically created agents (SubAgent). Includes a general-purpose subagent by default. ```typescript import { createDeepAgent, createSubAgentMiddleware, type SubAgent, type CompiledSubAgent } from "deepagents"; import { tool } from "langchain"; import { z } from "zod"; import { HumanMessage } from "@langchain/core/messages"; // Define tools for subagents const verifyClaim = tool( (input) => `Verified: "${input.claim}" - Status: Confirmed`, { name: "verify_claim", description: "Verify a factual claim", schema: z.object({ claim: z.string() }), } ); // SubAgent: dynamically created at runtime const factChecker: SubAgent = { name: "fact-checker", description: "Verifies factual claims and statements", systemPrompt: "You are a fact-checking specialist. Verify claims thoroughly.", tools: [verifyClaim], }; // Create a deep agent to use as a compiled subagent const researchAgent = createDeepAgent({ systemPrompt: "You are a research specialist.", tools: [verifyClaim], subagents: [factChecker], }); // CompiledSubAgent: pre-built agent used as subagent const compiledResearcher: CompiledSubAgent = { name: "research-specialist", description: "Conducts thorough research with fact-checking capabilities", runnable: researchAgent, }; // Main orchestrator agent with both subagent types const mainAgent = createDeepAgent({ systemPrompt: "You coordinate research and fact-checking tasks.", subagents: [factChecker, compiledResearcher], }); // The agent automatically gets a "task" tool for delegation const result = await mainAgent.invoke({ messages: [new HumanMessage("Research quantum computing and verify key claims")], }); // The model decides when to use task tool vs direct tools console.log(result.messages[result.messages.length - 1].content); ``` ## createSkillsMiddleware - Load and Use Agent Skills Creates middleware for loading skills from backend storage using the Agent Skills specification. Skills follow a progressive disclosure pattern where skill names and descriptions are shown in the system prompt, but full instructions are read on-demand from SKILL.md files. ```typescript import { createDeepAgent, createSkillsMiddleware, FilesystemBackend } from "deepagents"; import { HumanMessage } from "@langchain/core/messages"; import fs from "node:fs"; // Create skill directory structure const skillsDir = "/project/skills"; fs.mkdirSync(`${skillsDir}/web-research`, { recursive: true }); fs.writeFileSync(`${skillsDir}/web-research/SKILL.md`, `--- name: web-research description: Structured approach to conducting thorough web research on any topic license: MIT compatibility: Requires web search tools --- # Web Research Skill ## When to Use - User asks you to research a topic - User needs comprehensive information gathering ## Workflow 1. Define scope and clarify requirements 2. Search using web search tools 3. Analyze and extract key information 4. Synthesize findings into a coherent summary 5. Cite all sources `); // Create agent with skills const backend = new FilesystemBackend({ rootDir: "/project", virtualMode: true }); const agent = createDeepAgent({ systemPrompt: "You are a research assistant.", backend: backend, skills: ["/skills/"], // Skill source directories }); // Or use createSkillsMiddleware directly for more control const skillsMiddleware = createSkillsMiddleware({ backend: backend, sources: ["/skills/user/", "/skills/project/"], // Later sources override earlier }); const result = await agent.invoke({ messages: [new HumanMessage("What skills do you have available?")], }); // Agent will list available skills with descriptions // When needed, it reads full SKILL.md for detailed instructions console.log(result.messages[result.messages.length - 1].content); ``` ## createMemoryMiddleware - Persistent Context from AGENTS.md Files Creates middleware for loading persistent context from AGENTS.md files that follow the agents.md specification. Memory content is loaded at agent startup and injected into the system prompt. ```typescript import { createDeepAgent, createMemoryMiddleware, FilesystemBackend } from "deepagents"; import { HumanMessage } from "@langchain/core/messages"; import fs from "node:fs"; // Create AGENTS.md file with project context fs.writeFileSync("/project/AGENTS.md", `# Project Context ## Code Style - Use TypeScript with strict mode - Prefer functional patterns - Always add JSDoc comments ## Build Commands - \`npm run build\` - Build the project - \`npm test\` - Run tests - \`npm run lint\` - Lint code ## Architecture This project uses a middleware-based architecture with pluggable backends. `); // Use memory parameter for simple setup const backend = new FilesystemBackend({ rootDir: "/project", virtualMode: true }); const agent = createDeepAgent({ systemPrompt: "You are a coding assistant for this project.", backend: backend, memory: ["/AGENTS.md"], // Paths to memory files }); // Or use createMemoryMiddleware for more control const memoryMiddleware = createMemoryMiddleware({ backend: backend, sources: ["/AGENTS.md", "/docs/AGENTS.md"], addCacheControl: true, // Enable Anthropic cache control headers }); const result = await agent.invoke({ messages: [new HumanMessage("What are the code style guidelines for this project?")], }); // Agent responds with knowledge from AGENTS.md console.log(result.messages[result.messages.length - 1].content); // Output: "Based on the project guidelines, you should use TypeScript with strict mode..." ``` ## createSummarizationMiddleware - Automatic Conversation Summarization Creates middleware that automatically summarizes conversation history when token limits are approached. Supports backend offloading to store full conversation history while keeping a summarized version in context. ```typescript import { createDeepAgent, createSummarizationMiddleware, FilesystemBackend } from "deepagents"; import { HumanMessage } from "@langchain/core/messages"; const backend = new FilesystemBackend({ rootDir: "/workspace", virtualMode: true }); // createDeepAgent includes summarization by default // For custom configuration, use the middleware directly const summarizationMiddleware = createSummarizationMiddleware({ model: "claude-sonnet-4-5-20250929", backend: backend, // Trigger summarization at 85% of context window // Keep 10% of original messages after summarization // These defaults are auto-computed from model profile }); const agent = createDeepAgent({ systemPrompt: "You are a helpful assistant.", backend: backend, middleware: [summarizationMiddleware], // Add custom summarization config }); // Long conversations are automatically summarized const result = await agent.invoke({ messages: [ new HumanMessage("Let's have a long discussion about programming..."), // ... many more messages ], }); // When summarization occurs: // 1. Full history is offloaded to backend storage // 2. A summary message replaces older messages // 3. Recent messages are preserved for context console.log(result.messages.length); // Kept within token limits ``` ## Streaming - Real-Time Agent Responses DeepAgents supports streaming for real-time updates from both main agents and subagents. Use `stream()` with `subgraphs: true` to receive events from the full agent hierarchy. ```typescript import { createDeepAgent, type SubAgent } from "deepagents"; const researcher: SubAgent = { name: "researcher", description: "Researches topics in depth", systemPrompt: "You are a thorough researcher.", }; const agent = createDeepAgent({ systemPrompt: "You are a helpful research assistant.", subagents: [researcher], }); // Stream with subgraph events for await (const [namespace, chunk] of await agent.stream( { messages: [{ role: "user", content: "Research quantum computing advances" }], }, { streamMode: "updates", // Get incremental updates subgraphs: true, // Include subagent events } )) { if (namespace.length > 0) { // Subagent event - namespace identifies which subagent console.log(`[subagent: ${namespace.join("|")}]`, chunk); } else { // Main agent event console.log("[main agent]", chunk); } } // Stream modes available: // - "updates": Incremental state updates // - "values": Full state after each step // - "messages": Just message content // - "debug": Detailed debugging information ``` ## createSettings - Project Detection and Path Management Utility for detecting project roots and managing standard paths for skills and memory files. Provides consistent path resolution across user-level and project-level resources. ```typescript import { createSettings } from "deepagents"; // Create settings with project detection const settings = createSettings({ startPath: process.cwd(), // Start from current directory }); console.log("Environment:"); console.log(` Project root: ${settings.projectRoot || "(not in a git project)"}`); console.log(` User deepagents dir: ${settings.userDeepagentsDir}`); console.log(` Has project: ${settings.hasProject}`); // Output: // Project root: /home/user/my-project // User deepagents dir: /home/user/.deepagents // Has project: true // Get agent-specific paths const agentName = "my-assistant"; // User-level paths console.log(`User agent dir: ${settings.getAgentDir(agentName)}`); // Output: /home/user/.deepagents/my-assistant console.log(`User agent.md: ${settings.getUserAgentMdPath(agentName)}`); // Output: /home/user/.deepagents/my-assistant/agent.md console.log(`User skills dir: ${settings.getUserSkillsDir(agentName)}`); // Output: /home/user/.deepagents/my-assistant/skills // Project-level paths console.log(`Project agent.md: ${settings.getProjectAgentMdPath()}`); // Output: /home/user/my-project/.deepagents/agent.md console.log(`Project skills dir: ${settings.getProjectSkillsDir()}`); // Output: /home/user/my-project/.deepagents/skills // Ensure directories exist settings.ensureAgentDir(agentName); settings.ensureUserSkillsDir(agentName); settings.ensureProjectSkillsDir(); ``` ## Summary DeepAgents.js is designed for building production-ready AI agents that need sophisticated capabilities like task delegation, persistent memory, and filesystem access. The middleware-based architecture allows developers to compose agents with exactly the features they need, from simple chatbots to complex multi-agent systems with hierarchical delegation. Common integration patterns include: using `createDeepAgent` with `FilesystemBackend` for local development and code assistance; combining `StoreBackend` with custom namespaces for multi-tenant applications with user-isolated storage; extending `BaseSandbox` for secure code execution environments; and leveraging subagents for parallel task processing and specialized domain expertise. The library's TypeScript-first design ensures type safety throughout, with full inference for middleware state, subagent types, and structured responses.