* fix(workflows): stop idle agent waits from consuming worker turns
While a script step waited on a child Agent run, the supervisor sent an
empty response frame to the QuickJS worker every 20 ms and each round
trip counted toward the 10,000-turn cap, so any workflow whose Agent
calls kept it waiting for about 209 s failed with "Worker turn limit"
regardless of `timeout_seconds`.
The worker now reports when its job queue has drained, and the
supervisor waits on the pending calls locally while the worker is idle,
still re-checking cancellation and faults every 20 ms, without
exchanging frames. `timeout_seconds` is the only wall-clock bound again;
scripts that spin the job queue still hit the turn cap. The cap is a
module constant so tests can lower it.
Fixes bytedance/deer-flow#7022
* fix(workflows): default a frame without idle to the polling path
Review follow-up: read `idle` with `frame.get("idle", False)` so an
outcome-less frame that lacks the key degrades to the previous poll
behaviour instead of failing the run with a KeyError, and give the
cancel-latency regression test a 3 s budget so store writes and process
reaping on a loaded CI runner cannot flake it.
* fix(workflows): detect worker exit during idle Agent waits
Check worker exit in the existing local poll and clean up pending child runs. Adapt the work-frame budget regression from PR #7025 while retaining precise idle detection.
---------
Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
Develop an extension from an existing example
Start with the smallest example that covers your extension. Each directory is an
independent Python package using the public deerflow-extension-api contract.
| Start here | What it demonstrates |
|---|---|
| Extension example | Middleware, task lifecycle, model observations, services, and HTTP routes. Start here for backend extensions. |
| Conversation bookmarks | A browser page, conversation action, backend actions, packaged resources, and a model tool. Start here for full-stack plugins. |
| Agent teams | Full Agent orchestration. Use this after the basic contribution and lifecycle patterns are familiar. |
Additional examples cover text-list classification, context pruning, and advisory screening of fetched content.
Edit, test, check, then install
-
Copy the selected example outside the DeerFlow checkout. Rename its Python package, distribution and
deerflow.extensionsentry point. For a full-stack plugin, also choose its own namespace and browser module name. -
Follow the example's README to configure its dependencies and run its tests. Keep package behavior tests alongside the extension.
-
From the DeerFlow checkout root, prepare the backend environment with
make -C backend install, then check the package:uv run --project backend --no-sync python scripts/check_extension.py /absolute/path/to/your-extensionTo try the checker on an unchanged example:
uv run --project backend --no-sync python scripts/check_extension.py examples/deerflow-extension-bookmarks -
Follow that example's deployment and try-it instructions. Restart Gateway, refresh the browser when applicable, and exercise the installed feature. Use
make extension-upgrade SOURCE=/absolute/path/to/your-extensionto apply later source edits: local installs are snapshots.
What the checker covers
The script builds a wheel in a temporary directory, checks exactly one extension
entry point and its packaged Python module, parses packaged Python syntax, and
checks that the API dependency range accepts this checkout's contract version.
It validates conventional ui_manifest.json resources with the same validator
used by Gateway, including detecting manifests left out of the wheel in flat or
src/ layouts. A custom manifest filename needs an explicit wheel-relative path:
uv run --project backend --no-sync python scripts/check_extension.py /absolute/path/to/your-extension --manifest your_package/resources.json
The build executes the package's build backend, so check trusted sources. The
checker does not import the extension, call install(), install the extension, or
change deployment configuration. Registration/configuration behavior and the
@extension version marker are verified when loading the plugin; continue to run
the package tests and the installed feature after packaging checks pass.