Skip to content

feat(sdk,code,quickjs)!: make the ToDoListMiddleware list opt-in - #4929

Merged
ccurme (ccurme) merged 11 commits into
mainfrom
davibinboi/sdk/remove-todolist-middleware
Jul 23, 2026
Merged

feat(sdk,code,quickjs)!: make the ToDoListMiddleware list opt-in#4929
ccurme (ccurme) merged 11 commits into
mainfrom
davibinboi/sdk/remove-todolist-middleware

Conversation

@davibinboi

@davibinboi Shrikar Seshadri (davibinboi) commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Makes TodoListMiddleware opt-in instead of a built-in default in create_deep_agent.

Breaking Change

Agents built without explicitly passing TodoListMiddleware no longer expose the write_todos tool, the todos state channel, or the todo-planning prompt. To restore the previous behavior, pass middleware=[TodoListMiddleware()].

Why We're Making This Decision

We benchmarked TodoListMiddleware across GPT-5.6 Terra, Claude Opus 4.8, and GLM 5.2 on the Deep Agents evals suite. Results showed no statistically significant accuracy improvement on any model, while token usage increased on two of three models. Since there's no measurable accuracy benefit and a cost/complexity increase, this middleware shouldn't be on by default.

Model With todo micro avg@3 Without todo micro avg@3 Micro delta (no todo - todo) With todo macro avg@3 Without todo macro avg@3 Macro delta (no todo - todo) With todo cost/trial Without todo cost/trial Cost delta (todo - no todo) Result
GPT-5.6 Terra 25.5% 33.3% 7.8 pp 25.8% 35.2% 9.3 pp $0.585 $0.473 +$0.112 (+23.8%) No significant gain; no todo leads and is cheaper
Claude Opus 4.8 25.5% 26.5% 1.0 pp 22.3% 24.1% 1.8 pp $1.347 $1.510 -$0.163 (-10.8%) No significant gain; todo is cheaper, but slightly worse on avg@3
GLM 5.2 3.9% 5.9% 2.0 pp 3.0% 5.1% 2.1 pp $0.467 $0.464 +$0.003 (+0.7%) No significant gain; no todo leads and cost is effectively flat

What This PR Does

  • Removes the default TodoListMiddleware() from all three assembled middleware stacks: the main agent, the general-purpose subagent the model invokes, and the declarative subagents users instantiate. Removing it also drops the write_todos tool, the todos state channel, and the todo-planning prompt section.
  • Keeps the middleware fully opt-in: pass middleware=[TodoListMiddleware()] to create_deep_agent to restore it on the main agent.
  • Mirrors a main-agent opt-in onto the general-purpose subagent by matching the caller's exact instance by type and inserting it after the core tools, ahead of the profile/prompt-caching tail. If no opt-in is passed, neither stack includes TodoListMiddleware.
  • Declarative subagents opt in independently through their own spec's middleware and do not inherit the main-agent opt-in - this preserves existing isolation semantics.
  • Preserves todos for the OpenAI Codex profile via extra_middleware, since its system_prompt instructs the model to reconcile plan items via write_todos.

Tests

  • Full deepagents unit suite passes: 2367 passed, 100 skipped, 4 xfailed. make lint (ruff + format + ty) is clean.
  • Updated assert_all_deepagent_qualities (tests/utils.py) to stop asserting todos on default agents, and swapped a fake-model write_todos call in test_end_to_end.py for a file-listing one using the bounded ls command.
  • In test_graph.py: removed the now-obsolete TodoListMiddleware construction mocks, repurposed the exclusion test to assert that excluding a now-absent TodoListMiddleware raises the coverage error, and added new tests covering:
    • Default Deep Agent instantiation has no todos on either the main or general-purpose subagent
    • When the main agent gets TodoListMiddleware, the general-purpose subagent inherits it too
    • Declarative subagents do not inherit the main agent's opt-in
    • Profile extra_middleware todos appear in both the main agent and general-purpose subagent
  • Regenerated 14 smoke snapshots (7 prompt .md + 7 tool .json); the diff only removes the write_todos schema and the todo-planning prompt section.

Docs

Updated the create_deep_agent docstring: removed write_todos from the default tool list and base-stack ordering, and added a note explaining that todos are opt-in via middleware=[TodoListMiddleware()].

Remove `TodoListMiddleware` from the default main-agent, general-purpose
subagent, and declarative subagent stacks. Agents no longer receive the
`write_todos` tool, the `todos` state channel, or todo prompt text unless
the caller opts in via `middleware=[TodoListMiddleware()]`.

A caller-supplied instance on the main agent is mirrored onto the auto
general-purpose subagent (matched by type, inserted after the core tools
and ahead of the caching tail) so the two share a todo list. Declarative
subagents opt in through their own spec's `middleware` and do not inherit
the main-agent opt-in. The OpenAI Codex profile re-adds it via
`extra_middleware` since its system prompt references `write_todos`.

Benchmarking found no statistically significant accuracy improvement from
`TodoListMiddleware` and higher token usage on two of three models. No
public signatures, exports, or serialization formats change.

BREAKING CHANGE: agents built without passing `TodoListMiddleware` no
longer expose the `write_todos` tool, the `todos` state channel, or the
todo-planning prompt section. Pass `middleware=[TodoListMiddleware()]` to
restore the previous default.
@github-actions github-actions Bot changed the title feat(deepagents)!: make the todo list opt-in feat(sdk)!: make the todo list opt-in Jul 22, 2026
@github-actions github-actions Bot added breaking Breaking change! deepagents Related to the `deepagents` SDK / agent harness feature New feature/enhancement or request for one internal User is a member of the `langchain-ai` GitHub organization size: L 500-999 LOC labels Jul 22, 2026
@davibinboi Shrikar Seshadri (davibinboi) changed the title feat(sdk)!: make the todo list opt-in feat(sdk): make ToDoListMiddleware opt-in for SDK Users Jul 22, 2026
@github-actions github-actions Bot removed the breaking Breaking change! label Jul 22, 2026

@open-swe open-swe Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Open SWE Review found 1 potential issue.

Open in WebView Open SWE trace

Comment thread libs/deepagents/deepagents/graph.py
Regenerate the SDK smoke snapshot added on main
(`system_prompt_with_read_file_only`) and the quickjs prompt snapshots
so they no longer contain the `write_todos` tool now that the todo list
is opt-in.
@github-actions github-actions Bot added the quickjs QuickJS sandbox partner package label Jul 22, 2026
@davibinboi Shrikar Seshadri (davibinboi) changed the title feat(sdk): make ToDoListMiddleware opt-in for SDK Users feat(deepagents,quickjs)!: make the todo list opt-in Jul 22, 2026
@github-actions github-actions Bot changed the title feat(deepagents,quickjs)!: make the todo list opt-in feat(sdk,quickjs)!: make the todo list opt-in Jul 22, 2026
@github-actions github-actions Bot added the breaking Breaking change! label Jul 22, 2026
The mirror only shares the `write_todos` tool with the general-purpose
subagent; the `todos` state is isolated per subagent, so each keeps its
own list.
…-todolist-middleware

# Conflicts:
#	libs/partners/quickjs/uv.lock
@davibinboi Shrikar Seshadri (davibinboi) changed the title feat(sdk,quickjs)!: make the todo list opt-in feat(sdk,quickjs)!: make the ToDoListMiddleware list opt-in Jul 22, 2026
Comment thread libs/deepagents/deepagents/graph.py Outdated

@mdrxy Mason Daugherty (mdrxy) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's move # Breaking changes section in description to the top

…-todolist-middleware

# Conflicts:
#	libs/deepagents/deepagents/graph.py
#	libs/deepagents/tests/unit_tests/smoke_tests/snapshots/custom_system_message.md
#	libs/deepagents/tests/unit_tests/smoke_tests/snapshots/system_prompt_with_execute.md
#	libs/deepagents/tests/unit_tests/smoke_tests/snapshots/system_prompt_with_memory_and_skills.md
#	libs/deepagents/tests/unit_tests/smoke_tests/snapshots/system_prompt_with_read_file_only.md
#	libs/deepagents/tests/unit_tests/smoke_tests/snapshots/system_prompt_with_routed_backend.md
#	libs/deepagents/tests/unit_tests/smoke_tests/snapshots/system_prompt_with_sandbox_default.md
#	libs/deepagents/tests/unit_tests/smoke_tests/snapshots/system_prompt_with_sync_and_async_subagents.md
#	libs/deepagents/tests/unit_tests/smoke_tests/snapshots/system_prompt_without_execute.md
#	libs/partners/quickjs/tests/unit_tests/smoke_tests/snapshots/quickjs_system_prompt_mixed_foreign_functions.md
#	libs/partners/quickjs/tests/unit_tests/smoke_tests/snapshots/quickjs_system_prompt_mixed_foreign_functions_call.md
#	libs/partners/quickjs/tests/unit_tests/smoke_tests/snapshots/quickjs_system_prompt_mixed_foreign_functions_turn.md
#	libs/partners/quickjs/tests/unit_tests/smoke_tests/snapshots/quickjs_system_prompt_no_tools.md
#	libs/partners/quickjs/tests/unit_tests/smoke_tests/snapshots/quickjs_system_prompt_no_tools_call.md
#	libs/partners/quickjs/tests/unit_tests/smoke_tests/snapshots/quickjs_system_prompt_no_tools_turn.md
@github-actions github-actions Bot added the dcode Related to `deepagents-code` label Jul 23, 2026
@ccurme ccurme (ccurme) changed the title feat(sdk,quickjs)!: make the ToDoListMiddleware list opt-in feat(sdk,code,quickjs)!: make the ToDoListMiddleware list opt-in Jul 23, 2026
@ccurme
ccurme (ccurme) merged commit 9340518 into main Jul 23, 2026
71 checks passed
@ccurme
ccurme (ccurme) deleted the davibinboi/sdk/remove-todolist-middleware branch July 23, 2026 14:35
Nick Hollon (nick-hollon-lc) added a commit that referenced this pull request Jul 23, 2026
…re PR]

Isolates strange unified-eval scores by re-enabling the write_todos
default that #4929 made opt-in, alongside the trimmed tool descriptions.
Revert before opening the PR.
Nick Hollon (nick-hollon-lc) pushed a commit that referenced this pull request Jul 23, 2026
…ty-prompt]

Stacks main's #4929 todo removal on top of the empty-prompt state, so this
branch = empty system prompt + no write_todos, progressively transforming
canonical toward main. Isolates whether todo removal (in the empty-prompt
context) drives the regression. Throwaway diagnostic branch.
Mason Daugherty (mdrxy) added a commit that referenced this pull request Jul 24, 2026
Pins the next `deepagents-code` release at `0.1.46` so release-please
stops treating #4929's breaking `!` as a `0.2.0` cut for code.

---

`#4929` landed as `feat(sdk,code,quickjs)!…`, and pre-1.0 minor-on-break
policy rewrote [release PR
#4965](#4965) to `0.2.0`.
This temporary `"release-as": "0.1.46"` override on the code package
forces the next code release back onto the `0.1.x` line without changing
the SDK bump path.

Remove this key in a follow-up immediately after release-please rewrites
#4965 to `0.1.46`, or every later code release will stay pinned.
Mason Daugherty (mdrxy) added a commit that referenced this pull request Jul 27, 2026
Removes a dead prompt template that dcode no longer references.

Since `deepagents==0.7.0b2` made `ToDoListMiddleware` opt-in, dcode
stopped injecting the todo-list prompt (`#4929`). The
`todo_list_prompt.md` template was left behind with no remaining
references in code or tests, yet it is still packaged into the wheel
through the `deepagents_code/**/*.md` include. This deletes the orphaned
artifact.

Scoped narrowly to the dead file only. The remaining `write_todos`
rendering/compatibility code in the TUI is intentionally kept so
persisted threads and plugin-provided tools still display correctly.

This came out of a broader audit of dcode against the v0.7 release
notes; the larger prompt/profile simplifications flagged there are
behavioral and better handled as separate, eval-backed PRs.

Made by [Open
SWE](https://openswe.vercel.app/agents/0b8e4f55-532f-45a9-5caa-784572d4b951)

## References
- Plan:
https://openswe.vercel.app/agents/0b8e4f55-532f-45a9-5caa-784572d4b951/plan

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Mason Daugherty (mdrxy) added a commit that referenced this pull request Jul 29, 2026
> [!CAUTION]
> Merging this PR will automatically publish to **PyPI** and create a
**GitHub release**.

For the full release process, see
[`.github/RELEASING.md`](https://github.com/langchain-ai/deepagents/blob/main/.github/RELEASING.md).

---

_Release notes preview: keep this section in sync with the package
`CHANGELOG.md`. Publish reads the merged CHANGELOG via `release.yml`,
not this PR description — keep them aligned anyway so the PR stays an
accurate historical record for reviewers and anyone returning later._

---


##
[0.7.0](deepagents==0.6.12...deepagents==0.7.0)
(2026-07-29)

See [the
docs](https://docs.langchain.com/oss/python/releases/changelog#deepagents-v0-7-0)
for curated release notes.

### ⚠ BREAKING CHANGES

* `create_deep_agent` no longer includes `TodoListMiddleware` by
default, the `write_todos` tool, `todos` state channel, and
todo-planning prompt are now absent. Pass
`middleware=[TodoListMiddleware()]` to restore them on the main agent;
add it to each `SubAgent`'s middleware to restore them there.
([#4929](#4929))
([9340518](9340518))
* Default agent prompts are now lean: the authored base prompt is empty,
and tool-usage prose that duplicates tool schemas is trimmed.
`BASE_AGENT_PROMPT` is deprecated (removal in `deepagents==0.9.0`) but
remains importable and still returns the previous authored prompt
verbatim; pass it as
`create_deep_agent(system_prompt=BASE_AGENT_PROMPT)` to restore the old
behavior.
([#4859](#4859))
([#4979](#4979))
([a8d1b32](a8d1b32))
([d9f54fc](d9f54fc))
* The built-in tool-usage prompt constants `TASK_SYSTEM_PROMPT`,
`ASYNC_TASK_SYSTEM_PROMPT`, `SUMMARIZATION_SYSTEM_PROMPT`,
`FILESYSTEM_SYSTEM_PROMPT`, and `EXECUTION_SYSTEM_PROMPT` are removed,
and the `system_prompt` default on `SubAgentMiddleware`,
`AsyncSubAgentMiddleware`, `SummarizationToolMiddleware`, and
`create_summarization_tool_middleware` is now `None`, which injects no
prose. Pass your own string to restore prompt text.
([#4859](#4859))
([a8d1b32](a8d1b32))
* `FilesystemBackend` and `LocalShellBackend` now default to
`virtual_mode=True`. Filesystem paths are anchored under `root_dir`,
`..` traversal is rejected, and paths resolving outside `root_dir` raise
`ValueError`. Previously an unspecified `virtual_mode` emitted a
deprecation warning and fell back to `False`, where absolute host paths
were used as-is and `..` could escape `root_dir`. Pass
`virtual_mode=False` explicitly to restore the old filesystem behavior.
([#4541](#4541))
([540a0fa](540a0fa))
* Agents now see a destructive, recursive `delete` filesystem tool
whenever the backend supports it, and filesystem permissions classify
`delete` as a write operation — so an existing rule allowing writes to a
path also authorizes recursively deleting that subtree unless a narrower
deny or interrupt rule covers the target. Because recursive deletes
affect descendants, deny and interrupt checks use bulk path overlap
instead of exact-path matching. To keep the previous behavior, add a
deny or interrupt rule, or omit `delete` from
`FilesystemMiddleware(tools=...)`. Missing paths return a not-found
error, `CompositeBackend` reports an unsupported-operation error when a
routed sub-backend cannot delete, and the tool is hidden from the model
entirely when the backend itself does not implement it.
([#3659](#3659))
([#3691](#3691))
([#3765](#3765))
([#3851](#3851))
([f2a21ec](f2a21ec))
* `write_file` can now create a file if it is missing and replaces it
entirely if it already exists, instead of returning a file-exists error.
The `write_file` tool description no longer requires reading the file
first. There is no "create-only" compatibility mode. Workflows, prompts,
tests, or guardrails that relied on the file-exists error to force
`edit_file` usage or to protect existing content must omit `write_file`,
add explicit permission or interrupt rules, or use `edit_file` where
preserving existing content matters.
([#4109](#4109))
([2506fcc](2506fcc))
* Removed deprecated backend compatibility shims. Callers must pass
concrete `BackendProtocol` instances (not factories), configure
`StoreBackend` with an explicit `namespace`, and use the current `ls` /
`glob` / `grep` / `ReadResult` APIs.
([#4541](#4541))
([540a0fa](540a0fa))
* The deprecated `files_update` attribute and constructor keyword are
removed from `WriteResult` and `EditResult`. Custom backends must stop
passing `files_update=`, and callers must stop reading
`result.files_update`; state writes are emitted directly by
`StateBackend`.
([#4541](#4541))
([540a0fa](540a0fa))
* Removed the deprecated `BackendProtocol` methods `ls_info`,
`als_info`, `glob_info`, `aglob_info`, `grep_raw`, and `agrep_raw`. Use
`ls` / `glob` / `grep` and their async counterparts.
([#4541](#4541))
([540a0fa](540a0fa))
* `SummarizationMiddleware(history_path_prefix=...)` was removed and now
raises `TypeError`. Configure `CompositeBackend(artifacts_root=...)`
instead.
([#4541](#4541))
([540a0fa](540a0fa))
* Agent-facing `ls` and `glob` tool output now renders empty results as
`No files found` instead of `[]`; direct backend APIs continue to return
structured empty `LsResult` and `GlobResult` values. Callers that parse
tool output should update those checks.
([#3709](#3709))
([efafd1e](efafd1e))
* `read_file` no longer renders raw text with a fixed-width `cat
-n`-style line-number gutter and tab separator. Line and continuation
markers are dynamically aligned and separated from source content by two
spaces, and the `LINE_NUMBER_WIDTH` constant is removed from
`deepagents.backends.utils` and `deepagents.middleware.filesystem`.
Callers that parse raw tool output should update those parsers.
([#4561](#4561))
([cf057b4](cf057b4))

### Features

* Custom middleware passed to `create_deep_agent(..., middleware=[...])`
can replace a default middleware instance when `.name` matches, so
defaults such as `SummarizationMiddleware` can be overridden without
also excluding the built-in instance.
([#4251](#4251))
([90c8472](90c8472))
* `FilesystemMiddleware(tools=[...])` accepts a keyword-only allowlist
of built-in filesystem tools, typed by the newly exported `FsToolName`
literal (`"ls"`, `"read_file"`, `"write_file"`, `"edit_file"`,
`"delete"`, `"glob"`, `"grep"`, `"execute"`); pass `"all"` or omit the
argument to keep every tool. A list must include `"read_file"` or the
constructor raises `ValueError`. Omitted built-in tools are
non-executable, and custom user tools are unaffected.
([#4325](#4325))
([#4698](#4698))
([704a70d](704a70d))
([9709525](9709525))
* Shorten LLM-facing descriptions for the `task` tool and filesystem
tools (`read_file`, `grep`, `edit_file`, `glob`, `execute`).
([#5009](#5009))
([761f5f0](761f5f0))
* `GrepResult` and `GlobResult` now carry a `truncated` flag so
supporting backends can return valid partial results when a match cap or
backend deadline is reached; agent-facing tool output adds a note
telling the model to narrow the search. `FilesystemBackend` returns
partial `grep` and `glob` results on its backend timeout rather than
erroring, while other backend or middleware timeouts may still return
errors. Its `glob` also gains brace expansion such as `*.{py,md}`
(already supported by the state and store backends).
([#4063](#4063))
([ef591e7](ef591e7))
* The agent-facing `grep` match cap is configurable:
`FilesystemMiddleware(grep_max_count=...)` sets the default (`1000`;
`None` disables it) and the model can override it per call through the
tool's new `max_count` argument. `grep` / `agrep` on `BackendProtocol`
and all built-in backends accept a keyword-only `max_count`. Local
ripgrep output is streamed and terminated once the cap is reached.
Direct `FilesystemBackend.grep()` callers can request surrounding lines
with keyword-only `context_lines`.
([#4570](#4570))
([#4706](#4706))
([8e86f5e](8e86f5e))
([65230df](65230df))
* Paginated built-in `read_file` responses report the returned
source-line range and next `offset`; total and remaining line counts are
included when the backend knows the file length. Resume offsets remain
safe when sandbox or middleware limits shorten the visible page.
([#4540](#4540))
([8321194](8321194))
* Optional video frame extraction for `read_file`, enabled by the new
`deepagents[video]` extra. Video files are sampled into JPEG frames,
with `offset` and `limit` interpreted as seconds. Without the extra,
existing generic video/file content-block behavior remains.
([#4094](#4094))
([b927147](b927147))
* `FilesystemMiddleware` can capture oversized `execute` tool output
directly inside the sandbox artifact path on compatible, opted-in
`BaseSandbox` implementations to reduce round trips; `LangSmithSandbox`
opts in by default.
([#4230](#4230))
([02f5bd7](02f5bd7))
* Automatically enable Fireworks prompt-cache session affinity when a
compatible `langchain-fireworks` installation is available.
([#4598](#4598))
([5d878bf](5d878bf))
* Add a built-in NVIDIA Nemotron 3 Ultra harness profile and NVIDIA NIM
app-origin attribution.
([#4192](#4192))
([#4455](#4455))
([d5a60ec](d5a60ec))
([4cb4749](4cb4749))
* `RubricMiddleware` now accepts any positive `max_iterations` cap
instead of enforcing a hard upper bound.
([#4405](#4405))
([d6692a7](d6692a7))

### Bug Fixes

* Keep fields marked with `PrivateStateAttr`, including fields declared
through `create_deep_agent(state_schema=...)`, out of subagent inputs
and returned parent-state updates.
([#4587](#4587))
([a4662c0](a4662c0))
* Preserve `ContextT` through the `create_deep_agent(...,
middleware=[...])` type annotation so type checkers accept context-aware
middleware when a matching `context_schema` is passed.
([#4055](#4055))
([7be76c7](7be76c7))
* Accept YAML list values as well as comma-separated strings for skill
`allowed-tools` frontmatter, and make skill truncation warnings
actionable with field name, path, length, configured limit, and impact.
([#4140](#4140))
([#4141](#4141))
([d62534c](d62534c))
([2f5f5b8](2f5f5b8))
* Align filesystem instructions with the tools that remain after
allowlist and backend-capability filtering, so agents no longer
reference hidden `grep`/`glob` tools or prohibit equivalent shell search
when dedicated search tools are unavailable.
([#4920](#4920))
([#4921](#4921))
([d3650c7](d3650c7))
([b65cc00](b65cc00))
* Propagate default-backend failures from `CompositeBackend.ls("/")` and
`CompositeBackend.als("/")` instead of returning successful route-only
listings.
([#4925](#4925))
([4c3b166](4c3b166))
* Correct `CompositeBackend.glob` / `CompositeBackend.aglob` routing so
explicit default-backend paths such as `/tools` do not also return files
from routed backends such as `/memories`.
([#4531](#4531))
([cbdb0a7](cbdb0a7))
* Propagate default- and routed-backend failures from root
`CompositeBackend.glob(..., path=None)` / `aglob(..., path=None)` and
`path="/"` searches instead of returning incomplete successful results.
([#4063](#4063))
([ef591e7](ef591e7))
* Constrain sandbox `glob` and slash-pattern `grep` searches to their
declared search root by treating leading `/` as search-root-relative,
rejecting `..` traversal segments, and filtering symlink-resolved
matches outside the root.
([#4588](#4588))
([c6c7213](c6c7213))
* Unify `grep(..., glob=...)` include-glob semantics across filesystem
and in-memory backends: basename patterns like `*.py` match at any
depth, and slash-containing patterns like `src/**/*.py` match relative
paths consistently.
([#3936](#3936))
([feab6e0](feab6e0))
* Improve agent-facing `grep` descriptions and no-match hints to steer
regex-looking patterns toward literal searches, route slash-containing
sandbox include-globs correctly, and shorten default search timeouts so
bad patterns and huge trees return guidance faster.
([#4168](#4168))
([b1dbf5e](b1dbf5e))
* Align sandbox delete behavior with other backends by returning
not-found errors for missing paths, and avoid over-blocking unrelated
sibling deletes when deny rules use glob patterns.
([#4321](#4321))
([d77496b](d77496b))
* Improve rubric grader failure diagnostics with configured model,
structured-output strategy, and integer HTTP status when available.
([#4938](#4938))
([#4967](#4967))
([f51d3a0](f51d3a0))
([bca70aa](bca70aa))
* Emit `max_iterations_reached` as the terminal `RubricMiddleware`
status when the iteration cap is exhausted, instead of a final
`needs_revision` event that will not loop.
([#4406](#4406))
([a51c8d2](a51c8d2))
* Handle missing async subagent URLs consistently in `check_async_task`
and `cancel_async_task`.
([#3967](#3967))
([b0d92c0](b0d92c0))

### Performance Improvements

* Run LangSmith sandbox commands over the async client.
([#5061](#5061))
([0d08747](0d08747))

---

_End release notes preview._

---

> [!NOTE]
> A **New Contributors** section is appended to the GitHub release notes
automatically at publish time (see [Release
Pipeline](https://github.com/langchain-ai/deepagents/blob/main/.github/RELEASING.md#release-pipeline),
step 2).

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Mason Daugherty <github@mdrxy.com>
Marcelo5444 pushed a commit to Marcelo5444/deepagents that referenced this pull request Jul 30, 2026
Marcelo5444 pushed a commit to Marcelo5444/deepagents that referenced this pull request Jul 30, 2026
…ain-ai#5028)

Pins the next `deepagents-code` release at `0.1.46` so release-please
stops treating langchain-ai#4929's breaking `!` as a `0.2.0` cut for code.

---

`langchain-ai#4929` landed as `feat(sdk,code,quickjs)!…`, and pre-1.0 minor-on-break
policy rewrote [release PR
langchain-ai#4965](langchain-ai#4965) to `0.2.0`.
This temporary `"release-as": "0.1.46"` override on the code package
forces the next code release back onto the `0.1.x` line without changing
the SDK bump path.

Remove this key in a follow-up immediately after release-please rewrites
langchain-ai#4965 to `0.1.46`, or every later code release will stay pinned.
Marcelo5444 pushed a commit to Marcelo5444/deepagents that referenced this pull request Jul 30, 2026
Removes a dead prompt template that dcode no longer references.

Since `deepagents==0.7.0b2` made `ToDoListMiddleware` opt-in, dcode
stopped injecting the todo-list prompt (`langchain-ai#4929`). The
`todo_list_prompt.md` template was left behind with no remaining
references in code or tests, yet it is still packaged into the wheel
through the `deepagents_code/**/*.md` include. This deletes the orphaned
artifact.

Scoped narrowly to the dead file only. The remaining `write_todos`
rendering/compatibility code in the TUI is intentionally kept so
persisted threads and plugin-provided tools still display correctly.

This came out of a broader audit of dcode against the v0.7 release
notes; the larger prompt/profile simplifications flagged there are
behavioral and better handled as separate, eval-backed PRs.

Made by [Open
SWE](https://openswe.vercel.app/agents/0b8e4f55-532f-45a9-5caa-784572d4b951)

## References
- Plan:
https://openswe.vercel.app/agents/0b8e4f55-532f-45a9-5caa-784572d4b951/plan

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Marcelo5444 pushed a commit to Marcelo5444/deepagents that referenced this pull request Jul 30, 2026
> [!CAUTION]
> Merging this PR will automatically publish to **PyPI** and create a
**GitHub release**.

For the full release process, see
[`.github/RELEASING.md`](https://github.com/langchain-ai/deepagents/blob/main/.github/RELEASING.md).

---

_Release notes preview: keep this section in sync with the package
`CHANGELOG.md`. Publish reads the merged CHANGELOG via `release.yml`,
not this PR description — keep them aligned anyway so the PR stays an
accurate historical record for reviewers and anyone returning later._

---


##
[0.7.0](langchain-ai/deepagents@deepagents==0.6.12...deepagents==0.7.0)
(2026-07-29)

See [the
docs](https://docs.langchain.com/oss/python/releases/changelog#deepagents-v0-7-0)
for curated release notes.

### ⚠ BREAKING CHANGES

* `create_deep_agent` no longer includes `TodoListMiddleware` by
default, the `write_todos` tool, `todos` state channel, and
todo-planning prompt are now absent. Pass
`middleware=[TodoListMiddleware()]` to restore them on the main agent;
add it to each `SubAgent`'s middleware to restore them there.
([langchain-ai#4929](langchain-ai#4929))
([9340518](langchain-ai@9340518))
* Default agent prompts are now lean: the authored base prompt is empty,
and tool-usage prose that duplicates tool schemas is trimmed.
`BASE_AGENT_PROMPT` is deprecated (removal in `deepagents==0.9.0`) but
remains importable and still returns the previous authored prompt
verbatim; pass it as
`create_deep_agent(system_prompt=BASE_AGENT_PROMPT)` to restore the old
behavior.
([langchain-ai#4859](langchain-ai#4859))
([langchain-ai#4979](langchain-ai#4979))
([a8d1b32](langchain-ai@a8d1b32))
([d9f54fc](langchain-ai@d9f54fc))
* The built-in tool-usage prompt constants `TASK_SYSTEM_PROMPT`,
`ASYNC_TASK_SYSTEM_PROMPT`, `SUMMARIZATION_SYSTEM_PROMPT`,
`FILESYSTEM_SYSTEM_PROMPT`, and `EXECUTION_SYSTEM_PROMPT` are removed,
and the `system_prompt` default on `SubAgentMiddleware`,
`AsyncSubAgentMiddleware`, `SummarizationToolMiddleware`, and
`create_summarization_tool_middleware` is now `None`, which injects no
prose. Pass your own string to restore prompt text.
([langchain-ai#4859](langchain-ai#4859))
([a8d1b32](langchain-ai@a8d1b32))
* `FilesystemBackend` and `LocalShellBackend` now default to
`virtual_mode=True`. Filesystem paths are anchored under `root_dir`,
`..` traversal is rejected, and paths resolving outside `root_dir` raise
`ValueError`. Previously an unspecified `virtual_mode` emitted a
deprecation warning and fell back to `False`, where absolute host paths
were used as-is and `..` could escape `root_dir`. Pass
`virtual_mode=False` explicitly to restore the old filesystem behavior.
([langchain-ai#4541](langchain-ai#4541))
([540a0fa](langchain-ai@540a0fa))
* Agents now see a destructive, recursive `delete` filesystem tool
whenever the backend supports it, and filesystem permissions classify
`delete` as a write operation — so an existing rule allowing writes to a
path also authorizes recursively deleting that subtree unless a narrower
deny or interrupt rule covers the target. Because recursive deletes
affect descendants, deny and interrupt checks use bulk path overlap
instead of exact-path matching. To keep the previous behavior, add a
deny or interrupt rule, or omit `delete` from
`FilesystemMiddleware(tools=...)`. Missing paths return a not-found
error, `CompositeBackend` reports an unsupported-operation error when a
routed sub-backend cannot delete, and the tool is hidden from the model
entirely when the backend itself does not implement it.
([langchain-ai#3659](langchain-ai#3659))
([langchain-ai#3691](langchain-ai#3691))
([langchain-ai#3765](langchain-ai#3765))
([langchain-ai#3851](langchain-ai#3851))
([f2a21ec](langchain-ai@f2a21ec))
* `write_file` can now create a file if it is missing and replaces it
entirely if it already exists, instead of returning a file-exists error.
The `write_file` tool description no longer requires reading the file
first. There is no "create-only" compatibility mode. Workflows, prompts,
tests, or guardrails that relied on the file-exists error to force
`edit_file` usage or to protect existing content must omit `write_file`,
add explicit permission or interrupt rules, or use `edit_file` where
preserving existing content matters.
([langchain-ai#4109](langchain-ai#4109))
([2506fcc](langchain-ai@2506fcc))
* Removed deprecated backend compatibility shims. Callers must pass
concrete `BackendProtocol` instances (not factories), configure
`StoreBackend` with an explicit `namespace`, and use the current `ls` /
`glob` / `grep` / `ReadResult` APIs.
([langchain-ai#4541](langchain-ai#4541))
([540a0fa](langchain-ai@540a0fa))
* The deprecated `files_update` attribute and constructor keyword are
removed from `WriteResult` and `EditResult`. Custom backends must stop
passing `files_update=`, and callers must stop reading
`result.files_update`; state writes are emitted directly by
`StateBackend`.
([langchain-ai#4541](langchain-ai#4541))
([540a0fa](langchain-ai@540a0fa))
* Removed the deprecated `BackendProtocol` methods `ls_info`,
`als_info`, `glob_info`, `aglob_info`, `grep_raw`, and `agrep_raw`. Use
`ls` / `glob` / `grep` and their async counterparts.
([langchain-ai#4541](langchain-ai#4541))
([540a0fa](langchain-ai@540a0fa))
* `SummarizationMiddleware(history_path_prefix=...)` was removed and now
raises `TypeError`. Configure `CompositeBackend(artifacts_root=...)`
instead.
([langchain-ai#4541](langchain-ai#4541))
([540a0fa](langchain-ai@540a0fa))
* Agent-facing `ls` and `glob` tool output now renders empty results as
`No files found` instead of `[]`; direct backend APIs continue to return
structured empty `LsResult` and `GlobResult` values. Callers that parse
tool output should update those checks.
([langchain-ai#3709](langchain-ai#3709))
([efafd1e](langchain-ai@efafd1e))
* `read_file` no longer renders raw text with a fixed-width `cat
-n`-style line-number gutter and tab separator. Line and continuation
markers are dynamically aligned and separated from source content by two
spaces, and the `LINE_NUMBER_WIDTH` constant is removed from
`deepagents.backends.utils` and `deepagents.middleware.filesystem`.
Callers that parse raw tool output should update those parsers.
([langchain-ai#4561](langchain-ai#4561))
([cf057b4](langchain-ai@cf057b4))

### Features

* Custom middleware passed to `create_deep_agent(..., middleware=[...])`
can replace a default middleware instance when `.name` matches, so
defaults such as `SummarizationMiddleware` can be overridden without
also excluding the built-in instance.
([langchain-ai#4251](langchain-ai#4251))
([90c8472](langchain-ai@90c8472))
* `FilesystemMiddleware(tools=[...])` accepts a keyword-only allowlist
of built-in filesystem tools, typed by the newly exported `FsToolName`
literal (`"ls"`, `"read_file"`, `"write_file"`, `"edit_file"`,
`"delete"`, `"glob"`, `"grep"`, `"execute"`); pass `"all"` or omit the
argument to keep every tool. A list must include `"read_file"` or the
constructor raises `ValueError`. Omitted built-in tools are
non-executable, and custom user tools are unaffected.
([langchain-ai#4325](langchain-ai#4325))
([langchain-ai#4698](langchain-ai#4698))
([704a70d](langchain-ai@704a70d))
([9709525](langchain-ai@9709525))
* Shorten LLM-facing descriptions for the `task` tool and filesystem
tools (`read_file`, `grep`, `edit_file`, `glob`, `execute`).
([langchain-ai#5009](langchain-ai#5009))
([761f5f0](langchain-ai@761f5f0))
* `GrepResult` and `GlobResult` now carry a `truncated` flag so
supporting backends can return valid partial results when a match cap or
backend deadline is reached; agent-facing tool output adds a note
telling the model to narrow the search. `FilesystemBackend` returns
partial `grep` and `glob` results on its backend timeout rather than
erroring, while other backend or middleware timeouts may still return
errors. Its `glob` also gains brace expansion such as `*.{py,md}`
(already supported by the state and store backends).
([langchain-ai#4063](langchain-ai#4063))
([ef591e7](langchain-ai@ef591e7))
* The agent-facing `grep` match cap is configurable:
`FilesystemMiddleware(grep_max_count=...)` sets the default (`1000`;
`None` disables it) and the model can override it per call through the
tool's new `max_count` argument. `grep` / `agrep` on `BackendProtocol`
and all built-in backends accept a keyword-only `max_count`. Local
ripgrep output is streamed and terminated once the cap is reached.
Direct `FilesystemBackend.grep()` callers can request surrounding lines
with keyword-only `context_lines`.
([langchain-ai#4570](langchain-ai#4570))
([langchain-ai#4706](langchain-ai#4706))
([8e86f5e](langchain-ai@8e86f5e))
([65230df](langchain-ai@65230df))
* Paginated built-in `read_file` responses report the returned
source-line range and next `offset`; total and remaining line counts are
included when the backend knows the file length. Resume offsets remain
safe when sandbox or middleware limits shorten the visible page.
([langchain-ai#4540](langchain-ai#4540))
([8321194](langchain-ai@8321194))
* Optional video frame extraction for `read_file`, enabled by the new
`deepagents[video]` extra. Video files are sampled into JPEG frames,
with `offset` and `limit` interpreted as seconds. Without the extra,
existing generic video/file content-block behavior remains.
([langchain-ai#4094](langchain-ai#4094))
([b927147](langchain-ai@b927147))
* `FilesystemMiddleware` can capture oversized `execute` tool output
directly inside the sandbox artifact path on compatible, opted-in
`BaseSandbox` implementations to reduce round trips; `LangSmithSandbox`
opts in by default.
([langchain-ai#4230](langchain-ai#4230))
([02f5bd7](langchain-ai@02f5bd7))
* Automatically enable Fireworks prompt-cache session affinity when a
compatible `langchain-fireworks` installation is available.
([langchain-ai#4598](langchain-ai#4598))
([5d878bf](langchain-ai@5d878bf))
* Add a built-in NVIDIA Nemotron 3 Ultra harness profile and NVIDIA NIM
app-origin attribution.
([langchain-ai#4192](langchain-ai#4192))
([langchain-ai#4455](langchain-ai#4455))
([d5a60ec](langchain-ai@d5a60ec))
([4cb4749](langchain-ai@4cb4749))
* `RubricMiddleware` now accepts any positive `max_iterations` cap
instead of enforcing a hard upper bound.
([langchain-ai#4405](langchain-ai#4405))
([d6692a7](langchain-ai@d6692a7))

### Bug Fixes

* Keep fields marked with `PrivateStateAttr`, including fields declared
through `create_deep_agent(state_schema=...)`, out of subagent inputs
and returned parent-state updates.
([langchain-ai#4587](langchain-ai#4587))
([a4662c0](langchain-ai@a4662c0))
* Preserve `ContextT` through the `create_deep_agent(...,
middleware=[...])` type annotation so type checkers accept context-aware
middleware when a matching `context_schema` is passed.
([langchain-ai#4055](langchain-ai#4055))
([7be76c7](langchain-ai@7be76c7))
* Accept YAML list values as well as comma-separated strings for skill
`allowed-tools` frontmatter, and make skill truncation warnings
actionable with field name, path, length, configured limit, and impact.
([langchain-ai#4140](langchain-ai#4140))
([langchain-ai#4141](langchain-ai#4141))
([d62534c](langchain-ai@d62534c))
([2f5f5b8](langchain-ai@2f5f5b8))
* Align filesystem instructions with the tools that remain after
allowlist and backend-capability filtering, so agents no longer
reference hidden `grep`/`glob` tools or prohibit equivalent shell search
when dedicated search tools are unavailable.
([langchain-ai#4920](langchain-ai#4920))
([langchain-ai#4921](langchain-ai#4921))
([d3650c7](langchain-ai@d3650c7))
([b65cc00](langchain-ai@b65cc00))
* Propagate default-backend failures from `CompositeBackend.ls("/")` and
`CompositeBackend.als("/")` instead of returning successful route-only
listings.
([langchain-ai#4925](langchain-ai#4925))
([4c3b166](langchain-ai@4c3b166))
* Correct `CompositeBackend.glob` / `CompositeBackend.aglob` routing so
explicit default-backend paths such as `/tools` do not also return files
from routed backends such as `/memories`.
([langchain-ai#4531](langchain-ai#4531))
([cbdb0a7](langchain-ai@cbdb0a7))
* Propagate default- and routed-backend failures from root
`CompositeBackend.glob(..., path=None)` / `aglob(..., path=None)` and
`path="/"` searches instead of returning incomplete successful results.
([langchain-ai#4063](langchain-ai#4063))
([ef591e7](langchain-ai@ef591e7))
* Constrain sandbox `glob` and slash-pattern `grep` searches to their
declared search root by treating leading `/` as search-root-relative,
rejecting `..` traversal segments, and filtering symlink-resolved
matches outside the root.
([langchain-ai#4588](langchain-ai#4588))
([c6c7213](langchain-ai@c6c7213))
* Unify `grep(..., glob=...)` include-glob semantics across filesystem
and in-memory backends: basename patterns like `*.py` match at any
depth, and slash-containing patterns like `src/**/*.py` match relative
paths consistently.
([langchain-ai#3936](langchain-ai#3936))
([feab6e0](langchain-ai@feab6e0))
* Improve agent-facing `grep` descriptions and no-match hints to steer
regex-looking patterns toward literal searches, route slash-containing
sandbox include-globs correctly, and shorten default search timeouts so
bad patterns and huge trees return guidance faster.
([langchain-ai#4168](langchain-ai#4168))
([b1dbf5e](langchain-ai@b1dbf5e))
* Align sandbox delete behavior with other backends by returning
not-found errors for missing paths, and avoid over-blocking unrelated
sibling deletes when deny rules use glob patterns.
([langchain-ai#4321](langchain-ai#4321))
([d77496b](langchain-ai@d77496b))
* Improve rubric grader failure diagnostics with configured model,
structured-output strategy, and integer HTTP status when available.
([langchain-ai#4938](langchain-ai#4938))
([langchain-ai#4967](langchain-ai#4967))
([f51d3a0](langchain-ai@f51d3a0))
([bca70aa](langchain-ai@bca70aa))
* Emit `max_iterations_reached` as the terminal `RubricMiddleware`
status when the iteration cap is exhausted, instead of a final
`needs_revision` event that will not loop.
([langchain-ai#4406](langchain-ai#4406))
([a51c8d2](langchain-ai@a51c8d2))
* Handle missing async subagent URLs consistently in `check_async_task`
and `cancel_async_task`.
([langchain-ai#3967](langchain-ai#3967))
([b0d92c0](langchain-ai@b0d92c0))

### Performance Improvements

* Run LangSmith sandbox commands over the async client.
([langchain-ai#5061](langchain-ai#5061))
([0d08747](langchain-ai@0d08747))

---

_End release notes preview._

---

> [!NOTE]
> A **New Contributors** section is appended to the GitHub release notes
automatically at publish time (see [Release
Pipeline](https://github.com/langchain-ai/deepagents/blob/main/.github/RELEASING.md#release-pipeline),
step 2).

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Mason Daugherty <github@mdrxy.com>
Mason Daugherty (mdrxy) added a commit that referenced this pull request Jul 30, 2026
> [!CAUTION]
> Merging this PR will automatically publish to **PyPI** and create a
**GitHub release**.

For the full release process, see
[`.github/RELEASING.md`](https://github.com/langchain-ai/deepagents/blob/main/.github/RELEASING.md).

---

_Release notes preview: keep this section in sync with the package
`CHANGELOG.md`. Publish reads the merged CHANGELOG via `release.yml`,
not this PR description — keep them aligned anyway so the PR stays an
accurate historical record for reviewers and anyone returning later._

---


##
[0.7.0](deepagents==0.6.12...deepagents==0.7.0)
(2026-07-29)

See [the
docs](https://docs.langchain.com/oss/python/releases/changelog#deepagents-v0-7-0)
for curated release notes.

### ⚠ BREAKING CHANGES

* `create_deep_agent` no longer includes `TodoListMiddleware` by
default, the `write_todos` tool, `todos` state channel, and
todo-planning prompt are now absent. Pass
`middleware=[TodoListMiddleware()]` to restore them on the main agent;
add it to each `SubAgent`'s middleware to restore them there.
([#4929](#4929))
([9340518](9340518))
* Default agent prompts are now lean: the authored base prompt is empty,
and tool-usage prose that duplicates tool schemas is trimmed.
`BASE_AGENT_PROMPT` is deprecated (removal in `deepagents==0.9.0`) but
remains importable and still returns the previous authored prompt
verbatim; pass it as
`create_deep_agent(system_prompt=BASE_AGENT_PROMPT)` to restore the old
behavior.
([#4859](#4859))
([#4979](#4979))
([a8d1b32](a8d1b32))
([d9f54fc](d9f54fc))
* The built-in tool-usage prompt constants `TASK_SYSTEM_PROMPT`,
`ASYNC_TASK_SYSTEM_PROMPT`, `SUMMARIZATION_SYSTEM_PROMPT`,
`FILESYSTEM_SYSTEM_PROMPT`, and `EXECUTION_SYSTEM_PROMPT` are removed,
and the `system_prompt` default on `SubAgentMiddleware`,
`AsyncSubAgentMiddleware`, `SummarizationToolMiddleware`, and
`create_summarization_tool_middleware` is now `None`, which injects no
prose. Pass your own string to restore prompt text.
([#4859](#4859))
([a8d1b32](a8d1b32))
* `FilesystemBackend` and `LocalShellBackend` now default to
`virtual_mode=True`. Filesystem paths are anchored under `root_dir`,
`..` traversal is rejected, and paths resolving outside `root_dir` raise
`ValueError`. Previously an unspecified `virtual_mode` emitted a
deprecation warning and fell back to `False`, where absolute host paths
were used as-is and `..` could escape `root_dir`. Pass
`virtual_mode=False` explicitly to restore the old filesystem behavior.
([#4541](#4541))
([540a0fa](540a0fa))
* Agents now see a destructive, recursive `delete` filesystem tool
whenever the backend supports it, and filesystem permissions classify
`delete` as a write operation — so an existing rule allowing writes to a
path also authorizes recursively deleting that subtree unless a narrower
deny or interrupt rule covers the target. Because recursive deletes
affect descendants, deny and interrupt checks use bulk path overlap
instead of exact-path matching. To keep the previous behavior, add a
deny or interrupt rule, or omit `delete` from
`FilesystemMiddleware(tools=...)`. Missing paths return a not-found
error, `CompositeBackend` reports an unsupported-operation error when a
routed sub-backend cannot delete, and the tool is hidden from the model
entirely when the backend itself does not implement it.
([#3659](#3659))
([#3691](#3691))
([#3765](#3765))
([#3851](#3851))
([f2a21ec](f2a21ec))
* `write_file` can now create a file if it is missing and replaces it
entirely if it already exists, instead of returning a file-exists error.
The `write_file` tool description no longer requires reading the file
first. There is no "create-only" compatibility mode. Workflows, prompts,
tests, or guardrails that relied on the file-exists error to force
`edit_file` usage or to protect existing content must omit `write_file`,
add explicit permission or interrupt rules, or use `edit_file` where
preserving existing content matters.
([#4109](#4109))
([2506fcc](2506fcc))
* Removed deprecated backend compatibility shims. Callers must pass
concrete `BackendProtocol` instances (not factories), configure
`StoreBackend` with an explicit `namespace`, and use the current `ls` /
`glob` / `grep` / `ReadResult` APIs.
([#4541](#4541))
([540a0fa](540a0fa))
* The deprecated `files_update` attribute and constructor keyword are
removed from `WriteResult` and `EditResult`. Custom backends must stop
passing `files_update=`, and callers must stop reading
`result.files_update`; state writes are emitted directly by
`StateBackend`.
([#4541](#4541))
([540a0fa](540a0fa))
* Removed the deprecated `BackendProtocol` methods `ls_info`,
`als_info`, `glob_info`, `aglob_info`, `grep_raw`, and `agrep_raw`. Use
`ls` / `glob` / `grep` and their async counterparts.
([#4541](#4541))
([540a0fa](540a0fa))
* `SummarizationMiddleware(history_path_prefix=...)` was removed and now
raises `TypeError`. Configure `CompositeBackend(artifacts_root=...)`
instead.
([#4541](#4541))
([540a0fa](540a0fa))
* Agent-facing `ls` and `glob` tool output now renders empty results as
`No files found` instead of `[]`; direct backend APIs continue to return
structured empty `LsResult` and `GlobResult` values. Callers that parse
tool output should update those checks.
([#3709](#3709))
([efafd1e](efafd1e))
* `read_file` no longer renders raw text with a fixed-width `cat
-n`-style line-number gutter and tab separator. Line and continuation
markers are dynamically aligned and separated from source content by two
spaces, and the `LINE_NUMBER_WIDTH` constant is removed from
`deepagents.backends.utils` and `deepagents.middleware.filesystem`.
Callers that parse raw tool output should update those parsers.
([#4561](#4561))
([cf057b4](cf057b4))

### Features

* Custom middleware passed to `create_deep_agent(..., middleware=[...])`
can replace a default middleware instance when `.name` matches, so
defaults such as `SummarizationMiddleware` can be overridden without
also excluding the built-in instance.
([#4251](#4251))
([90c8472](90c8472))
* `FilesystemMiddleware(tools=[...])` accepts a keyword-only allowlist
of built-in filesystem tools, typed by the newly exported `FsToolName`
literal (`"ls"`, `"read_file"`, `"write_file"`, `"edit_file"`,
`"delete"`, `"glob"`, `"grep"`, `"execute"`); pass `"all"` or omit the
argument to keep every tool. A list must include `"read_file"` or the
constructor raises `ValueError`. Omitted built-in tools are
non-executable, and custom user tools are unaffected.
([#4325](#4325))
([#4698](#4698))
([704a70d](704a70d))
([9709525](9709525))
* Shorten LLM-facing descriptions for the `task` tool and filesystem
tools (`read_file`, `grep`, `edit_file`, `glob`, `execute`).
([#5009](#5009))
([761f5f0](761f5f0))
* `GrepResult` and `GlobResult` now carry a `truncated` flag so
supporting backends can return valid partial results when a match cap or
backend deadline is reached; agent-facing tool output adds a note
telling the model to narrow the search. `FilesystemBackend` returns
partial `grep` and `glob` results on its backend timeout rather than
erroring, while other backend or middleware timeouts may still return
errors. Its `glob` also gains brace expansion such as `*.{py,md}`
(already supported by the state and store backends).
([#4063](#4063))
([ef591e7](ef591e7))
* The agent-facing `grep` match cap is configurable:
`FilesystemMiddleware(grep_max_count=...)` sets the default (`1000`;
`None` disables it) and the model can override it per call through the
tool's new `max_count` argument. `grep` / `agrep` on `BackendProtocol`
and all built-in backends accept a keyword-only `max_count`. Local
ripgrep output is streamed and terminated once the cap is reached.
Direct `FilesystemBackend.grep()` callers can request surrounding lines
with keyword-only `context_lines`.
([#4570](#4570))
([#4706](#4706))
([8e86f5e](8e86f5e))
([65230df](65230df))
* Paginated built-in `read_file` responses report the returned
source-line range and next `offset`; total and remaining line counts are
included when the backend knows the file length. Resume offsets remain
safe when sandbox or middleware limits shorten the visible page.
([#4540](#4540))
([8321194](8321194))
* Optional video frame extraction for `read_file`, enabled by the new
`deepagents[video]` extra. Video files are sampled into JPEG frames,
with `offset` and `limit` interpreted as seconds. Without the extra,
existing generic video/file content-block behavior remains.
([#4094](#4094))
([b927147](b927147))
* `FilesystemMiddleware` can capture oversized `execute` tool output
directly inside the sandbox artifact path on compatible, opted-in
`BaseSandbox` implementations to reduce round trips; `LangSmithSandbox`
opts in by default.
([#4230](#4230))
([02f5bd7](02f5bd7))
* Automatically enable Fireworks prompt-cache session affinity when a
compatible `langchain-fireworks` installation is available.
([#4598](#4598))
([5d878bf](5d878bf))
* Add a built-in NVIDIA Nemotron 3 Ultra harness profile and NVIDIA NIM
app-origin attribution.
([#4192](#4192))
([#4455](#4455))
([d5a60ec](d5a60ec))
([4cb4749](4cb4749))
* `RubricMiddleware` now accepts any positive `max_iterations` cap
instead of enforcing a hard upper bound.
([#4405](#4405))
([d6692a7](d6692a7))

### Bug Fixes

* Keep fields marked with `PrivateStateAttr`, including fields declared
through `create_deep_agent(state_schema=...)`, out of subagent inputs
and returned parent-state updates.
([#4587](#4587))
([a4662c0](a4662c0))
* Preserve `ContextT` through the `create_deep_agent(...,
middleware=[...])` type annotation so type checkers accept context-aware
middleware when a matching `context_schema` is passed.
([#4055](#4055))
([7be76c7](7be76c7))
* Accept YAML list values as well as comma-separated strings for skill
`allowed-tools` frontmatter, and make skill truncation warnings
actionable with field name, path, length, configured limit, and impact.
([#4140](#4140))
([#4141](#4141))
([d62534c](d62534c))
([2f5f5b8](2f5f5b8))
* Align filesystem instructions with the tools that remain after
allowlist and backend-capability filtering, so agents no longer
reference hidden `grep`/`glob` tools or prohibit equivalent shell search
when dedicated search tools are unavailable.
([#4920](#4920))
([#4921](#4921))
([d3650c7](d3650c7))
([b65cc00](b65cc00))
* Propagate default-backend failures from `CompositeBackend.ls("/")` and
`CompositeBackend.als("/")` instead of returning successful route-only
listings.
([#4925](#4925))
([4c3b166](4c3b166))
* Correct `CompositeBackend.glob` / `CompositeBackend.aglob` routing so
explicit default-backend paths such as `/tools` do not also return files
from routed backends such as `/memories`.
([#4531](#4531))
([cbdb0a7](cbdb0a7))
* Propagate default- and routed-backend failures from root
`CompositeBackend.glob(..., path=None)` / `aglob(..., path=None)` and
`path="/"` searches instead of returning incomplete successful results.
([#4063](#4063))
([ef591e7](ef591e7))
* Constrain sandbox `glob` and slash-pattern `grep` searches to their
declared search root by treating leading `/` as search-root-relative,
rejecting `..` traversal segments, and filtering symlink-resolved
matches outside the root.
([#4588](#4588))
([c6c7213](c6c7213))
* Unify `grep(..., glob=...)` include-glob semantics across filesystem
and in-memory backends: basename patterns like `*.py` match at any
depth, and slash-containing patterns like `src/**/*.py` match relative
paths consistently.
([#3936](#3936))
([feab6e0](feab6e0))
* Improve agent-facing `grep` descriptions and no-match hints to steer
regex-looking patterns toward literal searches, route slash-containing
sandbox include-globs correctly, and shorten default search timeouts so
bad patterns and huge trees return guidance faster.
([#4168](#4168))
([b1dbf5e](b1dbf5e))
* Align sandbox delete behavior with other backends by returning
not-found errors for missing paths, and avoid over-blocking unrelated
sibling deletes when deny rules use glob patterns.
([#4321](#4321))
([d77496b](d77496b))
* Improve rubric grader failure diagnostics with configured model,
structured-output strategy, and integer HTTP status when available.
([#4938](#4938))
([#4967](#4967))
([f51d3a0](f51d3a0))
([bca70aa](bca70aa))
* Emit `max_iterations_reached` as the terminal `RubricMiddleware`
status when the iteration cap is exhausted, instead of a final
`needs_revision` event that will not loop.
([#4406](#4406))
([a51c8d2](a51c8d2))
* Handle missing async subagent URLs consistently in `check_async_task`
and `cancel_async_task`.
([#3967](#3967))
([b0d92c0](b0d92c0))

### Performance Improvements

* Run LangSmith sandbox commands over the async client.
([#5061](#5061))
([0d08747](0d08747))

---

_End release notes preview._

---

> [!NOTE]
> A **New Contributors** section is appended to the GitHub release notes
automatically at publish time (see [Release
Pipeline](https://github.com/langchain-ai/deepagents/blob/main/.github/RELEASING.md#release-pipeline),
step 2).

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Mason Daugherty <github@mdrxy.com>
Mason Daugherty (mdrxy) pushed a commit that referenced this pull request Aug 24, 2026
…agent` (#5759)

Fixes #5753

---

#4929 removed the three `TodoListMiddleware(system_prompt="")`
instantiations and the corresponding import from `create_deep_agent`'s
assembly, but left behind the comment sentence describing that
middleware. This deletes just that sentence, as approved in #5753; the
rest of the comment block still accurately describes the trimmed-prompt
rationale for the filesystem/subagent middleware and the skills/memory
fragments, so it is kept as-is.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking Breaking change! dcode Related to `deepagents-code` deepagents Related to the `deepagents` SDK / agent harness feature New feature/enhancement or request for one internal User is a member of the `langchain-ai` GitHub organization quickjs QuickJS sandbox partner package size: L 500-999 LOC

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants