Codebase structure
This page says which package should own a change.
Choose a destination #
reef/ holds every shared mechanism, including the harness evolution engine at reef/train/harness_backend/ and the harness source tree at reef/harness/tree/. The built-in SFT recipe lives under reef/recipe/sft/, and its Slime loss family is in reef/train/slime_backend/sft.py. Paper-backed methods live in separate packages under recipes/ (sao, tttd, openclawrl, gepa, meta_harness, ace, reasoning_bank). Beta methods live under recipes/beta/ (coral, spade, autoenvscaling, reefine) until they publish reproducible results. A weight method holds its recipe, processor and training objective, with the slime/ subpackage only the training plane imports. A harness method holds its Method, its prompts, and a scorer when it needs its own; it adds a recipe subclass only when it changes more than the tree, such as the delivery surface. Nothing under reef/ imports a method package.
Reef is organized around an application kernel and three capability domains, not a strict stack of top-level packages. The arrows below show the primary composition and use paths; they are not an exhaustive Python import graph:
Method packages provide policy through reef/recipe and may bind reef/train machinery directly. HTTP and CLI entrypoints compose Reef through reef/service; the transport-free dispatcher and scenario aggregate coordinate serving, evolution, and state. reef/service also imports reef/artifact directly to stream artifact bytes.
Concrete integrations may depend on shared contracts; shared contracts never import a concrete integration.
|
Package |
Owns |
Does not own |
|---|---|---|
|
reef/core/ |
shared value types, wire shapes, artifact identity, root errors |
storage, I/O, runtime behavior |
|
reef/service/ |
HTTP routes, auth, streaming, process lifecycle |
training methods or domain logic tied to aiohttp |
|
reef/scenario/ |
scenario binding, commit ordering, recovery, and lifecycle |
training algorithms, repository implementations |
|
reef/recipe/ |
the contract a method implements, dotted resolution, runtime binding, the base harness evolution recipe, and the built-in generated-task recipe |
external cookbook methods |
|
reef/train/ |
the trainer, the training job loop, the training pipeline, job data types, training components |
HTTP endpoints, deployment configuration parsing |
|
reef/record2sample/ |
which records Reef uses, which train together, and their samples (Record2Sample, ReportSamples, JudgedSamples): report grouping, judging, eligibility checks, the staleness check; the samples service; and the generator service that writes, checks, and runs Harbor tasks |
job data shape, record storage, training loops |
|
reef/evaluation/ |
candidate evaluation: running and scoring evaluation runs, the harness history and its score cache, the harness publication policies, and the evaluation plugin configuration |
making candidates, training loops, artifact publication |
|
reef/sample2job/ |
shaping the samples of the buffer into one job's data (Sample2Job), and the job size |
which records train, the training loop, step signals |
|
reef/runtime/ |
backend-neutral contracts: training components, inference runtimes, saved-weight serving, executors |
concrete inference and training integrations |
|
reef/inference/ |
concrete inference backends, native engine control, request adaptation and loading saved weights |
training algorithms and publication decisions |
|
reef/surface/ |
delivering a published artifact to the process or client that uses it |
proposing, evaluating, or selecting updates |
|
reef/artifact/ |
artifact bytes, repositories, materialization, release heads |
commit policy or delivery behavior |
|
reef/harness/ |
adapters (the parts of each agent's tree and its descriptor), the source tree (patches, validation, rendering), task runs, runners, trajectories, and the loopback gateway an agent process reaches its model and tools through |
recipe policy, the release chain |
|
reef/execution/ |
job scheduling, process ownership, isolation, file transfer and environment lifecycle |
harness rendering, evaluation, recipe policy |
|
recipes/ |
one method per package: the recipe, processor and objective of a weight method, or the Method of a harness method, with its runnable examples |
shared machinery, or another method |
|
tests/ |
repository-level tests grouped by responsibility |
tests hidden inside an integration subtree |
|
docker/ |
container and GPU environment setup |
Python dependency declarations |
Package import direction #
Imports between the top-level Reef packages form a directed acyclic graph. tests/contributing/test_dependency_boundaries.py scans every Python file, including relative imports and imports inside functions. Importing the root reef facade from an internal package also counts as a dependency; internal code imports the owning module directly.
The following table records direct package dependencies (excluding each package's own submodules and third-party libraries):
|
Package |
Imports |
|---|---|
|
core |
None |
|
storage, artifact |
core |
|
observability |
storage, core |
|
surface |
artifact, core |
|
runtime |
surface, artifact, core |
|
inference |
runtime, artifact, core |
|
execution |
core |
|
harness |
inference, execution, runtime, surface, artifact, core |
|
evaluation |
harness, execution, runtime, core |
|
train |
evaluation, harness, execution, runtime, artifact, storage, observability, core |
|
recipe |
train, evaluation, harness, execution, inference, runtime, surface, artifact, storage, observability, core |
|
scenario |
recipe, train, inference, runtime, surface, artifact, storage, observability, core |
|
dispatcher |
scenario, recipe, train, harness, runtime, artifact, storage, observability, core |
|
service |
dispatcher, scenario, recipe, train, inference, harness, runtime, surface, record2sample, evaluation, execution, artifact, storage, observability, core |
|
cli |
service, core |
execution/lifecycle.py defines the shared Execution interface using only the standard library. execution/processes.py adds local process ownership and depends only on that interface and the standard library. execution/jobs.py depends only on these two modules and the standard library. Sandbox executors and generator checks also use execution/processes.py for local child ownership. The shared worker must not import execution.sandbox or its providers and executor adapters.
Shared job data and candidate evaluation contracts live in core/job_data.py and core/evaluation.py. core/training_request.py validates training-request payloads and holds the queued instruction carried by a job's data. Request requirements and their release-chain interpretation live in core/requirements.py. Storage owns commit record encoding; scenario owns commit ordering and recovery. Artifact admission lives with surface contracts. recipe/harness.py assembles the harness evolution backend. service/deploy/training.py selects the training deployment definition that training.backend names and assembles the services it needs; service/deploy/inference.py adds the local inference component when the deployment serves saved weights on one. runtime/ is a namespace package with exactly seven Python modules and the executor/ package; it has no __init__.py or import facade:
runtime/ interfaces.py jobs.py durable_files.py deployment.py recovery.py residency.py serving.py executor/
interfaces.py defines the InferenceRuntime and InferenceBackend contracts, TrainingMethod and its learning-rate schedule, and runtime load IDs. jobs.py defines bounded training jobs and the TrainingComponent interface. deployment.py owns runtime factories, RuntimeRegistry and the inference service contracts. durable_files.py writes JSON files and directories durably, for the training components' job records. recovery.py owns InferenceControl and EngineHealthMonitor. residency.py holds the AdapterResidencyManager. serving.py loads saved weights into serving engines that the control plane controls directly. executor/ owns worker launch and control RPC.
jobs.py, interfaces.py and durable_files.py import no other runtime module; serving.py may import every other module except executor/. tests/contributing/test_dependency_boundaries.py checks this order. Runtime contracts have no direct imports of concrete inference or training code; the deployment registry resolves the selected factory explicitly.
In train/, trainer.py holds the Trainer; jobs.py holds the JobLoop and the committed JobLoopState; local_jobs.py holds LocalJobComponent, the base of the built-in training components; deployment.py holds the TrainingDeployment definitions; and backend.py holds PreparedStep and the committed releases that a harness step reads its head from. train/slime_backend/component.py and train/tinker_backend/component.py supply the Slime and Tinker training components, and each launch.py supplies its deployment definition and runtime factory. Both components render each sample that has no tokens with core/chat_rendering.py, which turns an ATIF trajectory and its teacher requests into token IDs with the model's chat template. It is in reef/core/ because train/ must not import inference/. No training backend builds serving: service/deploy/serving.py selects and configures it from the inference section and the component's release format.
HTTP provider handling lives in inference/http.py. inference/provider_protocol.py holds the provider wire format that the proxy, the model clients and the recorders share: authentication headers, Server-Sent Events, stream folding and token usage. inference/chat.py holds the engine-neutral OpenAI and Anthropic chat facade over a token-native generate route: it renders the prompt, builds the provider response from a CapturedGeneration and streams protocol frames. The response carries no training tensors. Each engine supplies a NativeGenerateClient that shapes its request, parses its response and builds its tool-call parser. inference/engine_control.py holds the control classes that SGLang and vLLM share: the inference backend, the inference service, the control actor and its default serving executor. inference/sglang/ owns SGLang engine launch, response parsing and control independently of training; inference/vllm/ owns vLLM response parsing, the KV connector that stamps tokens with their weight version, and engine launch and control over vLLM's HTTP control routes. inference/remote/ is the inference component: python -m reef.inference.remote runs the engines and serves their control operations and requests over HTTP. RemoteInferenceBackend is the control plane's client for it, and inference/remote/runtime.py supplies the remote_serving runtime kind and builds the engines' input (serving_engine_config). inference/null.py is the runtime of inference.backend: none: it runs no engine and refuses every request. inference/tinker.py serves Tinker's sampler. tinker/ holds the Tinker SDK pieces that the Tinker training component and the Tinker serving runtime share: tinker/sampling.py renders and samples text chat, for serving and, with the training capture, for the component's own rollouts.
The extension points those packages expose are in Python API.
-
Is it a value or error needed by unrelated layers without behavior attached? Put it in reef/core/.
-
Does it own scenario state, commit ordering, recovery, activation, or training starts? Put it in reef/scenario/. reef/storage/commits.py defines the persisted CommitRecord and RecordProgress values without storage behavior. Checkpoint recovery uses the same CommitRecord type; initial registration has no commit. reef/storage/scenario.py defines the ScenarioStore and ScenarioStorage abstract bases. storage/commits.py also encodes artifact metadata and decodes existing checkpoint metadata into registration information and a CommitRecord. ScenarioFactory receives the storage service from deployment assembly and handles registration, release selection, and recovery. It opens a session, restores committed artifacts, builds the trainer, replays records, and returns a complete Scenario; failure closes its owned resources. committer.py owns writes and retry ordering; releases.py owns release and artifact queries under the same publication lock. history.py pages retained records and commits. registry.py owns loaded instances and scenario archival coordination. The registry reads and writes each scenario's settings (such as the training mode and the activation rule) through the injected ScenarioStorage, like records and commits; it imports no storage implementation. Dispatcher calls the storage service directly for retention and closes it after closing the loaded scenarios. It never imports or chooses a concrete record backend.
-
Does it define shared record operations or retention limits? Put the contract or value in reef/storage/records.py. It defines the RecordStore abstract base without importing scenario coordination, training, or concrete adapters. ScenarioStore combines a RecordStore with committed scenario state and opens the scenario's task stores (reef/storage/tasks.py) and its sample store (reef/storage/samples.py); ScenarioStorage owns scenario settings, archival, and retention.
-
Does it turn a designer's replies into Harbor tasks, check them with Harbor or run them with an agent? Put it in reef/record2sample/generator/, the generator service reef serve starts beside the HTTP service from a generator section. reef/service/deploy/generator.py assembles that child, and reef/service/deploy/generator_process.py runs it. The built-in generated-task recipe, which generates tasks through that service and trains on them, is in reef/recipe/generated_tasks/, with the TaskGenerator contract (generator.py). The request, TaskGenerationRequest, is in reef/record2sample/generator/inputs.py, because the generator service reads it too. reef/core/tasks/ keeps the Harbor task values and the split manifests. What a method asks the designer for, and what it does with the results, stays in the method's task generator under recipes/.
-
Does it implement storage? Put it in reef/storage/. sql_records.py shares SQL record and retention operations, and ScopedTable, one table with the namespace of one store. sql_tasks.py, sql_samples.py, sql_evaluations.py and sql_commits.py share the task, training sample, artifact evaluation and commit tables and their operations in the same database. tasks.py holds the local TaskFileStore next to the task contracts. sqlite.py supplies SQLite schema, connections, transactions, and file maintenance. postgres.py supplies PostgreSQL tables, pooled transactions, and retention. commit_history.py owns the CommitHistory base and CommitHistoryScenarioStore, which accepts any RecordStore, TaskStorage and CommitHistory. migrations.py holds one-time upgrades of older schemas and files. sqlite.py and postgres.py assemble their respective scenario storage services against the interfaces in scenario.py. Storage implementations depend on domain contracts, never the reverse.
-
Does it persist or materialize versioned bytes? Put it in reef/artifact/. If it decides how consumers activate those bytes, put that behavior in reef/surface/ instead.
-
Does it define a backend-neutral model-service contract? Put it in reef/runtime/, beside the training component and serving contracts. Put concrete inference engines and their request/control adapters in reef/inference/<integration>/; put implementation tied to a concrete training stack in its own reef/train/<integration>/ subtree. reef/train/slime_backend/ trains weights.
-
Is it part of harness evolution? Each part has one owner. Data, evaluation and release are Reef's, shared with weight training; evolve and sync are the harness's own. reef/harness/tree/ holds the tree that every part reads, and reef/train/harness_backend/backend.py runs one step through evolve, evaluation and release. component.py is the harness training component: it runs each step as one training job, in the training service, and keeps the harness state after each job in the job's outcome.
-
Data: the training pipeline below turns the agent's recorded calls, their reports and the uploaded tasks into a step's job data. The harness backend only reads job data.
-
Evolve: HarnessBackend.propose in backend.py makes the step's candidate. The backend holds the deployment's Method; propose calls Method.step once in the step's workspace (workspace.py) and reads back the tree. contract.py is the method contract. agent/ runs the deployment's coding agent for a method (evolution.agent, AgentMethod, protocol.md). It starts the agent with launch_agent in reef/harness/tasks/run.py, as an evaluation run does, and reef/harness/gateway.py is the loopback gateway the agent reaches its model and tools through.
-
Evaluation: reef/evaluation/ holds the contract that every candidate passes, weights and trees alike (evaluate, then decide). reef/evaluation/harness/evaluator.py scores trees by running tasks, with the history as the score cache, and policy.py decides.
-
Release: the harness backend turns a selected tree into the step's release, and the recipe's HarnessJobLoop names the parts that it changes from the job's start (changed_kinds). The scenario committer publishes it, and the scenario's activation rule (reef/evaluation/activation.py) decides whether it serves.
-
Sync: reef/harness/sync.py moves a tree between Reef and a person's machine, in both directions: the release as a layer over the person's own configuration (run.layer of the adapter's adapter.yaml), and the person's changes merged back (the merge of each part in its parts). The client half is reef_client.harness.
-
-
Does it decide which records train, in which groups, or how a record set becomes samples? Put the shared contract in reef/record2sample/. Does it shape samples into job data? Put it in reef/sample2job/. Does it turn job data into a step signal? Put it in reef/train/algos/. reef/train/pipeline.py drives the two stages. A recipe selects and binds that machinery; it should not reimplement it.
-
Does one service tell another what to do? Do it through the shared store, not a call. reef/storage/work_queue.py defines the WorkQueue contract of the jobs, samples, evaluations and data queues; reef/storage/served_models.py the served_models table, which control writes and the inference service reads; reef/storage/control_lease.py the lease that makes one control instance active; and reef/storage/marks.py the named positions that a service keeps, such as how far the data service copied each scenario's records. reef/storage/sql_coordination.py keeps these tables in SQLite or PostgreSQL. reef/execution/workers.py holds QueueWorker, the loop that takes, leases and finishes queue items. The workers that take queue items live with their service: reef/train/job_queue.py (training), reef/record2sample/service/ (samples), reef/evaluation/rollout_worker.py (evaluation) and reef/service/data_service.py (data). Control's writer of served_models, its watcher of the store and its worker of the data_sync items are in reef/dispatcher/served.py, reef/dispatcher/store_changes.py and reef/dispatcher/data_sync_worker.py. reef/service/inference_service.py is the inference service, and reef/service/components.py builds the app of each service for reef serve --component.
-
Does it handle the data routes? reef/service/data.py creates, reads, updates and deletes data items and asks control to sync the touched scenarios (reef/storage/data_sync.py). reef/service/data_transfer.py runs imports, exports and item archives, and reef/service/scenario_files.py reads an artifact's files and a scenario's training jobs. reef/storage/record_items.py copies records to record items. reef/storage/artifact_items.py defines the artifact items of the artifact library, and copy_scenario_artifacts in reef/service/data_service.py makes them. create_data_app in reef/service/app.py builds the data service's app; the aiohttp adapters are reef/service/routes/data.py and reef/service/routes/scenario_files.py.
-
Is it HTTP-specific? Keep the aiohttp adapter in reef/service/routes/ and put transport-independent behavior in a service or domain object.
-
Does it orchestrate a benchmark, task, grader, or external environment? Keep it under recipes/<name>/examples/ or in the external harness.
Repository-level homes #
Code for a concrete training integration lives together under reef/train/<integration>/, but its surrounding files remain at repository level:
-
component and integration tests in tests/<owner>/;
-
cookbook method tests in tests/recipes/<method>/;
-
import and packaging contracts in tests/plugin_contracts/;
-
service-facing contracts in tests/reef_service/;
-
the learn-nothing deployment stacks, and the smallest example around them, in recipes/basic/;
-
configuration for one runnable deployment under recipes/<name>/examples/;
-
container and environment setup under docker/; and
-
Python dependencies, package data, and plugin entry points in pyproject.toml.
The test directory map defines the owner directories, shared support, and rules for moving tests.
Do not copy third-party source into an integration subtree. Pin or declare the dependency in pyproject.toml and keep Reef-owned adapters local to the integration.
Where the detailed rules live #
Each package's __init__ docstring states the boundaries it holds and how to extend it; there are no READMEs under reef/. Design pages for the two packages that need more than a docstring are Surfaces and Training pipeline; the extension points every package exposes are in Python API, and the public harness wire contract is HTTP API. The top-level README shows how the cookbook methods sit beside reef/.
The harness method contract is in the reef/train/harness_backend/ package docstring, and Write a harness method explains it. reef/harness/adapters/parts.py defines the parts a harness tree may hold, and each adapter declares its own parts in the evolve section of its adapter.yaml, such as reef/harness/adapters/pi/adapter.yaml. Harness adapters explains the file.
Adding a new subpackage under reef/ or a new method under recipes/ requires an RFC that states which layer owns the behavior.
Deployment modules #
reef/service/deploy/ separates configuration input from process startup:
-
config_utils.py reads YAML, expands environment/config references and locates recipe source packages. It does not download models or validate process graphs.
-
service_config.py declares shared HTTP, storage and runtime fields and converts effective values into ServiceConfig for app assembly. With a task-import section, assembly wraps the scenario storage in reef/service/task_import.py, so that each scenario that opens imports the deployment's Harbor tasks.
-
deployment_config.py declares DeploymentConfig defaults, loads selected recipe/runtime declarations, translates the versioned public layout and validates component values.
-
cli.py builds help and applies dotted command-line overrides before shared type conversion. CLI values take precedence over YAML.
-
inference.py assembles provider or local inference processes and resolves model snapshots; training.py selects training deployment definitions and assembles the training dependencies and HTTP process.
-
execution.py validates process definitions and dependency order and selects executors. process.py owns worker processes; guard.py cleans up a remote process group when its Ray owner disappears.
-
diagnostics.py lists the resolved settings with their sources (file, command line, environment, automatic, default) for the startup log, masking credentials.
-
orchestrator.py coordinates configuration resolution, launch, readiness, supervision and shutdown, including the internal HTTP child entrypoint.
Shared parsing types come directly from reef.core.config. Native backend argument encoding comes from reef.runtime.executor.arguments. The package exports in reef.service.deploy remain the entrypoints for app assembly and launching; internal module names are not a compatibility API.