Skip to content

new StateBackend() crashes on write_file / edit_file, while (runtime) => new StateBackend(runtime) works #547

Description

Summary

Passing an explicit StateBackend instance to createDeepAgent() appears to break filesystem tool calls in some runtimes.

In my case, asking the agent to create a file causes a crash, but:

  • omitting backend entirely works
  • using a backend factory works: const backend = (runtime) => new StateBackend(runtime);

The docs/examples suggest new StateBackend() is valid, and some integrations (for example, interpreter with skillsBackend) benefit from sharing a backend reference explicitly.

Versions

  • deepagents: 1.10.2
  • @langchain/quickjs: 0.4.0
  • langchain: 1.4.x

Reproduction

Minimal shape:

import { createDeepAgent, StateBackend } from "deepagents";
const backend = new StateBackend();
const agent = createDeepAgent({
  model: "openai:gpt-5.4",
  backend,
});
const stream = await agent.streamEvents(undefined, {
  configurable: {
    thread_id: "thread-1",
  },
  version: "v3",
  context: {},
});

Then prompt the agent with something that triggers write_file, for example:

Create a file /notes.txt with the content hello

Actual behavior

The tool call fails with:

TypeError: Cannot read properties of undefined (reading 'configurable')
    at MiddlewareError.wrap (errors.js:77:10)
    at ToolNode.wrappedHandler [as wrapToolCall] (utils.js:393:67)
    at async ToolNode.runTool (ToolNode.js:265:11)
    at async ToolNode.run (ToolNode.js:300:15)
    at async ToolNode.invoke (RunnableCallable.js:40:23)
    at async RunnableSequence.invoke (base.js:973:69)
    at async _runWithRetry (retry.js:55:13)
    at async PregelRunner._executeTasksWithRetry (runner.js:148:24)
    at async PregelRunner.tick (runner.js:69:49)
    at async CompiledStateGraph._runLoop (index.js:1223:5)
Caused by: TypeError: Cannot read properties of undefined (reading 'configurable')
    at get files (index.js:657:81)
    at StateBackend.write (index.js:753:24)
    at Object.write (index.js:487:41)

Expected behavior

I’d expect one of these to be true:

  1. new StateBackend() should work correctly when passed explicitly to createDeepAgent(), or
  2. the docs/examples should clearly say that StateBackend must be passed as a factory:
    const backend = (runtime) => new StateBackend(runtime);

Right now the instance form and factory form are not equivalent in practice.

Workaround

This works reliably for me:

import { createDeepAgent, StateBackend } from "deepagents";
import { createCodeInterpreterMiddleware } from "@langchain/quickjs";
const backend = (runtime) => new StateBackend(runtime);
const agent = createDeepAgent({
  model: "openai:gpt-5.4",
  backend,
  skills: ["/skills/"],
  middleware: [createCodeInterpreterMiddleware({ skillsBackend: backend })],
});

Omitting backend also works, but that does not help when another middleware needs the same backend reference.

Possible cause

It looks like there are two different StateBackend code paths:

  • zero-arg instance mode: new StateBackend()
  • runtime-injected mode: new StateBackend(runtime)

The runtime-injected form works, while the zero-arg form eventually tries to read from getConfig().configurable and crashes because that config is undefined in this execution path.

So this seems like either:

  • a runtime bug in StateBackend zero-arg mode, or
  • a docs/API inconsistency where the instance form is presented as supported but is not actually safe in all runtimes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions