kohulan/chemaudit/chemaudit-structure-filter
Claude Code and agent skill by kohulan/chemaudit
- community
Checking that the SKILL.md file is still in the repository.
Filter generative-chemistry outputs through ChemAudit's 6-stage multi-stage funnel with a composite 0-1 scorer and REINVENT 4-compatible scoring endpoint. Use when user says "filter molecules", "drug-like filter", "structure filter", "filter generative output", "REINVENT scoring", "REINVENT Component", "lead-like filtering", "fragment filter", "funnel these SMILES", "novelty filter", or "score generative batch". Four built-in presets (drug_like, lead_like, fragment_like, permissive). Sync for ≤1000 SMILES, async for larger.
Install
npx vskill@latest install kohulan/chemaudit/chemaudit-structure-filterSKILL.md
ChemAudit Structure Filter
Overview
Multi-stage funnel for generative-chemistry outputs and virtual screening hits. Six sequential stages, each of which can reject a molecule independently:
parse— RDKit parse + sanitization.valence— valence validity check.alerts— structural alert catalogs (PAINS, Brenk, Kazius, NIBR — configurable).property— MW, LogP, TPSA, rotatable bonds, rings within bounds.sa_score— synthetic accessibility score ≤ threshold.dedup— InChIKey-based deduplication.
Optional 7th stage:
novelty— Tanimoto similarity vs ChEMBL (gated byenable_novelty).
Counts how many molecules enter and leave each stage (funnel diagram data).
Paired with a composite 0-1 scorer that blends validity / QED / alert-free / SA into a single reward, useful for generative-model reinforcement learning loops. Invalid SMILES score null, never 0.0 (D-14 / Pitfall 4) so generative agents can distinguish "unparseable" from "parseable but terrible".
REINVENT 4 Component API is supported out of the box.
Four built-in presets
See references/preset-configs.md for full threshold details.
| Preset | MW | LogP | TPSA | RotB | Rings | SA | Alerts | |
|---|---|---|---|---|---|---|---|---|
drug_like | 200–500 | -1 to 5 | ≤140 | ≤10 | — | ≤5.0 | PAINS + Brenk + Kazius | |
lead_like | 200–350 | -1 to 3.5 | ≤140 | ≤7 | — | ≤4.0 | PAINS + Brenk + Kazius + NIBR | |
fragment_like | 100–300 | -1 to 3 | ≤100 | ≤3 | ≤3 | ≤3.0 | PAINS only | |
permissive | 100–800 | -5 to 8 | ≤200 | ≤15 | — | ≤7.0 | none |
Weight vectors for the composite score differ per preset (D-15):
| Preset | validity | qed | alert_free | sa | |
|---|---|---|---|---|---|
drug_like | 0.3 | 0.3 | 0.2 | 0.2 | |
lead_like | 0.2 | 0.4 | 0.2 | 0.2 | |
fragment_like | 0.2 | 0.2 | 0.3 | 0.3 | |
permissive | 0.4 | 0.3 | 0.1 | 0.2 |
Sync vs async split (D-22)
POST /structure-filter/filterwith ≤ 1000 SMILES → syncFilterResponse.POST /structure-filter/filterwith > 1000 SMILES → returnsStructureFilterBatchUploadResponsewithjob_id, task runs on Celery.POST /structure-filter/batch/upload(file upload) → always async.
Workflow
1. Filter with a preset (sync, ≤1000 SMILES)
Response (synchronous):
2. Filter with explicit config (overrides preset)
If both preset and config are given, preset wins.
3. Composite score per molecule (0-1)
Response: {"scores": [0.412, 0.871, null]}. null means unparseable — preserve that in downstream ML pipelines rather than coercing to 0.
4. REINVENT 4 Component API
The endpoint accepts the REINVENT 4 input contract verbatim (raw list, not wrapped in a model):
Response:
Critical invariant: invalid SMILES are omitted, not scored 0.0 (REINVENT expects this — see Pitfall 4 / D-14). Don't insert zeros yourself.
REINVENT 4 config.toml snippet:
5. Async batch (file upload, always async)
Or with explicit JSON config:
6. Track async progress
WebSocket:
Poll:
Response: {job_id, status, progress, current_stage}.
7. Async results
Returns the same FilterResponse shape wrapped in {job_id, status, result}.
8. Download
Examples
Example 1 — "Filter 10K generated SMILES and save the passing ones"
POST /structure-filter/batch/uploadwith the file andpreset=drug_like→ getjob_id.- Track via WS or poll
/status. GET /structure-filter/batch/<job_id>/download/passed_txt→ plain-text file of passed SMILES.
Example 2 — "Integrate with REINVENT"
Wire the /reinvent-score endpoint as an ExternalProcess component. Choose the preset via query string. REINVENT's query_id round-trip is preserved; agents skip invalid SMILES naturally.
Example 3 — "Fragment-like filter on a small library"
POST /structure-filter/filterwithsmiles_list(≤1000) andpreset="fragment_like".- Read
molecules[], keep those withstatus="passed". - Render the funnel:
stages[]hasinput_count/passed_count/rejected_countper stage.
Example 4 — "Turn on novelty filtering vs ChEMBL"
Set enable_novelty: true and novelty_threshold: 0.85 in an explicit config (no preset enables novelty by default):
Molecules with Tanimoto > 0.85 to any ChEMBL compound are rejected at the novelty stage.
Rate limits
/structure-filter/filter: 20/min./structure-filter/score,/structure-filter/reinvent-score: 30/min./structure-filter/batch/upload: 3/min./structure-filter/batch/<job_id>/status: 60/min./structure-filter/batch/<job_id>/results: 30/min./structure-filter/batch/<job_id>/download/<format>: 10/min.
Troubleshooting
400 "Unknown preset '<name>'"
Valid presets: drug_like, lead_like, fragment_like, permissive. Case-sensitive.
400 "No valid SMILES found in input"
File parsed but every row errored. For CSV, ensure the column is named exactly SMILES. For SDF, ensure molecules have valid MOL blocks.
Score 0.0 vs null — which is it?
null = parse failure or SMILES rejected before scoring. 0.0 = parsed and scored but every component was 0. Critical distinction for generative models; never collapse them.
REINVENT returns fewer items than I sent
Expected — invalid SMILES are omitted from successes_list, not zero-scored. Match by query_id, not list position.
Async job_id found in /status but no results
Celery worker crashed. Check docker compose logs worker and re-upload. Redis TTL is 1 hour on metadata.
Funnel shows 0 passed but all stages have 100% input
All molecules pass individual stages but none make it through dedup. Means the input contains only duplicates (identical InChIKeys). Deduplicate before filtering, or disable dedup by adjusting the pipeline.
High rejection count at alerts stage for a fragment-screen
fragment_like preset has only PAINS enabled. If you want Brenk filtering for fragments, use an explicit config rather than the preset.
Further reading
references/preset-configs.md— exhaustive threshold tables and weight vectors.chemaudit-qsar-ready— different goal: ML-ready curation with provenance, not pass/fail filtering.chemaudit-molecule-validation— single-molecule scoring when you need per-check detail.
Security
- Security scanPassed, 95 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/chemaudit-structure-filter/SKILL.md
Popularity
- Repository stars
- 63
- Repository forks
- 7
- 7-day trend score
- 21
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/kohulan/chemaudit/chemaudit-structure-filter)