Skip to content

Stage 0: Environment and Source Code Map

Course: DeerFlow Source Code Class · Stage Exam Prerequisites: Able to read Python and TypeScript, familiar with HTTP and asynchronous tasks Corresponding Overview: overview.md Goal of This Stage: When seeing any file, be able to determine whether it belongs to the ‘reusable kernel,’ ‘product assembly layer,’ or ‘runtime assets.’

DeerFlow has a considerable amount of code, but not many entry points. First, establish a three-layer map:

Reusable core: agent, tools, sandbox, models, runtime
backend/packages/extension-api/ Extension Contract
backend/app/ Product assembly: Gateway, channels, scheduling, MCP tasks
frontend/ + contracts/ + deploy/ Interface, cross-end contracts, deployed assets

The most important hard boundary is:

app/* → deerflow/* allowed
deerflow/* → app/* forbidden

This is not about being a pedant with the directory. deerflow It should be reusable by embedded clients, SDKs, and other hosts; once the core imports a certain Web route or IM table, it is no longer a general harness. backend/tests/test_harness_boundary.py Turn this rule into a CI failure.

“Can this code exist independently of a specific product entry in DeerFlow?”

If yes, it usually belongs to the harness; if not, it usually belongs to the app. When you see from deerflow..., you are reading the core; when you see from app..., you are reading the host assembly. Dependencies like app appearing in the core are boundary degradation, not for “convenient reuse.”

  1. The ASGI entry is at backend/app/gateway/app.py, the routing is at backend/app/gateway/routers/.
  2. The unified admission function is backend/app/gateway/services.py::start_run.
  3. The Run control plane is at runtime/runs/manager.py, and the execution plane is at runtime/runs/worker.py::run_agent.
  4. The Agent factory is agents/__init__.py::make_lead_agent, ultimately entering agents/lead_agent/agent.py and agents/factory.py.
  5. Capability boundaries are handled respectively by tools/, sandbox/, models/, mcp/, skills/.
  6. State and evidence are handled by runtime/checkpointer/, runtime/journal.py, runtime/events/.
  7. Product extensions are at backend/app/channels/, backend/app/scheduler/, backend/app/mcp_tasks/.
Object Facts Owned Should Not Be Forged By
RunRecord run state, owner, lease, idempotency key client, single middleware
ThreadState.messages dialogue state of the current graph any metadata in external requests
checkpoint LangGraph recoverable state business database records
RunJournal run events, tool/delivery facts SSE consumers
sandbox lease usage rights of a particular isolated execution path parameters generated by models
frontend / SDK
→ app.gateway.app
→ routers/thread_runs.py
→ services.start_run
→ RunManager
→ worker.run_agent
→ make_lead_agent
→ tools / sandbox / model
→ journal / checkpoint

Observation point: When a request returns, Run is often still pending; the real running appears after try_start() in the worker. Do not infer that the model has started executing based on the HTTP return time.

终端窗口
rg -n "from app" backend/packages/harness/deerflow

Reference acceptance: There should be no legitimate hits of kernel dependencies on the app; If they do, first determine whether it is a test or compatibility bridge.

Experiment B: Confirm the configuration entry

Section titled “Experiment B: Confirm the configuration entry”

Open the root directory config.example.yaml and find the five types of configurations: model whitelist, sandbox provider, summarization, memory, and channel. Reference observation: The configuration is “what is allowed,” not “what the client wants to use.”

Mark 3000, 8001, 8002, and 2026 respectively as frontend, Gateway, sandbox provisioner, and reverse proxy. The acceptance point is that each port only undertakes one clear role.

  1. Valid results should only appear in tests, samples, or explicit compatibility bridges from app; If harness production code depends on an app, it means the kernel boundary is inverted.
  2. It should be able to locate the model whitelist, sandbox provider, summarization, memory, and channel configurations separately; These constraints restrict what the server allows, and client requests can only be selected within these constraints.
  3. Confirm the sole responsibility of each port according to the actual warehouse configuration: do not use frontend, Gateway/API, sandbox provisioner, or reverse proxy together; The value of port diagrams is to expose error coupling.
Phenomenon Check first What not to do
Import error at startup Dependencies, Python version, working directory Change business code to mask environment issues
Harness Reverse Dependency App test_harness_boundary.py Delete the test
Frontend cannot connect Gateway port, proxy, authentication Directly bypassing start_run
sandbox cannot start provisioner and provider configuration Switch to the host shell to “run first”
  1. deerflow Why can’t I import app?
  2. What do RunRecord, checkpoint, and RunJournal each store?
  3. Why can’t HTTP return to check that Run has been running?
  4. How do you distinguish the responsibilities of port 8001 and 8002?
  1. Because deerflow is a reusable kernel, and app is the assembly layer of a product host. Reverse dependencies bind the kernel to specific Web/IM/databases, losing the reusability of embedded clients, SDKs, and other hosts, and are blocked by boundary testing.
  2. RunRecord Stores control surface status, owner, leases, and powers; Checkpoint stores the recoverable graph state of LangGraph; RunJournal Stores process events, tokens, tools, and delivery facts. The former manages scheduling, the middle manages continuation, and the latter manages observation and auditing.
  3. The routing returns the order result, so Run may still be pending. Only after the worker completes state migration and acquires ownership through try_start() does it become running; This delay is the window for queuing, cancellation, and concurrency competition.
  4. 8001 is the FastAPI Gateway, responsible for admission, authentication, SSE, and product assembly; 8002 is the sandbox provisioner control service, responsible for preparing and reclaiming the isolated environment, and does not handle the Run lifecycle.
  • backend/tests/test_harness_boundary.py
  • backend/app/gateway/app.py
  • backend/app/gateway/services.py
  • backend/packages/harness/deerflow/agents/__init__.py
  • backend/packages/harness/deerflow/runtime/runs/manager.py

Entering Stage 1: Split “Acceptance” into verifiable status migration and explain why pending is not a decorative state.