skills/md-simulation/SKILL.md
Run molecular dynamics (MD) simulations via the FastFold Workflows API. Today supports the CALVADOS+OpenMM workflow (calvados_openmm_v1) from either an existing fold job (AF structure + PAE auto-resolved) or manual PDB+PAE upload, then waits for completion, fetches metrics/plots/CSV artifacts, and extracts trajectory frames as PDB files. Use when running an MD simulation with FastFold, CALVADOS + OpenMM, reading MD metrics/plots, extracting frames, or scripting submit → wait → results for an MD run.
npx skillsauth add fastfold-ai/skills md-simulationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill drives the FastFold Workflows API to run molecular dynamics simulations, retrieve metrics/plots/CSV plot data, and extract trajectory frames as PDB files.
Current engine:
calvados_openmm_v1), preset single_af_go (AF structure + PAE).Flows covered:
sourceType: fold_job) — auto-resolve structure + PAE.workflow_input.files.Both paths end in the same result shape: artifacts list, metrics, and metricsJson inside the latest task's result_raw_json.
Completed OpenMM workflows can also extract a specific trajectory conformation with POST /v1/workflows/openmm/<workflow_id>/extract-frame.
Get an API key: create one at the FastFold dashboard. Keep it secret.
Use the key: scripts read FASTFOLD_API_KEY from .env or environment in this order:
FASTFOLD_API_KEY already in environment..env in workspace/current parent directories.~/.fastfold-cli/config.json (api.fastfold_cloud_key).Do not ask users to paste secrets in chat.
If no key is resolved:
references/.env.example to .env at the workspace root..env and set FASTFOLD_API_KEY=sk-.... Create a key at https://cloud.fastfold.ai/api-keys."calvados_openmm_v1, OpenMM workflow, AF + PAE → MD, manual PDB/PAE upload for MD.Scripts live under skills/md-simulation/scripts/ and use only the Python standard library. Run them from the skill directory:
cd skills/md-simulation
Available scripts:
python scripts/submit_from_fold_job.py <fold_job_id> [--name "OpenMM via fold"] [--simulation-name my_run] [--preset single_af_go] [--sim-length-ns 0.2] [--step-size-ns 0.01] [--temperature 293.15] [--ionic 0.15] [--ph 7.5] [--box-length 20] [--force-field calvados3] [--charged-n-terminal-amine|--no-charged-n-terminal-amine] [--charged-c-terminal-carboxyl|--no-charged-c-terminal-carboxyl] [--charged-histidine|--no-charged-histidine] [--public]python scripts/fetch_uniprot.py <UNIPROT_ID> --out-dir <dir> [--json] — writes AF-<ID>.pdb and AF-<ID>.json into --out-dir and prints their paths. Pipe these into submit_manual_af_pae.py.python scripts/submit_manual_af_pae.py --pdb path/to/structure.pdb --pae path/to/pae.json [--name "OpenMM manual"] [--simulation-name my_run] [--sim-length-ns 0.2] [--step-size-ns 0.01] [--temperature 293.15] [--ionic 0.15] [--ph 7.5] [--box-length 20] [--force-field calvados3] [--charged-n-terminal-amine|--no-charged-n-terminal-amine] [--charged-c-terminal-carboxyl|--no-charged-c-terminal-carboxyl] [--charged-histidine|--no-charged-histidine] [--public]/openmm/results/<workflow_id>):
python scripts/submit_from_workflow.py <workflow_id> [--name "OpenMM copy"] [--simulation-name my_run] [--component-name FUSRGG3] [--sim-length-ns 10] [--step-size-ns 0.01] [--temperature 293.15] [--ionic 0.15] [--ph 7.5] [--box-length 50] [--force-field calvados3] [--topology center] [--box-eq|--no-box-eq] [--pressure 0.1,0,0] [--periodic|--no-periodic] [--charged-n-terminal-amine|--no-charged-n-terminal-amine] [--charged-c-terminal-carboxyl|--no-charged-c-terminal-carboxyl] [--charged-histidine|--no-charged-histidine] [--json] — fetches the source workflow's input_payload, reuses the same input file refs, applies explicit parameter overrides, then submits a new workflow.python scripts/submit_from_yml_refs.py --config-yaml ./config.yaml --components-yaml ./components.yaml --residues-csv ./residues.csv --fasta ./input.fasta [--simulation-name my_run] [--component-name FUSRGG3] [--topology center] [--box-length 50] [--json]python scripts/submit_from_yml_refs.py --config-yaml ./config.yaml --components-yaml ./components.yaml --residues-csv ./residues.csv --pdb ./structure.pdb --pae ./pae.json [...]python scripts/wait_for_workflow.py <workflow_id> [--timeout 1800] [--metrics-timeout 900] [--poll-interval 5] [--json]python scripts/fetch_results.py <workflow_id> [--json]python scripts/extract_frame.py <workflow_id> --time-ns 5.0 [--selection "protein or resname LIG"] [--dt-in-ps 0] [--download ./frame.pdb] [--json] — validates the requested time against sim_length_ns when available, calls the frame extraction endpoint, and prints the extracted PDB URL.python scripts/toggle_public.py <workflow_id> --public (or --private) — when set public, prints the shareable URL https://cloud.fastfold.ai/openmm/results/<workflow_id>?shared=true.Use --force-field to set workflow_input.residue_profile. --profile is still accepted as a backwards-compatible alias.
In workflow payloads, force_field_family is the model family (typically calvados) and residue_profile is the specific force-field parameter set (for example calvados3 or c2rna).
The agent runs these scripts for the user. Do not hand users a list of commands; execute them directly.
python scripts/<name>.py .... Do not search for them with find / locate / ls in arbitrary folders — they live alongside this SKILL.md.requests / urllib POST to /v1/workflows). Use the bundled scripts so the preset, file refs, share URLs, and settle polling behave consistently.submit_from_yml_refs.py as an advanced lane-2 tool. Use it only when the user explicitly asks for custom YML-reference uploads and file-binding control.--public to submit_from_fold_job.py / submit_manual_af_pae.py. Only add --public when the user explicitly asks for a public link, sharable link, or the workflow to be shared. Correspondingly, only surface the ?shared=true URL when the workflow is actually public./tmp; use wait_for_workflow.py.--timeout and --metrics-timeout), never open-ended loops.wait_for_workflow.py handles the extra settle window for you.POST /v1/workflows with workflow_name: calvados_openmm_v1 and an OpenMM workflow_input.GET /v1/workflows/status/<workflow_id> → status in INITIALIZED, QUEUED, RUNNING, COMPLETED, FAILED, STOPPED.GET /v1/workflows/task-results/<workflow_id> (for task-level output summary).isPublic: true was set): GET /v1/workflows/public/<workflow_id> — returns full input_payload and tasks[-1].result_raw_json (artifacts, metrics, metricsJson).Important: on successful runs,
metrics,metricsJson, and artifact URLs populate insideresult_raw_jsonof the last task. Allow a short settle window after terminal status.
sourceType: fold_job)Use when the user already has an existing FastFold fold job (AlphaFold2/OpenFold/Boltz/Chai-1/OpenFold3/IntelliFold) and wants MD from that structure.
GET /v1/jobs/<JOB_ID>/resultsjobRunId (top-level) — or fallback from job.jobRunIdsequenceId = sequences[].id where type == "protein" (pick the protein chain; fall back to first sequence id if needed){
"workflow_name": "calvados_openmm_v1",
"name": "OpenMM AF+PAE via fold job",
"workflow_input": {
"preset": "single_af_go",
"name": "af_pae_run",
"force_field_family": "calvados",
"residue_profile": "calvados3",
"temp": 293.15,
"ionic": 0.15,
"pH": 7.5,
"step_size_ns": 0.01,
"sim_length_ns": 0.2,
"box_length": 20,
"files": {},
"sourceType": "fold_job",
"sourceJobId": "<JOB_ID>",
"sourceJobRunId": "<JOB_RUN_ID>",
"sourceSequenceId": "<SEQUENCE_ID>",
"isPublic": true
}
}
The backend auto-attaches files.pdb and files.pae from the source fold job.
Use this when the user gives an /openmm/results/<workflow_id> page as the
reference and asks to run with the same inputs/settings. This is not a backend
rerun. The script fetches the source workflow, copies its input_payload
explicitly, applies any parameter values the user stated, then submits a new
POST /v1/workflows request.
Component selection rule (important):
workflow_input.component_name to choose which sequence/component CALVADOS runs.single_idr_fasta), component_name must match a sequence label or FASTA record ID.--component-name in submit_from_workflow.py whenever the source has multiple sequence labels.--box-eq/--no-box-eq, --pressure X,Y,Z, and --periodic/--no-periodic to override workflow_input.config.box_eq, workflow_input.config.pressure, and workflow_input.component_defaults.periodic.--charged-n-terminal-amine/--no-charged-n-terminal-amine, --charged-c-terminal-carboxyl/--no-charged-c-terminal-carboxyl, and --charged-histidine/--no-charged-histidine.Run:
python scripts/submit_from_workflow.py <workflow_id> \
--sim-length-ns 10 \
--component-name FUSRGG3 \
--box-eq \
--pressure 0.1,0,0 \
--periodic \
--charged-n-terminal-amine \
--no-charged-c-terminal-carboxyl \
--no-charged-histidine \
--step-size-ns 0.01 \
--temperature 293.15 \
--ionic 0.15 \
--ph 7.5 \
--box-length 50 \
--force-field calvados3 \
--topology center
Then wait and fetch results:
python scripts/wait_for_workflow.py <new_workflow_id> --timeout 3700 --metrics-timeout 900 --poll-interval 5
python scripts/fetch_results.py <new_workflow_id>
The source workflow's stored input file refs are part of input_payload.files.
Do not download those files from cloud.fastfold.ai, and do not upload new
copies unless the user explicitly asks to replace inputs.
If fetching the reference workflow fails, tell the user they may not have access to that workflow or it may no longer exist. Ask them to get the owner to share the workflow/files, or switch to another input mode:
python scripts/submit_manual_af_pae.py if they can provide local PDB + PAE files;python scripts/fetch_uniprot.py followed by python scripts/submit_manual_af_pae.py if they know a UniProt accession;python scripts/submit_from_fold_job.py if the source is an accessible FastFold fold job.Use when the user has local .pdb structure + .json PAE files (e.g., an AlphaFold EBI PAE JSON).
POST /v1/library/create with body { "name": "...", "type": "file", "fileType": "protein" | "json", "origin": "USER_UPLOAD", "metadata": {} }201 with id (use this as libraryItemId).POST /v1/library/<item_id>/upload-files as multipart/form-data with field files=@<path>.GET /v1/library/<item_id> → use metadata.files[0].file_name (UUID-prefixed on the server).{
"workflow_name": "calvados_openmm_v1",
"name": "OpenMM AF+PAE manual upload",
"workflow_input": {
"preset": "single_af_go",
"name": "manual_af_pae_run",
"force_field_family": "calvados",
"residue_profile": "calvados3",
"temp": 293.15,
"ionic": 0.15,
"pH": 7.5,
"step_size_ns": 0.01,
"sim_length_ns": 0.2,
"box_length": 20,
"files": {
"pdb": { "libraryItemId": "<PDB_ITEM_ID>", "fileName": "<PDB_STORED_FILE_NAME>" },
"pae": { "libraryItemId": "<PAE_ITEM_ID>", "fileName": "<PAE_STORED_FILE_NAME>" }
},
"isPublic": true
}
}
When the user gives a UniProt accession (e.g. P00698) instead of local files, mirror the /openmm/new UniProt action: pull the AlphaFold DB PDB + PAE JSON, then reuse the manual-upload flow.
python scripts/fetch_uniprot.py <UNIPROT_ID> --out-dir /tmp/uniprot --json
https://alphafold.ebi.ac.uk/api/prediction/<UNIPROT_ID>, reads pdbUrl + paeDocUrl from the first entry, downloads them, validates the PAE is parseable JSON, and writes AF-<id>.pdb + AF-<id>.json.python scripts/submit_manual_af_pae.py --pdb /tmp/uniprot/AF-<UNIPROT_ID>.pdb --pae /tmp/uniprot/AF-<UNIPROT_ID>.json ...Use this only with preset single_af_go.
Use only when the user explicitly asks for this advanced lane-2 flow.
submit_from_yml_refs.py does the following:
config.yaml, components.yaml, and required input files (residues + FASTA or residues + PDB/PAE) to Library.files refs.workflow_input.yml_reference for provenance/future YML-native migration.Important behavior:
yml_reference) for reproducibility.submit_from_fold_job.py, submit_manual_af_pae.py, or submit_from_workflow.py flows.On a successful run, tasks[-1].result_raw_json contains:
artifacts: list of { path, sizeBytes, url? } entries (e.g., analysis/metrics.json, analysis/<name>_fel.png, analysis/<name>_fel.csv, analysis/<name>_rg.svg, analysis/<name>_rg.csv, the DCD/PDB trajectory and topology, etc.).metrics: structured summary. Top-level keys:
rmsd, rmsf, radius_of_gyration, free_energy_landscapebinding_energy, protein_ligand_distance (only meaningful when ligand_detected: true)analysis_name, analysis_parameters, output_filesmetricsJson: raw analysis/metrics.json content (also downloadable as artifact).Use scripts/fetch_results.py <workflow_id> to print a concise summary and the artifact URLs.
Use this after an OpenMM workflow has completed and has trajectory artifacts (top.pdb + .dcd). If the user gives an /openmm/results/<workflow_id> page and asks for a snapshot/conformation/frame at a time in ns, run:
python scripts/extract_frame.py <workflow_id> --time-ns <time_ns>
Optional parameters:
--selection "protein or resname LIG" — MDAnalysis atom selection. Defaults to protein plus ligand if present.--dt-in-ps 0 — timestep override in ps; 0 means use the trajectory metadata.--download ./frame.pdb — also download the returned PDB URL to a local path.--json — print the full response.The script fetches the workflow first and validates --time-ns against sim_length_ns when available. The API still extracts the closest available trajectory frame and returns frameIndex, actualTimeNs, atomCount, and a signed pdbUrl.
As soon as the workflow is terminal with results populated, the agent must proactively surface two links to the user.
URL formatting rule (required): print every URL as a bare, unwrapped URL on its own line, exactly as emitted by the scripts. Do not wrap URLs as markdown link-titles ([title](url)), HTML anchors, footnotes, or numbered reference lists — terminal UIs render those with the URL hidden, so the user can't click or copy it. Also do not shorten or truncate URLs.
Fastfold Cloud dashboard (always) — where the user can browse the run, view plots inline, and download artifacts. Print verbatim:
https://cloud.fastfold.ai/openmm/results/<workflow_id>
If the workflow is public (isPublic: true), also share the shareable variant:
https://cloud.fastfold.ai/openmm/results/<workflow_id>?shared=true
Py2DMol trajectory viewer (always) — precede the URL with this sentence, then print the URL on its own line:
Trajectory is available for this run to visualize simulation, generate animations, and use playback controls in Py2DMol.
https://cloud.fastfold.ai/py2dmol/new?from=openmm_workflow&workflow_id=<workflow_id>
Individual plot/data URLs — each artifacts[].url that ends in .png / .svg / .csv / .json should likewise be printed as a bare URL on its own line, prefixed with its filename (e.g. rmsd.png: https://…). No markdown link-titles, no numbered lists of short labels.
wait_for_workflow.py and fetch_results.py already print these URLs as raw strings; forward them to the user verbatim — do not reformat.
INITIALIZED — ready to runQUEUED — queued for dispatchRUNNING — executingCOMPLETED — success (artifacts/metrics populated shortly after)FAILED — error (check logs; metrics will not be populated)STOPPED — stopped before completionOnly trust artifacts, metrics, metricsJson when task status is COMPLETED.
Workflows default to private. Two ways to make a run public:
--public to submit_from_fold_job.py or submit_manual_af_pae.py, which adds workflow_input.isPublic = true to POST /v1/workflows.python scripts/toggle_public.py <workflow_id> --public (or --private) which calls PATCH /v1/workflows/<workflow_id>/public with { "isPublic": true | false }.Dashboard URL (always share this with the user):
https://cloud.fastfold.ai/openmm/results/<workflow_id>
When the workflow is public (isPublic: true), also share the no-login variant:
https://cloud.fastfold.ai/openmm/results/<workflow_id>?shared=true
If the run fails or the API behaves unexpectedly, tell the user to contact the FastFold team at [email protected] and include the workflow_id. Specifically:
FAILED or STOPPED.--timeout in wait_for_workflow.py.COMPLETED but metrics/artifacts never appear within --metrics-timeout (exit code 3 from wait_for_workflow.py).5xx response or persistent 4xx (other than 401 Unauthorized, which is an API key issue the user must fix themselves)./v1/library/{item_id}/upload-files fails repeatedly.Do not retry indefinitely — report the error, the workflow_id, and the failing step, and suggest contacting FastFold support.
workflow_id / job_id / library item_id as UUIDs before embedding in API paths or filenames.If the user asks about the method (what CALVADOS is, the residue model, calvados2 vs calvados3, IDP/multi-domain coverage, citations for a paper), read references/calvados_method.md first.
Canonical sources to cite:
.env template: references/.env.exampletools
Share markdown reports to the user's configured Slack agent_cli_report channel via Fastfold API, and persist the markdown as a library item.
development
Submits and manages FastFold protein folding jobs via the Jobs API (Boltz-2, OpenFold 3, Chai-1, IntelliFold, AlphaFold2, SimpleFold). Covers authentication, job payloads, modifications, constraints, webhooks, polling, and CIF/PDB URLs. Use when folding with FastFold, OpenFold 3/Chai-1/IntelliFold complexes, ligands/affinity, or scripting create → wait → results.
development
Maintainer-only workflow for handling GitHub Secret Scanning alerts on OpenClaw. Use when Codex needs to triage, redact, clean up, and resolve secret leakage found in issue comments, issue bodies, PR comments, or other GitHub content.
development
Maintainer workflow for OpenClaw releases, prereleases, changelog release notes, and publish validation. Use when Codex needs to prepare or verify stable or beta release steps, align version naming, assemble release notes, check release auth requirements, or validate publish-time commands and artifacts.