mirror of
https://github.com/langchain-ai/deepagentsjs.git
synced 2026-07-18 16:04:44 -04:00
Closed
opened 2026-06-05 17:22:36 -04:00 by yindo
·
0 comments
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
pull-request
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#310
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?
📋 Pull Request Information
Original PR: https://github.com/langchain-ai/deepagentsjs/pull/261
Author: @hntrl
Created: 3/1/2026
Status: ✅ Merged
Merged: 3/6/2026
Merged by: @hntrl
Base:
main← Head:hunter/repl📝 Commits (8)
819eaa3feat(quickjs): add @langchain/quickjs — sandboxed JS/TS REPL with PTC, env isolation, and RLM support82771d6chore: split changesets into quickjs minor + deepagents patchd7f76cfrefactor(quickjs): remove env/secrets, lazy runtime, buffered writes, fix thread_id propagation4c9c93fcr1d17979crece8a92docs(quickjs): add README and LICENSE, fix lint errors9cfed2ecr78dca5acr📊 Changes
26 files changed (+2834 additions, -18 deletions)
View changed files
➕
.changeset/deepagents-ptc-task.md(+7 -0)➕
.changeset/quickjs-repl.md(+10 -0)📝
examples/package.json(+3 -0)➕
examples/repl/data-analysis-agent.ts(+50 -0)➕
examples/repl/rlm-agent.ts(+105 -0)📝
libs/deepagents/src/index.ts(+1 -0)📝
libs/deepagents/src/middleware/subagents.ts(+18 -2)➕
libs/providers/quickjs/.npmignore(+13 -0)➕
libs/providers/quickjs/LICENSE(+21 -0)➕
libs/providers/quickjs/README.md(+166 -0)➕
libs/providers/quickjs/package.json(+87 -0)➕
libs/providers/quickjs/src/index.ts(+41 -0)➕
libs/providers/quickjs/src/middleware.int.test.ts(+59 -0)➕
libs/providers/quickjs/src/middleware.test.ts(+125 -0)➕
libs/providers/quickjs/src/middleware.ts(+281 -0)➕
libs/providers/quickjs/src/session.test.ts(+458 -0)➕
libs/providers/quickjs/src/session.ts(+413 -0)➕
libs/providers/quickjs/src/transform.test.ts(+115 -0)➕
libs/providers/quickjs/src/transform.ts(+276 -0)➕
libs/providers/quickjs/src/types.ts(+73 -0)...and 6 more files
📄 Description
Summary
Adds
@langchain/quickjs— a sandboxed JavaScript/TypeScript REPL tool for deepagents, powered by QuickJS-NG compiled to WASM via quickjs-emscripten.Motivation
LLMs are unreliable at arithmetic, data transformation, and multi-step logic. They hallucinate calculations, lose track of intermediate state, and can't natively express patterns like parallel fan-out or programmatic aggregation. The standard workaround — giving agents a code execution tool — traditionally requires either an unsandboxed Node.js
eval(a security nightmare) or a heavyweight container/VM.This PR introduces a third option: a WASM-sandboxed QuickJS interpreter that runs in-process with no network access, no filesystem access, and no Node.js APIs. The sandbox boundary is the WebAssembly memory model itself — guest code physically cannot reach host resources unless we explicitly bridge them in.
On top of this sandbox, there are two capabilities that make the REPL useful for deepagents:
1. Programmatic Tool Calling (PTC)
Any tool passed to a deepagents agent can be exposed inside the REPL as a typed async function. Instead of the LLM emitting tool calls one at a time through the standard request/response cycle, it writes code that calls tools directly — loops, conditionals, error handling, parallel execution, and result transformation all happen in code rather than in the LLM's attention.
As a specific carve-out of this pattern, PTC enables the Recursive Language Model (RLM) architecture: when the
tasktool is exposed inside the REPL, the LLM can spawn sub-agents in parallel viaPromise.all+tools.task(), collect their results, and aggregate programmatically — all within a singlejs_evalcall. This turns code into a control plane for multi-agent orchestration.PTC configuration is progressive:
false(off),true(all tools minus VFS defaults),string[](allowlist),{ include }/{ exclude }(fine-grained control).2. TypeScript Support & Cross-Eval State Persistence
LLMs naturally generate TypeScript (type annotations, interfaces,
ascasts). Rather than requiring the model to write pure JavaScript, we run an AST-based transform pipeline (acorn + estree-walker + magic-string) that strips TypeScript syntax, hoists top-level declarations toglobalThisfor persistence across evaluations, auto-returns the last expression, and wraps everything in an async IIFE.This means:
const data = await readFile("/data.json")in eval #1 →datais available in eval #2awaitworks naturallyChanges
New package:
@langchain/quickjs(libs/providers/quickjs/)types.tsQuickJSMiddlewareOptions,ReplSessionOptions,ReplResultsession.tsReplSession— lazy WASM runtime lifecycle, VFS bridge, console capture, PTC host functions, buffered writes, timeout management, serialization (toJSON/fromJSON)transform.tstransformForEval()— AST pipeline: strip TS → remove imports/exports → hoist declarations toglobalThis→ auto-return → async IIFE wrapmiddleware.tscreateQuickJSMiddleware()— agent integration: injectsjs_evaltool, assembles dynamic system prompt (base + auto-generated PTC type signatures), resolves backend per-threadutils.tstoCamelCase,formatReplResult,safeToJsonSchema,toolToTypeSignatureindex.ts68 unit tests across 4 test files + 1 integration test (session: 33, middleware: 9, transform: 16, utils: 10, integration: 1).
Key dependencies:
quickjs-emscripten,@jitl/quickjs-ng-wasmfile-release-asyncify(asyncify variant needed for async host functions),acorn,@sveltejs/acorn-typescript,estree-walker,magic-string,json-schema-to-typescript,dedent.deepagentscore changeslibs/deepagents/src/middleware/subagents.ts— Thetasktool previously threw if invoked without atoolCall.id(which is always absent in PTC context). Now it gracefully returns the sub-agent's last message as a plain string when called via PTC, and returns the normalCommandwith state update when called as a standard tool. This enables the RLM pattern —tools.task()inside the REPL returns the sub-agent's response directly to the calling code.libs/deepagents/src/index.ts— ExportsStateAndStoretype (needed by the middleware for backend resolution).Examples (
examples/repl/)data-analysis-agent.ts— Agent with QuickJS REPL for data analysis tasksrlm-agent.ts— Recursive Language Model example: PTC-enabled agent that spawns sub-agents inside the REPL viatools.task()+Promise.allArchitecture
Design Decisions
@jitl/quickjs-ng-wasmfile-release-asyncify— asyncify is required forevalCodeAsyncwhich enables async host functions (VFS reads, PTC tool calls). The-ngvariant uses QuickJS-NG (actively maintained fork).threadIdin a staticMap. This ensures REPL state persists across multiplejs_evalcalls within an agent thread while preventing cross-thread contamination..eval()call.ReplSession.getOrCreate()is synchronous — it returns a lightweight handle immediately. This makes sessions safe to create duringwrapModelCalland survive graph interrupts.writeFile()inside the sandbox pushes to apendingWritesarray synchronously. After eval, the caller flushes writes to the backend. This prevents partial writes from failed scripts and keeps the sandbox deterministic.wrapModelCallreceives aruntimeobject that is intentionally frozen to{context, writer, interrupt, signal}—configurable(withthread_id) is not exposed. Tool handlers receive the fullRunnableConfigincludingconfig.configurable.thread_id. Therefore session lookup/creation happens in thejs_evaltool handler.toJSON()/fromJSON()methods serialize only the session id — on restore,fromJSON()reconnects to the live runtime if it still exists, or creates a fresh session.executionTimeoutMsto a negative value disables both the CPU interrupt handler and the promise polling deadline, allowing unbounded execution for long-running PTC workflows.🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.