Skip to content

fastfold-ai/fastfold-python

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

FastFold Python SDK and CLI

Python client and CLI for the FastFold Jobs API.

Open In Colab

Installation

From the project root:

pip install .

Or for development:

pip install -e .

Requires Python 3.8+.

Authentication

Set your API key in the environment:

export FASTFOLD_API_KEY="sk-...your-api-key"

You can also pass an API key when creating the client or via the CLI flag --api-key.

SDK Usage

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)

# Wait for completion, then fetch CIF URL (boltz-2 complex)
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)
# Generate a shareable viewer link for this job
link = results.get_viewer_link()
print("Open in viewer:", link)

Advanced usage for Boltz-2 with Affinity prediction and pockets:

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},
                ],
            }
        ]
    },
)

# Wait for completion and fetch CIF URL (boltz-2 complex)
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)

# Create a non-complex job with two protein chains and fetch per-sequence artifacts by index
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",
    },
)

# Wait for completion then access per-sequence artifacts by index
results = client.jobs.wait_for_completion(myJob.id, poll_interval=5.0, timeout=900.0)
# Access per-sequence artifacts by index
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)

# Generate a shareable viewer link for this job
link = results.get_viewer_link()
print("Open in viewer:", link)

Create with library source (from_id) and additional params

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

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

Fetch results and status

# Prefer waiting for completion in scripts/notebooks
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

# Ensure we have completed results
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

# Ensure the job has completed
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 existing job by ID

from fastfold import Client

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

# Wait for the existing job to complete
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)

# Optional: viewer link
link = results.get_viewer_link()
print("Open in viewer:", link)
# Non-complex example (index into sequences)
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)

CLI Usage

Submit a folding job:

fastfold-cli fold --sequence "LLGDFFRKSKEKIGKEFKRIVQRIKDFLRNLVPRTES" --model boltz-2

Optional flags:

fastfold-cli fold \
  --sequence "..." \
  --model boltz-2 \
  --name "My Job" \
  --api-key "sk-..." \
  --base-url "https://api.fastfold.ai"

On success the CLI prints the created job ID to stdout.

AI Research Agent

Launch the FastFold AI research agent (installs fastfold-agent-cli automatically if not present):

fastfold-cli agent "what are the top EGFR inhibitors for lung cancer?"

Any flags or arguments are forwarded directly to the agent.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Languages