

Also from Kynth Studios


Also from Kynth Studios


Also from Kynth Studios
1## Service Startup Contracts23The root `PORT` value configures Docker's published nginx ingress only; local4orchestration pins Next.js to `3000`. Runtime commands launch from the already5synchronized environment with `uv run --no-sync`. Production Compose probes6Gateway `/health`, and `deploy.sh` waits for all services before reporting7success; failures print Compose status and recent Gateway logs.89## Backend Static Analysis Commands1011The root `detect-thread-boundaries` target statically inventories execution12boundaries under `backend/app/` and `backend/packages/harness/deerflow/`. It13prints a concise count by execution domain and writes the complete, versioned14JSON payload to `.deer-flow/thread-boundary-inventory.json`. Every finding has15a stable `boundary_kind`: `asyncio_default_executor`, `dedicated_executor`,16`anyio_worker_thread`, `direct_event_loop_blocking`, `separate_event_loop`, or17`unresolved_dynamic_boundary`.1819The AST inventory covers `asyncio.to_thread`, default and explicit20`run_in_executor` submissions, imported aliases, simple same-module helper21wrappers (after pre-registering dedicated executor targets), `set_default_executor`,22`ThreadPoolExecutor` construction/submission,23additional event loops, synchronous LangChain tools, and direct24`BaseChatModel` fallback inheritance. It remains read-only and does not alter25executor routing or sizing.2627To supplement the static scan with configured runtime types, run:2829```bash30python scripts/detect_thread_boundaries.py \31 --runtime-config config.yaml \32 --json-output .deer-flow/thread-boundary-inventory.json33```3435Runtime inspection imports configured tool objects and model classes so it can36record concrete tool names/types/modules, sync functions, async coroutines,37and `_agenerate`/`_astream` ownership. It does not invoke tools, instantiate38models, or call external services; import failures remain in the JSON as39`unresolved_dynamic_boundary` records. The detector implementation and focused40coverage live in `tests/support/detectors/thread_boundaries.py` and41`tests/test_detect_thread_boundaries.py`.4243The `detect-blocking-io` target parses `app/`, `packages/harness/deerflow/`,44and `scripts/` with AST. By default it reports only blocking IO candidates that45are inside async code, reachable from async code in the same file, or reachable46from sync-only `AgentMiddleware` before/after hooks that LangGraph can execute47on the async graph path. It prints a concise summary and writes complete JSON48findings to `.deer-flow/blocking-io-findings.json` at the repository root49(both `make detect-blocking-io` from the repo root and `cd backend && make50detect-blocking-io` resolve to the same repo-root path). JSON findings include51`priority`, `location`, `blocking_call`, `event_loop_exposure`, `reason`, and52`code` for model-assisted or manual review. `priority` is a deterministic53review ordering from operation type, not proof of a bug. Bare-name same-file54calls are resolved by function name, so duplicate helper names in one file can55conservatively over-report async reachability. The call graph also resolves56multi-hop `self.`/`cls.` attribute chains (`self.store.flush()`) and local57variables or parameters traced back — within the same function only — to a58`self.`/`cls.` attribute (`store = self.store; store.flush()`); both fall back59to the same bare-method-name resolution as an unresolvable receiver, so they60share its over-report risk rather than adding a new kind. Deeper cross-function61or cross-module aliasing is out of scope and stays an unreported false62negative.6364That same-function alias tracing is deliberately narrower than the symbolic65names `dotted_name()` builds for blocking-call pattern matching elsewhere in66this module: receiver/alias extraction uses a restricted extractor that only67recognizes `Name`/`Attribute` chains, so a `Call` or `Subscript` result (e.g.68`factory().flush()`, or `client = factory(); client.flush()` /69`client = clients[0]; client.flush()`) is never treated as inheriting its70base's alias-worthiness — including when the unsupported node is buried71deeper in the chain (`factory().client.flush()`, `clients[0].client.flush()`):72an unrecognized shape anywhere in the chain makes the whole receiver73unresolved, it never falls back to just the chain's trailing attribute name,74or that name alone could still collide with an unrelated traced parameter or75local alias. Reassigning a traced name to a non-traceable value (anything76other than a `self.`/`cls.` attribute or an already-traced name) kills its77alias instead of leaving it traceable, so a stale alias from an earlier78assignment cannot keep exposing an unrelated same-named method after the79variable is reassigned to something else; the assignment's right-hand side is80always analyzed against the alias state as it stood *before* this kill-or-add81update, matching Python's own evaluate-then-bind order, so82`client = client.flush()` still resolves that call against `client`'s prior83(pre-reassignment) alias instead of the state after it's gone. `if`/`else`84branches get isolated alias state — an alias added in one branch cannot leak85into the other — and the state after the whole `if` is the union of what each86branch produced (a conservative may-alias join), so the result no longer87depends on which branch is textually `body` vs. `orelse`. This branch88isolation is deliberately scoped to `ast.If` only; `ast.Try`/`ast.Match` have89different, more complex control-flow semantics and keep the older unisolated90traversal. Finally, a function's decorators and parameter defaults are91analyzed in the *enclosing* scope rather than the new function's own, and92parameter/return annotations get the same enclosing-scope treatment unless93the module postpones annotation evaluation (`from __future__ import94annotations`), in which case they are skipped entirely, in either scope —95those expressions run at definition time, before the function has ever been96called (or, when postponed, never run at all), so a call there is never97attributed to the function being defined (it moves to whatever scope actually98contains the `def`, e.g. the enclosing function, or disappears if that scope99is module/class level and therefore never async-reachable). PEP 695100type-parameter bounds are not visited in either scope: CPython evaluates each101one lazily, in its own hidden function, only if something like `T.__bound__`102is actually accessed, never as part of running the `def` statement itself.103A `lambda`'s body and a bare generator expression's element/filters/later104`for` clauses are excluded from traversal ONLY while walking another105function's own definition-time expressions (decorators, parameter defaults/106annotations, return annotation): there, we know structurally that the107enclosing `def` statement is executing right now, and neither a lambda body108nor a generator's element runs just because the lambda/generator object is109created — only a lambda's own parameter defaults and a generator's110outermost iterable are genuinely eager at that moment. This exclusion is111absolute and has no exceptions: even a lambda that is immediately invoked at112its own definition site (`(lambda: ...)()`), or a generator passed directly113to an eager-consuming builtin, is still excluded when it appears inside114another function's decorator/default/annotation — a narrow, intentional115limitation given how rarely a definition-time expression contains an116executed call at all, preferred over special-casing specific shapes there.117118Everywhere else — module level, class bodies, and ordinary function-body119statements — a lambda body or generator expression's element is scanned120unconditionally, the same conservative, over-report-rather-than-infer stance121this file already takes for reachability elsewhere (the `ast.If` may-alias122union, the bare-name call-graph resolution). This file does not attempt to123distinguish a lambda that is invoked immediately, invoked later through a124stored variable, passed as a callback, or never called at all, nor a125generator that is consumed by an eager builtin (`list`, `sum`, `any`, etc.),126wrapped in another lazy iterator (`map`, `filter`), or never consumed —127telling these apart in the general case would mean inferring evaluation128order and consumption across arbitrary code rather than reading a fixed,129structural fact, so none of them are special-cased; all are scanned the130same way. This is intentionally informational and is not run from CI in131this round.132133For a diff-scoped view of the same findings, `scripts/scan_changed_blocking_io.py`134(repo root) reports findings on the added lines of `git diff <base>...HEAD`135plus findings new versus the merge base (so a new async caller exposing an136untouched sync helper in the same file is still reported) — used by the137`blocking-io-guard` skill (`.agent/skills/blocking-io-guard/`) as the138deterministic scope step before routing each candidate to a fix and/or a139`tests/blocking_io/` runtime anchor.140141Regression tests related to Docker/provisioner behavior:142- `tests/test_docker_sandbox_mode_detection.py` (mode detection from `config.yaml`)143- `tests/test_provisioner_kubeconfig.py` (kubeconfig file/directory handling)144- `tests/test_provisioner_request_threading.py` (keeps provisioner sandbox CRUD145 endpoints as sync FastAPI handlers so synchronous K8s client calls run in the146 Starlette worker pool instead of on the ASGI event loop)147148Blocking-IO runtime gate (`tests/blocking_io/`):149- Wraps every item under `tests/blocking_io/` with a strict Blockbuster150 context scoped to `app.*` and `deerflow.*` (see151 `tests/support/detectors/blocking_io_runtime.py`). Any sync blocking IO152 call whose stack passes through DeerFlow business code while running on153 the asyncio event loop raises `BlockingError` and fails the test.154- Regression anchors live there: `test_skills_load.py` (locks the155 `asyncio.to_thread` offload around `LocalSkillStorage.load_skills`, fix156 for #1917); `test_sqlite_lifespan.py` (locks the offload around157 SQLite path resolution plus `ensure_sqlite_parent_dir`, fix for #1912);158 `test_jsonl_run_event_store.py` (locks `JsonlRunEventStore`'s async159 API — including idempotent singleton-event writes — offloading its file IO160 via `asyncio.to_thread`); `test_run_journal_callbacks.py` (locks161 `RunJournal.run_inline` tool callbacks to in-memory/event-loop-safe work);162 `test_integrations_router.py` (locks Lark integration install and auth163 completion route handlers offloading archive filesystem work and `lark-cli`164 subprocesses);165 `test_uploads_middleware.py` (locks `UploadsMiddleware.abefore_agent`166 offloading the uploads-directory scan off the event loop);167 `test_uploads_router.py` (locks Gateway upload/list/delete endpoints168 offloading upload directory creation, staged writes, chmod/cleanup,169 directory scans/deletes, and remote sandbox sync off the event loop);170 `test_feishu_receive_file.py` (locks Feishu attachment path preparation and171 persistence plus remote sandbox acquisition/sync off the event loop, and172 skips redundant sandbox sync when thread data is already mounted);173 `test_channel_outbound_files.py` (locks Feishu, Telegram, and WeCom outbound174 attachment open/read/hash work off the event loop);175 `test_openviking_memory_backend.py` (locks the official OpenViking backend's176 async add/context/search entrypoints offloading synchronous SDK and cursor177 filesystem IO); and178 `test_workspace_changes_recorder.py` (locks the offload around the snapshot179 text cache lifecycle — roots resolution, `mkdtemp`, and the `shutil.rmtree`180 on both the capture-failure branch and `record_workspace_changes`' `finally`).181- `test_gate_smoke.py` is a meta-test asserting the gate actually catches182 unoffloaded blocking IO and that the `@pytest.mark.allow_blocking_io`183 opt-out works.184- Coverage boundary: the gate only sees code that test execution actually185 touches. Static AST coverage is a separate concern (out of scope for186 this PR).187- CI: runs on every PR via `.github/workflows/backend-blocking-io-tests.yml`,188 hard-fail.189190Boundary check (harness → app import firewall):191- `tests/test_harness_boundary.py` — ensures `packages/harness/deerflow/` never imports from `app.*`192193Memory backend async boundary:194- `MemoryMiddleware.aafter_agent` calls `MemoryManager.aadd`; network-backed195 managers must override their `a*` methods to offload or use native async I/O.196- The mem0 backend requires an HTTPS `base_url` by default because requests197 carry an API token. Plain HTTP requires the explicit198 `backend_config.allow_insecure_http: true` local-development opt-in.199- Gateway memory routes offload the synchronous management contract with200 `asyncio.to_thread`, so backend file or HTTP I/O does not run on the ASGI201 event loop. Gateway startup and shutdown also resolve the manager off-loop,202 because a backend's `from_config` may perform a fail-fast connectivity check.203- A backend may set `requires_passive_writes_in_tool_mode = True` when tool-mode204 search is supported but durable writes still depend on conversation-level205 extraction. Such backends receive memory tools and retain `MemoryMiddleware`.206- Prompt recall rethrows `MemoryManagerError` only when backend config declares207 `failure_policy.read: fail_closed`; other recall errors preserve the existing208 log-and-empty-context behavior.209210CI runs these regression tests for every pull request via [.github/workflows/backend-unit-tests.yml](../.github/workflows/backend-unit-tests.yml).211212Agentic browser sessions are process-local. The Gateway startup safety gate rejects213`GATEWAY_WORKERS > 1` when `browser_navigate` is configured, because ordinary214uvicorn worker dispatch does not provide thread affinity for browser tools, REST215navigation, and the Live WebSocket.216217Browser Live screenshots remain JPEG bytes inside the harness and the Gateway's218bounded, drop-oldest frame queue. WebSocket clients that request219`frame_format=binary` receive binary messages; control metadata remains JSON.220The legacy no-parameter protocol still base64-encodes frames into JSON at the221Gateway boundary for backward compatibility. Unknown `frame_format` values222receive a JSON error and close code 1008.223
One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| bytedance/deer-flowAGENTS.md · 80k | AGENTS.md | setuptestlint-formatstyle+1 | 93/100 | today | |
| bytedance/deer-flowbackend/packages/harness/deerflow/subagents/AGENTS.md · 80k | AGENTS.md | archdependenciesmonorepo | 38/100 | today | |
| bytedance/deer-flowbackend/packages/harness/deerflow/tools/AGENTS.md · 80k | AGENTS.md | setuptestarchdependencies+1 | 50/100 | today | |
| bytedance/deer-flowbackend/app/channels/AGENTS.md · 80k | AGENTS.md | monorepo | 29/100 | today | |
| bytedance/deer-flowbackend/app/gateway/AGENTS.md · 80k | AGENTS.md | testing-strategyapimonorepo | 22/100 | today | |
| bytedance/deer-flowbackend/packages/harness/deerflow/AGENTS.md · 80k | AGENTS.md | archdependenciesmonorepo | 55/100 | today | |
| bytedance/deer-flowbackend/packages/harness/deerflow/agents/AGENTS.md · 80k | AGENTS.md | agent-behaviour | 38/100 | today | |
| bytedance/deer-flowbackend/packages/harness/deerflow/agents/memory/AGENTS.md · 80k | AGENTS.md | archdependenciesperformancemonorepo | 18/100 | today | |
| bytedance/deer-flowbackend/packages/harness/deerflow/agents/middlewares/AGENTS.md · 80k | AGENTS.md | no sections | 29/100 | today | |
| bytedance/deer-flowbackend/packages/harness/deerflow/config/AGENTS.md · 80k | AGENTS.md | styletypesdatabaseperformance | 55/100 | today | |
| bytedance/deer-flowbackend/packages/harness/deerflow/extensions/AGENTS.md · 80k | AGENTS.md | setuptest | 47/100 | today | |
| bytedance/deer-flowbackend/packages/harness/deerflow/mcp/AGENTS.md · 80k | AGENTS.md | archdependenciesmonorepo | 45/100 | today | |
| bytedance/deer-flowbackend/packages/harness/deerflow/models/AGENTS.md · 80k | AGENTS.md | setuparchdependenciesmonorepo | 51/100 | today | |
| bytedance/deer-flowbackend/packages/harness/deerflow/persistence/migrations/AGENTS.md · 80k | AGENTS.md | archtypesdependenciesdatabase+1 | 52/100 | today | |
| bytedance/deer-flowbackend/packages/harness/deerflow/runtime/AGENTS.md · 80k | AGENTS.md | no sections | 32/100 | today | |
| bytedance/deer-flowbackend/packages/harness/deerflow/sandbox/AGENTS.md · 80k | AGENTS.md | testarchdependenciesmonorepo+1 | 22/100 | today | |
| bytedance/deer-flowbackend/packages/harness/deerflow/skills/AGENTS.md · 80k | AGENTS.md | archdependenciesperformancemonorepo | 42/100 | today | |
| bytedance/deer-flowbackend/packages/harness/deerflow/tracing/AGENTS.md · 80k | AGENTS.md | archdependenciesmonorepo | 38/100 | today | |
| bytedance/deer-flowbackend/packages/harness/deerflow/tui/AGENTS.md · 80k | AGENTS.md | testarchdependenciesmonorepo | 46/100 | today | |
| bytedance/deer-flowfrontend/src/AGENTS.md · 80k | AGENTS.md | styleui | 27/100 | today |
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| vllm-project/vllmAGENTS.md · 89k | AGENTS.md | setuptestlint-formatstyle+5 | 100/100 | 14 days ago | |
| deepseek-ai/deepseek-harnessnative/landlock-run/AGENTS.md · 104k | AGENTS.md | setupteststylearch+3 | 100/100 | today | |
| code-yeongyu/oh-my-openagentpackages/web/AGENTS.md · 68k | AGENTS.md | setupbuildtestlint-format+6 | 100/100 | 13 days ago | |
| TryGhost/Ghoste2e/AGENTS.md · 55k | AGENTS.md | setupteststylearch+2 | 100/100 | today | |
| n8n-io/n8npackages/@n8n/agents/AGENTS.md · 201k | AGENTS.md | buildteststylearch+3 | 100/100 | 14 days ago | |
| duckduckgo/content-scope-scriptsspecial-pages/AGENTS.md · 70 | AGENTS.md | buildteststylearch+3 | 100/100 | 14 days ago | |
| aaif-goose/gooseAGENTS.md · 53k | AGENTS.md | setupbuildtestlint-format+7 | 100/100 | 8 days ago | |
| mui/material-uiAGENTS.md · 99k | AGENTS.md | setupbuildtestlint-format+9 | 100/100 | 14 days ago |
A badge carrying the measured quality of the strongest agent config file in this repository, out of 100. It reads from this index every time somebody loads your page, so it changes when the measurement changes and there is nothing to keep up to date. Free, no account, and the value is not something you or we can set by hand.
[](https://rulestack.kynth.studio/configs/bytedance-deer-flow-scripts-agents)Would rather not hotlink us? Every badge is also served in shields.io’s endpoint schema, so shields renders the image and your readers never talk to our domain:
Published by Toolproof, the masthead over this index and eight others. The method behind the number is at toolproof.kynth.studio/methodology, and the whole thing is readable as JSON with no key at /api.