Fastfold Docs

Recipes & Examples

Reference workflows by job type (single-sequence, complex/ligand, non-complex indexing, artifacts, metrics, fetch-by-id).

This page collects reference workflows for the FastFold Python SDK, grouped by common job types and model usage.

Quick map (job types → typical models)

  • Single-sequence fold: common starting point (example uses boltz-2)
  • Complex with ligand + optional constraints (pockets): advanced structure + property prediction (example uses boltz-2)
  • Non-complex multi-sequence (indexing): multiple independent sequences; access artifacts via results[i] (example uses simplefold_100M)
  • Create from library (from_id): start from a known library entry and override parameters (example uses boltz-2)
  • Fetch by job id: resume work in another script/notebook (works for complex and non-complex jobs)

Minimal SDK usage (single sequence)

from fastfold import Client

client = Client()  # Reads FASTFOLD_API_KEY from env by default

myJob = client.fold.create(
    sequence="LLGDFFRKSKEKIGKEFKRIVQRIKDFLRNLVPRTES",
    model="boltz-2",
    is_public=True,
)
print("Job ID:", myJob.id)

results = client.jobs.wait_for_completion(myJob.id, poll_interval=5.0, timeout=900.0)
print("Status:", results.job.status)
print("CIF URL:", results.cif_url())
print("Mean PLDDT:", results.metrics().mean_PLDDT)

link = results.get_viewer_link()
print("Open in viewer:", link)

Advanced Boltz-2: affinity prediction + pockets

from fastfold import Client

client = Client()

myJob = client.fold.create(
    name="Streptococcal protein G with Pocket",
    model="boltz-2",
    sequences=[
        {
            "proteinChain": {
                "sequence": "MTYKLILNGKTLKGETTTEAVDAATAEKVFKQYANDNGVDGEWTYDDATKTFTVTE",
                "count": 1,
                "chain_id": "A",
                "label": "mobile-purple",
            }
        },
        {
            "ligandSequence": {
                "sequence": "ATP",
                "count": 1,
                "chain_id": "B",
                "label": "constitutional-brown",
                "is_ccd": True,
                "property_type": "affinity",
            }
        },
    ],
    params={
        "modelName": "boltz-2",
        "weightSet": "Boltz-2",
        "relaxPrediction": True,
        "method": "Boltz-2",
        "recyclingSteps": 3,
        "samplingSteps": 200,
        "diffusionSample": 1,
        "stepScale": 1.638,
        "affinityMwCorrection": False,
        "samplingStepsAffinity": 200,
        "diffusionSamplesAffinity": 5,
    },
    constraints={
        "pocket": [
            {
                "binder": {"chain_id": "B"},
                "contacts": [
                    {"chain_id": "A", "res_idx": 12},
                    {"chain_id": "A", "res_idx": 15},
                    {"chain_id": "A", "res_idx": 18},
                ],
            }
        ]
    },
)

results = client.jobs.wait_for_completion(myJob.id, poll_interval=5.0, timeout=900.0)
print("Completed CIF URL:", results.cif_url())

metrics = results.metrics()
print("Mean PLDDT:", metrics.mean_PLDDT)
print("ptm_score:", metrics.ptm_score)
print("iptm_score:", metrics.iptm_score)

# Boltz-2 affinity metrics (present only if provided by API)
print("affinity_pred_value:", metrics.affinity_pred_value)
print("affinity_probability_binary:", metrics.affinity_probability_binary)
print("affinity_pred_value1:", metrics.affinity_pred_value1)
print("affinity_probability_binary1:", metrics.affinity_probability_binary1)
print("affinity_pred_value2:", metrics.affinity_pred_value2)
print("affinity_probability_binary2:", metrics.affinity_probability_binary2)

link = results.get_viewer_link()
print("Open in viewer:", link)

Non-complex multi-sequence artifacts (indexing)

Use indexing (results[0], results[1], …) to access per-sequence artifacts when the job is not a complex.

from fastfold import Client

client = Client()

myJob = client.fold.create(
    name="My Protein List",
    model="simplefold_100M",
    sequences=[
        {
            "proteinChain": {
                "sequence": "MCNTNMSVSTEGAASTSQIPASEQETLVRPKPLLLKLLKSVGAQNDTYTMKEIIFYIGQYIMTKRLYDEKQQHIVYCSNDLLGDVFGVPSFSVKEHRKIYAMIYRNLVAV",
                "count": 1,
                "chain_id": "A",
                "label": "specific-white",
            }
        },
        {
            "proteinChain": {
                "sequence": "SQETFSGLWKLLPPE",
                "count": 1,
                "chain_id": "B",
                "label": "wily-amethyst",
            }
        },
    ],
    params={
        "modelName": "simplefold_100M",
        "weightSet": "SimpleFold",
        "method": "SimpleFold",
    },
)

results = client.jobs.wait_for_completion(myJob.id, poll_interval=5.0, timeout=900.0)

cif_url_chain_a = results[0].cif_url()
cif_url_chain_b = results[1].cif_url()

print("Chain A CIF:", cif_url_chain_a)
print("Chain B CIF:", cif_url_chain_b)

m0 = results[0].metrics()
m1 = results[1].metrics()
print("Chain A mean PLDDT:", m0.mean_PLDDT)
print("Chain B mean PLDDT:", m1.mean_PLDDT)

link = results.get_viewer_link()
print("Open in viewer:", link)

Create with library source (from_id) and additional params

from fastfold import Client

client = Client()

myJob = client.fold.create(
    model="boltz-2",
    sequence="LLGDFFRKSKEKIGKEFKRIVQRIKDFLRNLVPRTES",
    from_id="770e8400-e29b-41d4-a716-446655440002",
    params={"relaxPrediction": True, "recyclingSteps": 2},
)

results = client.jobs.wait_for_completion(myJob.id, poll_interval=5.0, timeout=900.0)
print("Completed:", results.job.status)

Fetch results and status

from fastfold import Client

client = Client()

results = client.jobs.wait_for_completion(myJob.id, poll_interval=5.0, timeout=900.0)
status = results.job.status
print("Status:", status)

Status could be:

  • PENDING: Job queued but not yet initialized
  • INITIALIZED: Job created and ready to run
  • RUNNING: Job is processing
  • COMPLETED: Job finished successfully
  • FAILED: Job encountered an error
  • STOPPED: Job was stopped before completion

Update visibility

client.jobs.set_public(myJob.id, True)  # make job publicly accessible

Get artifact URLs

from fastfold import Client

client = Client()

results = client.jobs.wait_for_completion(myJob.id, poll_interval=5.0, timeout=900.0)

# Complex jobs (shared artifacts at top level)
if results.job.is_complex:
    cif_url = results.cif_url()
    pdb_url = results.pdb_url()
    pae_url = results.pae_plot_url()
    plddt_url = results.plddt_plot_url()
else:
    # Non-complex: per-sequence artifacts via indexing
    cif_url = results[0].cif_url()
    pdb_url = results[0].pdb_url()

Get metrics

from fastfold import Client

client = Client()

results = client.jobs.wait_for_completion(myJob.id, poll_interval=5.0, timeout=900.0)

# Complex (boltz-2) jobs: top-level metrics
if results.job.is_complex:
    metrics = results.metrics()
    print("mean_PLDDT:", metrics.mean_PLDDT)
    print("ptm_score:", metrics.ptm_score)
    print("iptm_score:", metrics.iptm_score)
    print("max_pae_score:", metrics.max_pae_score)
    # Boltz-2 affinity metrics (present only if provided by API)
    print("affinity_pred_value:", metrics.affinity_pred_value)
    print("affinity_probability_binary:", metrics.affinity_probability_binary)
    print("affinity_pred_value1:", metrics.affinity_pred_value1)
    print("affinity_probability_binary1:", metrics.affinity_probability_binary1)
    print("affinity_pred_value2:", metrics.affinity_pred_value2)
    print("affinity_probability_binary2:", metrics.affinity_probability_binary2)
else:
    # Non-complex: per-sequence metrics via indexing
    m0 = results[0].metrics()
    print("Chain A mean PLDDT:", m0.mean_PLDDT)
    m1 = results[1].metrics()
    print("Chain B mean PLDDT:", m1.mean_PLDDT)

Fetch an existing job by ID

from fastfold import Client

client = Client()
job_id = "550e8400-e29b-41d4-a716-446655440000"

results = client.jobs.wait_for_completion(job_id, poll_interval=5.0, timeout=900.0)
print("Status:", results.job.status)

# Complex job example (top-level artifacts)
cif_url = results.cif_url()
pdb_url = results.pdb_url()
pae_url = results.pae_plot_url()
plddt_url = results.plddt_plot_url()
print("CIF URL:", cif_url)
print("PDB URL:", pdb_url)
print("PAE URL:", pae_url)
print("pLDDT URL:", plddt_url)

metrics = results.metrics()
print("mean_PLDDT:", metrics.mean_PLDDT)
print("ptm_score:", metrics.ptm_score)
print("iptm_score:", metrics.iptm_score)
print("max_pae_score:", metrics.max_pae_score)

link = results.get_viewer_link()
print("Open in viewer:", link)
# Non-complex example (index into sequences)
from fastfold import Client

client = Client()
job_id = "550e8400-e29b-41d4-a716-446655440000"

results = client.jobs.wait_for_completion(job_id, poll_interval=5.0, timeout=900.0)
cif_seq0 = results[0].cif_url()
pdb_seq0 = results[0].pdb_url()
m0 = results[0].metrics()
print("Seq0 CIF:", cif_seq0)
print("Seq0 PDB:", pdb_seq0)
print("Seq0 mean_PLDDT:", m0.mean_PLDDT)

A practical “safe” wrapper (error handling)

If you’re running this in a pipeline, you’ll usually want a small wrapper so failures are obvious and easy to debug.

from fastfold import Client

def fold_and_print(sequence: str, model: str = "boltz-2") -> None:
    client = Client()
    job = client.fold.create(sequence=sequence, model=model, is_public=True)
    results = client.jobs.wait_for_completion(job.id, poll_interval=5.0, timeout=900.0)

    if results.job.status != "COMPLETED":
        raise RuntimeError(f"FastFold job did not complete: status={results.job.status} job_id={job.id}")

    print("Job ID:", job.id)
    print("CIF URL:", results.cif_url())
    print("Mean PLDDT:", results.metrics().mean_PLDDT)
    print("Viewer:", results.get_viewer_link())

Last updated on

On this page