Install
openclaw skills install @zhonghua-wang/molqlThis skill should be used when users need to translate natural language molecular structure queries into MolQL (Mol-Script) expressions. It handles basic atom/residue/chain selection, distance-based queries, property-based filtering, complex multi-part queries, and provides clarification for ambiguous requests.
openclaw skills install @zhonghua-wang/molqlThis skill translates natural language molecular structure queries into valid MolQL (Mol-Script) expressions. It enables users to describe what they want to select or visualize in natural language, and returns the corresponding MolQL expression that can be used with Mol* or compatible molecular viewers.
Trigger this skill when users:
Do NOT use for:
Parse the user's natural language request to identify:
Map to MolQL patterns using the reference syntax in references/molql-syntax.md:
(sel.atom.chains ...), (sel.atom.res ...), (sel.atom.atoms ...)(sel.atom.within ...), (sel.atom.include-surroundings ...)(sel.atom.pick :test ...)(sel.atom.merge ...), (sel.atom.intersect ...)Construct the MolQL expression following S-expression syntax:
: prefixReturn output in this format:
**MolQL Expression:**
```lisp
(your-molql-expression-here)
Explanation: [Brief description of what the expression selects]
| Natural Language | MolQL Pattern |
|---|---|
| "Select chain A" | (sel.atom.chains (= atom.chain A)) |
| "Show residues 10-20" | (sel.atom.res (in-range atom.resno 10 20)) |
| "Select alanine residues" | (sel.atom.res (= atom.resname ALA)) |
| "Show carbon atoms" | (sel.atom.atoms (= atom.el C)) |
| "Select CA atoms" | (sel.atom.atoms (= atom.name CA)) |
| Natural Language | MolQL Pattern |
|---|---|
| "Atoms within 5Å of iron" | (sel.atom.include-surroundings (sel.atom.atoms (= atom.el _Fe)) :radius 5 :as-whole-residues true) |
| "Residues near the ligand" | (sel.atom.within (sel.atom.atom-groups :residue-test (= atom.entity-type non-polymer)) :target (sel.atom.atom-groups :entity-test (= atom.entity-type polymer)) :max-radius 5) |
| Natural Language | MolQL Pattern |
|---|---|
| "Residues with B-factor > 30" | (sel.atom.pick (sel.atom.res (= atom.entity-type polymer)) :test (> atom.bfactor 30)) |
| "Show modified residues" | (sel.atom.res atom.is-modified) |
| Natural Language | MolQL Pattern |
|---|---|
| "Chain A and chain B" | (sel.atom.merge (sel.atom.chains (= atom.chain A)) (sel.atom.chains (= atom.chain B))) |
| "Helices in chain A" | (sel.atom.pick (sel.atom.chains (= atom.chain A)) :test (core.flags.has-any atom.key.sec-struct (secondary-structure-flags helix))) |
| "Everything except chain A" | (sel.atom.except-by (sel.atom.all) :by (sel.atom.chains (= atom.chain A))) |
When the user's request is ambiguous, ask clarifying questions:
Ambiguous: "Select the active site" Clarification: "Active site can be defined in different ways. Do you want to:
Ambiguous: "Show the binding pocket" Clarification: "To select the binding pocket, I need to know:
references/molql-syntax.md: Complete MolQL syntax reference manual (1150 lines) covering all operators, selectors, atom properties, and examples. Load this reference when you need to look up specific syntax patterns or verify expression structure.(sel.atom.atoms test)(sel.atom.res test)(sel.atom.chains test)atom.chain - Chain ID (A, B, C...)atom.resno - Residue sequence numberatom.resname - Residue name (ALA, GLY, etc.)atom.name - Atom name (CA, CB, N, C, O...)atom.el - Element symbol (C, N, O, Fe...)atom.bfactor - B-factor (temperature factor)atom.entity-type - Entity type (polymer, non-polymer, water)(= a b) - Equal(!= a b) - Not equal(< a b), (> a b) - Less/greater than(in-range v min max) - Range check(and c1 c2) - Logical AND(or c1 c2) - Logical OR(not c) - Logical NOT(set.has {A B C} value) - Set membership(sel.atom.merge s1 s2 ...) - Union of selections(sel.atom.intersect s1 s2 ...) - Intersection(sel.atom.except-by s :by other) - Exclusion(sel.atom.include-surroundings s :radius 5) - Expand by distance(sel.atom.include-connected s :layer-count 2) - Expand by connectivityUser: "Select chain A"
Response:
(sel.atom.chains (= atom.chain A))
Explanation: Selects all atoms in chain A, grouped by chain.
User: "Show me residues 130 to 180"
Response:
(sel.atom.res (in-range atom.resno 130 180))
Explanation: Selects all residues with sequence numbers between 130 and 180 (inclusive), grouped by residue.
User: "Find residues within 5 angstroms of the iron atom"
Response:
(sel.atom.include-surroundings
(sel.atom.atoms (= atom.el _Fe))
:radius 5
:as-whole-residues true)
Explanation: First selects iron atoms, then expands the selection to include all residues with any atom within 5Å of the iron.
User: "Which residues have high B-factors, say above 50?"
Response:
(sel.atom.pick
(sel.atom.res (= atom.entity-type polymer))
:test (> atom.bfactor 50))
Explanation: Selects polymer residues where the B-factor is greater than 50.
User: "Select all helices in chain A that are near the heme group"
Response:
(sel.atom.within
(sel.atom.pick
(sel.atom.chains (= atom.chain A))
:test (core.flags.has-any
atom.key.sec-struct
(secondary-structure-flags helix)))
:target (sel.atom.res (= atom.resname HEM))
:max-radius 5)
Explanation: First selects helical secondary structure elements in chain A, then filters to only those within 5Å of HEM residues.
Wrong selector level: Using sel.atom.atoms when you want residue-level selection. Remember:
sel.atom.atoms for individual atom selectionsel.atom.res for residue-level groupingsel.atom.chains for chain-level groupingMissing named parameter colon: Named parameters must have : prefix
(sel.atom.include-surroundings sel radius 5)(sel.atom.include-surroundings sel :radius 5)Wrong element symbol format: Element symbols in comparisons use underscore prefix
(= atom.el Fe)(= atom.el _Fe)String vs symbol: Chain IDs and residue names are symbols, not strings
(= atom.chain "A")(= atom.chain A)If you cannot confidently translate a query: