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.

9 min read • View on GitHub • More from langchain-ai

A command center built around a physical filesystem cabinet, with drawers for plans, research, tools, subagents, and summaries. It explains that the framework treats files as working memory, not as a side channel.
The core idea is not a smarter prompt. It is a working system where files, not chat history, hold the durable state.
Key Takeaways

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.

The framework’s signature move is ordering. Each middleware layer changes the request in a specific way, and that sequence is part of the product.

ApproachPrimary abstractionMemory modelDelegationPersistenceType safetyBest fit
deepagentsjsOpinionated harnessFilesystem-backed working stateBuilt-in sub-agentsNative, structuredStrong TypeScript inferenceDurable, multi-step work
Plain tool loopPrompt plus toolsChat historyManualAd hocDepends on app codeSimple assistants
CrewAIRole-based crewConversation centricTeam-like coordinationExternal plumbingMixedMulti-agent workflows
AutoGenConversation networkMessage threadsFlexible dialogExternal plumbingVaries by setupResearch and experiments
OpenAI SwarmLightweight orchestratorSession-centricTool routingMinimal by defaultLightSmall 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.

A close-up assembly line where a request passes through several stations in a fixed order, each one stamping, redirecting, or condensing it. It explains how middleware turns an agent loop into a deterministic pipeline.
The framework behaves less like a loose loop and more like a controlled factory line for requests and state.
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.
MiddlewareWhat it changesWhy it exists
patchToolCallsNormalizes tool invocationsKeeps the request shape predictable
filesystemMiddlewareAdds file read and write behaviorTurns files into working memory
subagentMiddlewareEnables recursive delegationPrevents the main thread from becoming a junk drawer
summarizationMiddlewareCompresses long historiesKeeps 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.

CapabilityShallow agentdeepagentsjs
Large output handlingUsually stays in chatCan be written to files
RecoveryManual and fragileStructured and searchable
Long-running workContext tends to driftState survives through the filesystem
SafetyOften app-specificBackend 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.

FrameworkMental modelWhat it optimizes forWhere it is less opinionated than deepagentsjs
deepagentsjsFilesystem-backed agent harnessDurable, structured, long-running workIt is already opinionated about memory and delegation
CrewAITeam of collaborating agentsRole coordinationYou wire more of the workflow yourself
AutoGenConversational multi-agent systemFlexible agent interactionsPersistence and planning are less baked in
SwarmLightweight router for agentsSimple orchestrationLess of a full working-state model
Plain LangChain/LangGraphBuilding blocksGeneral orchestrationYou 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.