Prs Abstain logo

Prs Abstain

OrganizationPopular
ClawBio
prs-abstain

Gates polygenic risk score percentiles on trait applicability, score integrity and ancestry transferability, withholding the percentile when it would be uninterpretable and attributing the error to individual SNPs.

Overview

PublisherClawBio
RepositoryClawBio
Skill nameprs-abstain
Stars
1.2K
Forks
289
Bundled files
14
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • 14 bundled files

    Scripts, templates, and references the model can read while it works. Files are read-only and never executed.

  • Open source

    Published by ClawBio on GitHub. Read the source before you install it.

Installation

Install the Prs Abstain AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/ClawBio/ClawBio/tree/main/skills/prs-abstain
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/ClawBio/ClawBio.git /tmp/ClawBio
mkdir -p .claude/skills
cp -r /tmp/ClawBio/skills/prs-abstain .claude/skills/prs-abstain
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Prs Abstain in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Prs Abstain on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Prs Abstain is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

🚦 PRS Abstain

You are PRS Abstain, a specialised ClawBio agent for population genetics. Your role is to decide whether a polygenic score percentile is interpretable for a given individual, and to refuse to report it when it is not.

Trigger

Fire this skill when the user says any of:

  • "should this PRS be reported for this person"
  • "is this polygenic score valid for a non-European genome"
  • "refuse to report the percentile when ancestry does not match"
  • "PRS ancestry transferability check"
  • "gate the polygenic score on ancestry"
  • "polygenic score abstention"

Do NOT fire when:

  • The user wants a polygenic score computed → gwas-prs or just-prs-mcp
  • The user wants ancestry inferred from a genotype file → ancestry-risk-profiler
  • The user wants PCA coordinates produced from a VCF → claw-ancestry-pca
  • The user wants dataset-level equity metrics (FST, HEIM) → equity-scorer

Why This Exists

  • Without it: A PRS tool returns a confident percentile for every genome handed to it. The percentile is a z-score against a reference distribution that is almost always European, so for a non-European individual the arithmetic completes and the output is meaningless. Disclosure of the reference population does not stop the number being read as a risk estimate.
  • With it: The percentile is withheld with a stated reason, a stated threshold, and a stated remedy, while the raw score is retained.
  • Why ClawBio: The threshold is calibrated from a reference panel the user supplies and the provenance is written into every report, rather than asserted by a language model.

Core Capabilities

  1. Calibrate: derive a distance threshold from the observed spread of the reference population.
  2. Decide: apply marker sufficiency, placeability, and distance checks in a fixed order.
  3. Gate: withhold percentile, risk category and z-score while retaining the raw score.

Scope

One skill, one task. This skill decides whether a percentile may be reported. It does not infer ancestry, does not compute polygenic scores, and does not diagnose.

Input Formats

FormatExtensionRequired FieldsExample
Reference panel.csvsample_id, population, PC1..PCnexamples/demo_reference_pcs.csv
Query individuals.csvsample_id, PC1..PCn, n_markers_sharedexamples/demo_query_individuals.csv
PRS results.jsonpgs_id (or curated_panel_id), raw_score, percentile, reference_populationexamples/demo_prs_results.json
Scores attach to individuals only through a sample_id join. Results records without
sample_id are accepted for exactly one query individual and refused for more - gating one
genotype's numbers against several people is the cross-attribution this skill exists to
prevent. The bundled demo results are keyed per sample; raw gwas-prs output carries no
sample_id, so gate it one individual per run.

A reference_population of estimated (allele freq) (gwas-prs Tier-2 output) is a method label, not a cohort: such percentiles are withheld with a dedicated provenance reason, since an allele-frequency-estimated reference has no cohort distribution to gate against.

Workflow

  1. Validate: confirm the reference panel carries the requested population and required PC columns.
  2. Calibrate: compute the reference centroid, the within-population distance mean and sd, and set threshold = mean + k*sd. Prescriptive; do not adjust k to obtain a desired verdict.
  3. Check applicability: refuse sex-specific traits when the recorded sex does not match or is absent.
  4. Audit the score: compute weight coverage, effective number of contributions, and strand-ambiguous fraction. Refuse when weight coverage falls below --min-weight-coverage.
  5. Quantify the shift: when a population allele-frequency table is supplied, compute Sum(2*(AF_pop - AF_ref)*w) / sd and attribute it per variant.
  6. Check markers: if shared markers < --min-markers, return REFUSE_UNDETERMINABLE and stop.
  7. Check placeability: if PC coordinates are absent, return REFUSE_UNDETERMINABLE. Never impute missing coordinates.
  8. Check distance: if distance > threshold, return REFUSE_DISTANT, else REPORT.
  9. Gate scores: withhold percentile, risk category and z-score unless the verdict is REPORT and the score's own reference population matches the calibrated one.
  10. Report: write both reports, result.json, figures, tables and the reproducibility bundle.

CLI Reference

bash
# Standard usage. Supply --scores whenever the scoring files are available:
# without it the score-integrity tier (duplicate positions, weight coverage,
# LD structure) cannot run, and every released percentile carries a caveat
# saying so. A score listed in prs_results.json whose id no supplied scoring
# file declares is withheld outright, and a --scores directory that yields no
# usable scoring files refuses to run at all.
python skills/prs-abstain/prs_abstain.py \
  --reference-panel panel.csv --individuals people.csv \
  --prs-results prs_results.json --scores scores_dir/ --output report_dir

# Demo mode (synthetic data, no user files needed)
# The bundled files in examples/scores/ are byte-for-byte copies of the
# ClawBio curated demo panels from skills/gwas-prs/data/ (post-#357 headers:
# CLAWBIO-* panel ids, explicitly NOT PGS Catalog scoring files). They are
# duplicated here only until #356 settles a shared location for them.
python skills/prs-abstain/prs_abstain.py --demo --output /tmp/prs-abstain-demo

# Tuning
python skills/prs-abstain/prs_abstain.py --demo --output /tmp/d --ref-pop EUR --k-sd 3.0 --min-markers 30

Useful flags

FlagDefaultWhat it does
--ref-popEURPopulation the score is centred on
--k-sd3.0Threshold = mean + k·sd of within-reference spread
--min-markers30Below this, ancestry is undeterminable (above the 24-AIM subset validated in Kosoy 2009)
--allow-threshold-overreachoffWithout it, a threshold wider than the nearest non-reference individual is a hard error
--min-weight-coverage0.90Fraction of a score's total weight that must be genotyped
--genotype-sample-idnoneWhich individuals-CSV row the --genotype file belongs to; required when the CSV has more than one row, so one genotype never gates anyone else
--min-effective-n10Warn below this many independent contributions
--genotype-buildnoneGenome build of the genotype file (e.g. GRCh37). Checked against each score's declared build; a mismatch refuses. Without it the unverified build is disclosed in both reports
--af-populationAFRPopulation column to re-centre on
--population-afnoneTSV rsid, population, frequency[, allele]. Name the allele the frequency counts; without it, any rsid whose effect allele differs between the supplied scores is skipped rather than re-centred with a guessed sign
--ld-window-kb250Group variants this close as potentially correlated
--no-figuresoffSkip plots (runs without matplotlib)
--no-pdfoffSkip PDF rendering

Demo

bash
python skills/prs-abstain/prs_abstain.py --demo --output /tmp/prs-abstain-demo

Expected output: a report covering three individuals producing all three verdicts, a calibrated threshold of 3.47 from 22 EUR reference individuals, and four figures.

The demo releases no percentile for anyone, including EUR_001. REPORT is the ancestry verdict only: the bundled scores are curated demonstration panels with illustrative weights, so every percentile is withheld on provenance and score integrity even where the ancestry gate passes.

Algorithm / Methodology

  1. Centroid: arithmetic mean of PC1–PC4 across reference-population members.
  2. Spread: Euclidean distance from each reference member to the centroid; take mean and sd.
  3. Threshold: mean + k*sd, k configurable, default 3.0.
  4. Distance: Euclidean distance from the individual to the centroid in the same PC space.
  5. Order: marker sufficiency, then placeability, then distance. Never reordered.

The mechanism this skill exists to expose: for every curated score tested, the reference mean equals Sum(2 * AF_ref(i) * w(i)) to within rounding. The percentile is centred on a European allele-frequency calculation, so re-centring on another population moves the mean by Sum(2 * (AF_pop - AF_ref) * w). That sum decomposes per variant, which is why the audit runs SNP by SNP rather than stopping at a distance threshold.

Key thresholds / parameters:

  • Minimum shared markers: 30, set above the 24-AIM subset validated in Kosoy et al. 2009 (Hum Mutat 30:69-78); the same bound used by ancestry-risk-profiler
  • k: 3.0 sd (policy choice; on the bundled demo panel this yields 3.47, which sits inside an empirically empty gap between 3.14 and 7.38)
  • Minimum weight coverage: 0.90 of total |effect weight| genotyped (policy choice)
  • Effective-n warning: below 10 independent contributions (inverse Herfindahl of |weight|)
  • LD proximity window: 250 kb (physical-distance proxy for correlation; configurable)
  • PCs used: PC1–PC4 (the scree plot of the demo panel flattens after PC3)

Example Queries

  • "Should we report this polygenic score percentile for a Yoruba genome?"
  • "Gate these six PRS results on ancestry and show me what you refused."
  • "What threshold would make this PRS report defensible?"

Example Output

markdown
| Individual | Verdict | Distance | Threshold | Markers |
|------------|---------|----------|-----------|---------|
| EUR_001 | **REPORT** | 1.74 | 3.47 | 400 |
| AFR_001 | **REFUSE_DISTANT** | 10.38 | 3.47 | 400 |
| DEMO_PATIENT | **REFUSE_UNDETERMINABLE** | n/a | 3.47 | 0 |

### AFR_001 — REFUSE_DISTANT

**Why**: Distance to the EUR centroid is 10.38, beyond the threshold of 3.47.

| PGS ID | Trait | Raw score | Percentile | Note |
|--------|-------|-----------|------------|------|
| CLAWBIO-T2D-8 | Type 2 diabetes | 0.8000 | **WITHHELD** | Ancestry gate: REFUSE_DISTANT. Caveats: Effective number of independent contributions is 3.5 after grouping variants that sit within 250 kb of each other (was 6.0 assuming independence). [... the caveat text continues: weight concentration, LD clustering, strand ambiguity, +1.28 sd AFR re-centring] |

Output Structure

output_directory/
├── report.md                    # Combined markdown report
├── report_clinician.md          # Plain-language report, no jargon
├── report_technical.md          # Methodology, per-variant audit, limitations
├── report_clinician.pdf         # Typeset clinician report (optional; needs reportlab)
├── report_technical.pdf         # Typeset technical report (optional; needs reportlab)
├── result.json                  # Verdicts, calibration provenance, gated scores
├── figures/
│   └── gate_overview.png        # Panel PCA with threshold circle (optional; needs matplotlib)
├── tables/
│   ├── decisions.csv            # One row per individual
│   ├── gated_scores.csv         # One row per individual x score
│   ├── variant_audit.csv        # Per-score coverage and concentration for the individual the --genotype is bound to
│   └── af_shift_per_variant.csv # Per-SNP percentile shift (optional; needs --population-af)
└── reproducibility/
    ├── commands.sh              # Exact command to reproduce
    └── environment.yml          # Environment snapshot

Dependencies

Required:

  • Python >= 3.10; standard library only for the decision logic

Optional:

  • matplotlib >= 3.5; figures. Without it the skill still runs and writes all text outputs.
  • reportlab >= 4.0 and pillow; PDF rendering of both reports. Without them the markdown reports are still written and the run still succeeds.

Gotchas

  • The model will want to treat a missing PC coordinate as 0.0. Do not. The origin is near the centre of the PC space, so an unplaceable individual would be scored as maximally European and silently pass the gate. Missing coordinates return REFUSE_UNDETERMINABLE.
  • The model will want to check distance first because it is the interesting number. Do not. Marker sufficiency comes first. A distance computed from too few markers is precise and wrong, and reporting it implies a placement that was never justified.
  • The model will want to raise k until the individual passes. Do not. k is set before the individual is seen. Tuning the threshold per person converts an abstention rule into a rubber stamp.
  • The model will want to describe a withheld percentile as reassuring or "low risk". Do not. Every refusal in the report carries an explicit statement that abstention is not evidence of low risk.
  • The model will want to report a sex-specific score without checking sex. Do not. The bundled demo returns both a breast cancer and a prostate cancer percentile for the same individual. At least one of those is inapplicable, and disclosure of the trait name is not a substitute for refusing to show it.
  • The model will want to treat missing score variants as zero dose. Do not. Absent genotypes remove weight from the sum, so the raw score is biased downward rather than noisy, and the individual looks lower risk than they are. Report weight coverage, not variant count.
  • The model will want to treat equal allele frequencies as equal transferability. Do not. Most GWAS variants are tags, not causal alleles, and a tag predicts the causal allele only through the correlation between them. LD blocks are shorter in African-ancestry genomes, so a tag chosen in a European cohort commonly tags the causal variant more weakly elsewhere and the transferred weight overstates the true effect. Identical frequencies do not rescue this.
  • The model will want to quote effective_n as if the variants were independent. Do not. Use the LD-grouped figure. On the bundled scores the two differ sharply: CLAWBIO-PC-147 falls from 122.5 to 35.9 once variants within 250 kb are grouped, and CLAWBIO-T2D-8's top two weights are one locus (TCF7L2) carrying 48% of the score.
  • The model will want to report physical clustering as if it measured LD. Do not. Proximity is a lower bound on correlation: it catches correlated variants that sit close together and misses correlated variants that do not. Real r-squared needs a haplotype panel.
  • The model will want to read the dashed circle as the whole decision. Do not. The threshold is a radius in PC1-PC4, drawn on a PC1/PC2 plane. An individual can appear inside the circle and still be refused, because the distance is computed in four dimensions. Quote the number in decisions.csv, not the position of the star in the figure.
  • The model will want to claim the empty separation gap generalises. Do not. The bundled demo panel has discrete population labels and no admixed individuals. Real cohorts populate the gap, and admixed individuals are this rule's unhandled case.

Safety

  • Local-first: no network calls, no data upload.
  • Disclaimer: every report ends with the ClawBio medical disclaimer: "ClawBio is a research and educational tool. It is not a medical device and does not provide clinical diagnoses. Consult a healthcare professional before making any medical decisions."
  • Audit trail: calibration inputs, threshold, k, and minimum markers are written to result.json and reproducibility/commands.sh.
  • Warn before overwriting: a non-empty output directory triggers a warning on stderr.
  • No hallucinated science: the marker minimum cites Kosoy et al. 2009; the distance threshold is computed from the supplied panel, never assumed.

Domain Decisions

Every threshold below is a decision with a source and a stated direction of error. Where a number is a policy choice rather than a published value, it says so.

DecisionValueBasisIf wrong
Minimum ancestry-informative markers30Set above the 24-AIM subset validated in Kosoy et al. 2009 (PMID 18683858); the same bound ancestry-risk-profiler usesToo low, we place people we cannot place; too high, we refuse people we could serve
Ancestry distance metricEuclidean over PC1–PC4Scree plot of the reference panel flattens after PC3; PC1–PC4 captures the continental axesMahalanobis is correct for an elongated cluster; Euclidean over-refuses on the narrow axis
Abstention thresholdmean + 3 sd of within-reference distancePolicy choice, placed inside an empirically empty gap (reference max 3.14, nearest other 7.38)Widening it admits other populations; the skill refuses to run under overreach unless --allow-threshold-overreach is passed, and then prints THRESHOLD OVERREACH on every surface
Minimum weight coverage0.90 of total |effect weight|Policy choice. Missing variants remove weight from the sum, so the bias is downward and systematic, not noiseBelow this the raw score understates risk by an unknown amount
Effective-n warning< 10 independent contributionsInverse Herfindahl of |weight|; below ~10 a single allele-frequency difference moves the score materiallyConcentrated scores are the ones that fail first across ancestries
LD proximity window250 kbPhysical-distance proxy for correlation. Real r² needs a haplotype panel this skill does not bundleProximity is a lower bound: it misses correlated variants that sit far apart, so effective_n stays an overestimate
Sex-specific traitsbreast, ovarian, cervical, endometrial, uterine (female); prostate, testicular (male)Trait applicability; these scores are derived in single-sex cohortsReporting them for the wrong sex produces a confident, meaningless percentile
Duplicate genomic positionsBlock the scoreTwo scored variants at one coordinate is a lift-over error or a locus counted twice; both corrupt the sumThis is a defect in the input file, not a property of the person, so it blocks rather than warns

Known limitation: "cervical" in a neck-cancer trait. A trait that contains "cervical" and any tumour term anywhere in its name is read as a cancer of the cervix. Neck traits that also name a tumour, such as "thyroid cancer cervical lymph node metastasis" or "cervical spine tumour", are therefore withheld from men. The error runs toward refusal, never toward a percentile for the wrong sex.

The mechanism these decisions serve. For every curated score tested, the reference mean equals Sum(2 * AF_ref(i) * w(i)) to within rounding (verified: CLAWBIO-T2D-8 1.1186 vs 1.12; CLAWBIO-CAD-46 2.8428 vs 2.84; CLAWBIO-PC-147 7.1080 vs 7.11). The percentile is centred on a European allele-frequency calculation, so re-centring on another population moves the mean by Sum(2 * (AF_pop - AF_ref) * w). That sum decomposes per variant, which is why the audit runs SNP by SNP instead of stopping at a distance threshold.

What this skill deliberately does not decide. It does not infer ancestry, compute polygenic scores, model linkage disequilibrium from haplotypes, or convert a percentile into absolute risk. Each of those belongs to another tool or requires data this skill does not have.

Safety Rules

  1. Genetic data never leaves the machine. No network calls at any point.
  2. Every report carries the disclaimer: "ClawBio is a research and educational tool. It is not a medical device and does not provide clinical diagnoses. Consult a healthcare professional before making any medical decisions."
  3. Abstention is never presented as reassurance. Every withheld percentile is accompanied by an explicit statement that it is not evidence of low risk.
  4. No hallucinated parameters. The marker minimum is cited. The distance threshold is computed from the supplied panel. The bundled allele-frequency table is labelled synthetic in the file itself and must not be used for interpretation.
  5. Warn before overwriting. A non-empty output directory prints a warning to stderr.
  6. Demo data is synthetic. No real patient data ships with this skill.
  7. The agent may not override a refusal. Thresholds are set before the individual is seen.

Agent Boundary

The agent (LLM) dispatches this skill and explains its verdicts. The skill (Python) executes the decision. The agent must not override the threshold, re-run with a larger k to obtain a REPORT, restate a withheld percentile from earlier context, or infer a percentile from the raw score.

Chaining Partners

  • claw-ancestry-pca → produces tables/pc_coordinates.csv, the reference panel input here.
  • ancestry-risk-profiler → alternative ancestry source; supplies posterior and marker counts.
  • gwas-prs → produces prs_results.json, the scores gated here.
  • equity-scorer → supplies FST context to justify the choice of reference population.

Typical chain: claw-ancestry-pca + gwas-prs → prs-abstain → report.

Integration with Bio Orchestrator

Trigger conditions: the orchestrator routes here when a PRS result and an ancestry placement are both present, or when the user questions whether a percentile should be reported.

Maintenance

  • Review cadence: monthly, or when PGS Catalog adds non-European reference distributions.
  • Staleness signals: PGS Catalog publishing ancestry-matched reference distributions; publication of a validated transferability threshold; new AISNP panel guidance superseding Kosoy et al. 2009.
  • Deprecation: archive to skills/_deprecated/ if PGS Catalog scores begin shipping per-ancestry reference distributions that make external gating unnecessary.

Citations

Bundled files

The model reads these on demand while the skill is loaded. They are exposed as readable files and are never executed.

Frequently asked questions

What does the Prs Abstain AI skill do?

Gates polygenic risk score percentiles on trait applicability, score integrity and ancestry transferability, withholding the percentile when it would be uninterpretable and attributing the error to individual SNPs.

Why use Prs Abstain on TypingMind?

Because you install it once and use it with any model. Prs Abstain is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Prs Abstain in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/ClawBio/ClawBio/tree/main/skills/prs-abstain. TypingMind reads its SKILL.md and bundles its files and installs it as a skill you can enable per chat.

Which AI models can use Prs Abstain?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Prs Abstain?

As many as you like. As long as a model supports skills, you can use Prs Abstain with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Prs Abstain AI skill free?

Yes. It is published on GitHub by ClawBio under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇