| name | deepagents-filesystem |
| description | Using FilesystemMiddleware with virtual filesystems, backends (State, Store, Filesystem, Composite), and context management for Deep Agents. |
| language | python |
deepagents-filesystem (Python)
Overview
FilesystemMiddleware solves context engineering challenges by providing file operations through a pluggable backend system. It allows agents to offload large context to filesystem storage, preventing context window overflow.
Built-in Filesystem Tools:
ls - List files in a directory
read_file - Read entire files or specific line ranges
write_file - Create new files
edit_file - Edit existing files with exact string replacement
glob - Find files matching patterns
grep - Search for text across files
When to Use Filesystem Middleware
| Use Filesystem Tools When | Alternative Approach |
|---|
| Tool results are variable-length (web_search, RAG) | Keep in message history (if small) |
| Working with large documents or code | Use specialized tools |
| Need persistent storage across turns | Use short-term message history |
| Multiple files need coordination | Single-turn operations |
Backend Types
StateBackend (Default)
Ephemeral storage in agent state - persists within a thread only.
from deepagents import create_deep_agent
agent = create_deep_agent()
result = agent.invoke({
"messages": [{"role": "user", "content": "Write notes to /draft.txt"}]
})
FilesystemBackend (Local Disk)
Direct access to local filesystem.
from deepagents import create_deep_agent
from deepagents.backends import FilesystemBackend
agent = create_deep_agent(
backend=FilesystemBackend(
root_dir=".",
virtual_mode=True
)
)
result = agent.invoke({
"messages": [{"role": "user", "content": "Read the README.md file"}]
})
Security Considerations:
- Use
virtual_mode=True to prevent .., ~, and absolute path access
- Enable Human-in-the-Loop for sensitive operations
- Never use in web servers - use StateBackend or sandbox instead
- Secrets (API keys, .env) are readable by the agent
StoreBackend (Persistent Cross-Thread)
Storage that persists across threads using LangGraph's Store.
from deepagents import create_deep_agent
from deepagents.backends import StoreBackend
from langgraph.store.memory import InMemoryStore
store = InMemoryStore()
agent = create_deep_agent(
backend=lambda rt: StoreBackend(rt),
store=store
)
CompositeBackend (Hybrid Storage)
Route different paths to different backends.
from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend
from langgraph.store.memory import InMemoryStore
store = InMemoryStore()
composite_backend = lambda rt: CompositeBackend(
default=StateBackend(rt),
routes={
"/memories/": StoreBackend(rt),
}
)
agent = create_deep_agent(
backend=composite_backend,
store=store
)
Decision Table: Which Backend to Use
| Use Case | Backend | Why |
|---|
| Temporary working files | StateBackend | Default, no setup needed |
| Local development CLI | FilesystemBackend | Direct disk access |
| Cross-session memory | StoreBackend | Persists across threads |
| Hybrid storage | CompositeBackend | Mix ephemeral + persistent |
| Production web app | StateBackend or Sandbox | Never use FilesystemBackend |
Code Examples
Example 1: Managing Large Context
from deepagents import create_deep_agent
agent = create_deep_agent()
result = agent.invoke({
"messages": [{
"role": "user",
"content": "Search for information about Python asyncio and save the results for later analysis"
}]
})
Example 2: Custom Tool Descriptions
from langchain.agents import create_agent
from deepagents.middleware.filesystem import FilesystemMiddleware
agent = create_agent(
model="claude-sonnet-4-5-20250929",
middleware=[
FilesystemMiddleware(
backend=None,
system_prompt="Save intermediate results to /workspace/ directory",
custom_tool_descriptions={
"read_file": "Read files you've previously written. Use offset/limit for large files.",
"write_file": "Save data to avoid context overflow. Organize in /workspace/.",
}
),
],
)
Example 3: Long-term Memory with CompositeBackend
from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend
from langgraph.store.memory import InMemoryStore
store = InMemoryStore()
agent = create_deep_agent(
backend=lambda rt: CompositeBackend(
default=StateBackend(rt),
routes={"/memories/": StoreBackend(rt)}
),
store=store
)
config1 = {"configurable": {"thread_id": "thread-1"}}
agent.invoke({
"messages": [{"role": "user", "content": "Save my preference: I like concise explanations to /memories/prefs.txt"}]
}, config=config1)
config2 = {"configurable": {"thread_id": "thread-2"}}
agent.invoke({
"messages": [{"role": "user", "content": "Read my preferences and explain asyncio"}]
}, config=config2)
Example 4: FilesystemBackend for Local Development
from deepagents import create_deep_agent
from deepagents.backends import FilesystemBackend
agent = create_deep_agent(
backend=FilesystemBackend(
root_dir="/Users/username/project",
virtual_mode=True
),
interrupt_on={"write_file": True, "edit_file": True}
)
result = agent.invoke({
"messages": [{"role": "user", "content": "Analyze the code in src/main.py"}]
})
Boundaries
What Agents CAN Configure
✅ Backend type and configuration
✅ Custom tool descriptions
✅ File paths and organization
✅ Human-in-the-loop for file operations
✅ Root directory for FilesystemBackend
✅ Routing rules for CompositeBackend
What Agents CANNOT Configure
❌ Tool names (ls, read_file, write_file, edit_file, glob, grep)
❌ The fundamental file operation protocol
❌ Disable filesystem tools in create_deep_agent
❌ Access files outside virtual_mode restrictions
❌ Cross-thread file access without proper backend setup
Gotchas
1. StateBackend Files Don't Persist Across Threads
config1 = {"configurable": {"thread_id": "thread-1"}}
agent.invoke({"messages": [{"role": "user", "content": "Write to /notes.txt"}]}, config=config1)
config2 = {"configurable": {"thread_id": "thread-2"}}
agent.invoke({"messages": [{"role": "user", "content": "Read /notes.txt"}]}, config=config2)
2. FilesystemBackend Needs virtual_mode for Security
backend = FilesystemBackend(root_dir="/project", virtual_mode=False)
backend = FilesystemBackend(root_dir="/project", virtual_mode=True)
3. StoreBackend Requires a Store Instance
agent = create_deep_agent(
backend=lambda rt: StoreBackend(rt)
)
from langgraph.store.memory import InMemoryStore
agent = create_deep_agent(
backend=lambda rt: StoreBackend(rt),
store=InMemoryStore()
)
4. edit_file Requires Exact String Match
old_string = "def hello():\n print('hi')"
new_string = "def hello():\n print('hi')"
old_string = " print('hi')"
new_string = " print('hi')"
Full Documentation