DeerFlow: who decides what

The gallery · Make a map of your own system · The repository

The DeerFlow agent harness (its Python harness package and the gateway, channel and scheduler code that answers the harness's requests) in bytedance/deer-flow, read at commit 14abd9a2 (2026-11-02). Claims about how the code behaves refer to that commit. Their code is MIT-licensed; this page quotes short identifiers and cites files and lines at that commit.

How to read this page

A seat is a judgment the agent makes over and over: which model runs a turn, what the model sees, may this tool call run, is the work done. Each card records the question, how it is answered, and who or what holds it, with the code that implements or exposes that decision. Seat ids (A1, D12 …) are links.

Each answer describes what DeerFlow does by default at the commit named above. Exceptions named are the main ones, not a complete list.

The chip on each card has two words. The first is about the question: a RULE has one right answer given its inputs, so a run that answers differently is a bug; a RULING is one that competent people could answer differently. Enforcing a limit someone set is a RULE; choosing what to keep, what to trust or when the work is done is a RULING, even when code holds it.

The second word is who holds it: llm = a language-model call; code = code in their repository; human = a person; external = something outside the repository that the agent hands the decision to (a hosted service, a sandbox provider, a configured command).

Paths are relative to the repository root. A file name written without its folder is in the folder of the full path written before it on the same card. A bare :120-140 means lines in the file named just before it.

Counts

133 seats across 9 stages: A 12, B 26, C 6, D 31, E 17, F 19, G 7, H 10, I 5.

Kind of question · holderSeats
RULE · code65
RULING · code28
RULING · llm23
RULING · external10
RULING · human4
RULE · external3

What this edition does not have

There is no list of gaps. No coverage figure: this edition does not say how many of DeerFlow's model calls and decision points the seats leave out. Each card shows the question, the answer and its holder; for most seats we also recorded what checks the judgment and how it has failed, but those notes are not shown here.

What is left out of this edition

17 of the 133 cards are left out of this edition. The counts above include them.

A. Intake and routing (12 seats)

A1 Which configured model is chosen for this conversation turn, before model-use authorization? RULE · code
Answered how

Code takes the request's model_name/model, else the custom agent's model, else config.models[0]. An unknown name falls back to the first configured model with a log warning, unless the run marks it as an explicit model selection; then the run is refused.

Held by

backend/packages/harness/deerflow/agents/lead_agent/agent.py:228 (called at backend/packages/harness/deerflow/agents/lead_agent/agent.py:1077; explicit selection backend/packages/harness/deerflow/agents/lead_agent/agent.py:1081-1089)

A2 Is extended thinking on, and at what reasoning effort, for this run? RULE · code
Answered how

Code applies precedence request > custom-agent default > runtime default (backend/packages/harness/deerflow/agents/lead_agent/agent.py:167-180, _resolve_runtime_option), then normalizes against the model's reasoning contract: unsupported thinking is turned off, required thinking is forced on (or rejected), and an out-of-vocabulary effort is aliased or replaced by the contract default.

Held by

backend/packages/harness/deerflow/models/reasoning.py:142 (called at backend/packages/harness/deerflow/agents/lead_agent/agent.py:1103 and again inside the factory at backend/packages/harness/deerflow/models/factory.py:615)

A3 Which provider class, endpoint and request payload does the chosen model get? RULE · code
Answered how

Code resolves the model class by reflection, layers per-agent sampling overrides, merges thinking templates, and applies provider defaults such as routing the gpt-6 family to the OpenAI Responses API unless a custom endpoint is set.

Held by

backend/packages/harness/deerflow/models/factory.py:536

A4 Which build path does this request take: bootstrap agent creator, a named custom agent, or the default lead agent? RULE · code
Answered how

Code reads is_bootstrap and agent_name from the run config; bootstrap gets a narrow skill set plus setup_agent, a named agent loads its own config, SOUL and tool groups, otherwise the default lead agent is built.

Held by

backend/packages/harness/deerflow/agents/lead_agent/agent.py:1169

A5 Does the user's message explicitly ask for a skill (/skill-name task), and which one? RULE · code
Answered how

Code matches a strict leading /name token (lowercase letters, digits, hyphens, followed by whitespace or end), skips nine reserved control names always and /context compact only in that exact form, and then resolves the name against the installed, enabled skills this agent may use.

Held by

backend/packages/harness/deerflow/agents/middlewares/skill_activation_middleware.py:317 (grammar at backend/packages/harness/deerflow/skills/slash.py:18)

A6 Which DeerFlow thread does an inbound IM message continue? RULE · code
Answered how

Code looks up the conversation/topic in the connection repository when the message carries a bound connection, else in the global channel store; no mapping means a new thread is created.

Held by

backend/app/channels/connection_identity.py:47

A7 Which agent handles an IM message? RULE · code
Answered how

Code applies a fixed precedence: per-message override (GitHub fan-out), thread pin from /agent use, user session layer, channel layer, default session, manager default; a custom agent name is routed through lead_agent plus agent_name context.

Held by

backend/app/channels/manager.py:1743

A8 Which model does an IM conversation use after a user pins one with /model? RULE · code
Answered how

Code applies the thread's /model pin over every session-config layer; the agent factory then prefers this requested name over the custom agent's own model.

Held by

backend/app/channels/manager.py:2191

A9 Is an inbound IM text a channel command or a chat turn? RULE · code
Answered how

Code checks whether text that starts with / begins with one of the known slash commands (/new, /status, /models, /model, /memory, /goal, /agent, /bootstrap, /help …), case-insensitively.

Held by

backend/app/channels/commands.py:87-91 (leading mentions are stripped separately, for adapters that leave them in the text, at :46-65)

A10 Does this GitHub event wake this agent binding? RULE · code
Answered how

Code applies the binding's configured gates in order: action allowlist, allow_authors bypass, then a boundary-aware @mention requirement.

Held by

backend/app/gateway/github/triggers.py:150

A11 How should the user's rough draft be rewritten before it is sent? RULING · llm
Answered how

On request from the composer, a one-shot model call rewrites the draft into a clearer instruction; the user sees the result and decides whether to send it.

Held by

model setting input_polish.model_name, read at backend/app/gateway/routers/input_polish.py:86 (falls back to the default model inside run_oneshot_llm); call at backend/app/gateway/routers/input_polish.py:88

A12 Which follow-up questions should the user be offered next? RULING · llm
Answered how

A one-shot model call reads the recent conversation (supplied by the client) and proposes N short follow-up questions.

Held by

model setting from request model_name, else the default model, at backend/app/gateway/routers/suggestions.py:145; call at backend/app/gateway/routers/suggestions.py:140

B. Context: what the model sees (26 seats)

B3 Which skill, if any, should the model load for this task? RULING · llm
Answered how

The lead model decides from the advertised skill metadata whether a skill matches and loads its SKILL.md with read_file (or first calls describe_skill in deferred mode).

Held by

the run's lead model, resolved at backend/packages/harness/deerflow/agents/lead_agent/agent.py:1077

B4 Which skills match the model's describe_skill query? RULING · code
Answered how

Code ranks the catalog by literal intent-term coverage (name hits preferred), returns at most 5; select: returns exact names uncapped.

Held by

backend/packages/harness/deerflow/skills/catalog.py:145

B10 Which tools are bound to the lead model for this run? RULE · code
Answered how

Code assembles candidate tools from configured tools, built-ins, platform and personal MCP tools, ACP and plugin tools, filtered by the agent's settings and the run context, drops later duplicates by name, and then applies further additions and filters before the final tool set is bound.

Held by

backend/packages/harness/deerflow/tools/tools.py:103

B11 Is this channel trusted enough to offer the agent its self-modification tool (update_agent)? RULING · code
Answered how

Code offers update_agent to every named custom agent unless the run came from a channel in a fixed set, which today contains only github.

Held by

backend/packages/harness/deerflow/agents/lead_agent/agent.py:1329 (set at backend/packages/harness/deerflow/agents/lead_agent/agent.py:92)

B12 Which deferred MCP tool schemas can the model see on this call? RULE · code
Answered how

Code hides every deferred (MCP) tool schema whose name is not in the thread's promoted set for the current catalog hash and current genuine user turn, and blocks calls to hidden ones with an error telling the model to call tool_search.

Held by

backend/packages/harness/deerflow/agents/middlewares/deferred_tool_filter_middleware.py:93

B13 Which deferred tools match the model's tool_search query? RULING · code
Answered how

Code matches the query against deferred tool names and descriptions: select: exact names (uncapped), keywords: literal term coverage, +name required-substring plus regex, or plain regex with name hits ranked first; at most 5 results under a 100 ms regex budget.

Held by

backend/packages/harness/deerflow/tools/builtins/tool_search.py:128

B14 Which deferred MCP tools are auto-promoted from what the user just said? RULING · code
Answered how

Code checks whether any MCP server's configured routing keyword occurs as a case-insensitive substring of the latest genuine user message, and promotes the top-k matches by configured priority, before the model call.

Held by

backend/packages/harness/deerflow/agents/middlewares/mcp_routing_middleware.py:92

B17 Which personal data in the user's messages is replaced before the model sees it? RULING · code
Answered how

When enabled (default off), code runs deterministic regex detectors over genuine user messages and the compaction summary and swaps matches for irreversible value-derived placeholders.

Held by

backend/packages/harness/deerflow/agents/middlewares/pii_redaction_middleware.py:418

B18 Which of this turn's uploaded files are described to the model, and how? RULE · code
Answered how

Code lists files attached to the latest user message (capped by count, in upload order), with size, path and either a heading outline or a short preview, all tag-neutralized, prepended to that message; historical uploads are left to the list_uploaded_files tool.

Held by

backend/packages/harness/deerflow/agents/middlewares/uploads_middleware.py:239

B19 Of the images viewed in the thread, which are re-sent as pixels on this model call, and which are replaced by an "omitted" note? RULING · code
Answered how

On each model call, code removes the earlier image-context messages that carry its reserved id prefix and server-owned marker (an unmarked one from an older checkpoint stays, and can stop the rebuild, backend/packages/harness/deerflow/agents/middlewares/view_image_middleware.py:80-82, :450-461) and, when a rebuild is due and authorized, builds a new one from the thread's viewed-image records. It examines the records newest first: an image gets a read attempt only while the attempt count is under the smaller of 4 and the configured image cap and its estimated size still fits the 28 MiB base64 budget and the configured character cap; otherwise it gets "(omitted: image injection budget reached; call view_image again to re-view this image)" and the scan goes on, so a smaller, older image can still fit after a large one is omitted. Each attempted image is read fresh, with its recorded size and digest passed to the reader; one that is unavailable or changed gets a note instead.

Held by

backend/packages/harness/deerflow/agents/middlewares/view_image_middleware.py:386

B20 What compacted history, delegation ledger, active skills, artifacts, goal and task notes does the model see? RULE · code
Answered how

Code renders, per model call, one hidden <durable_context_data> block: the active goal, the bounded conversation summary, the delegation ledger, active skill references, artifact registry and task notes, each escaped and length-bounded.

Held by

backend/packages/harness/deerflow/agents/middlewares/durable_context_middleware.py:101 (injected at :400)

B22 What one-line description does a project document get on the shelf the model reads? RULING · llm
Answered how

A background model call reads up to 16,384 characters of the document and writes a single descriptive sentence, stored once per document.

Held by

model setting projects.summary_model_name, read at backend/packages/harness/deerflow/projects/summaries.py:160; call at backend/packages/harness/deerflow/projects/summaries.py:335

B23 Which knowledge scope applies to this turn, and is knowledge search offered at all? RULE · code
Answered how

Code takes the Gateway-admitted scope from runtime context, or the single knowledge_scope carried on a current-run user message, canonicalizes it, strips scope data from model-visible messages, and removes and blocks knowledge_search when the scope is disabled.

Held by

backend/packages/harness/deerflow/agents/middlewares/knowledge_scope_middleware.py:44

B25 How are the separate system messages merged before the provider sees the request? RULE · code
Answered how

Code merges the static system prompt and every in-history SystemMessage into one leading system message per request, keeping only the newest date reminder.

Held by

backend/packages/harness/deerflow/agents/middlewares/system_message_coalescing_middleware.py:64

B26 Which message content blocks must be downgraded to text placeholders for the selected model? RULE · code
Answered how

Code rewrites URL-sourced file blocks and non-fetchable-scheme image blocks into neutralized text placeholders on the request view only, keeping http(s) URLs where the selected model's serializer accepts them.

Held by

backend/packages/harness/deerflow/agents/middlewares/model_content_compatibility_middleware.py:231

B27 What does the model receive when the user explicitly activates a skill? RULE · code
Answered how

Code inserts, before the user's message and for that turn only, an escaped copy of the full SKILL.md plus the remaining task text, recording the activation so retries in the same run replay the same text.

Held by

backend/packages/harness/deerflow/agents/middlewares/skill_activation_middleware.py:541

C. Choosing the next action (6 seats)

C2 Before the model is called again, how is a broken tool-call transcript repaired: which calls get an "interrupted" or "invalid arguments" placeholder, which results are dropped as orphans, and how are empty names and ids relabelled? RULE · code
Answered how

Code rewrites the model-bound message list (request only, state untouched): synthetic ids for missing call ids, unknown_tool for empty names, {} for non-JSON arguments, an error ToolMessage after each unanswered call, and silent removal of ToolMessages whose call is gone.

Held by

backend/packages/harness/deerflow/agents/middlewares/dangling_tool_call_middleware.py:429

C3 When a model call fails (HTTP error, timeout, in-stream error, empty completion), is it transient (retry, with what delay and budget) or final (quota, auth, generic), and what does the person see? RULING · code
Answered how

Code classifies the exception by class name, status code, in-band status text and substring patterns (_QUOTA_PATTERNS, _AUTH_PATTERNS, _BURST_PATTERNS, _BUSY_PATTERNS), retries up to a per-class / per-reason budget with Retry-After or decorrelated jitter, and on exhaustion replaces the model output with an AIMessage marked deerflow_error_fallback.

Held by

backend/packages/harness/deerflow/agents/middlewares/llm_error_handling_middleware.py:623

C4 When the model stops normally but says nothing and calls nothing, is that an answer, a provider glitch to retry once, or (after tools ran) a failed run? RULING · code
Answered how

Code, at two points. At the model boundary _raise_for_empty_response turns a stop/end_turn/None finish with no visible content and no tool-call intent into a retriable EmptyModelResponseError, one retry per run (context key). After the model, TerminalResponseMiddleware replaces a still-empty response that follows a tool result in the current turn with a visible fallback marked deerflow_error_fallback, which the worker turns into run status error (E14).

Held by

backend/packages/harness/deerflow/agents/middlewares/llm_error_handling_middleware.py:59 (boundary); backend/packages/harness/deerflow/agents/middlewares/terminal_response_middleware.py:42 (terminal)

C5 Did the provider stop because the output budget ran out, and if so must the possibly truncated tool calls be suppressed and the person told? RULE · code
Answered how

Code: four detectors (OpenAI-compatible finish_reason=length, Anthropic stop_reason=max_tokens, Gemini MAX_TOKENS, Responses status=incomplete + max_output_tokens) recognise the cap; on a hit all tool calls (structured, invalid, raw) are removed, stop_reason=model_length_capped is stamped in run context (and kept per run id for the subagent executor's consume_stop_reason), and a notice is appended when tool calls were removed or no visible text remains.

Held by

backend/packages/harness/deerflow/agents/middlewares/model_length_finish_reason_middleware.py:121 (detectors backend/packages/harness/deerflow/agents/middlewares/model_length_termination_detectors.py:130)

C6 When a provider's safety system terminated the response (content_filter, refusal, SAFETY), should its tool calls be blocked and an empty message back-filled? RULE · code
Answered how

Code: configurable detectors (OpenAICompatibleContentFilterDetector, AnthropicRefusalDetector, GeminiSafetyDetector) read finish_reason/stop_reason; on a hit with tool calls or blank content it clears tool calls, stamps stop_reason=safety_capped, records an audit event and appends a notice.

Held by

backend/packages/harness/deerflow/agents/middlewares/safety_finish_reason_middleware.py:359

D. Gatekeeping: may this action run? (31 seats)

D1 When authorization is on, is this user's role allowed to execute this specific tool call? RULE (enforcing an operator-supplied role policy) · code
Answered how

Code. GuardrailMiddleware wraps a GuardrailAuthorizationAdapter, which builds a Principal from server-set run context and asks the configured AuthorizationProvider (built-in: RBAC role→tools allow/deny lists, deny wins); a deny returns an error ToolMessage instead of running the tool.

Held by

backend/packages/harness/deerflow/authz/adapter.py:137

D2 Is this tool (and, for a custom provider, these arguments) permitted by the configured guardrail policy? RULE (name membership against a supplied list); a custom provider may hold a RULING (e.g. blocked-pattern matching) — not knowable from this repo. · code
Answered how

Code by default — AllowlistProvider checks the tool name against configured allowed/denied lists; a custom provider (any class on guardrails.provider.use, e.g. an OAP passport evaluator) is external code the system hands the decision to.

Held by

backend/packages/harness/deerflow/guardrails/builtin.py:28

D3 Is this specific call risky enough to refuse before it runs? RULING · external
Answered how

A hosted TypeSafe "Jev" service scores one question (risky_tool_call) on the tool name + full canonical argument JSON; code denies when the returned probability >= threshold (default 0.5). Local preflight first: tools outside allowed_tools are refused, tools outside tools are allowed un-probed, unserialisable or over-max_state_chars (4000) arguments are refused.

Held by

backend/packages/harness/deerflow/guardrails/typesafe.py:352

D4 Before a bash call runs, should it be blocked as high-risk, run with a warning, or run silently? RULING (which commands are "high-risk" is a judgment; their own guide calls it "defense-in-depth and audit, not a security boundary") · code
Answered how

Code. SandboxAuditMiddleware rejects empty / >10,000-char / NUL-containing commands, then classifies with regex + shlex splitting (_HIGH_RISK_PATTERNS, command-position substitution patterns, _MEDIUM_RISK_PATTERNS); "block" returns an error ToolMessage without running, "warn" runs and appends a warning to the result.

Held by

backend/packages/harness/deerflow/agents/middlewares/sandbox_audit_middleware.py:570

D5 When the sandbox is the local host provider, may the agent execute shell commands at all? RULE (reads an operator setting) · code
Answered how

Code. is_host_bash_allowed returns True for any non-local sandbox provider, and for the local provider only when sandbox.allow_host_bash: true; the bash tool returns an error string otherwise, and tool assembly hides bash.

Held by

backend/packages/harness/deerflow/sandbox/security.py:45

D6 With host bash opted in, does this command reference host paths it should not? RULING (a regex/token heuristic over shell text deciding "is this a host-path reference"; their docstring: "best-effort guard … not a secure sandbox boundary") · code
Answered how

Code. validate_local_bash_command_paths rejects file:// URLs, absolute paths outside /mnt/user-data, skills, ACP, custom mounts and a small system-path allowlist, shell-variable path prefixes other than $PWD (outside the single-quoted inline program of an awk command, which is exempt), and named-tilde paths; raises PermissionError, returned to the model as an error string.

Held by

backend/packages/harness/deerflow/sandbox/tools.py:1793

D7 Is this virtual path inside the families a structured file tool may touch, and is a write allowed there? RULE · code
Answered how

Code. validate_local_tool_path rejects .. segments, allows /mnt/user-data/* read+write and the bare /mnt/user-data root for reads only, skills and ACP workspace read-only, custom mounts per their read_only flag, and refuses everything else.

Held by

backend/packages/harness/deerflow/sandbox/tools.py:1020

D8 Is this user's role permitted to execute anything in a sandbox? RULE · code
Answered how

Code. Before any sandbox reuse or acquire, authorize_sandbox_execution asks the authorization provider authorize(principal, "sandbox", "execute", target="*"); deny raises SandboxAuthorizationError, surfaced as an error ToolMessage.

Held by

backend/packages/harness/deerflow/authz/sandbox_authz.py:149

D9 When the AIO sandbox is in restricted network mode, may an outbound connection to host:port proceed? RULE · code
Answered how

Code in a per-sandbox proxy sidecar: in allowlist mode it allows hosts matching operator domain rules (DEERFLOW_ALLOW_DOMAINS_JSON, exact or leading *.) or an unexpired grant; isolated (default) allows nothing. IP-literal destinations are refused, and a name is refused unless every address it resolves to is public (Docker Desktop's synthetic 198.18.0.0/15 range counts as public only when DEERFLOW_ALLOW_SYNTHETIC_DNS=1, backend/packages/harness/deerflow/community/aio_sandbox/network_proxy.py:99-102, :218-220); a policy denial is recorded as a pending event for D10/D11 only when DEERFLOW_RECORD_DENIALS=1, and the IP-literal and resolution refusals record none.

Held by

backend/packages/harness/deerflow/community/aio_sandbox/network_proxy.py:130

D10 The sandbox tried to reach a host outside the allowlist; does the person allow it temporarily, for the sandbox's life, or deny it? RULING · human
Answered how

A person, via a Human Input card raised after the tool call; the chosen option (deny / allow_temporary / allow_sandbox) is applied at the start of the next turn as a grant in the sidecar. The blocked call is NOT replayed.

Held by

the user of an interactive run (response applied at backend/packages/harness/deerflow/sandbox/middleware.py:350)

D11 In scheduled/webhook/autonomous runs and in subagents, what happens to a blocked connection that would otherwise go to a person? RULE · code
Answered how

Code. If the resolved run interaction policy does not allow clarification, or the call is from a subagent, every unsurfaced denial is atomically marked deny and no card is raised.

Held by

backend/packages/harness/deerflow/sandbox/middleware.py:640

D12 Is this run interactive (a person may be asked) or unattended (scheduled, webhook, autonomous)? RULE · code
Answered how

Code. resolve_run_interaction_policy takes an explicit interaction_mode, else maps legacy flags in order (non_interactive → scheduled, channel_name == "github" → webhook, disable_clarification → autonomous), else interactive. The result removes ask_clarification, switches the prompt guidance, makes ClarificationMiddleware answer "proceed without asking", and auto-denies network approvals (D11).

Held by

backend/packages/harness/deerflow/agents/interaction_policy.py:150

D15 Given the agent's question (missing info, approach choice, risk confirmation, suggestion), what does the person choose or say? RULING · human
Answered how

A person, through a Human Input card (web) or IM text; the run ends at the interrupt and the answer arrives as the next user turn (a hidden HumanMessage with human_input_response metadata).

Held by

the run's user; interrupt issued at backend/packages/harness/deerflow/agents/middlewares/clarification_middleware.py:553

D16 If a model turn contains ask_clarification plus other tool calls, do the others wait for the answer? RULE · code
Answered how

Code. In interactive runs ClarificationMiddleware rewrites the AIMessage to keep only the clarification call(s), so siblings never execute; in unattended runs it leaves them.

Held by

backend/packages/harness/deerflow/agents/middlewares/clarification_middleware.py:479

D17 May this write_file / str_replace on an existing file run, given what the model last read? RULE · code
Answered how

Code. ReadBeforeWriteMiddleware reads the file's current content and compares its hash with the newest read_file mark carried on ToolMessages; a mismatch or missing mark returns an error ToolMessage telling the model to read first.

Held by

backend/packages/harness/deerflow/agents/middlewares/read_before_write_middleware.py:367

D19 Is this user's role allowed to activate (load and follow) this specific skill? RULE · code
Answered how

Code. skill_activation_allowed asks the authorization provider authorize(principal, "skill", "activate", skill_name); used by slash activation, describe_skill and skill-file loads.

Held by

backend/packages/harness/deerflow/authz/skill_filter.py:62

D20 Is this role allowed to use the selected model; if denied and the run did not explicitly select it, which authorized model replaces it? RULE · code
Answered how

Code, only when authorization.enabled is true. A model the run explicitly selected is refused on denial and never replaced. Otherwise _authorize_model_name checks authorize("model","use"); on a denial it walks the provider's visible model list and takes the first other model that also passes use. With none left it raises when fail_closed is true, which is the default; with fail_closed: false it logs a warning and keeps the denied model, as the function's docstring says.

Held by

backend/packages/harness/deerflow/agents/lead_agent/agent.py:285; explicit selection backend/packages/harness/deerflow/models/selection.py:93-121 (called at backend/packages/harness/deerflow/agents/lead_agent/agent.py:1089)

D21 Is this skill text or script the agent wants to create/edit safe to write (no prompt-injection, privilege escalation, exfiltration, unsafe code)? RULING · llm
Answered how

Two holders in sequence. First code: SkillScan's deterministic analyzers block any CRITICAL finding (D22). Then a moderation model (skill_evolution.moderation_model_name or the default model) classifies the content allow/warn/block; block refuses the write, and executable content must get allow.

Held by

backend/packages/harness/deerflow/skills/security_scanner.py:158

D22 Does a deterministic scan of the skill (secrets, shell pipes to interpreters, exfiltration hosts, executable binaries, …) find a CRITICAL issue? RULING (pattern-based severity of code/prose; their rule specs choose what is CRITICAL) · code
Answered how

Code. enforce_static_scan runs SkillScan over the candidate directory and raises StaticScanBlockedError on any CRITICAL finding; lower findings are logged and passed to D21 as context.

Held by

backend/packages/harness/deerflow/skills/skillscan/orchestrator.py:232

D23 Is the scheduler tool usable in this run — feature on, not a subagent, the host bound a capability of the right mode (interactive for management, scheduled for self-stop)? RULE · code
Answered how

Code. _capability returns the host-bound capability only when scheduler.tool_enabled, the run is not a subagent, the capability mode matches, and the resolved interaction policy mode equals that mode; the Gateway capability then re-checks interactive mode, live owner authentication, route permissions and the originating thread (backend/app/gateway/scheduled_task_access.py:338-350, 384-388).

Held by

backend/packages/harness/deerflow/tools/scheduled_tasks.py:31

D24 Should the agent create (or update/resume/delete) a recurring task that will run later with no person present? RULING · llm
Answered how

The lead model, guided by the schedule_task tool description ("Use create only after the user asked for scheduled or recurring work … Use delete only when the user explicitly asks"). The host checks permissions, field validity and safety caps, but NOT that the current user turn asked — unlike trial (D25) and note (D26), which it does check.

Held by

the lead agent's chat model calling schedule_task (backend/packages/harness/deerflow/tools/scheduled_tasks.py:35)

D25 Before dispatching a trial run, is the person's latest message a direct "run it now" request (not a bare "yes", a mention, a quote or a conditional)? RULING (deciding consent from free text; implemented as an exact phrase list) · code
Answered how

Code. _has_explicit_trial_request normalises the turn, strips up to two leading acknowledgements and one trailing particle, and requires the whole remainder to be one of a fixed set of English/Chinese direct-run phrases (or one naming the opaque task id).

Held by

backend/app/gateway/scheduled_task_access.py:155

D26 May the agent save this standing instruction for all future runs of the task? RULE · code
Answered how

Code. _note accepts the note only if it is a non-empty substring (≤500 chars) of the current user message.

Held by

backend/app/gateway/scheduled_task_access.py:539

D27 Before discovering or calling tools on a user's personal MCP server, is it a privileged (non-public-network) definition, and is the owner a current admin? RULE · code
Answered how

Code. A personal server not marked personal_public_network: true requires a fresh admin lookup via a host-installed checker; no checker, a failed lookup or a non-admin → the server is omitted from discovery and every call raises.

Held by

backend/packages/harness/deerflow/mcp/personal_access.py:38

D28 For an HTTP/SSE MCP server configured with per-user (user_auth) or per-request (headers_from_context) credentials, may a call run when the credential is missing or unusable? RULE · code
Answered how

Code. The interceptor resolves the credential for the authenticated user / request secrets; missing or empty → ToolException unless the operator set on_missing: "passthrough"; a value that cannot be a header is always denied without echoing it.

Held by

backend/packages/harness/deerflow/mcp/user_scoped_auth.py:107 (user_auth); request-scoped context headers by a separate interceptor at backend/packages/harness/deerflow/mcp/context_headers.py:138-205

D29 Is this URL an http(s) address that resolves only to public IPs, and is a self-hosted fetch backend's egress confirmed isolated? RULE · code
Answered how

Code. validate_public_http_url refuses non-http(s) schemes and any host resolving to a private, loopback, link-local, reserved, multicast, CGNAT or metadata address; validate_delegated_backend_url refuses a self-hosted Browserless/crawl4ai/fastcrw/firecrawl backend unless network_isolation_confirmed.

Held by

backend/packages/harness/deerflow/community/url_safety.py:140

D30 Does this inherited environment variable look like a credential that must be withheld from sandbox processes? RULING (a name-shape heuristic for "is this a secret") · code
Answered how

Code. is_blocked_env_name blocks exact names (connection strings, MYSQL_PWD, …) and wildcard patterns (*KEY*, *SECRET*, *TOKEN*, *PASS*, *CREDENTIAL*, *DSN*); build_sandbox_env drops them, then adds explicitly configured and request-scoped values.

Held by

backend/packages/harness/deerflow/sandbox/env_policy.py:105

D31 Does an uploaded file's name and target path stay inside the thread's upload directory without traversal, links, reserved names or non-portable forms? RULE · code
Answered how

Code. normalize_filename first keeps only the base name (Path(filename).name, backend/packages/harness/deerflow/uploads/manager.py:75, so ../../etc/passwd becomes passwd), then rejects an empty or unsafe base name, NUL, remaining backslashes, over-255-byte, staging-pattern and non-Windows-portable names; validate_upload_destination / validate_path_traversal refuse non-regular or escaping destinations, and refuse an existing multi-link destination only on the default (non-exclusive) path (not on the exclusive first-claim path) and only off Windows, where the link count is treated as unreliable (manager.py:170-179, 194-195). At this pin the default path no longer overwrites: a same-name collision is written under the next free _N name.

Held by

backend/packages/harness/deerflow/uploads/manager.py:59

D32 In a scheduled run, does the work now meet the stop rule written into the task, so the recurring schedule should pause after this run? RULING · llm
Answered how

The run's model decides, guided by the stop_scheduled_task tool description ("Call this when the stop rule in your task instructions is met … Meeting this run's goal does not by itself mean the stop rule is met"). The host checks only that this is a scheduled run with its own task and occurrence and that the owner may write, then records the stop request; it does not judge whether the stop rule holds.

Held by

the scheduled run's chat model calling stop_scheduled_task (backend/packages/harness/deerflow/tools/scheduled_tasks.py:166)

E. Execution and observation (17 seats)

E1 If a tool call throws, does the run stop, or does the model receive an error result it can recover from, and how much of the error text does it see? RULE · code
Answered how

Code catches every non-control-flow exception around the tool handler and returns an error ToolMessage Error: Tool '<name>' failed with <Class>: <detail≤500 chars>. Continue with available context, or choose an alternative tool.; task failures also get the subagent failure contract.

Held by

backend/packages/harness/deerflow/agents/middlewares/tool_error_handling_middleware.py:112 (wrappers :309-344)

E2 For every tool result, what status (success / error / partial_success), error type, "recoverable by the model?" flag and recommended next action is stamped on it? RULING · code
Answered how

Code: exception text, an Error: content prefix, a JSON error field (except on read_file, whose JSON is document data), a nonzero bash exit marker, a web_fetch error-page title, or partial-result substrings (truncated, no results found, ...) are matched against keyword rules (_ERROR_RULES); a producer-supplied stamp is kept as is, except an old content-analysis "success" on a bash result whose exit marker reports failure.

Held by

backend/packages/harness/deerflow/agents/middlewares/tool_result_meta.py:263

E3 When a tool result exceeds its budget, is it saved to a file with a synopsis and a pointer, or cut to a head-and-tail excerpt, and which tools are exempt? RULING · code
Answered how

Code: above externalize_min_chars (default 12,000) the full text is written to the thread's .tool-results dir (or a blob store) and replaced with a typed synopsis plus a read_file pointer; if persistence is impossible, content above fallback_max_chars (30,000) is cut to 8,000 head + 3,000 tail; read_file is exempt by default.

Held by

backend/packages/harness/deerflow/agents/middlewares/tool_output_budget_middleware.py:532

E4 Once a file written earlier has since been read or modified again, can the model stop seeing the old written content, and which recent writes must stay visible? RULING · code
Answered how

Code, only when elide_superseded_writes is turned on (default off at this pin): replaces the content argument of successful, superseded write_file calls in the model-bound request with a placeholder, above superseded_write_min_chars (2,000), keeping the newest keep_recent_writes (1); state, receipts and journal keep the original.

Held by

backend/packages/harness/deerflow/agents/middlewares/tool_output_budget_middleware.py:1065

E6 When the agent runs bash, in which environment, with which path rewriting, under which deadline, and how is long output cut? RULE · code
Answered how

Code: bash_tool initializes the sandbox, rewrites virtual paths and the working directory, runs the provider's execute_command with bash_command_timeout (default 600 s) and middle-truncates the output to bash_output_max_chars (default 20,000, 50/50 head/tail, exit marker kept).

Held by

backend/packages/harness/deerflow/sandbox/tools.py:2835 (execution :2345)

E7 When a command echoes a credential it was given, which values are replaced with [redacted]? RULE · code
Answered how

Code replaces every injected or blocked-name env value of at least 8 characters, longest first, with [redacted] in bash output and in bash error strings.

Held by

backend/packages/harness/deerflow/sandbox/tools.py:2418

E8 For read_file, which part of a long file is returned, and how is the model told where to continue? RULE · code
Answered how

Code head-truncates to read_file_output_max_chars (default 50,000) at the last line boundary and appends a marker naming the next start_line (or a whole-line / bash continuation for very long lines).

Held by

backend/packages/harness/deerflow/sandbox/tools.py:2566 (tool :3259)

E9 Is a write_file / str_replace executed as asked, and when is it refused (size cap, missing match), with what message? RULE · code
Answered how

Code: a non-append write_file refuses content over DEERFLOW_WRITE_FILE_MAX_BYTES (default 80 KiB, 0 disables) with guidance to split; appends are not size-checked; str_replace replaces one or all occurrences after matching the file's line endings. Whether the write may run at all is decided by a separate gatekeeping seat.

Held by

backend/packages/harness/deerflow/sandbox/tools.py:3375 (str_replace_tool :3509)

E10 Given the model's query, which results (titles, URLs, snippets) come back, from which provider, and how many? RULING · external
Answered how

An external search provider chosen by configuration (DuckDuckGo, Tavily, Brave, Serper, SearXNG, Exa, Firecrawl, InfoQuest, ...) ranks and returns results; each provider's web_search tool shapes them into text; image_search is the same family.

Held by

the configured web_search tool, e.g. backend/packages/harness/deerflow/community/ddg_search/tools.py:181 (setting tools[] in config.yaml)

E11 When the agent fetches a URL, which part of the page counts as its content, and how much of it is kept? RULING · code
Answered how

Code plus provider: the cited fetch tools keep at most the first 4,096 characters of the page content, with no truncation notice. Three of them (Jina, InfoQuest, Browserless) run DeerFlow's readability extractor (main-article choice); the others keep the content the provider returns.

Held by

backend/packages/harness/deerflow/community/jina_ai/tools.py:71 (readability call backend/packages/harness/deerflow/community/jina_ai/tools.py:70; same cut at backend/packages/harness/deerflow/community/infoquest/tools.py:120, backend/packages/harness/deerflow/community/crawl4ai/tools.py:137, backend/packages/harness/deerflow/community/browserless/tools.py:350, backend/packages/harness/deerflow/community/firecrawl/tools.py:170, backend/packages/harness/deerflow/community/fastcrw/tools.py:154, backend/packages/harness/deerflow/community/tavily/tools.py:130, backend/packages/harness/deerflow/community/exa/tools.py:164; constants backend/packages/harness/deerflow/community/sofya/tools.py:27, backend/packages/harness/deerflow/community/unbrowse/tools.py:27, backend/packages/harness/deerflow/community/groundroute/tools.py:37)

E12 When an MCP server answers, which content blocks reach the model (text, images, files, resource links), what becomes a placeholder, and when is the answer treated as a failure? RULE · code
Answered how

Code converts MCP content: text is kept (with local-path rewriting to virtual paths), images are kept, a ResourceLink becomes a text placeholder (an http(s) image also stays an image), a data:/blob: URI is omitted while its placeholder remains, structured content moves to the artifact channel; isError=true raises ToolException (then E1).

Held by

backend/packages/harness/deerflow/mcp/tools.py:476

E13 For MCP work submitted as a durable task, when is it complete, failed or still running? RULE · external
Answered how

The remote MCP server reports status through its status tool; code maps running to working, a valid task_not_found result or malformed structured output becomes a permanent failure, a status call that returns isError=true is retried, and a background service polls the task with leases.

Held by

remote server status tool, read by backend/packages/harness/deerflow/mcp/tasks/ordinary.py:204 (status map :88, task_not_found rule :154); polled with leases by McpTaskService at backend/app/mcp_tasks/service.py:1503-1554

E14 When the graph finishes, is the run recorded as success, error or cancelled, and with which stop reason? RULING (reclassified in pass 1: whether a guard-capped run "succeeded" is a judgment competent people would answer differently; the code answers "success + stop_reason") · code
Answered how

Code: cancellation wins; else any deerflow_error_fallback marker on a message produced in this run (from C3 or C4) or a journal-recorded fallback marks error; else a delivery-receipt check decides success vs error; a run stopped by a guard cap keeps its stop reason and goes through that same check, so it is recorded as success unless delivery fails.

Held by

backend/packages/harness/deerflow/runtime/runs/worker.py:1757 (marker scan :3680)

E17 Before a tool runs, are artifact handles in its arguments resolved to their content, and what happens to an unknown handle? RULE · code
Answered how

Code resolves handles in tool-call arguments when tool_artifacts.enabled and resolve_handles_in_args are on; unknown handles become error results inside the receipt ledger.

Held by

backend/packages/harness/deerflow/agents/middlewares/artifact_resolution_middleware.py:45-101

F. Limits and memory (19 seats)

F1 How many graph steps may one run take before it is stopped? RULE · code
Answered how

The Gateway takes the request's recursion_limit if it is a positive integer, otherwise the configured default, and caps it at max_recursion_limit; LangGraph raises when the run exceeds it and the worker marks the run error.

Held by

backend/app/gateway/services.py:1319

F2 Is the conversation long enough that older context must be compacted now? RULE · external
Answered how

Before each model call (only when summarization.enabled), the inherited LangChain SummarizationMiddleware._should_summarize compares the token count (messages plus the existing summary) with the configured trigger (tokens, messages, or a fraction of the run model's context window).

Held by

backend/packages/harness/deerflow/agents/middlewares/summarization_middleware.py:739

F3 Which older messages get folded into the summary and which stay verbatim? RULING · external
Answered how

The library's _determine_cutoff_index picks a cutoff from the keep policy (default last 20 messages); DeerFlow then rescues every SystemMessage, tagged dynamic-context reminders and the latest genuine user request from the to-be-summarized side, and drops todo reminders before partitioning.

Held by

backend/packages/harness/deerflow/agents/middlewares/summarization_middleware.py:749

F4 What should the summary of the compacted conversation say? RULING · llm
Answered how

A chat model (the configured summarization.model_name, falling back to the run model) gets the summary prompt filled with the messages to compact (chunked when long) and the previous summary, and returns free text that replaces those messages in summary_text.

Held by

backend/packages/harness/deerflow/agents/middlewares/summarization_middleware.py:491

F5 Is the agent stuck repeating the same tool calls, and should it be warned or stopped? RULING · code
Answered how

After each model response, code hashes the set of tool calls (name plus normalized args) and counts repeats in a sliding window per run; at 3 identical sets it queues a "wrap up" warning for the next model call, at 5 it strips all tool calls and forces a final answer (stop_reason=loop_capped); a separate per-tool-name frequency layer warns at 30 and stops at 50.

Held by

backend/packages/harness/deerflow/agents/middlewares/loop_detection_middleware.py:634

F6 Has this run spent its token budget? RULE · code
Answered how

After each model response, code sums usage_metadata of every AIMessage in state (tracking per-message deltas), compares total/input/output with the configured limits, injects a warning at 80% and at 100% strips tool calls and forces a final answer (stop_reason=token_capped).

Held by

backend/packages/harness/deerflow/agents/middlewares/token_budget_middleware.py:303

F7 Has a particular tool stopped producing anything useful, so it should be blocked? RULING · code
Answered how

When tool_progress.enabled, code keeps a per-(thread, tool) state machine: an error, a partial success, or a success whose word set is at least 0.8 Jaccard-similar to recent results counts as a problem; 3 problems warn, 2 more (non-recoverable kinds) block the tool; auth/config/internal errors block at once.

Held by

backend/packages/harness/deerflow/agents/middlewares/tool_progress_middleware.py:528

F10 How many turns may a sub-agent take? RULE · code
Answered how

The executor converts the sub-agent's max_turns (general-purpose 150, bash 60, config default 50) into a LangGraph recursion limit scaled by the assembled middleware depth; exceeding it raises GraphRecursionError, which the executor turns into completed (if the last AIMessage has any text) or failed, both with stop_reason=turn_capped.

Held by

backend/packages/harness/deerflow/subagents/turn_budget.py:128

F11 How long may a sub-agent run before it is timed out? RULE · code
Answered how

The executor runs the sub-agent as a task and waits on it with asyncio.wait(..., timeout=timeout_seconds); on timeout it sets the cancel event, records TIMED_OUT immediately and cancels the task, leaving teardown to a supervisor; the parent's poll loop has its own backstop of (timeout + 60) / 5 polls.

Held by

backend/packages/harness/deerflow/subagents/executor.py:2335

F12 What should long-term memory learn from this conversation? RULING · llm
Answered how

After a run (memory on by default, mode: middleware), the turn's filtered user and final assistant messages are queued; a debounced worker calls the DeerMem memory model with the current memory and the new conversation, and it returns JSON proposing new facts, removals, summary rewrites and reinforcements (staleness and consolidation are F14 and F15).

Held by

backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/updater.py:1991

F13 Which of the memory model's proposed writes are accepted? RULE · code
Answered how

Code gates each proposal: a fact is accepted only if the model labelled it scope=user, durability=durable, authority=descriptive; summaries need scope=user and authority=descriptive; removals need scope=user and a reason; staleness removals must be real aged candidates and are capped per cycle; exact-duplicate facts are rejected.

Held by

backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/updater.py:141

F14 Should an aged fact be kept, removed, or given a longer life? RULING · llm
Answered how

When staleness_review_enabled, code selects aged, non-protected facts and adds a review section to the same memory-update call (F12); the model proposes staleFactsToRemove / staleFactsToExtend, which code intersects with the real candidates, caps per cycle (lowest confidence removed first) and bounds.

Held by

backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/updater.py:1991

F15 Should several related facts be merged into one? RULING · llm
Answered how

When consolidation_enabled, code selects candidate groups and adds a consolidation section to the memory-update call; the model proposes factsToConsolidate, which code validates at apply time.

Held by

backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/updater.py:1991

F16 Which facts are kept when memory is over capacity? RULING · code
Answered how

Code ranks facts by the configured policy and keeps max_facts: the default confidence policy keeps the facts with the highest stored confidence value; the opt-in hybrid-v1 policy keeps a few slots for corrections and fills the rest by a mix of confidence, confirmation freshness and access heat. Imports, new facts and automatic extraction enforce the cap; edits do not.

Held by

backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/eviction.py:157

F17 Is this conversation batch worth paying for a memory extraction call at all? RULING · external
Answered how

When memory.prescreen.mode is shadow or enforce (default off), a hosted TypeSafe classifier is asked whether the batch holds anything durable; in enforce, a "skip" verdict drops the extraction call and advances the watermark; any failure means extraction runs as usual.

Held by

backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/updater.py:1927

F18 Which messages are flushed into memory before compaction deletes them? RULE · code
Answered how

A before_summarization hook hands the about-to-be-summarized messages to the memory manager's immediate queue, with the watermark bypassed, unless the agent opted out of memory.

Held by

backend/packages/harness/deerflow/agents/memory/summarization_hook.py:14

F20 Should the model itself save, change or delete a memory fact right now (tool mode)? RULING · llm
Answered how

With memory.mode: tool, the lead model gets memory_add, memory_update and memory_delete (plus search and get) and decides when to call them; the write goes to storage through the capacity policy without the extraction scope gate.

Held by

backend/packages/harness/deerflow/agents/memory/tools.py:119

F21 What should the model note down for later in a long task, and what compacted history is archived? RULING · llm
Answered how

When task_continuity.enabled (default off), the model may call task_note to save keyed working notes that are re-injected into later requests, and code archives compacted messages into bounded batches searchable through history_search / history_read.

Held by

backend/packages/harness/deerflow/agents/task_continuity/tools.py:155

G. Judging the result (7 seats)

G1 Has the thread's active goal been fully met, judging only from what the conversation shows? RULING · llm
Answered how

After every run turn on a thread with an active /goal, the worker asks a chat model (the run's own model with thinking off) for a JSON verdict; a parsed satisfied: true makes the run a completion candidate, anything else either continues or stands down.

Held by

backend/packages/harness/deerflow/runtime/goal.py:539

G2 Is the finished turn in a state the goal evaluator may judge at all? RULE · code
Answered how

Before calling the evaluator, worker code stands the goal down without a model call if the turn ended on an unanswered Human Input Card (needs_user_input) or if there is no durable, fully checkpointed assistant end-of-turn (run_failed, no_durable_end_of_turn).

Held by

backend/packages/harness/deerflow/runtime/runs/worker.py:2806

G3 Should another hidden "keep working" turn be started for the goal? RULE · code
Answered how

Code: continue only when the verdict is not satisfied, the blocker is goal_not_met_yet, continuations used < max_continuations (capped at 8), no-progress count < max_no_progress_continuations (default 2), and the run did not end on a token or loop hard stop (token_capped / loop_capped); then a hidden <goal_continuation> HumanMessage restarts the graph.

Held by

backend/packages/harness/deerflow/runtime/goal.py:614

G4 Has the goal stopped making progress? RULING · code
Answered how

Code hashes the text of the latest visible assistant message; if the blocker and that hash are the same as the previous evaluation's, the no-progress counter increments, otherwise it resets to 0. When the turn made tool calls and the previous evaluation recorded operation hashes, the counter instead resets to 0 only if the turn produced a successful tool result (tool name, arguments, output hash) not in that recorded set, and otherwise increments, whatever the reply text.

Held by

backend/packages/harness/deerflow/runtime/goal.py:677

G5 Did the run actually hand over the output files it produced? RULING · code
Answered how

At run end, worker code diffs a before/after workspace snapshot of the outputs directory; if any file changed and none of the changed paths is covered by a present_files call this run, the run is marked error ("Artifact delivery incomplete") instead of success; a satisfied goal is cleared only after this passes.

Held by

backend/packages/harness/deerflow/runtime/runs/worker.py:402

G7 Do the receipt ids a sub-agent cites in its report point to real, successful tool calls? RULE · code
Answered how

When a task sub-agent completes, code parses every [rN] / [rN tool_name] citation in its report and checks each against the receipts harvested from the child's own tool calls; unknown ids or non-success receipts make citation_resolved false; a report with action-like wording and zero citations is flagged UNVERIFIED. The verdict is shown to the lead; it never changes the task status.

Held by

backend/packages/harness/deerflow/agents/middlewares/receipt_verification.py:79

G8 Do the lead's acceptance criteria for a delegated task hold, as far as code can tell? RULING · code
Answered how

When the lead attached acceptance_criteria to task (or batch_task), code checks each criterion after the child finishes: file: exists / non-empty / json-valid / csv-columns and file_written: by bounded reads in the shared workspace, tests_passed:<cmd> by matching a recorded bash execution with a success exit and a recognised test-summary shape; everything else is UNVERIFIED. The checklist is appended to the result the lead reads.

Held by

backend/packages/harness/deerflow/subagents/acceptance_checks.py:2155

H. Delegation (10 seats)

H1 Should this work go to a sub-agent, and with which type, prompt, acceptance criteria and context? RULING · llm
Answered how

The lead model decides by emitting a task tool call with prompt, subagent_type, optional acceptance_criteria and context_mode (isolated or snapshot); the tool then validates and runs it.

Held by

backend/packages/harness/deerflow/tools/builtins/task_tool.py:755

H2 May a delegation of this type run for this caller? RULE · code
Answered how

Code rejects the call unless the type is in the registry (built-ins, config custom agents, managed definitions) AND in the caller's snapshotted allowed_subagents list; bash is rejected when host bash is not allowed.

Held by

backend/packages/harness/deerflow/tools/builtins/task_tool.py:906

H3 How many sub-agents may the lead start in one response and in one run? RULE · code
Answered how

After each lead model response, code keeps at most max_concurrent task calls (resolved against process capacity, 1-64) and at most max_total per run (default 6, 1-50) counted from current-run entries in the durable delegation ledger; excess calls are stripped, and when the run total is exhausted a visible limit note is appended and stop_reason=subagent_limit_capped is set.

Held by

backend/packages/harness/deerflow/agents/middlewares/subagent_limit_middleware.py:147

H4 Is there a free slot to run this sub-agent now, or must it queue or be refused? RULE · code
Answered how

A process-wide admission controller (default 3 running) admits the execution, queues it up to max_queued with a timeout, or rejects it immediately under the reject policy or when the caller asks for a no-wait slot (the executor does so when the task's input gate cannot queue, backend/packages/harness/deerflow/subagents/executor.py:1690).

Held by

backend/packages/harness/deerflow/subagents/capacity.py:68

H5 Which parts of the parent conversation go along with a delegated task? RULING · code
Answered how

With context_mode="snapshot" (chosen by the lead, H1), code captures the parent's summary_text plus retained genuine user messages, visible AI messages and paired tool results as one background HumanMessage of neutralized historical data; with isolated (default) only the delegated prompt goes.

Held by

backend/packages/harness/deerflow/subagents/context_snapshot.py:98

H6 What does the sub-agent do, and what does it report back? RULING · llm
Answered how

The sub-agent runs its own model-tool loop on the delegated prompt, with its own system prompt plus a framework report contract. Its result is the matching direct-return tool result when the last turn ended on one, otherwise its last AIMessage text, otherwise the last message, or "No response generated".

Held by

backend/packages/harness/deerflow/subagents/executor.py:1933

H7 Did the sub-agent finish, fail, or stop on a cap? RULE · code
Answered how

At termination the executor reads the final state: a marked LLM-error fallback means FAILED; a direct-return tool error means FAILED; otherwise COMPLETED with any guard stop reason (token_capped, loop_capped, or model_length_capped when the provider cut the response at its output limit, backend/packages/harness/deerflow/subagents/executor.py:1398-1401); a turn-cap error salvages the last AI text as COMPLETED or else FAILED (F10); timeout gives TIMED_OUT (F11).

Held by

backend/packages/harness/deerflow/subagents/executor.py:2018

H8 What does the lead see about a finished delegation, and which earlier delegations stay open in its context? RULE · code
Answered how

Code formats the status, result, stop reason and verdicts into the task ToolMessage and its metadata, records each delegation in the durable ledger projected into later model calls, and on a new user turn marks earlier-run delegations still in_progress with no reply as cancelled.

Held by

backend/packages/harness/deerflow/agents/middlewares/durable_context_middleware.py:247

H9 Should a large set of tasks be submitted as a durable background batch? RULING · llm
Answered how

When the SQL-backed batch submitter is installed, the lead model may call batch_task with item keys, self-contained prompts and per-item criteria; a lease-based service runs items through the same executor and slots, and the lead later reads results with batch_status / read_batch_result.

Held by

backend/packages/harness/deerflow/tools/builtins/batch_task_tool.py:154

H10 What does an external coding agent do with a task handed to it over ACP? RULING · external
Answered how

When ACP agents are configured, the lead model may call invoke_acp_agent; DeerFlow launches the configured external agent process (for example a Codex or MiniMax adapter), sends the prompt, and returns only its message text; the external agent decides how to do the work.

Held by

backend/packages/harness/deerflow/tools/builtins/invoke_acp_agent_tool.py:275

I. Learning and feedback (5 seats)

I1 Was this run's answer good (thumbs up or down)? RULING · human
Answered how

A person rates a run +1 or -1 (with an optional comment) through the feedback API; the rating is stored per run and user and shown back in run and message listings.

Held by

backend/app/gateway/routers/feedback.py:62

I2 Which saved memories about me are right? RULING · human
Answered how

A person creates, edits or deletes individual memory facts through the memory API or settings UI; manually authored facts are marked [MANUAL] in the next extraction prompt and the prompt asks the extraction model to keep them unless the user explicitly corrects them; code does not enforce it.

Held by

backend/app/gateway/routers/memory.py:412

I3 Should the agent rewrite its own persona, skills, tools or model for future turns? RULING · llm
Answered how

In a custom agent's chat (not on webhook channels), the lead model may call update_agent to replace its own SOUL.md and change its description, skill allow-list, tool-group allow-list or default model; the change takes effect on the next user turn.

Held by

backend/packages/harness/deerflow/tools/builtins/update_agent_tool.py:78

I4 Should the bootstrap conversation create a new custom agent, and with what persona and config? RULING · llm
Answered how

In the bootstrap flow, the model calls setup_agent to persist a new agent's SOUL.md and config.yaml.

Held by

backend/packages/harness/deerflow/tools/builtins/setup_agent_tool.py:58

I5 Should the agent save what it learned as a reusable skill, or edit an existing one? RULING · llm
Answered how

When skill_evolution.enabled (default off), the lead model may call skill_manage to create, edit, patch or add files to a custom skill; each write passes the static SkillScan gate (which returns no findings when SkillScan is turned off, backend/packages/harness/deerflow/skills/skillscan/orchestrator.py:228-229) and an LLM moderation call before it lands, and is recorded in skill history after it is written. If the moderation call fails, non-executable content can still be written when security_fail_closed is false (backend/packages/harness/deerflow/skills/security_scanner.py:181-186).

Held by

backend/packages/harness/deerflow/tools/skill_manage_tool.py:353

How this map was made

Four readers each took a part of the agent and wrote seat cards from the source at an earlier commit. The map's author re-read every seat and corrected what the source did not support. For this edition every shown card was carried to the commit named above: its citations whose lines moved were renumbered, and every shown card citing code that changed was re-read at that commit. Reviews by a model from another family (read-only, at the commit named above) checked the answers against the code, and each of their findings was checked against the code before anything changed. Nothing on this page was produced by running their code.