Gears
A gear is a containerized, versioned algorithm registered with a Flywheel instance. Every gear declares the inputs it requires (file types, container types) and the configuration parameters it accepts. The SDK exposes methods to discover gears, inspect their input and config schemas, and launch them against your data.
This page covers finding, inspecting, and running gears. For what happens once a gear is launched, see Jobs and Analyses.
Gear types
Gears fall into two categories. The category determines where outputs are written and which SDK return value you receive from gear.run().
| Category | Outputs land on... | gear.run() returns |
|---|---|---|
utility | The destination container itself | A job ID |
analysis | A new analysis container attached to the destination | An analysis ID |
Utility gears are typically file converters, quality-control checks, and metadata extractors. Analysis gears are typically processing pipelines whose outputs need provenance — the analysis container preserves the input file references alongside the generated outputs.
Check a gear's category directly:
gear_path = "gears/dicom-qc"
--8 < --"test_docs_gears.py:check_is_analysis_gear"
Finding gears
fw.gears is a Finder, so the standard finder methods (find, find_first, iter, iter_find) all apply.
List all gears
Look up a gear by path
fw.lookup() accepts a gears/<name> path. Append /latest to pin to the latest version, or /<version> to pin to a specific one.
# Latest version (the default when no version is specified)
gear = fw.lookup("gears/dicom-qc")
# Explicit "latest" — equivalent to the line above
gear = fw.lookup("gears/dicom-qc/latest")
# Pinned to a specific version
gear = fw.lookup("gears/dicom-qc/0.6.0")
Note
The version segment matches the value of gear.gear.version exactly, including any pre-release suffix (for example, 0.6.0-rc4).
Find a gear with a filter
The gear's fields live under the nested gear. prefix, so filter expressions use gear.name, gear.version, gear.label, and so on. See Finder filter syntax for the full operator reference.
Inspecting a gear
Always inspect a gear before you run it. The gear manifest declares which inputs are required, which are optional, and which configuration parameters are available with what defaults.
List inputs
gear = fw.lookup("gears/dicom-qc")
--8 < --"test_docs_gears.py:inspect_gear_inputs"
List config parameters
Get the default config as a dict
gear.get_default_config() returns a fresh dict pre-populated with every config field's default value. It is the cleanest starting point when you want to override only a few parameters and accept defaults for the rest.
--8 < --"test_docs_gears.py:get_default_config"
config["check_bed_moving"] = False
Print a human-readable summary
gear.print_details() formats the full manifest to stdout. Use it during interactive exploration to see everything at once.
Example output:
Dicom QC
Validate dicom archive on a set of hardcoded and user-specified rules
Name: dicom-qc
Version: 0.6.0-rc4
Category: qa
Author: Flywheel <support@flywheel.io>
Maintainer: Flywheel <support@flywheel.io>
URL: https://gitlab.com/flywheel-io/scientific-solutions/gears/dicom-qc
Source: https://gitlab.com/flywheel-io/scientific-solutions/gears/dicom-qc
Inputs:
api-key (api-key, required)
dicom (file, required)
validation-schema (file, required)
Configuration:
check_bed_moving (boolean, default: True)
Check for duplicate slice positions (ImagePositionPatient)
check_embedded_localizer (boolean, default: True)
Check for existance of embedded localizer
check_instance_number_uniqueness (boolean, default: True)
Check for uniqueness of InstanceNumber
Running a gear
gear.run() is the primary way to launch a gear from the SDK. It accepts live SDK container and file objects directly, merges your config overrides against the gear's defaults, and returns the right ID for the gear's category — a job ID for utility gears, an analysis ID for analysis gears.
Pass inputs as keyword arguments. Each input value is either a file object (returned by container.get_file(...) or pulled from container.files) or a container object (for inputs whose base is a container reference rather than a file).
Utility gear
acquisition_id = "000123456789abcdefABCDEF"
acquisition = fw.get_acquisition(acquisition_id)
gear = fw.lookup("gears/dicom-qc")
job_id = gear.run(
destination=acquisition,
config={"check_bed_moving": False},
dicom=acquisition.get_file("scan.dcm.zip"),
validation_schema=acquisition.parents_project.get_file("schema.json"),
)
print(f"Scheduled utility job {job_id}")
The return value is a job ID. Track its progress through the methods documented in Jobs.
Analysis gear
Analysis gears require an analysis_label, which becomes the label of the analysis container created on the destination. A timestamp or run identifier makes the label easier to find later.
session_id = "000123456789abcdefABCDEF"
session = fw.get_session(session_id)
acquisition = session.acquisitions.find_first()
acquisition = acquisition.reload()
gear = fw.lookup("gears/afq")
analysis_id = gear.run(
analysis_label="AFQ 2026-05-11",
destination=session,
config={"dwi_algo": "NLLS"},
dwi_file=acquisition.get_file("dwi.nii.gz"),
bvec=acquisition.get_file("dwi.bvec"),
bval=acquisition.get_file("dwi.bval"),
)
print(f"Created analysis {analysis_id}")
The return value is the analysis container's ID. Open it with fw.get_analysis(...) to inspect inputs, outputs, and the backing job. See Analyses for details.
Tip
Combine get_default_config() with selective overrides for safer config handling. Starting from the gear's defaults guarantees that you do not accidentally omit a field the gear treats as required.
When gear.run() is not enough
A handful of advanced submission fields — priority, attempt, previous_job_id, compute_provider_id, role_id, and an explicit origin — are only reachable through the lower-level fw.add_job(InputJob(...)) call. add_job() also fits worker patterns where the caller receives container and file IDs over a queue and never holds live SDK container objects. It does not merge gear config defaults; the caller must build the full config dict. Reach for it deliberately — gear.run() covers everything else.