---
title: Design proteins | Boltz API Docs
description: Generate novel protein binders against a target, monitor progress, fetch results, and stop early if needed.
---

Protein design generates novel protein binders optimized for binding confidence and structure confidence. Results stream in as they’re generated — you can fetch them before the run finishes and stop early.

## Results and artifacts

Design runs generate protein results over time. As soon as a protein is computed, you can read and download the result without waiting for the full design run to finish.

Each generated protein result includes scoring metrics such as binding confidence, structure confidence, and interaction PAE. Each result also includes downloadable artifacts for the predicted bound structure and PAE.

## Define a target

There are two ways to define the target.

If you have a CIF file of your target structure, use a **structure template** target. The design engine uses the 3D coordinates for a more accurate target representation.

### Structure template target

Provide a CIF file and select which chains and residues to include. The file can be provided as a URL or base64-encoded content. Each chain gets a `crop_residues` field (an array of 0-indexed residue indices, or `"all"` to keep the entire chain). You can optionally specify `epitope_residues` (residues the binder should contact) and `flexible_residues` (residues allowed to move during design).

```
{
  "target": {
    "type": "structure_template",
    "structure": {
      "type": "base64",
      "media_type": "chemical/x-cif",
      "data": "ZGF0YV90YXJnZXQK..."
    },
    "chain_selection": {
      "A": {
        "chain_type": "polymer",
        "crop_residues": "all",
        "epitope_residues": [45, 46, 47, 48, 49],
        "flexible_residues": [44, 50]
      },
      "B": {
        "chain_type": "polymer",
        "crop_residues": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
      }
    }
  }
}
```

### No-template target

Define the target from an entity list when you don’t have a structure file. Optionally add `epitope_residues` (keyed by chain ID), `constraints`, and `bonds`.

```
{
  "target": {
    "type": "no_template",
    "entities": [
      { "type": "protein", "value": "MKTIIALSYIFCLVFA", "chain_ids": ["A"] }
    ],
    "epitope_residues": {
      "A": [45, 46, 47, 48, 49]
    }
  }
}
```

## Specify the binder

The binder specification is independent of the target type — you can combine either target mode with either binder mode.

If you have a CIF file of a binder scaffold you want to redesign, use a **structure template** binder. The engine uses the scaffold coordinates to guide design within specific regions you mark for redesign.

### Structure template binder

Provide a CIF file with the binder scaffold. For each chain, define `crop_residues` and `design_motifs` — the regions to redesign. There are two motif types:

- **Replacement**: Replace residues from `start_index` to `end_index` (inclusive, 0-indexed) with a designed region of `design_length_range` `{min, max}`.
- **Insertion**: Insert a designed region after `after_residue_index` with a `design_length_range` `{min, max}`. Use `-1` to insert at the beginning.

Set the `modality` to `peptide`, `antibody`, `nanobody`, or `custom_protein`. Optionally exclude specific amino acids via `rules.excluded_amino_acids`.

```
{
  "binder_specification": {
    "type": "structure_template",
    "modality": "nanobody",
    "structure": {
      "type": "base64",
      "media_type": "chemical/x-cif",
      "data": "ZGF0YV9iaW5kZXIK..."
    },
    "chain_selection": {
      "B": {
        "chain_type": "polymer",
        "crop_residues": "all",
        "design_motifs": [
          {
            "type": "replacement",
            "start_index": 26,
            "end_index": 32,
            "design_length_range": { "min": 5, "max": 15 }
          },
          {
            "type": "insertion",
            "after_residue_index": 50,
            "design_length_range": { "min": 3, "max": 8 }
          }
        ]
      }
    },
    "rules": {
      "excluded_amino_acids": ["C", "M"]
    }
  }
}
```

### No-template binder

Define the binder from entities when you don’t have a scaffold file. At least one entity must be a `designed_protein` — use a sequence pattern where uppercase letters are fixed residues and numbers (or ranges like `5..10`) represent designed regions of that length.

Examples:

- `"MKTAYI5..10VKSHFSRQ"` — fixed `MKTAYI`, then 5–10 designed residues, then fixed `VKSHFSRQ`
- `"20"` — 20 fully designed residues
- `"ACDE8GHI"` — fixed `ACDE`, 8 designed residues, fixed `GHI`

You can include additional fixed entities (protein, RNA, DNA, ligand) in the binder. Same `modality` and `rules` options apply.

```
{
  "binder_specification": {
    "type": "no_template",
    "modality": "custom_protein",
    "entities": [
      {
        "type": "designed_protein",
        "chain_ids": ["B"],
        "value": "MKTAYI10..20VKSHFSRQ"
      }
    ],
    "rules": {
      "excluded_amino_acids": ["C"]
    }
  }
}
```

- [Scientist Python](#tab-panel-20)
- [Scientist CLI](#tab-panel-21)
- [Platform Developer Python](#tab-panel-22)
- [Platform Developer Typescript](#tab-panel-23)
- [Agent CLI](#tab-panel-24)

## Run a design and download results

`run_protein_design()` submits the design run, waits for generated binders, downloads result archives, and returns a local run directory.

```
import os
from boltz_api import Boltz


client = Boltz(api_key=os.environ["BOLTZ_API_KEY"])


run_dir = client.experiments.run_protein_design(
    target={
        "type": "no_template",
        "entities": [
            {"type": "protein", "value": "MKTIIALSYIFCLVFA", "chain_ids": ["A"]},
        ],
        "epitope_residues": {"A": [10, 11, 12]},
    },
    binder_specification={
        "type": "no_template",
        "modality": "custom_protein",
        "entities": [
            {"type": "designed_protein", "chain_ids": ["B"], "value": "10..20"},
        ],
    },
    num_proteins=10,
    name="protein-design-hotspots",
)
print(run_dir)
```

The run directory contains the sanitized run record, resumable download state, a result manifest, and downloaded files for each designed binder:

```
boltz-experiments/protein-design-hotspots/
  .boltz-run.json
  run.json
  results/
    index.jsonl
    prot_des_result_.../
      metadata.json
      archive.tar.gz
      files/
        result/
          metrics.json
          predicted_structure.cif
          pae.npz
```

## Run a design and download results

The CLI starts the remote run, then `download-results` waits, resumes if interrupted, and writes results under `boltz-experiments/protein-design-hotspots/`.

Save your inputs to `protein-design.yaml`:

```
target:
  type: no_template
  entities:
    - type: protein
      value: MKTIIALSYIFCLVFA
      chain_ids: ["A"]
binder_specification:
  type: no_template
  modality: custom_protein
  entities:
    - type: designed_protein
      chain_ids: ["B"]
      value: 10..20
num_proteins: 10
```

Then start the run and download:

Terminal window

```
RUN_ID=$(
  boltz-api --format raw protein:design start \
    --input @yaml://./protein-design.yaml |
    jq -r '.id'
)


run_dir=$(boltz-api download-results --id "$RUN_ID" --name protein-design-hotspots)
echo "$run_dir"
```

Use `--input @json://./protein-design.json` if your input file is JSON.

The run directory contains the sanitized run record, resumable download state, a result manifest, and downloaded files for each designed binder:

```
boltz-experiments/protein-design-hotspots/
  .boltz-run.json
  run.json
  results/
    index.jsonl
    prot_des_result_.../
      metadata.json
      archive.tar.gz
      files/
        result/
          metrics.json
          predicted_structure.cif
          pae.npz
```

## Start a design run

**Structure template**

```
import os
from boltz_api import Boltz


client = Boltz(api_key=os.environ["BOLTZ_API_KEY"])


design = client.protein.design.start(
    target={
        "type": "structure_template",
        "structure": {
            "type": "base64",
            "media_type": "chemical/x-cif",
            "data": target_cif_b64,
        },
        "chain_selection": {
            "A": {
                "chain_type": "polymer",
                "crop_residues": "all",
                "epitope_residues": [45, 46, 47, 48, 49],
            },
        },
    },
    binder_specification={
        "type": "structure_template",
        "modality": "nanobody",
        "structure": {
            "type": "base64",
            "media_type": "chemical/x-cif",
            "data": binder_cif_b64,
        },
        "chain_selection": {
            "B": {
                "chain_type": "polymer",
                "crop_residues": "all",
                "design_motifs": [
                    {
                        "type": "replacement",
                        "start_index": 26,
                        "end_index": 32,
                        "design_length_range": {"min": 5, "max": 15},
                    },
                ],
            },
        },
    },
    num_proteins=10,
)
print(f"Design run ID: {design.id}, Status: {design.status}")
```

**No template**

```
import os
from boltz_api import Boltz


client = Boltz(api_key=os.environ["BOLTZ_API_KEY"])


design = client.protein.design.start(
    target={
        "type": "no_template",
        "entities": [
            {"type": "protein", "value": "MKTIIALSYIFCLVFA", "chain_ids": ["A"]},
        ],
    },
    binder_specification={
        "type": "no_template",
        "modality": "custom_protein",
        "entities": [
            {"type": "designed_protein", "chain_ids": ["B"], "value": "10..20"},
        ],
    },
    num_proteins=10,
)
print(f"Design run ID: {design.id}, Status: {design.status}")
```

## Start a design run

```
import Boltz from "boltz-api";


const apiKey = process.env["BOLTZ_API_KEY"];


const client = new Boltz({ apiKey });


let design = await client.protein.design.start({
  target: {
    type: "no_template",
    entities: [
      { type: "protein", value: "MKTIIALSYIFCLVFA", chain_ids: ["A"] },
    ],
  },
  binder_specification: {
    type: "no_template",
    modality: "custom_protein",
    entities: [
      { type: "designed_protein", chain_ids: ["B"], value: "10..20" },
    ],
  },
  num_proteins: 10,
});
console.log(`Design run ID: ${design.id}, Status: ${design.status}`);
```

## Run a design and download results

Ask the agent to save the payload to `protein-design.yaml`, estimate cost, then submit with a stable idempotency key.

```
target:
  type: no_template
  entities:
    - type: protein
      value: MKTIIALSYIFCLVFA
      chain_ids: ["A"]
binder_specification:
  type: no_template
  modality: custom_protein
  entities:
    - type: designed_protein
      chain_ids: ["B"]
      value: 10..20
num_proteins: 10
```

Terminal window

```
boltz-api protein:design estimate-cost \
  --input @yaml://./protein-design.yaml


RUN_ID=$(
  boltz-api protein:design start \
    --idempotency-key "protein-design-hotspots" \
    --input @yaml://./protein-design.yaml \
    --raw-output --transform id
)


boltz-api download-results \
  --id "$RUN_ID" \
  --name "protein-design-hotspots" \
  --root-dir "./boltz-experiments" \
  --poll-interval-seconds 10
```

- [Scientist Python](#tab-panel-25)
- [Scientist CLI](#tab-panel-26)
- [Platform Developer Python](#tab-panel-27)
- [Platform Developer Typescript](#tab-panel-28)
- [Agent CLI](#tab-panel-29)

## Start now, download later

The main `run_protein_design()` example already waits and downloads. To submit now and download later, use `start_protein_design()` and resume with `wait_and_download()`.

```
run_dir = client.experiments.start_protein_design(
    target={
        "type": "no_template",
        "entities": [
            {"type": "protein", "value": "MKTIIALSYIFCLVFA", "chain_ids": ["A"]},
        ],
        "epitope_residues": {"A": [10, 11, 12]},
    },
    binder_specification={
        "type": "no_template",
        "modality": "custom_protein",
        "entities": [
            {"type": "designed_protein", "chain_ids": ["B"], "value": "10..20"},
        ],
    },
    num_proteins=10,
    name="submit-now-finish-later",
)


client.experiments.wait_and_download(run_dir=run_dir)
```

## Resume downloads

`download-results` is the progress monitor and downloader. It can be rerun with the same name to resume from local checkpoint state.

Terminal window

```
boltz-api download-results --name protein-design-hotspots
boltz-api --format json download-status --name protein-design-hotspots
```

## Monitor progress

```
import time


while design.status not in ("succeeded", "failed", "stopped"):
    time.sleep(10)
    design = client.protein.design.retrieve(design.id)
    progress = design.progress
    print(
        f"Status: {design.status}, Generated: {progress.num_proteins_generated}/{progress.total_proteins_to_generate}"
    )
```

## Monitor progress

```
while (!["succeeded", "failed", "stopped"].includes(design.status)) {
  await new Promise((r) => setTimeout(r, 10000));
  design = await client.protein.design.retrieve(design.id);
  const progress = design.progress;
  console.log(
    `Status: ${design.status}, Generated: ${progress.num_proteins_generated}/${progress.total_proteins_to_generate}`,
  );
}
```

## Resume downloads

Agents can rerun `download-results` with the same name and root directory to resume from local checkpoint state.

Terminal window

```
boltz-api download-results \
  --name "protein-design-hotspots" \
  --root-dir "./boltz-experiments" \
  --poll-interval-seconds 10


boltz-api --format json download-status \
  --name "protein-design-hotspots" \
  --root-dir "./boltz-experiments"
```

- [Scientist Python](#tab-panel-30)
- [Scientist CLI](#tab-panel-31)
- [Platform Developer Python](#tab-panel-32)
- [Platform Developer Typescript](#tab-panel-33)
- [Agent CLI](#tab-panel-34)

## Inspect downloaded results

Result pages and artifact archives are already downloaded into the run directory.

```
print(run_dir)
for result_dir in (run_dir / "results").iterdir():
    print(result_dir)
```

## Inspect downloaded results

Result pages and artifact archives are already downloaded into the run directory.

Terminal window

```
ls boltz-experiments/protein-design-hotspots/results
```

## Fetch paginated results

```
for result in client.protein.design.list_results(design.id):
    print(f"Result {result.id}:")
    print(f"  Binding confidence: {result.metrics.binding_confidence}")
    print(f"  Structure confidence: {result.metrics.structure_confidence}")
    print(f"  Min interaction PAE: {result.metrics.min_interaction_pae}")
    print(f"  Archive URL: {result.artifacts.archive.url}")
```

## Fetch paginated results

```
for await (const result of client.protein.design.listResults(design.id)) {
  console.log(`Result ${result.id}:`);
  console.log(`  Binding confidence: ${result.metrics.binding_confidence}`);
  console.log(`  Structure confidence: ${result.metrics.structure_confidence}`);
  console.log(`  Min interaction PAE: ${result.metrics.min_interaction_pae}`);
  console.log(`  Archive URL: ${result.artifacts.archive.url}`);
}
```

## Inspect downloaded results

Use the local result manifest and downloaded artifact directories after `download-results` completes or while it is resuming.

Terminal window

```
ls ./boltz-experiments/protein-design-hotspots/results
head -n 5 ./boltz-experiments/protein-design-hotspots/results/index.jsonl
```

Advanced: generated SDK clients and the CLI resource command can also list remote pages directly with `list_results` / `list-results` if you need streaming access before local download completes.

## Stop early

- [Scientist Python](#tab-panel-35)
- [Scientist CLI](#tab-panel-36)
- [Platform Developer Python](#tab-panel-37)
- [Platform Developer Typescript](#tab-panel-38)
- [Agent CLI](#tab-panel-39)

```
client.experiments.stop(run_dir=run_dir)
```

Terminal window

```
boltz-api protein:design stop --id "$RUN_ID"
```

```
client.protein.design.stop(design.id)
```

```
await client.protein.design.stop(design.id);
```

Terminal window

```
boltz-api protein:design stop --id "<run-id-from-start>"
```

## Metrics

| Metric                 | Range     | What it measures                                                   |
| ---------------------- | --------- | ------------------------------------------------------------------ |
| `binding_confidence`   | 0–1       | Confidence that binding occurs.                                    |
| `structure_confidence` | 0–1       | Overall confidence in the predicted structure.                     |
| `iptm`                 | 0–1       | Interface predicted TM-score.                                      |
| `min_interaction_pae`  | Angstroms | Minimum predicted aligned error at the interface. Lower is better. |
| `helix_fraction`       | 0–1       | Fraction of designed residues in helices.                          |
| `sheet_fraction`       | 0–1       | Fraction of designed residues in sheets.                           |
| `loop_fraction`        | 0–1       | Fraction of designed residues in loops.                            |

## Status values

| Status      | Meaning                                                                           |
| ----------- | --------------------------------------------------------------------------------- |
| `pending`   | The run is queued and has not started yet.                                        |
| `running`   | The run is actively generating protein binders. Results may already be available. |
| `succeeded` | The run completed all requested proteins.                                         |
| `failed`    | The run encountered an error. Check the `error` field.                            |
| `stopped`   | The run was stopped early. Partial results are available.                         |
