Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Use when querying MyVariant.info variant annotations from the myvariant Python client: the getvariant/getvariants/query/querymany calling convention — HGVS ids, scopes, dotted fields, as_dataframe — which cheaper models do not emit by default.
.claude/skills/myvariant-info-client-conventions/SKILL.md| Model | Eval pass | Runs |
|---|---|---|
| gemini-3.6-flash | 100% | 5 |
| Model | Lift | Δ tokens | Δ turns | Cases | Verified |
|---|---|---|---|---|---|
| gemini-3.6-flashbest | +44% | +87% | 0% | 25 | 53d ago |
| gemini-3.5-flash | pending re-run | — | |||
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-15 | ✗→✓ | ▲ Improved | — | — |
| case-14 | ✗→✓ | ▲ Improved | — | — |
| case-01 | ✗→✓ | ▲ Improved | — | — |
| case-17 | ✗→✓ | ▲ Improved | — | — |
| case-10 | ✗→✓ | ▲ Improved | — | — |
Enforce the BioThings myvariant client convention when code imports myvariant to fetch variant annotations from MyVariant.info: the correct client object, the right method for each kind of input identifier, the HGVS _id string format, dotted-path fields selection, and as_dataframe. Apply to any Python that annotates variants through this library.
mv = myvariant.MyVariantInfo(). Nevermyvariant.MyVariant(), myvariant.Client(), MyVariantInfo.connect(), MyVariantClient(), and never hand-roll requests.get against the REST endpoint.
get* take an HGVS _id, not an rsID. getvariant(id) and getvariants([ids])accept an HGVS-based variant id, format chr<N>:g.<pos><ref>><alt> for an SNV, e.g. chr9:g.107620835G>A. Chromosome tokens are chr1..chr22, chrX, chrY. Build this string from coordinates + alleles; do NOT pass a bare rs… id to get*.
query/querymany. To look up variants by dbSNP rsID, usequery('dbsnp.rsid:<rsid>') for one/Lucene, or querymany(rsids, scopes='dbsnp.rsid') for a list. getvariant('rs…') misses (rsIDs are not the _id scope).
scopes= names the input namespace. For querymany, scopes declares what kind ofidentifiers the inputs are: 'dbsnp.rsid', 'clinvar.rcv_accession', 'cosmic.cosmic_id'. Several kinds in one call → one comma-separated string, e.g. scopes='dbsnp.rsid,clinvar.rcv_accession,cosmic.cosmic_id'.
fields= is a comma-string or list of dotted paths. Select the returned subtree withfields='dbsnp.rsid,cadd.phred' or fields=['cosmic.tumor_site','clinvar.rcv.clinical_significance']. Dotted paths pick nested leaves; fields='all' returns everything. Not columns=, not select=, not a positional second arg.
getvariants([...]) (plural; also accepts atuple or a comma-joined string). A list of rsIDs/other ids → querymany([...], scopes=…). Do not loop getvariant once per id.
as_dataframe=True. Pass as_dataframe=True to getvariants /querymany to get a pandas DataFrame back; don't assemble one by hand from the dict list.
query. Genomic window: query('chr1:69000-70000'). Fieldfilter: query('dbnsfp.genename:CDK2'). Iterate ALL hits with query(..., fetch_all=True) (a generator); cap a page with size=.
mv.getvariant('rs1042522') → mv.query('dbsnp.rsid:rs1042522') (or mv.querymany(['rs1042522'], scopes='dbsnp.rsid')).
[mv.getvariant(r) for r in rs_list] → mv.querymany(rs_list, scopes='dbsnp.rsid', fields='clinvar.rcv.clinical_significance').
mv.getvariant(chrom=17, pos=7676154, ref='G', alt='A') → mv.getvariant('chr17:g.7676154G>A').
a loop of getvariant → mv.getvariants(['chr17:g.7676154G>A','chr7:g.55019278T>G'], fields='cadd.phred').
mv.getvariant('chr7:g.140753336A>T', fields=['dbsnp','gnomad_exome']) → ..., fields='dbsnp.rsid,gnomad_exome.af.af'.
pd.DataFrame([mv.getvariant(v) for v in ids]) → mv.getvariants(ids, fields='cadd.phred,dbsnp.rsid', as_dataframe=True).
mv.getvariants(rcv_list) → mv.querymany(rcv_list, scopes='clinvar.rcv_accession').
mv.getvariant('chr1:69000-70000') → mv.query('chr1:69000-70000') (add fetch_all=True to page all hits).
query('dbsnp.rsid:rs…') returns a hit list (res['hits']); a one-itemquerymany([...], scopes='dbsnp.rsid') also works. Either is fine — just not getvariant.
_id (HGVS) from the query hit, then pass THAT togetvariant if you need the complete record.
querymany marks unmatched inputs with notfound: True;pass returnall=True to also get the missing/duplicate breakdown.
chrX:g.<pos><ref>><alt> / chrY:g.… (still g.).mv = myvariant.MyVariantInfo(). DON'T myvariant.MyVariant() / Client().querymany(rsids, scopes='dbsnp.rsid'). DON'T getvariants(rsids) with rsIDs.chr7:g.140753336A>T. DON'T pass chrom/pos/ref/alt as separate getvariant kwargs.fields='dbsnp.rsid,cadd.phred' (dotted). DON'T columns= / select=.as_dataframe=True. DON'T hand-build a DataFrame from the returned dicts.query('chr1:69000-70000') for a window. DON'T getvariant on a range.getvariant/getvariants (they take HGVS _ids → notfound).mv.get_rsid(), mv.lookup(), mv.fetch(),mv.get_by_rsid(), mv.annotate(), mv.search().
scopes on querymany, so rsIDs are matched against the default _id scope and miss.columns= / select= instead of fields=, or passing fields positionally.getvariant per id instead of one getvariants / querymany batch call.myvariant.MyVariantInfo()query('dbsnp.rsid:…') or querymany(scopes='dbsnp.rsid')getvariant/getvariants only for HGVS chr<N>:g.<pos><ref>><alt> idsfields= comma-string / list of dotted paths (or 'all')getvariants([...]) / querymany([...]) in one callas_dataframe=True for a pandas DataFramequery(...); fetch_all=True to page all hits| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-05 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-15 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-24 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-14 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-01 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-17 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-10 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-08 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-20 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-06 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-23 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-02 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-21 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-07 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-25 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-04 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-13 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-03 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-09 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-11 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-12 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-16 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-18 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-19 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-22 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 25 cases were attempted. The headline lift of +44 percentage points is the difference between those two pass rates over the 25 comparable cases.
The per-case answers from this run were removed by the retention sweep, so the case table below shows the verdicts without the text either arm produced. The counts above were recorded at the time and are unaffected. Answers are now kept for 180 days.
| Model | Method | Date | Lift |
|---|---|---|---|
| gemini-3.5-flash | verified | 7/10/2026 | +36% |
Other measured skills in the registry, with their headline benchmark lift.