feat(sdk): add total match cap and streaming to grep - #4570
Merged
Conversation
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Add max_count to the grep/agrep protocol and stream the local ripgrep path via Popen, terminating early once the total match cap is reached. Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Default the grep tool to a 1000-match cap, overridable per call via a new max_count argument, and generalize the truncation note to cover the cap. Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Move the max_count doc into the grep Args section, satisfy the type checker on the streamed ripgrep stdout, and let composite test doubles accept the new keyword. Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Mason Daugherty (mdrxy)
marked this pull request as ready for review
July 8, 2026 20:20
This was referenced Jul 10, 2026
Member
Author
|
TODO after #4541 merges: rebase this PR and remove the |
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
Closes langchain-ai#2834 `FilesystemMiddleware`'s `grep` tool now returns at most **1000 matches by default** (previously unbounded). When the cap is hit, results are truncated and a note tells the model to narrow the search or raise `max_count`. This bounds memory and context size on very large repositories. - The model can raise or lower the cap per call via the new `max_count` argument on the `grep` tool. - To restore the previous unbounded behavior, construct `FilesystemMiddleware(..., grep_max_count=None)`. - Direct backend callers (`backend.grep(...)`) are unaffected: `max_count` defaults to `None` (no cap) unless explicitly passed. --- Deep Agents' filesystem `grep` was already timeout-bounded, but it could still buffer an unbounded number of matches: the local ripgrep path ran `subprocess.run(capture_output=True)`, so a broad pattern on a huge repo (e.g. the Linux kernel) could buffer gigabytes of stdout before the tool layer got a chance to truncate, risking OOM. This adds a total-match cap and makes the local ripgrep path stream: - New keyword-only `max_count: int | None = None` on `BackendProtocol.grep`/`agrep` and every backend implementation (`filesystem`, `state`, `store`, `sandbox`, `composite`, `context_hub`). It is a total cap across all files, not per-file. Defaulting to `None` keeps existing direct-backend behavior unchanged. - `LocalFilesystemBackend` now streams ripgrep's `--json` output via `subprocess.Popen` line-by-line, stops and `terminate()`s the process once the cap is reached, and passes `-m` as a cheap secondary per-file guard. A `threading.Timer` watchdog preserves the existing time-limit behavior. The Python fallback early-returns at the cap. - `CompositeBackend` enforces the cap globally across routed backends, short-circuiting remaining routes once it is met. - `GrepResult.truncated` (already present) is set when the cap is hit, and `FilesystemMiddleware` gains a `grep_max_count` default of `1000` (configurable, and overridable per call via the tool's `max_count` argument). The truncation note shown to the model now covers both the time-limit and match-cap cases. Reviewers may want to focus on the rewritten `_ripgrep_search` streaming/termination/watchdog logic and the composite cross-route budget accounting. Made by [Open SWE](https://openswe.vercel.app/agents/389434e7-284f-e1ff-11ba-8c65c21683af) --------- 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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #2834
FilesystemMiddleware'sgreptool now returns at most 1000 matches by default (previously unbounded). When the cap is hit, results are truncated and a note tells the model to narrow the search or raisemax_count. This bounds memory and context size on very large repositories.max_countargument on thegreptool.FilesystemMiddleware(..., grep_max_count=None).backend.grep(...)) are unaffected:max_countdefaults toNone(no cap) unless explicitly passed.Deep Agents' filesystem
grepwas already timeout-bounded, but it could still buffer an unbounded number of matches: the local ripgrep path ransubprocess.run(capture_output=True), so a broad pattern on a huge repo (e.g. the Linux kernel) could buffer gigabytes of stdout before the tool layer got a chance to truncate, risking OOM.This adds a total-match cap and makes the local ripgrep path stream:
max_count: int | None = NoneonBackendProtocol.grep/agrepand every backend implementation (filesystem,state,store,sandbox,composite,context_hub). It is a total cap across all files, not per-file. Defaulting toNonekeeps existing direct-backend behavior unchanged.LocalFilesystemBackendnow streams ripgrep's--jsonoutput viasubprocess.Popenline-by-line, stops andterminate()s the process once the cap is reached, and passes-mas a cheap secondary per-file guard. Athreading.Timerwatchdog preserves the existing time-limit behavior. The Python fallback early-returns at the cap.CompositeBackendenforces the cap globally across routed backends, short-circuiting remaining routes once it is met.GrepResult.truncated(already present) is set when the cap is hit, andFilesystemMiddlewaregains agrep_max_countdefault of1000(configurable, and overridable per call via the tool'smax_countargument). The truncation note shown to the model now covers both the time-limit and match-cap cases.Reviewers may want to focus on the rewritten
_ripgrep_searchstreaming/termination/watchdog logic and the composite cross-route budget accounting.Made by Open SWE