mirror of
https://github.com/langchain-ai/deepagentsjs.git
synced 2026-07-19 16:33:38 -04:00
[GH-ISSUE #225] StateBackend.write() needs overwrite support (or add an overwrite/writeOrCreate method) #47
Open
opened 2026-02-16 06:16:58 -05:00 by yindo
·
1 comment
No Branch/Tag Specified
main
dependabot/npm_and_yarn/patch-deps-updates-main-c0f001c0f6
dependabot/npm_and_yarn/major-deps-updates-main-b7ceb5d816
dependabot/npm_and_yarn/minor-deps-updates-main-f52a01c0f6
dependabot/github_actions/major-deps-updates-5c183d6ffa
dependabot/github_actions/minor-deps-updates-38afab4f4d
dependabot/github_actions/patch-deps-updates-00a0d7aaea
dependabot/docker/examples/async-subagent-server/major-deps-updates-docker-4faa477378
feat/delete-backend-protocol
feat/write-file-overwrites
feat/recursive-delete-tool
corridor/fix-1119d955-1783568785287
open-swe/bump-langsmith-0-8-0
alex/initializer
cb/connectors-spec-19bb
open-swe/fs-interrupt-permissions
sydney/oolong-ptc-runners
cb/fs-permissions-interrupt-9517
hunter/swarm-oolong-eval
colifran/swarm-eval
colifran/interp-libs
colifran/workflow-poc
colifran/swarm-sub-mw-defaults
hunter/fix-ci-read-file-mime-guard
fix/filesystem-glob-suppress-permission-errors
hunter/middleware-replace-by-name
hunter/fix-node-vfs-absolute-exec-paths
colifran/lazy-skills
cb/fix-subagent-stream-same-type-isolation
fix/acp-filesystem-virtual-mode
colifran/skill-dist
colifran/skill-cli
open-swe/9065a8d9-c0c3-5c29-b106-1a195b97ddbd
colifran/permissions
colifran/repl-swarm
hunter/quickjs-pending-write-reads
colifran/swarm-in-repl
jacob/subagents
jacob/subagenttype
open-swe/7460276d-5f03-10ca-8a53-7653699f1133
colifran/swarm-tool
hunter/fix-sandbox-find-follow-symlinks
open-swe/dfd00850-86b7-5f87-2c10-3bd968b1c75e
colifran/swarm-refactor
colifran/swarm-table
colifran/swarm
open-swe/8d89ab28-9b47-3a19-427b-aacfa4c5d099
open-swe/086c3d27-2ff0-ebf5-5d74-4d35e38083c5
open-swe/23f64c62-afe9-dc40-bbe0-c86a558611b3
hunter/namespace-factories
alpha
baseten-integration
colifran/deprecate-backend-factories
colifran/agent-protocol-poc
colifran/a2a-subagents
ci/add-codeql-scanning
colifran/async-example
colifran/async-subagents-example
1.9.0-alpha.1
colifran/backend-rename
hunter/js-queue-lookahead-middleware
cb/secure-exec
cb/pass-checkpointer
colifran/multimodal-refactor-pr2
structured-output-evals
subagent-structured-output
colifran/multimodal-refactor-pr1
cb/async-agents
hunter/repl-rlm
cb/ptc-repl-network-policy
cb/ptc-repl
cb/ptc
open-swe/020b364c-2a7f-e2b2-30e0-4593befd0490
add-evals
hunter/structured-output-eval
cb/composite-fix
hunter/async-subagents
hunter/relo-evals
cb/summarization-improvements
hunter/deepbash
harbor-evals
hunter/trace-metadata
hunter/integration
cb/langsmith-sandbox
isolate-agent-skills
hunter/batch-task
fix-memory-load-state
add-e2e-test
cb/add-streaming-example
copilot/fix-partial-file-updates
copilot/fix-file-state-loss
nh/release-1.0.0
dqbd/fs-store
hunter/v1
dqbd/js
cb/createAgent-migration
cb/repo-update
palash/add-built-in-toosl
palash/skip-tools
palash/add-interrupt-config
brace/bump-langgraph
open-swe/6f37e688-42f4-458b-a26a-9de18f1c5ab8
palash/post-model-hook
palash/add-local
palash/add-post-model-hook-interrupt
palash/final-touch-ups
palash/subagent-fix
palash/add-langgraph-server
palash/update-readme
palash/change-name-to-deepagents
palash/fix-anthropic-zod-import
brace/fixes
open-swe/8357536e-2207-4292-a24d-00ea431ed4d4
open-swe/9453f008-7578-458d-bb92-e729e9fca363
deepagents@1.11.1
deepagents-acp@0.1.20
deepagents@1.11.0
deepagents-acp@0.1.19
@langchain/node-vfs@0.2.1
deepagents@1.10.8
deepagents-acp@0.1.18
deepagents@1.10.7
deepagents-acp@0.1.17
deepagents@1.10.6
deepagents-acp@0.1.16
@langchain/quickjs@0.6.0
@langchain/modal@0.1.5
@langchain/daytona@0.2.1
deepagents@1.10.5
deepagents-acp@0.1.15
@langchain/quickjs@0.5.1
deepagents@1.10.4
deepagents-acp@0.1.14
@langchain/quickjs@0.5.0
@langchain/node-vfs@0.2.0
deepagents@1.10.2
deepagents-acp@0.1.12
deepagents@1.10.1
deepagents-acp@0.1.11
@langchain/quickjs@0.4.0
deepagents@1.10.0
deepagents-acp@0.1.10
@langchain/quickjs@0.3.0
deepagents@1.9.1
deepagents-acp@0.1.9
@langchain/quickjs@0.2.6
deepagents@1.9.0
deepagents-acp@0.1.8
@langchain/sandbox-standard-tests@1.0.0
@langchain/quickjs@0.2.5
@langchain/node-vfs@0.1.4
@langchain/modal@0.1.4
deepagents@1.9.0-alpha.1
deepagents-acp@0.1.8-alpha.0
@langchain/quickjs@0.2.5-alpha.0
@langchain/node-vfs@0.1.4-alpha.0
@langchain/modal@0.1.4-alpha.0
@langchain/deno@0.2.2-alpha.0
@langchain/daytona@0.2.0-alpha.0
deepagents@1.8.8
deepagents-acp@0.1.7
@langchain/quickjs@0.2.4
deepagents@1.8.7
deepagents-acp@0.1.6
@langchain/quickjs@0.2.3
@langchain/daytona@0.2.0
deepagents@1.8.6
deepagents-acp@0.1.5
@langchain/quickjs@0.2.2
@langchain/deno@0.2.2
deepagents@1.9.0-alpha.0
deepagents-acp@0.1.5-alpha.0
@langchain/sandbox-standard-tests@1.0.0-alpha.0
@langchain/quickjs@1.0.0-alpha.0
@langchain/node-vfs@1.0.0-alpha.0
@langchain/modal@1.0.0-alpha.0
@langchain/deno@1.0.0-alpha.0
@langchain/daytona@1.0.0-alpha.0
deepagents@1.8.5
deepagents-acp@0.1.4
@langchain/quickjs@0.2.1
@langchain/node-vfs@0.1.3
deepagents@1.8.3
deepagents-acp@0.1.2
deepagents-acp@0.1.0
deepagents@1.8.1
@langchain/modal@0.1.3
deepagents@1.8.0
@langchain/sandbox-standard-tests@0.1.0
@langchain/node-vfs@0.1.2
@langchain/deno@0.2.1
@langchain/daytona@0.1.2
deepagents@1.7.6
deepagents@1.7.5
deepagents@1.7.4
@langchain/deno@0.2.0
@langchain/deno@0.1.2
deepagents@1.7.3
deepagents@1.7.2
@langchain/modal@0.1.2
deepagents@1.7.1
@langchain/node-vfs@0.1.1
@langchain/modal@0.1.1
@langchain/deno@0.1.1
@langchain/daytona@0.1.1
deepagents@1.7.0
@langchain/node-vfs@0.1.0
@langchain/modal@0.1.0
@langchain/deno@0.1.0
@langchain/daytona@0.1.0
deepagents@1.6.3
deepagents@1.6.2
deepagents@1.6.1
deepagents@1.6.0
deepagents@1.5.1
deepagents@1.5.0
deepagents@1.4.2
deepagents@1.4.1
deepagents@1.4.0
v1.3.1
v1.3.0
v1.2.0
v1.1.1
v1.1.0
No Label
Milestone
No items
No Milestone
Projects
Clear projects
No project
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: langchain-ai/deepagentsjs#47
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @Amedzro-Elikplim on GitHub (Feb 12, 2026).
Original GitHub issue: https://github.com/langchain-ai/deepagentsjs/issues/225
Originally assigned to: @hntrl on GitHub.
Hey team, love the library — ran into a friction point with StateBackend.write() that I think others will hit
too.
Right now write() flat out refuses if the file already exists:
write(filePath, content) {
if (filePath in this.getFiles())
return { error:
Cannot write to ${filePath} because it already exists...};// ...
}
Which makes sense as a safety guard, but it becomes a real pain in multi-tool workflows where several tools
need to write to the same file across a graph execution.
What happens in practice
Say you have a pipeline like:
tool_A (writes /state.json) → tool_B (generates new data, needs to update /state.json) → tool_C (reads
/state.json)
tool_B's write() silently fails because tool_A already created the file. No error thrown, just a quiet {
error: "..." } return with no filesUpdate. If you're not explicitly checking for it (and honestly, who
expects a write to a file they own to fail?), downstream tools read stale data and things break in confusing
ways.
The workaround we found is chaining readRaw() + edit() with the entire file content as oldString:
const fileData = backend.readRaw(filePath);
const currentContent = fileData.content.join('\n');
const editResult = backend.edit(filePath, currentContent, newContent);
It works, but it feels wrong — we're using a surgical find-and-replace tool to do a full file overwrite. It's
like using sed to replace an entire file.
What would help
An overwrite flag on write():
write(filePath: string, content: string, overwrite?: boolean): WriteResult
When overwrite: true, skip the existence check — use updateFileData (preserving created_at) if the file
exists, createFileData if it doesn't. Default stays false so nothing breaks for existing users.
Or if you'd prefer to keep write() strict, a separate method would work just as well:
writeOrOverwrite(filePath: string, content: string): WriteResult
Why edit() isn't a great workaround
that's leaking internals
Why we can't just let the agent handle it
In a lot of real-world workflows, waiting for the agent LLM to write files is too slow and unreliable. When a
tool already has the exact data (parsed API response, generated content, synced DB state), writing it
directly from tool code is way faster and more predictable than:
This matters most for intermediate state files that downstream tools depend on — the write needs to be
deterministic inside the tool, not an optional LLM action. The current restriction pushes you toward either
accepting that overhead or hacking around it with readRaw() + edit().
Real-world example
We have an agent where:
This kind of iterative state-building across tools feels like a natural pattern for agentic workflows, and
having a clean way to overwrite files from tool code would make it a lot smoother.
StateBackend.write() needs overwrite support (or add an overwrite/writeOrCreate method)to [GH-ISSUE #225] StateBackend.write() needs overwrite support (or add an overwrite/writeOrCreate method)@christian-bromann commented on GitHub (Feb 23, 2026):
Thanks for raising the issue @Amedzro-Elikplim, great insights on the use case. We will take this to the team and discuss the best approach here. Will share more soon!