From 8c945e126ce1133055be3e3ad349b0ec5283ff35 Mon Sep 17 00:00:00 2001 From: promptadmin Date: Sat, 29 Aug 2026 17:06:03 +0000 Subject: [PATCH 1/8] [upstream-sync] skills/rowan/SKILL.md from K-Dense-AI/scientific-agent-skills@72d742e1 [prompt] --- .../skills/rowan/SKILL.md | 850 ++---------------- 1 file changed, 81 insertions(+), 769 deletions(-) diff --git a/upstream/K-Dense-AI-scientific-agent-skills/skills/rowan/SKILL.md b/upstream/K-Dense-AI-scientific-agent-skills/skills/rowan/SKILL.md index f0c43bfd..ada00f1b 100644 --- a/upstream/K-Dense-AI-scientific-agent-skills/skills/rowan/SKILL.md +++ b/upstream/K-Dense-AI-scientific-agent-skills/skills/rowan/SKILL.md @@ -1,16 +1,24 @@ --- lineage_type: import -upstream_source: https://github.com/K-Dense-AI/scientific-agent-skills/blob/9c9bd2e9/skills/rowan/SKILL.md -upstream_sha: 9c9bd2e9 -imported_at: 2026-06-27 +upstream_source: https://github.com/K-Dense-AI/scientific-agent-skills/blob/72d742e1/skills/rowan/SKILL.md +upstream_sha: 72d742e1 +imported_at: 2026-08-29 prompt_class: prompt upstream_changes: accepted name: rowan description: Rowan is a cloud-native molecular modeling and medicinal-chemistry workflow platform with a Python API. Use for pKa and macropKa prediction, conformer and tautomer ensembles, docking and analogue docking, protein-ligand cofolding, MSA generation, molecular dynamics, permeability, descriptor workflows, and related small-molecule or protein modeling tasks. Ideal for programmatic batch screening, multi-step chemistry pipelines, and workflows that would otherwise require maintaining local HPC/GPU infrastructure. license: Proprietary (API key required) compatibility: Python 3.12+, API key required -required_environment_variables: [{"name": "ROWAN_API_KEY", "prompt": "Rowan computational chemistry API key.", "required_for": "full functionality"}] -metadata: {"version": "1.2", "skill-author": "Rowan Science", "trigger-keywords": "pKa prediction, molecular docking, conformer search, chemistry workflow, drug discovery, SMILES, protein structure, batch molecular modeling, cloud chemistry", "openclaw": {"primaryEnv": "ROWAN_API_KEY", "envVars": [{"name": "ROWAN_API_KEY", "required": true, "description": "Rowan computational chemistry API key."}]}} +metadata: + version: "1.5" + skill-author: Rowan Science + trigger-keywords: pKa prediction, molecular docking, conformer search, chemistry workflow, drug discovery, SMILES, protein structure, batch molecular modeling, cloud chemistry + openclaw: + primaryEnv: ROWAN_API_KEY + envVars: + - name: ROWAN_API_KEY + required: true + description: Rowan computational chemistry API key. --- # Rowan: Cloud-Native Molecular-Modeling and Drug-Design Workflows @@ -37,40 +45,6 @@ Use Rowan when you want to run medicinal-chemistry or molecular-design workflows - Simple molecular I/O (use RDKit directly) - Post-HF *ab initio* quantum chemistry or relativistic calculations -## Access and pricing model - -Rowan uses a credit-based usage model. All users, including free-tier users, can create API keys and use the Python API. - -### Free-tier access - -- Access to all Rowan core workflows -- 20 credits per week -- 500 signup credits - -### Pricing and credit consumption - -Credits are consumed according to compute type: - -- **CPU**: 1 credit per minute -- **GPU**: 3 credits per minute -- **H100/H200 GPU**: 7 credits per minute - -Purchased credits are priced per credit and remain valid for up to one year from purchase. - -### Typical cost estimates - -| Workflow | Typical Runtime | Estimated Credits | Notes | -|----------|----------------|-------------------|-------| -| Descriptors | <1 min | 0.5–2 | Lightweight, good for triage | -| pKa (single transition) | 2–5 min | 2–5 | Depends on molecule size | -| MacropKa (pH 0–14) | 5–15 min | 5–15 | Broader sampling, higher cost | -| Conformer search | 3–10 min | 3–10 | Ensemble quality matters | -| Tautomer search | 2–5 min | 2–5 | Heterocyclic systems | -| Docking (single ligand) | 5–20 min | 5–20 | Depends on pocket size, refinement | -| Analogue docking series (10–50 ligands) | 30–120 min | 30–100+ | Shared reference frame | -| MSA generation | 5–30 min | 5–30 | Sequence length dependent | -| Protein-ligand cofolding | 15–60 min | 20–50+ | AI structure prediction, GPU-heavy | - ## Quick start ```bash @@ -81,22 +55,24 @@ uv pip install rowan-python import rowan rowan.api_key = "your_api_key_here" # or set ROWAN_API_KEY env var -# Submit a descriptors workflow — completes in under a minute -wf = rowan.submit_descriptors_workflow("CC(=O)Oc1ccccc1C(=O)O", name="aspirin") +# Descriptors require a 3D Molecule, not a bare SMILES string. +mol = rowan.Molecule.from_smiles("CC(=O)Oc1ccccc1C(=O)O") +wf = rowan.submit_descriptors_workflow(mol, name="aspirin") result = wf.result() -print(result.descriptors['MW']) # 180.16 -print(result.descriptors['SLogP']) # 1.19 -print(result.descriptors['TPSA']) # 59.44 +print(result.descriptors["MW"]) # 180.042 — exact mass +print(result.descriptors["SLogP"]) # 1.31 +print(result.descriptors["TopoPSA"]) # 63.6 — topological PSA ``` -If that prints without error, you're set up correctly. +If that prints without error, you're set up correctly. These values and examples +were verified against `rowan-python` 3.1.13. ## Installation ```bash uv pip install rowan-python -# or: pip install rowan-python +# or: uv pip install rowan-python ``` ## User and webhook management @@ -122,33 +98,7 @@ Verify authentication: import rowan user = rowan.whoami() # Returns user info if authenticated print(f"User: {user.email}") -print(f"Credits available: {user.credits_available_string}") -``` - -### Webhook secret management - -For webhook signature verification, manage secrets through your user account: - -```python -import rowan - -# Get your current webhook secret (returns None if none exists) -secret = rowan.get_webhook_secret() -if secret is None: - secret = rowan.create_webhook_secret() -print(f"Secret key: {secret.secret}") - -# Rotate your secret (invalidates old, creates new) -# Use this periodically for security -new_secret = rowan.rotate_webhook_secret() -print(f"New secret created (old secret disabled): {new_secret.secret}") - -# Verify incoming webhook signatures -is_valid = rowan.verify_webhook_secret( - request_body=b"...", # Raw request body (bytes) - signature="X-Rowan-Signature", # From request header - secret=secret.secret -) +print(f"Credits available: {user.credits_available_string()}") ``` ## Molecule input formats @@ -159,7 +109,18 @@ Rowan accepts molecules in the following formats: - **SMARTS patterns** (for some workflows): subset of SMARTS for substructure matching - **InChI** (if supported in your API version): `"InChI=1S/C2H6O/c1-2-3/h3H,2H2,1H3"` -The API will validate input and raise a `rowan.ValidationError` if a molecule cannot be parsed. Always use canonicalized SMILES for reproducibility. +The API validates molecule inputs and raises `ValueError` for an unparseable +SMILES or a workflow-incompatible input type. Always use canonicalized SMILES +for reproducibility. + +### SMILES strings versus molecule objects + +Accepted input types vary by workflow in `rowan-python` 3.1.13. Only these +common workflows accept a bare string: pKa, conformer search, membrane +permeability, ADMET, LogP, macropKa, solubility, and pose-analysis MD. Most +others — including descriptors, tautomer search, docking, analogue docking, +BDE, NMR, and Fukui — require `rowan.Molecule.from_smiles(smiles)` or an RDKit +`Mol`/`RWMol`. A wrong type raises `ValueError` before submission. **Tip:** Use RDKit to validate SMILES before submission: @@ -184,21 +145,21 @@ import rowan # 1. Submit — use the specific workflow function (not the generic submit_workflow) workflow = rowan.submit_descriptors_workflow( - "CC(=O)Oc1ccccc1C(=O)O", + rowan.Molecule.from_smiles("CC(=O)Oc1ccccc1C(=O)O"), name="aspirin descriptors", ) # 2. & 3. Wait and retrieve result = workflow.result() # Blocks until done (default: wait=True, poll_interval=5) print(result.data) # Raw dict -print(result.descriptors['MW']) # 180.16 — use result.descriptors dict, not result.molecular_weight +print(result.descriptors["MW"]) # 180.042 exact mass; no result.molecular_weight property ``` For long-running workflows, use streaming: ```python for partial in workflow.stream_result(poll_interval=5): - print(f"Progress: {partial.complete}%") + print(f"Complete: {partial.complete}") # bool, not a percentage print(partial.data) ``` @@ -219,28 +180,30 @@ Rowan's API includes **typed workflow result objects** with convenience properti Results have two access patterns: -1. **Convenience properties** (recommended first): `result.descriptors`, `result.best_pose`, `result.conformer_energies` +1. **Convenience properties** (recommended first): `result.descriptors`, `result.best_pose`, `result.scores`. Result classes differ: conformer search uses `get_energies()` and `get_conformers()` methods. 2. **Raw fallback**: `result.data` — raw dictionary from the API Example: ```python result = rowan.submit_descriptors_workflow( - "CCO", + rowan.Molecule.from_smiles("CCO"), name="ethanol", ).result() -# Convenience property (returns dict of all descriptors): -print(result.descriptors['MW']) # 46.042 -print(result.descriptors['SLogP']) # -0.001 -print(result.descriptors['TPSA']) # 57.96 +# Convenience property (returns all descriptors): +print(result.descriptors["MW"]) # exact/monoisotopic mass +print(result.descriptors["SLogP"]) +print(result.descriptors["TopoPSA"]) # usual topological PSA -# Raw data fallback (descriptors are nested under 'descriptors' key): -print(result.data['descriptors']) -# {'MW': 46.042, 'SLogP': -0.001, 'TPSA': 57.96, 'nHBDon': 1.0, 'nHBAcc': 1.0, ...} +# Raw data fallback: +print(result.data["descriptors"]) ``` -**Note:** `DescriptorsResult` does **not** have a `molecular_weight` property. Descriptor keys use short names (`MW`, `SLogP`, `nHBDon`) not verbose names. +**Note:** `DescriptorsResult` does **not** have a `molecular_weight` property. +`MW` is exact/monoisotopic mass, not average molecular weight. `TPSA` is a 3D +charged-surface descriptor; use `TopoPSA` for the usual topological polar +surface area used in drug-likeness rules. ### Cache invalidation @@ -248,7 +211,7 @@ Some result properties are lazily loaded (e.g., conformer geometries, protein st ```python result.clear_cache() -new_structures = result.conformer_molecules # Refetched +new_structures = result.get_conformers() # Refetched for ConformerSearchResult ``` ## Projects, folders, and organization @@ -265,11 +228,13 @@ project = rowan.create_project(name="CDK2 lead optimization") rowan.set_project("CDK2 lead optimization") # All subsequent workflows go into this project -wf = rowan.submit_descriptors_workflow("CCO", name="test compound") +wf = rowan.submit_descriptors_workflow( + rowan.Molecule.from_smiles("CCO"), name="test compound" +) -# Retrieve later -project = rowan.retrieve_project("CDK2 lead optimization") -workflows = rowan.list_workflows(project=project, size=50) +# retrieve_project takes a UUID; list_workflows scopes with parent_uuid. +project = rowan.retrieve_project(project.uuid) +workflows = rowan.list_workflows(parent_uuid=project.uuid, size=50) ``` ### Folders @@ -285,7 +250,7 @@ wf = rowan.submit_docking_workflow( ) # List workflows in a folder -results = rowan.list_workflows(folder=folder) +results = rowan.list_workflows(parent_uuid=folder.uuid) ``` ## Workflow decision trees @@ -334,7 +299,7 @@ ADME assessment across GI pH: Use macropKa ```python # Step 1: Find best tautomer taut_wf = rowan.submit_tautomer_search_workflow( - initial_molecule="O=c1[nH]ccnc1", + initial_molecule=rowan.Molecule.from_smiles("O=c1[nH]ccnc1"), name="imidazole tautomers", ) best_taut = taut_wf.result().best_tautomer @@ -354,528 +319,6 @@ conf_wf = rowan.submit_conformer_search_workflow( | Analogue docking | 5–100+ related compounds | Protein + SMILES list + reference ligand | All poses, reference-aligned | | Protein-ligand cofolding | Sequence + ligand, no crystal structure | Protein sequence + SMILES | ML-predicted bound complex | -## Common workflow categories - -### 1. Descriptors - -A lightweight entry point for batch triage, SAR, or exploratory scripts. - -```python -wf = rowan.submit_descriptors_workflow( - "CC(=O)Oc1ccccc1C(=O)O", # positional arg, accepts SMILES string - name="aspirin descriptors", -) - -result = wf.result() -print(result.descriptors['MW']) # 180.16 -print(result.descriptors['SLogP']) # 1.19 -print(result.descriptors['TPSA']) # 59.44 -print(result.data['descriptors']) -# {'MW': 180.16, 'SLogP': 1.19, 'TPSA': 59.44, 'nHBDon': 1.0, 'nHBAcc': 4.0, ...} -``` - -**Common descriptor keys:** - -| Key | Description | Typical drug range | -|-----|-------------|-------------------| -| `MW` | Molecular weight (Da) | <500 (Lipinski) | -| `SLogP` | Calculated LogP (lipophilicity) | -2 to +5 | -| `TPSA` | Topological polar surface area (Ų) | <140 for oral bioavailability | -| `nHBDon` | H-bond donor count | ≤5 (Lipinski) | -| `nHBAcc` | H-bond acceptor count | ≤10 (Lipinski) | -| `nRot` | Rotatable bond count | <10 for oral drugs | -| `nRing` | Ring count | — | -| `nHeavyAtom` | Heavy atom count | — | -| `FilterItLogS` | Estimated aqueous solubility (LogS) | >-4 preferred | -| `Lipinski` | Lipinski Ro5 pass (1.0) or fail (0.0) | — | - -The result contains hundreds of additional molecular descriptors (BCUT, GETAWAY, WHIM, etc.); access any via `result.descriptors['key']`. - -### 2. Microscopic pKa - -For protonation-state energetics and acid/base behavior of a specific structure. - -Two methods are available: - -| Method | Input | Speed | Covers | Use when | -|--------|-------|-------|--------|----------| -| `chemprop_nevolianis2025` | SMILES string | Fast | Deprotonation only (anionic conjugate bases) | Acidic groups only; quick screening | -| `starling` | SMILES string | Fast | Acid + base (full protonation/deprotonation) | Most drug-like molecules; preferred SMILES method | -| `aimnet2_wagen2024` (default) | 3D molecule object | Slower, higher accuracy | Acid + base | You already have a 3D structure (e.g. from conformer search) | - -```python -# Fast path: SMILES input with full acid+base coverage (use starling method when available) -wf = rowan.submit_pka_workflow( - initial_molecule="c1ccccc1O", # phenol SMILES; param is initial_molecule, not initial_smiles - method="starling", # fast SMILES method, covers acid+base; chemprop_nevolianis2025 is deprotonation-only - name="phenol pKa", -) - -result = wf.result() -print(result.strongest_acid) # 9.81 (pKa of the most acidic site) -print(result.conjugate_bases) # list of {pka, smiles, atom_index, ...} per deprotonatable site -``` - -### 3. MacropKa - -For pH-dependent protonation behavior across a range. - -```python -wf = rowan.submit_macropka_workflow( - initial_smiles="CN1CCN(CC1)C2=NC=NC3=CC=CC=C32", # imidazole - min_pH=0, - max_pH=14, - min_charge=-2, # default - max_charge=2, # default - compute_aqueous_solubility=True, # default - name="imidazole macropKa", -) - -result = wf.result() -print(result.pka_values) # list of pKa values -print(result.logd_by_ph) # dict of {pH: logD} -print(result.aqueous_solubility_by_ph) # dict of {pH: solubility} -print(result.isoelectric_point) # isoelectric point -print(result.data) -# {'pKa_values': [...], 'logD_by_pH': {...}, 'aqueous_solubility_by_pH': {...}, ...} -``` - -### 4. Conformer search - -For 3D ensemble generation when ensemble quality matters. - -```python -wf = rowan.submit_conformer_search_workflow( - initial_molecule="CCOC(=O)N1CCC(CC1)Oc1ncnc2ccccc12", - num_conformers=50, # Optional: override default - name="conformer search", -) - -result = wf.result() -print(result.conformer_energies) # [0.0, 1.2, 2.5, ...] -print(result.conformer_molecules) # List of 3D molecules -print(result.best_conformer) # Lowest-energy conformer -``` - -### 5. Tautomer search - -For heterocycles and systems where tautomer state affects downstream modeling. - -```python -wf = rowan.submit_tautomer_search_workflow( - initial_molecule="O=c1[nH]ccnc1", # or keto tautomer - name="imidazolone tautomers", -) - -result = wf.result() -print(result.best_tautomer) # Most stable SMILES string -print(result.tautomers) # List of tautomeric SMILES -print(result.molecules) # List of molecule objects -``` - -### 6. Docking - -For protein-ligand docking with optional pose refinement and conformer generation. - -```python -# Upload protein once, reuse in multiple workflows -protein = rowan.upload_protein( - name="CDK2", - file_path="cdk2.pdb", -) - -# Define binding pocket -pocket = { - "center": [10.5, 24.2, 31.8], - "size": [18.0, 18.0, 18.0], -} - -# Submit docking -wf = rowan.submit_docking_workflow( - protein=protein, - pocket=pocket, - initial_molecule="CCNc1ncc(c(Nc2ccc(F)cc2)n1)-c1cccnc1", - do_pose_refinement=True, - do_conformer_search=True, - name="lead docking", -) - -result = wf.result() -print(result.scores) # Docking scores (kcal/mol) -print(result.best_pose) # Mol object with 3D coordinates -print(result.data) # Raw result dict -``` - -**Protein preparation tips:** - -- PDB files should be reasonably clean (remove water/heteroatoms unless intended) -- Use the same protein object across a docking series for consistency -- If you have a PDB ID, use `rowan.create_protein_from_pdb_id()` instead - -### 7. Analogue docking - -For placing a compound series into a shared binding context. - -```python -# Analogue series (e.g., SAR campaign) -analogues = [ - "CCNc1ncc(c(Nc2ccc(F)cc2)n1)-c1cccnc1", # reference - "CCNc1ncc(c(Nc2ccc(Cl)cc2)n1)-c1cccnc1", # chloro - "CCNc1ncc(c(Nc2ccc(OC)cc2)n1)-c1cccnc1", # methoxy - "CCNc1ncc(c(Nc2cc(C)c(F)cc2)n1)-c1cccnc1", # methyl, fluoro -] - -wf = rowan.submit_analogue_docking_workflow( - analogues=analogues, - initial_molecule=analogues[0], # Reference ligand - protein=protein, - pocket=pocket, - name="SAR series docking", -) - -result = wf.result() -print(result.analogue_scores) # List of scores for each analogue -print(result.best_poses) # List of poses -``` - -### 8. MSA generation - -For multiple-sequence alignment (useful for downstream cofolding). - -```python -wf = rowan.submit_msa_workflow( - initial_protein_sequences=[ - "MENFQKVEKIGEGTYGVVYKARNKLTGEVVALKKIRLDTETEGVP" - ], - output_formats=["colabfold", "chai", "boltz"], - name="target MSA", -) - -result = wf.result() -result.download_files() # Downloads alignments to disk -``` - -### 9. Protein-ligand cofolding - -For AI-based bound-complex prediction when no crystal structure is available. - -```python -wf = rowan.submit_protein_cofolding_workflow( - initial_protein_sequences=[ - "MENFQKVEKIGEGTYGVVYKARNKLTGEVVALKKIRLDTETEGVP" - ], - initial_smiles_list=[ - "CCNc1ncc(c(Nc2ccc(F)cc2)n1)-c1cccnc1" - ], - name="protein-ligand cofolding", -) - -result = wf.result() -print(result.predictions) # List of predicted structures -print(result.messages) # Model metadata/warnings - -predicted_structure = result.get_predicted_structure() -predicted_structure.write("predicted_complex.pdb") -``` - -## All supported workflow types - -All workflows follow the same submit → wait → retrieve pattern and support webhooks and project/folder organization. - -### Core molecular modeling workflows - -| Workflow | Function | When to use | -|----------|----------|-------------| -| Descriptors | `submit_descriptors_workflow` | First-pass triage: MW, LogP, TPSA, HBA/HBD, Lipinski filter | -| pKa | `submit_pka_workflow` | Single ionizable group; need protonation thermodynamics | -| MacropKa | `submit_macropka_workflow` | Multi-ionizable drugs; pH-dependent charge/LogD/solubility | -| Conformer Search | `submit_conformer_search_workflow` | 3D ensemble for docking, MD, or SAR; known tautomer | -| Tautomer Search | `submit_tautomer_search_workflow` | Heterocycles, keto–enol; uncertain tautomeric form | -| Solubility | `submit_solubility_workflow` | Aqueous or solvent-specific solubility prediction | -| Membrane Permeability | `submit_membrane_permeability_workflow` | Caco-2, PAMPA, BBB, plasma permeability | -| ADMET | `submit_admet_workflow` | Broad drug-likeness and ADMET property sweep | - -### Structure-based design workflows - -| Workflow | Function | When to use | -|----------|----------|-------------| -| Docking | `submit_docking_workflow` | Single ligand, known binding pocket | -| Analogue Docking | `submit_analogue_docking_workflow` | SAR series (5–100+ compounds) in a shared pocket | -| Batch Docking | `submit_batch_docking_workflow` | Fast library screening; large compound sets | -| Protein MD | `submit_protein_md_workflow` | Long-timescale dynamics; conformational sampling | -| Pose Analysis MD | `submit_pose_analysis_md_workflow` | MD refinement of a docking pose | -| Protein Cofolding | `submit_protein_cofolding_workflow` | No crystal structure; AI-predicted bound complex | -| Protein Binder Design | `submit_protein_binder_design_workflow` | De novo binder generation against a protein target | - -### Advanced computational chemistry - -| Workflow | Function | When to use | -|----------|----------|-------------| -| Basic Calculation | `submit_basic_calculation_workflow` | QM/ML geometry optimization or single-point energy | -| Electronic Properties | `submit_electronic_properties_workflow` | Dipole, partial charges, HOMO-LUMO, ESP | -| BDE | `submit_bde_workflow` | Bond dissociation energies; metabolic soft-spot prediction | -| Redox Potential | `submit_redox_potential_workflow` | Oxidation/reduction potentials | -| Spin States | `submit_spin_states_workflow` | Spin-state energy ordering for organometallics/radicals | -| Strain | `submit_strain_workflow` | Conformational strain relative to global minimum | -| Scan | `submit_scan_workflow` | PES scans; torsion profiles | -| Multistage Optimization | `submit_multistage_opt_workflow` | Progressive optimization across levels of theory | - -### Reaction chemistry - -| Workflow | Function | When to use | -|----------|----------|-------------| -| Double-Ended TS Search | `submit_double_ended_ts_search_workflow` | Transition state between two known structures | -| IRC | `submit_irc_workflow` | Confirm TS connectivity; intrinsic reaction coordinate | - -### Advanced properties - -| Workflow | Function | When to use | -|----------|----------|-------------| -| NMR | `submit_nmr_workflow` | Predicted 1H/13C chemical shifts for structure verification | -| Ion Mobility | `submit_ion_mobility_workflow` | Collision cross-section (CCS) for MS method development | -| Hydrogen Bond Strength | `submit_hydrogen_bond_basicity_workflow` | H-bond donor/acceptor strength for formulation/solubility | -| Fukui | `submit_fukui_workflow` | Site reactivity indices for electrophilic/nucleophilic attack | -| Interaction Energy Decomposition | `submit_interaction_energy_decomposition_workflow` | Fragment-level interaction analysis | - -### Binding free energy - -| Workflow | Function | When to use | -|----------|----------|-------------| -| RBFE/FEP | `submit_relative_binding_free_energy_perturbation_workflow` | Relative ΔΔG for congeneric series | -| RBFE Graph | `submit_rbfe_graph_workflow` | Build and optimize an RBFE perturbation network | - -### Sequence and structural biology - -| Workflow | Function | When to use | -|----------|----------|-------------| -| MSA | `submit_msa_workflow` | Multiple sequence alignment for cofolding (ColabFold, Chai, Boltz) | -| Solvent-Dependent Conformers | `submit_solvent_dependent_conformers_workflow` | Solvation-aware conformer ensembles | - -## Batch submission and retrieval - -For libraries or analogue series, submit in a loop using the specific workflow function. The generic `rowan.batch_submit_workflow()` and `rowan.submit_workflow()` functions currently return 422 errors from the API — use the named functions (`submit_descriptors_workflow`, `submit_pka_workflow`, etc.) instead. - -### Submit a batch - -```python -smileses = ["CCO", "CC(=O)O", "c1ccccc1O"] -names = ["ethanol", "acetic acid", "phenol"] - -workflows = [ - rowan.submit_descriptors_workflow(smi, name=name) - for smi, name in zip(smileses, names) -] - -print(f"Submitted {len(workflows)} workflows") -``` - -### Poll batch status - -```python -statuses = rowan.batch_poll_status([wf.uuid for wf in workflows]) -# Returns aggregate counts — not per-UUID: -# {'queued': 0, 'running': 1, 'complete': 2, 'failed': 0, 'total': 3, ...} - -if statuses["complete"] == statuses["total"]: - print("All workflows done") -elif statuses["failed"] > 0: - print(f"{statuses['failed']} workflows failed") -``` - -### Retrieve and collect results - -```python -results = [] -for wf in workflows: - try: - result = wf.result() - results.append(result.data) - except rowan.WorkflowError as e: - print(f"Workflow {wf.uuid} failed: {e}") - -# Optionally aggregate into DataFrame -import pandas as pd -df = pd.DataFrame(results) -``` - -### Non-blocking / fire-and-check pattern - -For long-running workflows where you don't want to hold a process open, submit workflows, save their UUIDs, and check back later in a separate process. - -**Session 1 — submit and save UUIDs:** - -```python -import rowan, json - -rowan.api_key = "..." -smileses = ["CCO", "CC(=O)O", "c1ccccc1O"] - -workflows = [ - rowan.submit_descriptors_workflow(smi, name=f"compound_{i}") - for i, smi in enumerate(smileses) -] - -# Save UUIDs to disk (or a database) -uuids = [wf.uuid for wf in workflows] -with open("workflow_uuids.json", "w") as f: - json.dump(uuids, f) - -print("Submitted. Check back later.") -``` - -**Session 2 — check status and collect results when ready:** - -```python -import rowan, json - -rowan.api_key = "..." - -with open("workflow_uuids.json") as f: - uuids = json.load(f) - -results = [] -for uuid in uuids: - wf = rowan.retrieve_workflow(uuid) - if wf.done(): - result = wf.result(wait=False) - results.append({"uuid": uuid, "data": result.data}) - else: - print(f"{uuid}: still running ({wf.status})") - -print(f"Collected {len(results)} completed results") -``` - -## Webhooks and asynchronous workflows - -For long-running campaigns or when you don't want to keep a process alive, use webhooks to notify your backend when workflows complete. - -### Setting up webhooks - -Every workflow submission function accepts a `webhook_url` parameter: - -```python -wf = rowan.submit_docking_workflow( - protein=protein, - pocket=pocket, - initial_molecule="CCO", - webhook_url="https://myserver.com/rowan_callback", - name="docking with webhook", -) - -print(f"Workflow submitted. Result will be POSTed to webhook when complete.") -``` - -Webhook URLs can be passed to any specific workflow function (`submit_docking_workflow()`, `submit_pka_workflow()`, `submit_descriptors_workflow()`, etc.). - -### Webhook authentication with secrets - -Rowan supports webhook signature verification to ensure requests are authentic. You'll need to: - -1. **Create or retrieve a webhook secret:** - -```python -import rowan - -# Create a new webhook secret -secret = rowan.create_webhook_secret() -print(f"Your webhook secret: {secret.secret}") - -# Or retrieve an existing secret -secret = rowan.get_webhook_secret() - -# Rotate your secret (invalidates old one, creates new) -new_secret = rowan.rotate_webhook_secret() -``` - -2. **Verify incoming webhook requests:** - -```python -import rowan -import hmac -import json - -def verify_webhook(request_body: bytes, signature: str, secret: str) -> bool: - """Verify the HMAC-SHA256 signature of a webhook request.""" - return rowan.verify_webhook_secret(request_body, signature, secret) -``` - -### Webhook payload and signature - -When a workflow completes, Rowan POSTs a JSON payload to your webhook URL with the header: - -```text -X-Rowan-Signature: -``` - -The request body contains the complete workflow result: - -```json -{ - "workflow_uuid": "wf_12345abc", - "workflow_type": "docking", - "workflow_name": "lead docking", - "status": "COMPLETED_OK", - "created_at": "2025-04-01T12:00:00Z", - "completed_at": "2025-04-01T12:15:30Z", - "data": { - "scores": [-8.2, -8.0, -7.9], - "best_pose": {...}, - "metadata": {...} - } -} -``` - -### Example webhook handler with signature verification (FastAPI) - -```python -from fastapi import FastAPI, Request, HTTPException -import rowan -import json - -app = FastAPI() -_ws = rowan.get_webhook_secret() or rowan.create_webhook_secret() -webhook_secret = _ws.secret - -@app.post("/rowan_callback") -async def handle_rowan_webhook(request: Request): - # Get request body and signature - body = await request.body() - signature = request.headers.get("X-Rowan-Signature") - - if not signature: - raise HTTPException(status_code=400, detail="Missing X-Rowan-Signature header") - - # Verify signature - if not rowan.verify_webhook_secret(body, signature, webhook_secret): - raise HTTPException(status_code=401, detail="Invalid webhook signature") - - # Parse and process - payload = json.loads(body) - wf_uuid = payload["workflow_uuid"] - status = payload["status"] - - if status == "COMPLETED_OK": - print(f"Workflow {wf_uuid} succeeded!") - result_data = payload["data"] - # Process result, update database, trigger next workflow, etc. - elif status == "FAILED": - print(f"Workflow {wf_uuid} failed!") - # Handle failure - - # Respond quickly to prevent retries - return {"status": "received"} -``` - -### Webhook best practices - -- **Always verify signatures** using `rowan.verify_webhook_secret()` to ensure requests are from Rowan -- **Respond quickly** (< 5 seconds); offload heavy processing to async tasks or background jobs -- **Implement idempotency**: workflows may retry; handle duplicate payloads gracefully using `workflow_uuid` -- **Log all events** for debugging and audit trails -- **Use for long campaigns**: webhooks shine with 50+ workflows; for small jobs, polling with `result()` is simpler -- **Rotate secrets regularly** using `rowan.rotate_webhook_secret()` for security -- **Return 2xx status** to confirm receipt; Rowan may retry on 5xx errors - ## Protein utilities ### Upload proteins @@ -909,167 +352,36 @@ my_proteins = rowan.list_proteins() - **Resolution**: Works with NMR structures, homology models, and cryo-EM; quality matters for downstream predictions - **Validation**: Rowan validates PDB syntax; severely malformed files may be rejected -## End-to-end example: Lead optimization campaign +## Workflow catalog -This example demonstrates a realistic workflow for optimizing a hit compound: +Nine common workflow categories — descriptors, microscopic pKa, MacropKa, conformer +search, tautomer search, docking, analogue docking, MSA generation, and protein-ligand +cofolding — each with submission code and result shapes, plus the complete list of every +supported workflow type (core modeling, structure-based design, advanced computational +chemistry, reaction chemistry, advanced properties, binding free energy, and sequence and +structural biology) are in +[references/workflow_catalog.md](references/workflow_catalog.md). -```python -import rowan -import pandas as pd +## Batch submission, webhooks, and asynchronous work -# 1. Create a project and folder for organization -project = rowan.create_project(name="CDK2 Hit Optimization") -rowan.set_project("CDK2 Hit Optimization") -folder = rowan.create_folder(name="round_1_tautomers_and_pka") +Batch submit/poll/retrieve, the non-blocking fire-and-check pattern, webhook setup, +secret creation and rotation, payload and signature verification (with a FastAPI +handler), and webhook best practices are in +[references/batch_and_webhooks.md](references/batch_and_webhooks.md). -# 2. Load hit compound and analogues -hit = "CCNc1ncc(c(Nc2ccc(F)cc2)n1)-c1cccnc1" # Known hit -analogues = [ - "CCNc1ncc(c(Nc2ccccc2)n1)-c1cccnc1", # Remove F - "CCNc1ncc(c(Nc2ccc(Cl)cc2)n1)-c1cccnc1", # Cl instead of F - "CCC(C)Nc1ncc(c(Nc2ccc(F)cc2)n1)-c1cccnc1", # Propyl instead of ethyl -] +## Access, pricing, and credits -# 3. Determine best tautomers (just in case) -print("Searching tautomeric forms...") -taut_workflows = [ - rowan.submit_tautomer_search_workflow( - smi, name=f"analog_{i}", folder=folder, - ) - for i, smi in enumerate(analogues) -] +Free-tier limits, credit consumption per workflow, and typical cost estimates are in +[references/access_and_pricing.md](references/access_and_pricing.md). -best_tautomers = [] -for wf in taut_workflows: - result = wf.result() - best_tautomers.append(result.best_tautomer) +## Worked example and troubleshooting -# 4. Predict pKa and basic properties for all analogues -print("Predicting pKa and properties...") -pka_workflows = [ - rowan.submit_pka_workflow( - smi, method="chemprop_nevolianis2025", name=f"pka_{i}", folder=folder, - ) - for i, smi in enumerate(best_tautomers) -] +A full lead-optimization campaign — project setup, tautomers, pKa across an analogue +series, result collection, and a docking follow-up — is in +[references/end_to_end_example.md](references/end_to_end_example.md). -descriptor_workflows = [ - rowan.submit_descriptors_workflow(smi, name=f"desc_{i}", folder=folder) - for i, smi in enumerate(best_tautomers) -] - -# 5. Collect results -pka_results = [] -for wf in pka_workflows: - try: - result = wf.result() - pka_results.append({ - "compound": wf.name, - "pka": result.strongest_acid, # pKa of the strongest acid site - "uuid": wf.uuid, - }) - except rowan.WorkflowError as e: - print(f"pKa prediction failed for {wf.name}: {e}") - -descriptor_results = [] -for wf in descriptor_workflows: - try: - result = wf.result() - desc = result.descriptors - descriptor_results.append({ - "compound": wf.name, - "mw": desc.get("MW"), - "logp": desc.get("SLogP"), - "hba": desc.get("nHBAcc"), - "hbd": desc.get("nHBDon"), - "uuid": wf.uuid, - }) - except rowan.WorkflowError as e: - print(f"Descriptor calculation failed for {wf.name}: {e}") - -# 6. Merge and summarize -df_pka = pd.DataFrame(pka_results) -df_desc = pd.DataFrame(descriptor_results) -df = df_pka.merge(df_desc, on="compound", how="outer") - -print("\n=== Preliminary SAR ===") -print(df.to_string()) - -# 7. Select promising compound for docking -# compound names are "pka_0", "pka_1", etc. — extract index to look up SMILES -top_idx = int(df.loc[df["pka"].idxmin(), "compound"].split("_")[1]) -top_smiles = best_tautomers[top_idx] - -print(f"\nProceeding with docking: {top_smiles}") - -# 8. Docking campaign -protein = rowan.create_protein_from_pdb_id(name="CDK2_1CKP", code="1CKP") -pocket = {"center": [10.5, 24.2, 31.8], "size": [18.0, 18.0, 18.0]} - -docking_wf = rowan.submit_docking_workflow( - protein=protein, - pocket=pocket, - initial_molecule=top_smiles, - do_pose_refinement=True, - name=f"docking_{top_compound}", -) - -dock_result = docking_wf.result() -print(f"\nDocking score: {dock_result.scores[0]:.2f} kcal/mol") -print(f"Best pose saved to: best_pose.pdb") -dock_result.best_pose.write("best_pose.pdb") -``` - -## Error handling and troubleshooting - -### Common errors and solutions - -```python -import rowan - -# Error 1: Invalid SMILES -try: - wf = rowan.submit_descriptors_workflow("CCCC(CC", name="bad smiles") # Invalid -except rowan.ValidationError as e: - print(f"Invalid SMILES: {e}") - # Solution: Use RDKit to validate before submission - from rdkit import Chem - smi = Chem.MolToSmiles(Chem.MolFromSmiles(smi)) - -# Error 2: API key not set -try: - wf = rowan.submit_descriptors_workflow("CCO") -except rowan.AuthenticationError: - print("API key not found. Set ROWAN_API_KEY env var or call rowan.api_key = '...'") - -# Error 3: Insufficient credits -try: - wf = rowan.submit_protein_cofolding_workflow(...) -except rowan.InsufficientCreditsError as e: - print(f"Not enough credits: {e}. Purchase more or reduce job size.") - -# Error 4: Workflow failed (bad molecule, etc.) -try: - wf = rowan.submit_docking_workflow(...) - result = wf.result() -except rowan.WorkflowError as e: - print(f"Workflow failed: {e}") - # Check wf.status for details - print(f"Status: {wf.status}") - -# Error 5: Workflow not yet done — poll manually -result = wf.result(wait=True, poll_interval=5) # waits and polls every 5s -# Or check status without blocking: -if not wf.done(): - print("Workflow still running. Call wf.result() again later.") -``` - -### Debugging tips - -- **Check workflow status**: `wf.status`, check `wf.done()`, or call `wf.get_status()` -- **Inspect raw result**: `result.data` instead of convenience properties -- **Re-run failed workflow**: Save UUIDs and retry with `rowan.retrieve_workflow(uuid)` -- **Validate molecules beforehand**: Use RDKit or Chemaxon before batch submission +Common errors with their fixes, and debugging tips, are in +[references/troubleshooting.md](references/troubleshooting.md). ## Recommended usage patterns -- 2.54.0 From 44a925eec05a442c4f47c8ef95e7565af8e96bf8 Mon Sep 17 00:00:00 2001 From: promptadmin Date: Sat, 29 Aug 2026 17:06:06 +0000 Subject: [PATCH 2/8] [upstream-sync] skills/rowan/references/batch_and_webhooks.md from K-Dense-AI/scientific-agent-skills@72d742e1 [prompt] --- .../rowan/references/batch_and_webhooks.md | 268 ++++++++++++++++++ 1 file changed, 268 insertions(+) create mode 100644 upstream/K-Dense-AI-scientific-agent-skills/skills/rowan/references/batch_and_webhooks.md diff --git a/upstream/K-Dense-AI-scientific-agent-skills/skills/rowan/references/batch_and_webhooks.md b/upstream/K-Dense-AI-scientific-agent-skills/skills/rowan/references/batch_and_webhooks.md new file mode 100644 index 00000000..9469308f --- /dev/null +++ b/upstream/K-Dense-AI-scientific-agent-skills/skills/rowan/references/batch_and_webhooks.md @@ -0,0 +1,268 @@ +--- +title: "Batch Submission, Webhooks, and Asynchronous Workflows" +task: "" +lineage_type: import +upstream_source: https://github.com/K-Dense-AI/scientific-agent-skills/blob/72d742e1/skills/rowan/references/batch_and_webhooks.md +upstream_sha: 72d742e1 +imported_at: 2026-08-29 +prompt_class: prompt +upstream_changes: accepted +author: upstream +validated: false +--- + +# Batch Submission, Webhooks, and Asynchronous Workflows + +Webhook secret management, batch submit/poll/retrieve, the non-blocking fire-and-check +pattern, webhook payloads and signature verification, and webhook best practices. + +### Webhook secret management + +For webhook signature verification, manage secrets through your user account: + +```python +import rowan + +# Get your current webhook secret (returns None if none exists) +secret = rowan.get_webhook_secret() +if secret is None: + secret = rowan.create_webhook_secret() +# These functions return the secret as a plain string. + +# Rotate your secret (invalidates old, creates new) +# Use this periodically for security. +secret = rowan.rotate_webhook_secret() + +# Verify incoming webhook signatures. +is_valid = rowan.verify_webhook_secret( + raw_body=b"...", # Raw request body (bytes) + signature_header="sha256=...", # Value from X-Rowan-Signature + secret=secret, +) +``` + +## Batch submission and retrieval + +For libraries or analogue series, submit in a loop using the specific workflow function. The generic `rowan.batch_submit_workflow()` and `rowan.submit_workflow()` functions currently return 422 errors from the API — use the named functions (`submit_descriptors_workflow`, `submit_pka_workflow`, etc.) instead. + +### Submit a batch + +```python +smileses = ["CCO", "CC(=O)O", "c1ccccc1O"] +names = ["ethanol", "acetic acid", "phenol"] + +workflows = [ + rowan.submit_descriptors_workflow(rowan.Molecule.from_smiles(smi), name=name) + for smi, name in zip(smileses, names) +] + +print(f"Submitted {len(workflows)} workflows") +``` + +### Poll batch status + +```python +statuses = rowan.batch_poll_status([wf.uuid for wf in workflows]) +# Returns aggregate counts — not per-UUID: +# {'queued': 0, 'running': 1, 'complete': 2, 'failed': 0, 'total': 3, ...} + +if statuses["complete"] == statuses["total"]: + print("All workflows done") +elif statuses["failed"] > 0: + print(f"{statuses['failed']} workflows failed") +``` + +### Retrieve and collect results + +```python +results = [] +for wf in workflows: + try: + result = wf.result() + results.append(result.data) + except rowan.WorkflowError as e: + print(f"Workflow {wf.uuid} failed: {e}") + +# Optionally aggregate into DataFrame +import pandas as pd +df = pd.DataFrame(results) +``` + +### Non-blocking / fire-and-check pattern + +For long-running workflows where you don't want to hold a process open, submit workflows, save their UUIDs, and check back later in a separate process. + +**Session 1 — submit and save UUIDs:** + +```python +import rowan, json + +rowan.api_key = "..." +smileses = ["CCO", "CC(=O)O", "c1ccccc1O"] + +workflows = [ + rowan.submit_descriptors_workflow( + rowan.Molecule.from_smiles(smi), name=f"compound_{i}" + ) + for i, smi in enumerate(smileses) +] + +# Save UUIDs to disk (or a database) +uuids = [wf.uuid for wf in workflows] +with open("workflow_uuids.json", "w") as f: + json.dump(uuids, f) + +print("Submitted. Check back later.") +``` + +**Session 2 — check status and collect results when ready:** + +```python +import rowan, json + +rowan.api_key = "..." + +with open("workflow_uuids.json") as f: + uuids = json.load(f) + +results = [] +for uuid in uuids: + wf = rowan.retrieve_workflow(uuid) + if wf.done(): + result = wf.result(wait=False) + results.append({"uuid": uuid, "data": result.data}) + else: + print(f"{uuid}: still running ({wf.get_status()})") + +print(f"Collected {len(results)} completed results") +``` + +## Webhooks and asynchronous workflows + +For long-running campaigns or when you don't want to keep a process alive, use webhooks to notify your backend when workflows complete. + +### Setting up webhooks + +Every workflow submission function accepts a `webhook_url` parameter: + +```python +wf = rowan.submit_docking_workflow( + protein=protein, + pocket=pocket, + initial_molecule=rowan.Molecule.from_smiles("CCO"), + webhook_url="https://myserver.com/rowan_callback", + name="docking with webhook", +) + +print(f"Workflow submitted. Result will be POSTed to webhook when complete.") +``` + +Webhook URLs can be passed to any specific workflow function (`submit_docking_workflow()`, `submit_pka_workflow()`, `submit_descriptors_workflow()`, etc.). + +### Webhook authentication with secrets + +Rowan supports webhook signature verification to ensure requests are authentic. You'll need to: + +1. **Create or retrieve a webhook secret:** + +```python +import rowan + +# Create a new webhook secret +secret = rowan.create_webhook_secret() # returns a string +# Store it securely; do not log it. + +# Or retrieve an existing secret +secret = rowan.get_webhook_secret() + +# Rotate your secret (invalidates old one, creates new) +new_secret = rowan.rotate_webhook_secret() +``` + +2. **Verify incoming webhook requests:** + +```python +import rowan +import hmac +import json + +def verify_webhook(request_body: bytes, signature: str, secret: str) -> bool: + """Verify the HMAC-SHA256 signature of a webhook request.""" + return rowan.verify_webhook_secret(request_body, signature, secret) +``` + +### Webhook payload and signature + +When a workflow completes, Rowan POSTs a JSON payload to your webhook URL with the header: + +```text +X-Rowan-Signature: +``` + +The request body contains the complete workflow result: + +```json +{ + "workflow_uuid": "wf_12345abc", + "workflow_type": "docking", + "workflow_name": "lead docking", + "status": "COMPLETED_OK", + "created_at": "2025-04-01T12:00:00Z", + "completed_at": "2025-04-01T12:15:30Z", + "data": { + "scores": [-8.2, -8.0, -7.9], + "best_pose": {...}, + "metadata": {...} + } +} +``` + +### Example webhook handler with signature verification (FastAPI) + +```python +from fastapi import FastAPI, Request, HTTPException +import rowan +import json + +app = FastAPI() +webhook_secret = rowan.get_webhook_secret() or rowan.create_webhook_secret() + +@app.post("/rowan_callback") +async def handle_rowan_webhook(request: Request): + # Get request body and signature + body = await request.body() + signature = request.headers.get("X-Rowan-Signature") + + if not signature: + raise HTTPException(status_code=400, detail="Missing X-Rowan-Signature header") + + # Verify signature + if not rowan.verify_webhook_secret(body, signature, webhook_secret): + raise HTTPException(status_code=401, detail="Invalid webhook signature") + + # Parse and process + payload = json.loads(body) + wf_uuid = payload["workflow_uuid"] + status = payload["status"] + + if status == "COMPLETED_OK": + print(f"Workflow {wf_uuid} succeeded!") + result_data = payload["data"] + # Process result, update database, trigger next workflow, etc. + elif status == "FAILED": + print(f"Workflow {wf_uuid} failed!") + # Handle failure + + # Respond quickly to prevent retries + return {"status": "received"} +``` + +### Webhook best practices + +- **Always verify signatures** using `rowan.verify_webhook_secret()` to ensure requests are from Rowan +- **Respond quickly** (< 5 seconds); offload heavy processing to async tasks or background jobs +- **Implement idempotency**: workflows may retry; handle duplicate payloads gracefully using `workflow_uuid` +- **Log all events** for debugging and audit trails +- **Use for long campaigns**: webhooks shine with 50+ workflows; for small jobs, polling with `result()` is simpler +- **Rotate secrets regularly** using `rowan.rotate_webhook_secret()` for security +- **Return 2xx status** to confirm receipt; Rowan may retry on 5xx errors -- 2.54.0 From c612f8708be9cc4fe43858f4103a9a96f7603485 Mon Sep 17 00:00:00 2001 From: promptadmin Date: Sat, 29 Aug 2026 17:06:08 +0000 Subject: [PATCH 3/8] [upstream-sync] skills/rowan/references/end_to_end_example.md from K-Dense-AI/scientific-agent-skills@72d742e1 [prompt] --- .../rowan/references/end_to_end_example.md | 132 ++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 upstream/K-Dense-AI-scientific-agent-skills/skills/rowan/references/end_to_end_example.md diff --git a/upstream/K-Dense-AI-scientific-agent-skills/skills/rowan/references/end_to_end_example.md b/upstream/K-Dense-AI-scientific-agent-skills/skills/rowan/references/end_to_end_example.md new file mode 100644 index 00000000..9dbf4065 --- /dev/null +++ b/upstream/K-Dense-AI-scientific-agent-skills/skills/rowan/references/end_to_end_example.md @@ -0,0 +1,132 @@ +--- +title: "End-to-End Example: Lead Optimization Campaign" +task: "" +lineage_type: import +upstream_source: https://github.com/K-Dense-AI/scientific-agent-skills/blob/72d742e1/skills/rowan/references/end_to_end_example.md +upstream_sha: 72d742e1 +imported_at: 2026-08-29 +prompt_class: prompt +upstream_changes: accepted +author: upstream +validated: false +--- + +# End-to-End Example: Lead Optimization Campaign + +A complete campaign: project and folder setup, tautomer selection, pKa and property +prediction across an analogue series, result collection and summary, and a docking +follow-up on the selected compound. + +## End-to-end example: Lead optimization campaign + +This example demonstrates a realistic workflow for optimizing a hit compound: + +```python +import rowan +import pandas as pd + +# 1. Create a project and folder for organization +project = rowan.create_project(name="CDK2 Hit Optimization") +rowan.set_project("CDK2 Hit Optimization") +folder = rowan.create_folder(name="round_1_tautomers_and_pka") + +# 2. Load hit compound and analogues +hit = "CCNc1ncc(c(Nc2ccc(F)cc2)n1)-c1cccnc1" # Known hit +analogues = [ + "CCNc1ncc(c(Nc2ccccc2)n1)-c1cccnc1", # Remove F + "CCNc1ncc(c(Nc2ccc(Cl)cc2)n1)-c1cccnc1", # Cl instead of F + "CCC(C)Nc1ncc(c(Nc2ccc(F)cc2)n1)-c1cccnc1", # Propyl instead of ethyl +] + +# 3. Determine best tautomers (just in case) +print("Searching tautomeric forms...") +taut_workflows = [ + rowan.submit_tautomer_search_workflow( + rowan.Molecule.from_smiles(smi), name=f"analog_{i}", folder=folder, + ) + for i, smi in enumerate(analogues) +] + +best_tautomers = [] +for wf in taut_workflows: + result = wf.result() + best_tautomers.append(result.best_tautomer) + +# 4. Predict pKa and basic properties for all analogues +print("Predicting pKa and properties...") +pka_workflows = [ + rowan.submit_pka_workflow( + smi, method="chemprop_nevolianis2025", name=f"compound_{i}", folder=folder, + ) + for i, smi in enumerate(best_tautomers) +] + +descriptor_workflows = [ + rowan.submit_descriptors_workflow( + rowan.Molecule.from_smiles(smi), name=f"compound_{i}", folder=folder + ) + for i, smi in enumerate(best_tautomers) +] + +# 5. Collect results +pka_results = [] +for wf in pka_workflows: + try: + result = wf.result() + pka_results.append({ + "compound": wf.name, + "pka": result.strongest_acid, # pKa of the strongest acid site + "uuid": wf.uuid, + }) + except rowan.WorkflowError as e: + print(f"pKa prediction failed for {wf.name}: {e}") + +descriptor_results = [] +for wf in descriptor_workflows: + try: + result = wf.result() + desc = result.descriptors + descriptor_results.append({ + "compound": wf.name, + "exact_mass": desc.get("MW"), + "topological_psa": desc.get("TopoPSA"), + "logp": desc.get("SLogP"), + "hba": desc.get("nHBAcc"), + "hbd": desc.get("nHBDon"), + "uuid": wf.uuid, + }) + except rowan.WorkflowError as e: + print(f"Descriptor calculation failed for {wf.name}: {e}") + +# 6. Merge and summarize +df_pka = pd.DataFrame(pka_results) +df_desc = pd.DataFrame(descriptor_results) +df = df_pka.merge(df_desc, on="compound", how="outer") + +print("\n=== Preliminary SAR ===") +print(df.to_string()) + +# 7. Select promising compound for docking +# compound names are "compound_0", "compound_1", etc. — extract the index +top_idx = int(df.loc[df["pka"].idxmin(), "compound"].split("_")[1]) +top_smiles = best_tautomers[top_idx] + +print(f"\nProceeding with docking: {top_smiles}") + +# 8. Docking campaign +protein = rowan.create_protein_from_pdb_id(code="1CKP", name="CDK2_1CKP") +pocket = [[10.5, 24.2, 31.8], [18.0, 18.0, 18.0]] + +docking_wf = rowan.submit_docking_workflow( + protein=protein, + pocket=pocket, + initial_molecule=rowan.Molecule.from_smiles(top_smiles), + do_pose_refinement=True, + name=f"docking_{top_idx}", +) + +dock_result = docking_wf.result() +print(f"\nDocking score: {dock_result.scores[0]:.2f} kcal/mol") +print(f"Best pose saved to: best_pose.pdb") +dock_result.best_pose.write("best_pose.pdb") +``` -- 2.54.0 From 40fc3e377669687a3e52dd251f9824b4aa2b9135 Mon Sep 17 00:00:00 2001 From: promptadmin Date: Sat, 29 Aug 2026 17:06:10 +0000 Subject: [PATCH 4/8] [upstream-sync] skills/rowan/references/troubleshooting.md from K-Dense-AI/scientific-agent-skills@72d742e1 [prompt] --- .../rowan/references/troubleshooting.md | 119 ++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 upstream/K-Dense-AI-scientific-agent-skills/skills/rowan/references/troubleshooting.md diff --git a/upstream/K-Dense-AI-scientific-agent-skills/skills/rowan/references/troubleshooting.md b/upstream/K-Dense-AI-scientific-agent-skills/skills/rowan/references/troubleshooting.md new file mode 100644 index 00000000..509c1396 --- /dev/null +++ b/upstream/K-Dense-AI-scientific-agent-skills/skills/rowan/references/troubleshooting.md @@ -0,0 +1,119 @@ +--- +title: "Error Handling and Troubleshooting" +task: "" +lineage_type: import +upstream_source: https://github.com/K-Dense-AI/scientific-agent-skills/blob/72d742e1/skills/rowan/references/troubleshooting.md +upstream_sha: 72d742e1 +imported_at: 2026-08-29 +prompt_class: prompt +upstream_changes: accepted +author: upstream +validated: false +--- + +# Error Handling and Troubleshooting + +Common errors — invalid SMILES, missing API keys, HTTP/API failures, failed +workflows, and polling — with verified handling for `rowan-python` 3.1.13. + +## Actual exception classes + +`rowan.ValidationError`, `rowan.AuthenticationError`, and +`rowan.InsufficientCreditsError` do **not** exist in SDK 3.1.13. Referencing one +in an `except` clause raises `AttributeError` while handling the original +failure. + +| Failure | Exception | +|---|---| +| Bad SMILES or wrong input type for a workflow | `ValueError` | +| Authentication, credit, or other HTTP/API failure | `httpx.HTTPStatusError` | +| Submitted workflow fails server-side | `rowan.WorkflowError` | + +## Validate molecules before submission + +```python +from rdkit import Chem + +smiles = "CCCC(CC" +mol = Chem.MolFromSmiles(smiles) +if mol is None: + raise ValueError(f"Invalid SMILES: {smiles}") +``` + +Input types vary by workflow. For example, descriptors require a molecule +object, while pKa accepts a SMILES string: + +```python +import rowan + +try: + rowan.submit_descriptors_workflow("CCO") +except ValueError as exc: + print(f"Input problem: {exc}") + +wf = rowan.submit_descriptors_workflow(rowan.Molecule.from_smiles("CCO")) +``` + +## Authentication and API errors + +```python +import httpx +import rowan + +try: + user = rowan.whoami() +except httpx.HTTPStatusError as exc: + if exc.response.status_code == 401: + print("Bad or missing API key — check ROWAN_API_KEY") + else: + # Includes credit limits and other API failures; inspect the response. + print(exc.response.status_code, exc.response.text) + raise +``` + +The SDK treats an environment variable set to an **empty string** as present. +That produces `401 Could not validate credentials` rather than a clear missing +key error. Check that `ROWAN_API_KEY` is non-empty without printing the key: + +```python +import os + +api_key = os.environ.get("ROWAN_API_KEY") +if not api_key: + raise RuntimeError("ROWAN_API_KEY is missing or empty") +``` + +Use `max_credits=N` on submission calls to bound spend. + +## Server-side workflow failures + +```python +try: + result = wf.result() +except rowan.WorkflowError as exc: + print(f"Workflow failed: {exc}") + print(f"Status: {wf.get_status()}") +``` + +## Polling and non-blocking checks + +```python +# Block and poll every five seconds. +result = wf.result(wait=True, poll_interval=5) + +# Or check without blocking. +if not wf.done(): + print(f"Still running: {wf.get_status()}") +else: + result = wf.result(wait=False) +``` + +`WorkflowResult.complete` is a boolean, not a percent-done value. For coarse +status, use `wf.get_status()` and `wf.fetch_latest()`. + +## Debugging tips + +- Inspect `result.data` when a convenience property is unavailable. +- Save workflow UUIDs and reconnect with `rowan.retrieve_workflow(uuid)`. +- Use `dir(result)` to discover properties for that result class; they differ. +- Validate SMILES locally with RDKit before any paid submission. -- 2.54.0 From 0eae1b9c418c4c9af10d294b56b2c05ddbb695b0 Mon Sep 17 00:00:00 2001 From: promptadmin Date: Sat, 29 Aug 2026 17:06:12 +0000 Subject: [PATCH 5/8] [upstream-sync] skills/rowan/references/workflow_catalog.md from K-Dense-AI/scientific-agent-skills@72d742e1 [unknown] --- .../rowan/references/workflow_catalog.md | 321 ++++++++++++++++++ 1 file changed, 321 insertions(+) create mode 100644 upstream/K-Dense-AI-scientific-agent-skills/catalogue/skills/rowan/references/workflow_catalog.md diff --git a/upstream/K-Dense-AI-scientific-agent-skills/catalogue/skills/rowan/references/workflow_catalog.md b/upstream/K-Dense-AI-scientific-agent-skills/catalogue/skills/rowan/references/workflow_catalog.md new file mode 100644 index 00000000..acaccf49 --- /dev/null +++ b/upstream/K-Dense-AI-scientific-agent-skills/catalogue/skills/rowan/references/workflow_catalog.md @@ -0,0 +1,321 @@ +--- +title: "Rowan Workflow Catalog" +task: "" +lineage_type: import +upstream_source: https://github.com/K-Dense-AI/scientific-agent-skills/blob/72d742e1/skills/rowan/references/workflow_catalog.md +upstream_sha: 72d742e1 +imported_at: 2026-08-29 +prompt_class: unknown +upstream_changes: accepted +author: upstream +validated: false +--- + +# Rowan Workflow Catalog + +Submission code, options, and result shapes for the common workflow categories, followed +by the complete list of supported workflow types. + +## Common workflow categories + +### 1. Descriptors + +A lightweight entry point for batch triage, SAR, or exploratory scripts. + +```python +wf = rowan.submit_descriptors_workflow( + rowan.Molecule.from_smiles("CC(=O)Oc1ccccc1C(=O)O"), + name="aspirin descriptors", +) + +result = wf.result() +print(result.descriptors["MW"]) # 180.042 — exact mass +print(result.descriptors["SLogP"]) # 1.31 +print(result.descriptors["TopoPSA"]) # 63.6 — topological PSA +print(result.descriptors["nHBAcc"]) # 3.0 +``` + +**Common descriptor keys:** + +| Key | Description | Typical drug range | +|-----|-------------|-------------------| +| `MW` | Exact/monoisotopic mass (Da), not average MW | <500 (Lipinski) | +| `SLogP` | Calculated LogP (lipophilicity) | -2 to +5 | +| `TopoPSA` | Topological polar surface area (Ų) | <140 for oral bioavailability | +| `TPSA` | 3D charged surface area, not topological PSA | — | +| `nHBDon` | H-bond donor count | ≤5 (Lipinski) | +| `nHBAcc` | H-bond acceptor count | ≤10 (Lipinski) | +| `nRot` | Rotatable bond count | <10 for oral drugs | +| `nRing` | Ring count | — | +| `nHeavyAtom` | Heavy atom count | — | +| `FilterItLogS` | Estimated aqueous solubility (LogS) | >-4 preferred | +| `Lipinski` | Lipinski Ro5 pass (1.0) or fail (0.0) | — | + +The result contains about 1,679 molecular descriptors in SDK 3.1.13 (BCUT, +GETAWAY, WHIM, etc.); access any via `result.descriptors["key"]`. For average +molecular weight, calculate it separately (for example, RDKit `MolWt`). + +### 2. Microscopic pKa + +For protonation-state energetics and acid/base behavior of a specific structure. + +Four methods are available: + +| Method | Input | Speed | Covers | Use when | +|--------|-------|-------|--------|----------| +| `chemprop_nevolianis2025` | SMILES string | Fast | Deprotonation only | Acidic groups only; quick screening | +| `starling` | SMILES string | Fast | Acid + base | Most drug-like molecules; preferred SMILES method | +| `aimnet2_wagen2024` | 3D molecule object | Slower | Acid + base | You already have a 3D structure | +| `gxtb_wagen2026` (**default**) | 3D molecule object | Slower | Acid + base | Current SDK default; set `method=` explicitly for reproducibility | + +```python +# Fast path: SMILES input with full acid+base coverage (use starling method when available) +wf = rowan.submit_pka_workflow( + initial_molecule="c1ccccc1O", # phenol SMILES; param is initial_molecule, not initial_smiles + method="starling", # fast SMILES method, covers acid+base; chemprop_nevolianis2025 is deprotonation-only + name="phenol pKa", +) + +result = wf.result() +print(result.strongest_acid) # 9.995 for phenol (verified; literature ~9.95) +print(result.strongest_base) # None when no basic site is found +print(result.conjugate_bases) # list of pKaMicrostate objects +# Access each microstate with .pka, .smiles, .atom_index, .delta_g, .uncertainty +``` + +### 3. MacropKa + +For pH-dependent protonation behavior across a range. + +```python +wf = rowan.submit_macropka_workflow( + initial_smiles="CN1CCN(CC1)C2=NC=NC3=CC=CC=C32", # imidazole + min_pH=0, + max_pH=14, + min_charge=-2, # default + max_charge=2, # default + compute_aqueous_solubility=True, # default + name="imidazole macropKa", +) + +result = wf.result() +print(result.pka_values) # list of pKa values +print(result.logd_by_ph) # dict of {pH: logD} +print(result.aqueous_solubility_by_ph) # dict of {pH: solubility} +print(result.isoelectric_point) # isoelectric point +print(result.data) +# {'pKa_values': [...], 'logD_by_pH': {...}, 'aqueous_solubility_by_pH': {...}, ...} +``` + +### 4. Conformer search + +For 3D ensemble generation when ensemble quality matters. + +```python +wf = rowan.submit_conformer_search_workflow( + initial_molecule="CCOC(=O)N1CCC(CC1)Oc1ncnc2ccccc12", + name="conformer search", +) + +result = wf.result() +print(result.num_conformers) +print(result.get_energies()) # [0.0, 1.2, 2.5, ...] +print(result.get_conformers()) # list of 3D molecules +print(result.get_conformer(0)) # lowest-energy conformer + +# There is no num_conformers submit parameter. Configure the generator and +# ensemble through conf_gen_settings. +``` + +### 5. Tautomer search + +For heterocycles and systems where tautomer state affects downstream modeling. + +```python +wf = rowan.submit_tautomer_search_workflow( + initial_molecule=rowan.Molecule.from_smiles("O=c1[nH]ccnc1"), + name="imidazolone tautomers", +) + +result = wf.result() +print(result.best_tautomer) # Most stable SMILES string +print(result.tautomers) # List of tautomeric SMILES +print(result.molecules) # List of molecule objects +``` + +### 6. Docking + +For protein-ligand docking with optional pose refinement and conformer generation. + +```python +# Upload protein once, reuse in multiple workflows +protein = rowan.upload_protein( + name="CDK2", + file_path="cdk2.pdb", +) + +# Binding pocket: [[center_x, center_y, center_z], [size_x, size_y, size_z]] in Å +pocket = [[10.5, 24.2, 31.8], [18.0, 18.0, 18.0]] + +# Submit docking +wf = rowan.submit_docking_workflow( + protein=protein, + pocket=pocket, + initial_molecule=rowan.Molecule.from_smiles( + "CCNc1ncc(c(Nc2ccc(F)cc2)n1)-c1cccnc1" + ), + do_pose_refinement=True, + do_csearch=True, + name="lead docking", +) + +result = wf.result() +print(result.scores) # Docking scores (kcal/mol) +print(result.best_pose) # Mol object with 3D coordinates +print(result.data) # Raw result dict +``` + +**Protein preparation tips:** + +- PDB files should be reasonably clean (remove water/heteroatoms unless intended) +- Use the same protein object across a docking series for consistency +- If you have a PDB ID, use `rowan.create_protein_from_pdb_id()` instead + +### 7. Analogue docking + +For placing a compound series into a shared binding context. + +```python +# Analogue series (e.g., SAR campaign) +analogues = [ + "CCNc1ncc(c(Nc2ccc(F)cc2)n1)-c1cccnc1", # reference + "CCNc1ncc(c(Nc2ccc(Cl)cc2)n1)-c1cccnc1", # chloro + "CCNc1ncc(c(Nc2ccc(OC)cc2)n1)-c1cccnc1", # methoxy + "CCNc1ncc(c(Nc2cc(C)c(F)cc2)n1)-c1cccnc1", # methyl, fluoro +] + +wf = rowan.submit_analogue_docking_workflow( + analogues=analogues, + initial_molecule=rowan.Molecule.from_smiles(analogues[0]), # reference ligand + protein=protein, + name="SAR series docking", +) +# Analogue docking does not accept a pocket parameter in SDK 3.1.13. + +result = wf.result() +print(result.analogue_scores) # List of scores for each analogue +print(result.best_poses) # List of poses +``` + +### 8. MSA generation + +For multiple-sequence alignment (useful for downstream cofolding). + +```python +wf = rowan.submit_msa_workflow( + initial_protein_sequences=[ + "MENFQKVEKIGEGTYGVVYKARNKLTGEVVALKKIRLDTETEGVP" + ], + output_formats=["colabfold", "chai", "boltz"], + name="target MSA", +) + +result = wf.result() +result.download_files() # Downloads alignments to disk +``` + +### 9. Protein-ligand cofolding + +For AI-based bound-complex prediction when no crystal structure is available. + +```python +wf = rowan.submit_protein_cofolding_workflow( + initial_protein_sequences=[ + "MENFQKVEKIGEGTYGVVYKARNKLTGEVVALKKIRLDTETEGVP" + ], + initial_smiles_list=[ + "CCNc1ncc(c(Nc2ccc(F)cc2)n1)-c1cccnc1" + ], + name="protein-ligand cofolding", +) + +result = wf.result() +print(result.predictions) # List of predicted structures +print(result.messages) # Model metadata/warnings + +predicted_structure = result.get_predicted_structure() +predicted_structure.write("predicted_complex.pdb") +``` + +## All supported workflow types + +All workflows follow the same submit → wait → retrieve pattern and support webhooks and project/folder organization. + +### Core molecular modeling workflows + +| Workflow | Function | When to use | +|----------|----------|-------------| +| Descriptors | `submit_descriptors_workflow` | First-pass triage: MW, LogP, TPSA, HBA/HBD, Lipinski filter | +| pKa | `submit_pka_workflow` | Single ionizable group; need protonation thermodynamics | +| MacropKa | `submit_macropka_workflow` | Multi-ionizable drugs; pH-dependent charge/LogD/solubility | +| Conformer Search | `submit_conformer_search_workflow` | 3D ensemble for docking, MD, or SAR; known tautomer | +| Tautomer Search | `submit_tautomer_search_workflow` | Heterocycles, keto–enol; uncertain tautomeric form | +| Solubility | `submit_solubility_workflow` | Aqueous or solvent-specific solubility prediction | +| Membrane Permeability | `submit_membrane_permeability_workflow` | Caco-2, PAMPA, BBB, plasma permeability | +| ADMET | `submit_admet_workflow` | Broad drug-likeness and ADMET property sweep | + +### Structure-based design workflows + +| Workflow | Function | When to use | +|----------|----------|-------------| +| Docking | `submit_docking_workflow` | Single ligand, known binding pocket | +| Analogue Docking | `submit_analogue_docking_workflow` | SAR series (5–100+ compounds) in a shared pocket | +| Batch Docking | `submit_batch_docking_workflow` | Fast library screening; large compound sets | +| Protein MD | `submit_protein_md_workflow` | Long-timescale dynamics; conformational sampling | +| Pose Analysis MD | `submit_pose_analysis_md_workflow` | MD refinement of a docking pose | +| Protein Cofolding | `submit_protein_cofolding_workflow` | No crystal structure; AI-predicted bound complex | +| Protein Binder Design | `submit_protein_binder_design_workflow` | De novo binder generation against a protein target | + +### Advanced computational chemistry + +| Workflow | Function | When to use | +|----------|----------|-------------| +| Basic Calculation | `submit_basic_calculation_workflow` | QM/ML geometry optimization or single-point energy | +| Electronic Properties | `submit_electronic_properties_workflow` | Dipole, partial charges, HOMO-LUMO, ESP | +| BDE | `submit_bde_workflow` | Bond dissociation energies; metabolic soft-spot prediction | +| Redox Potential | `submit_redox_potential_workflow` | Oxidation/reduction potentials | +| Spin States | `submit_spin_states_workflow` | Spin-state energy ordering for organometallics/radicals | +| Strain | `submit_strain_workflow` | Conformational strain relative to global minimum | +| Scan | `submit_scan_workflow` | PES scans; torsion profiles | +| Multistage Optimization | `submit_multistage_optimization_workflow` | Progressive optimization across levels of theory | + +### Reaction chemistry + +| Workflow | Function | When to use | +|----------|----------|-------------| +| Double-Ended TS Search | `submit_double_ended_ts_search_workflow` | Transition state between two known structures | +| IRC | `submit_irc_workflow` | Confirm TS connectivity; intrinsic reaction coordinate | + +### Advanced properties + +| Workflow | Function | When to use | +|----------|----------|-------------| +| NMR | `submit_nmr_workflow` | Predicted 1H/13C chemical shifts for structure verification | +| Ion Mobility | `submit_ion_mobility_workflow` | Collision cross-section (CCS) for MS method development | +| Hydrogen Bond Strength | `submit_hydrogen_bond_basicity_workflow` | H-bond donor/acceptor strength for formulation/solubility | +| Fukui | `submit_fukui_workflow` | Site reactivity indices for electrophilic/nucleophilic attack | +| Interaction Energy Decomposition | `submit_interaction_energy_decomposition_workflow` | Fragment-level interaction analysis | + +### Binding free energy + +| Workflow | Function | When to use | +|----------|----------|-------------| +| RBFE/FEP | `submit_relative_binding_free_energy_perturbation_workflow` | Relative ΔΔG for congeneric series | +| RBFE Graph | `submit_relative_binding_free_energy_graph_workflow` | Build and optimize an RBFE perturbation network | + +### Sequence and structural biology + +| Workflow | Function | When to use | +|----------|----------|-------------| +| MSA | `submit_msa_workflow` | Multiple sequence alignment for cofolding (ColabFold, Chai, Boltz) | +| Solvent-Dependent Conformers | `submit_solvent_dependent_conformers_workflow` | Solvation-aware conformer ensembles | -- 2.54.0 From 7b8888cb036533d557eb58cf777cb94c840522cc Mon Sep 17 00:00:00 2001 From: promptadmin Date: Sat, 29 Aug 2026 17:06:15 +0000 Subject: [PATCH 6/8] [upstream-sync] skills/stable-baselines3/SKILL.md from K-Dense-AI/scientific-agent-skills@72d742e1 [unknown] --- .../catalogue/skills/stable-baselines3/SKILL.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/upstream/K-Dense-AI-scientific-agent-skills/catalogue/skills/stable-baselines3/SKILL.md b/upstream/K-Dense-AI-scientific-agent-skills/catalogue/skills/stable-baselines3/SKILL.md index 2757bc0a..fc3d3180 100644 --- a/upstream/K-Dense-AI-scientific-agent-skills/catalogue/skills/stable-baselines3/SKILL.md +++ b/upstream/K-Dense-AI-scientific-agent-skills/catalogue/skills/stable-baselines3/SKILL.md @@ -1,8 +1,8 @@ --- lineage_type: import -upstream_source: https://github.com/K-Dense-AI/scientific-agent-skills/blob/9c9bd2e9/skills/stable-baselines3/SKILL.md -upstream_sha: 9c9bd2e9 -imported_at: 2026-06-27 +upstream_source: https://github.com/K-Dense-AI/scientific-agent-skills/blob/72d742e1/skills/stable-baselines3/SKILL.md +upstream_sha: 72d742e1 +imported_at: 2026-08-29 prompt_class: unknown upstream_changes: accepted name: stable-baselines3 @@ -10,7 +10,9 @@ description: Production-ready reinforcement learning algorithms (PPO, SAC, DQN, license: MIT license allowed-tools: Read Write Edit Bash compatibility: Requires Python 3.10+, PyTorch >= 2.3, and stable-baselines3 2.8+. Gymnasium environments; optional extras for TensorBoard and Atari (ale-py). -metadata: {"version": "1.1", "skill-author": "K-Dense Inc."} +metadata: + version: "1.2" + skill-author: K-Dense Inc. --- # Stable Baselines3 -- 2.54.0 From 6dfa33d85b4ad32e7c02ed70686ee4bcdf3b3192 Mon Sep 17 00:00:00 2001 From: promptadmin Date: Sat, 29 Aug 2026 17:06:17 +0000 Subject: [PATCH 7/8] [upstream-sync] skills/stable-baselines3/references/callbacks.md from K-Dense-AI/scientific-agent-skills@72d742e1 [prompt] --- .../skills/stable-baselines3/references/callbacks.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/upstream/K-Dense-AI-scientific-agent-skills/skills/stable-baselines3/references/callbacks.md b/upstream/K-Dense-AI-scientific-agent-skills/skills/stable-baselines3/references/callbacks.md index f347c902..1759ce95 100644 --- a/upstream/K-Dense-AI-scientific-agent-skills/skills/stable-baselines3/references/callbacks.md +++ b/upstream/K-Dense-AI-scientific-agent-skills/skills/stable-baselines3/references/callbacks.md @@ -2,9 +2,9 @@ title: "Stable Baselines3 Callback System" task: "" lineage_type: import -upstream_source: https://github.com/K-Dense-AI/scientific-agent-skills/blob/9c9bd2e9/skills/stable-baselines3/references/callbacks.md -upstream_sha: 9c9bd2e9 -imported_at: 2026-06-27 +upstream_source: https://github.com/K-Dense-AI/scientific-agent-skills/blob/72d742e1/skills/stable-baselines3/references/callbacks.md +upstream_sha: 72d742e1 +imported_at: 2026-08-29 prompt_class: prompt upstream_changes: accepted author: upstream @@ -580,5 +580,5 @@ class DebugCallback(BaseCallback): ## Additional Resources - Official SB3 Callbacks Guide: https://stable-baselines3.readthedocs.io/en/master/guide/callbacks.html -- Callback API Reference: https://stable-baselines3.readthedocs.io/en/master/common/callbacks.html +- Callback API Reference: https://stable-baselines3.readthedocs.io/en/master/guide/callbacks.html#module-stable_baselines3.common.callbacks - TensorBoard Documentation: https://www.tensorflow.org/tensorboard -- 2.54.0 From fda2d80af5a49377ca0329993aeb21f68578c412 Mon Sep 17 00:00:00 2001 From: promptadmin Date: Sat, 29 Aug 2026 17:06:20 +0000 Subject: [PATCH 8/8] [upstream-sync] skills/stable-baselines3/references/vectorized_envs.md from K-Dense-AI/scientific-agent-skills@72d742e1 [prompt] --- .../stable-baselines3/references/vectorized_envs.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/upstream/K-Dense-AI-scientific-agent-skills/skills/stable-baselines3/references/vectorized_envs.md b/upstream/K-Dense-AI-scientific-agent-skills/skills/stable-baselines3/references/vectorized_envs.md index 1b4e1842..74c3bcf4 100644 --- a/upstream/K-Dense-AI-scientific-agent-skills/skills/stable-baselines3/references/vectorized_envs.md +++ b/upstream/K-Dense-AI-scientific-agent-skills/skills/stable-baselines3/references/vectorized_envs.md @@ -2,9 +2,9 @@ title: "Vectorized Environments in Stable Baselines3" task: "" lineage_type: import -upstream_source: https://github.com/K-Dense-AI/scientific-agent-skills/blob/9c9bd2e9/skills/stable-baselines3/references/vectorized_envs.md -upstream_sha: 9c9bd2e9 -imported_at: 2026-06-27 +upstream_source: https://github.com/K-Dense-AI/scientific-agent-skills/blob/72d742e1/skills/stable-baselines3/references/vectorized_envs.md +upstream_sha: 72d742e1 +imported_at: 2026-08-29 prompt_class: prompt upstream_changes: accepted author: upstream @@ -589,5 +589,5 @@ model = PPO.load("model", env=eval_env) ## Additional Resources - Official SB3 VecEnv Guide: https://stable-baselines3.readthedocs.io/en/master/guide/vec_envs.html -- VecEnv API Reference: https://stable-baselines3.readthedocs.io/en/master/common/vec_env.html +- VecEnv API Reference: https://stable-baselines3.readthedocs.io/en/master/guide/vec_envs.html#module-stable_baselines3.common.vec_env - Multiprocessing Best Practices: https://docs.python.org/3/library/multiprocessing.html -- 2.54.0