ls, read_file, write_file, edit_file, glob, and grep. These tools operate through a pluggable backend.
This page explains how to choose a backend, route different paths to different backends, implement your own virtual filesystem (e.g., S3 or Postgres), add policy hooks, and comply with the backend protocol.
Quickstart
Here are a few pre-built filesystem backends that you can quickly use with your deep agent:| Built-in backend | Description | 
|---|---|
| Default | agent = create_deep_agent()Ephemeral in state. The default filesystem backend for an agent is stored in langgraphstate. Note that this filesystem only persists for a single thread. | 
| Local filesystem persistence | agent = create_deep_agent(backend=FilesystemBackend(root_dir="/Users/nh/Desktop/"))This gives the deep agent access to your local machine’s filesystem. You can specify the root directory that the agent has access to. Note that any provided root_dirmust be an absolute path. | 
| Durable store (LangGraph store) | agent = create_deep_agent(backend=lambda rt: StoreBackend(rt))This gives the agent access to long-term storage that is persisted across threads. This is great for storing longer term memories or instructions that are applicable to the agent over multiple executions. | 
| Composite | Ephemeral by default, /memories/persisted. The Composite backend is maximally flexible. You can specify different routes in the filesystem to point towards different backends. See Composite routing below for a ready-to-paste example. | 
Built-in backends
StateBackend (ephemeral)
- Stores files in LangGraph agent state for the current thread.
- Persists across multiple agent turns on the same thread via checkpoints.
- A scratch pad for the agent to write intermediate results.
- Aautomatic eviction of large tool outputs which the agent can then read back in piece by piece.
FilesystemBackend (local disk)
- Reads/writes real files under a configurable root_dir.
- Note: root_dirmust be an absolute path.
- You can optionally set virtual_mode=Trueto sandbox and normalize paths underroot_dir.
- Uses secure path resolution, prevents unsafe symlink traversal when possible, can use ripgrep for fast grep.
- Local projects on your machine
- CI sandboxes
- Mounted persistent volumes
StoreBackend (LangGraph Store)
- Stores files in a LangGraph BaseStoreprovided by the runtime, enabling cross‑thread durable storage.
- When you already run with a configured LangGraph store (for example, Redis, Postgres, or cloud implementations behind BaseStore).
- When you’re deploying your agent through LangSmith Deployments (a store is automatically provisioned for your agent).
CompositeBackend (router)
- Routes file operations to different backends based on path prefix.
- Preserves the original path prefixes in listings and search results.
- When you want to give your agent both ephemeral and cross-thread storage, a CompositeBackend allows you provide both a StateBackend and StoreBackend
- When you have multiple sources of information that you want to provide to your agent as part of a single filesystem.
- e.g. You have long-term memories stored under /memories/ in one Store and you also have a custom backend that has documentation accessible at /docs/.
 
Specify a backend
- Pass a backend to create_deep_agent(backend=...). The filesystem middleware uses it for all tooling.
- You can pass either:
- An instance implementing BackendProtocol(for example,FilesystemBackend(root_dir=".")), or
- A factory BackendFactory = Callable[[ToolRuntime], BackendProtocol](for backends that need runtime likeStateBackendorStoreBackend).
 
- An instance implementing 
- If omitted, the default is lambda rt: StateBackend(rt).
Route to different backends
Route parts of the namespace to different backends. Commonly used to persist/memories/* and keep everything else ephemeral.
- /workspace/plan.md→ StateBackend (ephemeral)
- /memories/agent.md→ FilesystemBackend under- /deepagents/myagent
- ls,- glob,- grepaggregate results and show original path prefixes.
- Longer prefixes win (for example, route "/memories/projects/"can override"/memories/").
- For StoreBackend routing, ensure the agent runtime provides a store (runtime.store).
Use a virtual filesystem
Build a custom backend to project a remote or database filesystem (e.g., S3 or Postgres) into the tools namespace. Design guidelines:- Paths are absolute (/x/y.txt). Decide how to map them to your storage keys/rows.
- Implement ls_infoandglob_infoefficiently (server-side listing where available, otherwise local filter).
- Return user-readable error strings for missing files or invalid regex patterns.
- For external persistence, set files_update=Nonein results; only in-state backends should return afiles_updatedict.
- Table files(path text primary key, content text, created_at timestamptz, modified_at timestamptz)
- Map tool operations onto SQL:
- ls_infouses- WHERE path LIKE $1 || '%'
- glob_infofilter in SQL or fetch then apply glob in Python
- grep_rawcan fetch candidate rows by extension or last modified time, then scan lines
 
Add policy hooks
Enforce enterprise rules by subclassing or wrapping a backend. Block writes/edits under selected prefixes (subclass):Protocol reference
Backends must implement theBackendProtocol.
Required endpoints:
- ls_info(path: str) -> list[FileInfo]- Return entries with at least path. Includeis_dir,size,modified_atwhen available. Sort bypathfor deterministic output.
 
- Return entries with at least 
- read(file_path: str, offset: int = 0, limit: int = 2000) -> str- Return numbered content. On missing file, return "Error: File '/x' not found".
 
- Return numbered content. On missing file, return 
- grep_raw(pattern: str, path: Optional[str] = None, glob: Optional[str] = None) -> list[GrepMatch] | str- Return structured matches. For an invalid regex, return a string like "Invalid regex pattern: ..."(do not raise).
 
- Return structured matches. For an invalid regex, return a string like 
- glob_info(pattern: str, path: str = "/") -> list[FileInfo]- Return matched files as FileInfoentries (empty list if none).
 
- Return matched files as 
- write(file_path: str, content: str) -> WriteResult- Create-only. On conflict, return WriteResult(error=...). On success, setpathand for state backends setfiles_update={...}; external backends should usefiles_update=None.
 
- Create-only. On conflict, return 
- edit(file_path: str, old_string: str, new_string: str, replace_all: bool = False) -> EditResult- Enforce uniqueness of old_stringunlessreplace_all=True. If not found, return error. Includeoccurrenceson success.
 
- Enforce uniqueness of 
- WriteResult(error, path, files_update)
- EditResult(error, path, files_update, occurrences)
- FileInfowith fields:- path(required), optionally- is_dir,- size,- modified_at.
- GrepMatchwith fields:- path,- line,- text.
Connect these docs programmatically to Claude, VSCode, and more via MCP for    real-time answers.