deepagentsjs: The Agent Framework That Treats Files Like Memory
A TypeScript harness for planning, sub-agents, and persistent state that makes long-running AI workflows feel like real software, not prompt glue.
- deepagentsjs replaces the fantasy of a single smart prompt with an operating model built from files, middleware, sub-agents, and typed state.
- Its filesystem-first design turns memory into something the agent can search, rewrite, and recover from, which makes long tasks feel durable instead of fragile.
- The middleware stack matters because order is part of the contract, so context shaping, tool patching, and summarization stay predictable.
- This is best understood as architectural engineering for agents, not a general-purpose chatbot framework.
Why This Agent Thinks in Files
deepagentsjs starts with a blunt bet: long-running agents should remember things the way software projects do, through files, not by stuffing everything into a conversation buffer. That changes the unit of work. Instead of asking a model to hold the world in context, you let it write notes, search artifacts, and reopen state later.
That matters because context windows are a bad database. They blur under load, they reward verbosity, and they make recovery awkward. A filesystem gives the agent a place to persist plans, intermediate research, and outputs that are too large or too important to keep in chat.
const agent = createDeepAgent({
model,
tools,
filesystem: true,
subagents: true,
summarization: true,
prompt: BASE_AGENT_PROMPT,
});
// The point is not just tool use.
// The point is durable work across turns.
Using an LLM to call tools in a loop is the simplest form of an agent. This architecture, however, can yield agents that are "shallow" and fail to plan and act over longer, more complex tasks. Applications like "Deep Research", "Manus", and "Claude Code" have gotten around this limitation by implementing a combination of four things: a planning tool, sub agents, access to a file system, and a detailed prompt.
From Prompting to Harness Design
The repo’s real shift is from prompt craftsmanship to harness design. The createDeepAgent factory does not hand you a giant blob of instructions and hope for the best. It assembles a controlled system around a base prompt that pushes the model through an Understand -> Act -> Verify loop.
| Approach | Primary abstraction | Memory model | Delegation | Persistence | Type safety | Best fit |
|---|---|---|---|---|---|---|
| deepagentsjs | Opinionated harness | Filesystem-backed working state | Built-in sub-agents | Native, structured | Strong TypeScript inference | Durable, multi-step work |
| Plain tool loop | Prompt plus tools | Chat history | Manual | Ad hoc | Depends on app code | Simple assistants |
| CrewAI | Role-based crew | Conversation centric | Team-like coordination | External plumbing | Mixed | Multi-agent workflows |
| AutoGen | Conversation network | Message threads | Flexible dialog | External plumbing | Varies by setup | Research and experiments |
| OpenAI Swarm | Lightweight orchestrator | Session-centric | Tool routing | Minimal by default | Light | Small agent prototypes |
The Middleware Stack Is the Real Product
The middleware stack is where the repo stops looking like a wrapper and starts looking like an architecture. The order is deliberate. patchToolCalls shapes requests before file access, filesystemMiddleware gives the agent durable working memory, subagentMiddleware isolates specialized work, and summarizationMiddleware keeps the whole thing from choking on its own history.
const agent = createDeepAgent({
model,
tools,
middleware: [
patchToolCalls(),
filesystemMiddleware(),
subagentMiddleware(),
summarizationMiddleware(),
],
});
// Order matters because each layer depends on the state
// produced by the layer before it.
| Middleware | What it changes | Why it exists |
|---|---|---|
| patchToolCalls | Normalizes tool invocations | Keeps the request shape predictable |
| filesystemMiddleware | Adds file read and write behavior | Turns files into working memory |
| subagentMiddleware | Enables recursive delegation | Prevents the main thread from becoming a junk drawer |
| summarizationMiddleware | Compresses long histories | Keeps context usable over time |
How Sub-Agents Make the System Deep
This is where the framework earns its name. A main agent can delegate to a sub-agent with a narrower job and a smaller context window, then collect the result back into the parent state. That keeps the main thread clean while letting specialized work happen in parallel or in sequence.
The practical effect is simple: the agent stops behaving like one overworked conversation and starts behaving like a team with compartments. Research can stay in one file set, implementation notes in another, and summaries can collapse the noise without losing the path back to the source.
Persistence Without Context Collapse
Under the hood, the backend protocol is what makes the filesystem more than a metaphor. The local filesystem backend and sandboxed execution path give the agent a durable place to read, write, search, and recover state. The code also leans into safety, with protections such as symlink-aware file handling instead of naive disk access.
That combination is what turns persistence into an engineering property. The agent can save large outputs, inspect them later, and keep moving even when a task gets too big for the immediate conversation. It is the difference between a session and a workspace.
| Capability | Shallow agent | deepagentsjs |
|---|---|---|
| Large output handling | Usually stays in chat | Can be written to files |
| Recovery | Manual and fragile | Structured and searchable |
| Long-running work | Context tends to drift | State survives through the filesystem |
| Safety | Often app-specific | Backend protocol plus file protections |
Why the Type System Matters
The TypeScript layer is not decoration. It is what lets middleware extend state without turning the developer experience into guesswork. If one layer adds a research field or a scratchpad, the merged agent type can carry that shape forward through the rest of the app.
type ResearchState = {
research: {
sources: string[];
notes: string[];
};
};
type AgentState = MergedDeepAgentState<BaseState, ResearchState>;
function addResearchMiddleware(agent: AgentState) {
agent.state.research.notes.push('Found a relevant source');
}
// The win is end-to-end autocomplete and fewer runtime surprises.
That sounds mundane until you compare it with ad hoc agent code, where every new tool or memory field can become a loose contract. Here, composition is typed. That makes the framework feel less like a demo kit and more like infrastructure.
How It Compares to Other Agent Frameworks
The useful comparison is not feature bingo. It is philosophy. Some frameworks optimize for flexible multi-agent conversation. Others optimize for orchestration. deepagentsjs optimizes for durable work with opinionated defaults that already assume files, summaries, and delegation.
| Framework | Mental model | What it optimizes for | Where it is less opinionated than deepagentsjs |
|---|---|---|---|
| deepagentsjs | Filesystem-backed agent harness | Durable, structured, long-running work | It is already opinionated about memory and delegation |
| CrewAI | Team of collaborating agents | Role coordination | You wire more of the workflow yourself |
| AutoGen | Conversational multi-agent system | Flexible agent interactions | Persistence and planning are less baked in |
| Swarm | Lightweight router for agents | Simple orchestration | Less of a full working-state model |
| Plain LangChain/LangGraph | Building blocks | General orchestration | You assemble the harness yourself |
That is why the best fit is narrow and strong. If you want a single-turn assistant, this is too much. If you want an agent that branches, persists, summarizes, and returns to work later, this is exactly the kind of abstraction you reach for.
What deepagentsjs Is Really For
The repo is not selling a smarter chatbot. It is selling a sane operating model for agents that have to do real work over time. Files hold memory. Middleware sets order. Sub-agents keep the parent clean. Types keep the composition honest.
That is the whole thesis. deepagentsjs is what happens when the agent problem is treated like software architecture instead of prompt decoration.