langchain-ai/deepagents · error · RuntimeError
StateBackend requires CONFIG_KEY_READ / CONFIG_KEY_SEND in t
Error message
StateBackend requires CONFIG_KEY_READ / CONFIG_KEY_SEND in the LangGraph config. Make sure the backend is used inside a graph node or tool, not called directly. To pre-populate files, pass them on invoke: agent.invoke({"messages": [...], "files": {...}}) What it means
`StateBackend` reads and writes the `files` channel through LangGraph Pregel internals using two reserved config keys (`CONFIG_KEY_READ` / `CONFIG_KEY_SEND`). `_get_config` raises this `RuntimeError` when a config exists but lacks these keys — i.e. the code is running inside LangChain but not inside a real graph node/tool where LangGraph injects them. It signals the backend is being called from a non-graph LangChain context such as a plain Runnable chain or direct tool invocation.
Source
Thrown at libs/deepagents/deepagents/backends/state.py:78
config = get_config()
except RuntimeError:
msg = (
"StateBackend must be used inside a LangGraph graph execution "
"(e.g. via create_deep_agent). It cannot read or write state "
"outside of a graph context. To pre-populate files, pass them "
'on invoke: agent.invoke({"messages": [...], "files": {...}})'
)
raise RuntimeError(msg) from None
configurable = config.get("configurable", {})
if CONFIG_KEY_READ not in configurable:
msg = (
"StateBackend requires CONFIG_KEY_READ / CONFIG_KEY_SEND in "
"the LangGraph config. Make sure the backend is used inside "
"a graph node or tool, not called directly. To pre-populate "
"files, pass them on invoke: "
'agent.invoke({"messages": [...], "files": {...}})'
)
raise RuntimeError(msg)
return config
def _read_files(self) -> dict[str, Any]:
"""Read the current `files` channel via Pregel internals.
Uses `CONFIG_KEY_READ` to read state directly — this lets us
initialize StateBackend once and fetch state on demand from any
graph context (tools, middleware nodes, etc.).
`fresh=True` applies any pending task writes through the channel's
reducer before returning, giving read-your-writes semantics within
a single superstep — e.g. a tool that writes a file and then reads
it back, or a code interpreter that issues multiple sub-tool calls
inside one eval.
"""
config = self._get_config()
read = config["configurable"][CONFIG_KEY_READ]
fresh = TrueView on GitHub (pinned to a1af029e6e)
Solutions
- Run the backend within a LangGraph graph node or tool (via `create_deep_agent`) so LangGraph injects CONFIG_KEY_READ/CONFIG_KEY_SEND
- In unit tests, use the repo's state-backend test fixtures that build a fake config containing both keys
- Pass files on invoke (`agent.invoke({'messages': [...], 'files': {...}})`) instead of touching the backend directly
- Use a non-state backend if you need standalone file I/O
Example fix
// before
backend = StateBackend()
backend.read(['/a.txt'], config={'configurable': {}}) # RuntimeError
// after
agent = create_deep_agent(backend=StateBackend(), tools=[...])
result = agent.invoke({'messages': [{'role': 'user', 'content': 'read /a.txt'}]}) Defensive patterns
Strategy: validation
Validate before calling
def config_has_state_keys(config) -> bool:
conf = (config or {}).get('configurable', {})
return CONFIG_KEY_READ in conf and CONFIG_KEY_SEND in conf
if not config_has_state_keys(config):
raise RuntimeError('StateBackend used outside a graph node') Try / catch
try:
files = backend._read_files()
except RuntimeError as e:
if 'CONFIG_KEY_READ' in str(e):
logger.error('StateBackend called outside a graph node; restructure the call')
raise Prevention
- Invoke the backend only from within LangGraph nodes/tools created via create_deep_agent
- In tests, use the repo's fake-config fixtures that inject CONFIG_KEY_READ/CONFIG_KEY_SEND
- Don't hand-construct configs for StateBackend; let LangGraph supply them
- Never assume a RunnableConfig implies graph context — check the keys
When it happens
Trigger: Calling StateBackend methods from a runnable/chain without LangGraph's Pregel runtime; invoking a tool that uses the backend outside a graph node; constructing a config dict manually without the CONFIG_KEY_READ/CONFIG_KEY_SEND entries.
Common situations: Migrating tools from plain LangChain to deep agents; testing with `config={'configurable': {}}` that looks plausible but lacks the internals; wrapping backend calls in background tasks that drop the injected config.
Related errors
- StateBackend must be used inside a LangGraph graph execution
- modes can only be provided when agent is a factory
- models can only be provided when agent is a factory
- -32601
- -32002
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/f3a22df038f3db81.
Report an issue: GitHub.