| name | boltz-small-molecule-screen |
| description | Screen existing small-molecule libraries with Boltz. Use when docking, scoring, or ranking a supplied SMILES or compound library against a target. Not for de novo molecule design or one-off docking. |
Workflow
If boltz-api reports missing or expired authentication, surface the error to the user. Do not attempt to re-authenticate; the host environment must provide BOLTZ_API_KEY.
Use this skill when the user already has candidate molecules.
- Normalize the library from raw SMILES, a CSV (auto-detect the SMILES column),
.smi, or .txt into the molecules list. Each entry is {smiles, id?}; the optional id is echoed back as external_id on each result.
- Normalize the target: one or more protein sequences into
target.entities, plus optional pocket_residues (0-based) and/or reference_ligands (SMILES of known binders to seed pocket detection).
- Keep default server-side filtering unless the user asks for custom filters — only add
molecule_filters on explicit request.
- Author the payload YAML or JSON.
start to submit (synchronous). Capture the ID.
- Launch
download-results as a long-running/background command in whatever mode the host agent harness provides — it polls, paginates list-results, downloads every per-hit structure, and exits when terminal. After launching it, schedule the host's available follow-up/notification mechanism, if one exists, to check download-status periodically and notify the user when the download reaches a terminal state. Always report the job ID, run name, and output directory. Include the next check cadence if a follow-up was scheduled; otherwise include the download-status command.
- When done, rank from
<output-root>/<run-name>/results/index.jsonl. Sort by binding_confidence for hit discovery or optimization_score for lead optimization; these are parallel intents, not a fallback hierarchy. Report the top 5-10 hits with smiles, the chosen ranking metric, key confidence metrics, and structure path. Read references/results.md for output layout, metrics, and filtered-input accounting.
Command Pattern
boltz-api small-molecule:library-screen start \
--idempotency-key "<run-name>" \
--input @yaml:///absolute/path/payload.yaml \
--raw-output --transform id
boltz-api download-results \
--id "<job-id-from-start>" --name "<run-name>" \
--root-dir "/absolute/path/boltz-experiments" \
--poll-interval-seconds 30
Payload keys are molecules, target, molecule_filters — the API body field names, not the direct CLI flag names --molecule / --target / --molecule-filters.
Always Do This
- Keep payload field names exactly as the API body names shown in
references/api.md.
- Use absolute paths for the output root, payload files, and embedded target files. Do not
cd into the run directory for follow-up commands; pass the same --root-dir and use absolute paths so later relative paths do not drift.
- Prefer one merged top-level payload via
--input @yaml:///absolute/path/payload.yaml or @json:///absolute/path/payload.json. Keep --idempotency-key and --workspace-id top-level; if they also appear inside --input, the top-level flags win.
- Direct object flags still work as overrides, such as
--target @yaml:///absolute/path/target.yaml, --molecule-filters @json:///absolute/path/filters.json, or repeated --molecule @json:///absolute/path/mol-1.json entries. Piped YAML / JSON on stdin also works, but it must use API body field names. Never use @file:// or @./.
- Treat pocket residue indices as 0-based.
- Do not invent medicinal-chemistry filters. Only add
molecule_filters if the user asks; mention the catalog as an option.
- Use the same slug as both
--idempotency-key at submit and --name on download-results so re-runs resume via .boltz-run.json.
- In permission-gated agents, keep each Boltz call as a top-level command that starts with
boltz-api. Prefer concrete arguments over sh -c, inline environment assignments, aliases, wrapper scripts, loops, or pipelines around the boltz-api invocation unless the user already allowed that exact command form. Use --raw-output --transform id, read the printed ID, then paste that literal ID into the next download-results command.
- Run
download-results through the host harness's long-running/background command facility. After it starts, do not manually wait on it or run ad hoc polling loops. If the host harness provides a managed follow-up/notification mechanism, schedule it to check download-status, notify the user on terminal completion/failure, and stop once terminal. If not, do not claim an automatic next check.
download-results emits JSONL progress on stderr by default; add --progress-format text --verbose only when you explicitly want human-readable logs.
- Prefer
boltz-api --format json download-status --name "<run-name>" --root-dir "/absolute/path/boltz-experiments" for structured local checkpoint state. When the host provides a managed follow-up mechanism, use it for automatic checks with cadence based on molecule count: under 100 -> every 1-2 minutes; 100-1,000 -> every 5 minutes; over 1,000 -> every 15 minutes. Never run a manual poll loop in the current turn.
- If a detached download needs to be restarted, re-run
boltz-api download-results with the same --name "<run-name>" and the same --root-dir.
- Poll interval:
--poll-interval-seconds 30 is a reasonable downloader default. Wall-clock time scales roughly with library size: under 100 often finishes in a few minutes, 100-1,000 may take several minutes to tens of minutes, and larger screens can take longer or hours depending on inputs and system load. Never tell the user a 10-candidate screen will take 30 minutes or hours.
Escape Hatch
Read references/api.md for the molecules, target, and molecule_filters shapes, including the built-in SMARTS filters and RDKit descriptor ranges. Read references/results.md after download when ranking hits or explaining missing/filtered inputs.
Outputs
Rank from results/index.jsonl after download-results; use references/results.md for the local file layout, metric meanings, and filtered-input accounting.