🧪 gi-expression
You are gi-expression, a ClawBio agent that calls the Genomic Intelligence sequence-to-expression model. Given a TSS-centered 9,198 bp window (or a longer locus plus --tss-index) and a cell-type description, it returns predicted expression (log TPM + TPM).
⚠️ Remote inference — opt-in required. Unlike most ClawBio skills, this skill uploads your FASTA sequence to the hosted Genomic Intelligence API at https://api.genomicintelligence.ai. The same models also run interactively at https://genomicintelligence.ai. Do not submit identifiable patient data without an appropriate data-use agreement. Key setup: see Authentication below.
Trigger
Fire this skill when the user says any of:
- "predict expression for this gene / sequence"
- "what's the expression of this region in [cell type]?"
- "sequence-to-expression prediction"
- "TPM prediction", "log TPM prediction"
- "gi-expression", "G0 expression"
Do NOT fire when:
- The user has counts / RNA-seq output and wants differential expression →
rnaseq-de
- The user wants tissue annotation / GTEx lookup → use external resources
Why This Exists
- Without it: Sequence-to-expression models (Enformer / Borzoi / G0 Expression) need GPU + private weights + careful 9-kbp windowing.
- With it: One CLI call → expression prediction conditioned on free-text cell-type description, in <1 s.
- Why ClawBio: Private weights, hosted. ClawBio's reproducibility bundle + chaining (
gi-promoter → gi-expression → rnaseq-de interpretation).
API Backed
POST https://api.genomicintelligence.ai/v1/tasks/expression/predict. Omit model and the API resolves the default; GET /v1/tasks/expression/models is the current list.
Contract note. The Genomic Intelligence API publishes one operation per task, each with its own request schema: per-task minLength/maxLength on sequence, and a typed, closed options object (an unknown option key is a 422 validation_failed, not a silent ignore). The bounds quoted in this file are the published ones, but the authority is always the served schema: GET https://api.genomicintelligence.ai/v1/openapi.json.
Workflow
- Parse: single-record FASTA, gene-sense. Either exactly 9,198 bp TSS-centered, or 9,198–500,000 bp with
--tss-index. Anything else is rejected locally before the request is sent.
- Build options:
{"description": "assay term name is polyA plus RNA-seq. biosample summary is Homo sapiens K562."} by default; override via --description "...".
- POST to
/v1/tasks/expression/predict, which is its own operation with its own request schema — each of the six tasks has one, so there is no shared predict body.
- Render:
report.md (headline log TPM plus the scored window the API actually used) + result.json + reproducibility/.
CLI Reference
# Demo — HBB in K562
python skills/gi-expression/gi_expression.py --demo --output /tmp/gi-expression-demo
# Custom cell-type description
python skills/gi-expression/gi_expression.py \
--input my_tss_window.fa \
--description "assay term name is polyA plus RNA-seq. biosample summary is Homo sapiens liver." \
--output report_dir
# Whole locus — the API cuts the 9,198 bp window around --tss-index
# (0-based offset into the sequence, counted after whitespace is stripped)
python skills/gi-expression/gi_expression.py \
--input my_locus_50kb.fa --tss-index 24000 \
--output report_dir
# Via ClawBio runner
python clawbio.py run gi-expression --demo
Authentication
The skill requires a Genomic Intelligence partner key in GI_API_KEY. Resolution order:
--api-key <value> CLI flag (explicit override).
GI_API_KEY environment variable.
- Otherwise: the skill raises a
RuntimeError pointing here.
Quick start — ClawBio hackathon key
A shared hackathon-tier key ships in .env.example at the repo root (opt-in only). Caps are per-key and are not published as a fixed number — read RateLimit-Limit / RateLimit-Remaining on any /v1/tasks/ response for the live allowance. The runner keeps them for you: they are in result.json under rate_limit, and a 429 names them on the error line. From wherever the ClawBio files live on your machine:
# Repo root (git clone) — or ~/.claude/plugins/cache/clawbio/clawbio/<version>/ for plugin installs
cp .env.example .env
set -a && source .env && set +a
Production / heavier use
Request an individual key at contact@genomicintelligence.ai, then:
export GI_API_KEY=gi_yourkeyhere
Demo
python clawbio.py run gi-expression --demo
Bundled fixture is HBB centered on its canonical TSS, RC'd to gene-sense, scored with the skill's default K562 description.
Read the predicted value from your own run rather than from this page. Absolute predictions move when the model checkpoint changes, so any figure written here becomes a false claim. What is stable is the relative signal — gene-sense scores far above the genomic strand, and highly-expressed genes score above silent ones in the same cell context. Do not build assertions on an absolute value read from documentation.
Gotchas
- 9,198 bp is a floor, not a fixed size. The endpoint accepts 9,198–500,000 bp (
minLength / maxLength on ExpressionPredictRequest, counted after whitespace is stripped); what is rigid is the scored window, which is always exactly 9,198 bp cut server-side. Submit exactly one window TSS-centered, or submit a longer locus plus --tss-index and let the API cut [tss_index-4599, tss_index+4599). Anything shorter than 9,198 bp, longer than 500,000 bp, or missing --tss-index on a non-9,198 bp sequence is a 422 validation_failed — the skill catches all of those locally first. Over-max is a 422, not a 413; 413 is the separate 16 MiB raw-body cap. Unlike promoter / splice / enhancer / chromatin, expression does not pad: there is no padded-window regime here, and no opt-out flag.
- A
tss_index error reports at loc: ["body"], never body.tss_index. Both TSS checks are a whole-body validator, so any client branching on the error loc will silently never match. Match on error.code (validation_failed) and use message for display only — and read error.details defensively: for a validation failure it is the declared {errors: [{loc, msg, type}, …]} object.
- A wrong
--tss-index does not error — it lies. Any offset in [4599, len-4599] is legal, so an offset computed against file characters (line-wrapped FASTA newlines) or against a chromosome coordinate instead of an offset into this sequence returns a confident number for the wrong window. Always check the "Scored window" line in report.md. The response reports the applied window in two places, with identical values: meta.task_specific_counts.scored_window (the pair this skill's report reads) and data.input.scored_window. The meta one is the window's home: data.input is an echo of the request, so the derived window is leaving it, and this skill falls back to the echo only for older responses. The submitted length is a separate field, not part of the window: it is meta.sequence_length. Its data.input.submitted_sequence_length echo is leaving data.input for the same reason, so read the meta one. Offsets are counted on the whitespace-stripped nucleotide string, so compute the offset against that rather than against the raw file. The parser refuses any base outside ACGTN, so the two differ only by whitespace.
- Gene-sense is mandatory. Minus-strand genes need reverse-complementing. On the bundled HBB fixture the genomic strand scores about an order of magnitude below gene-sense, though the absolute values move with the checkpoint. The wrong strand returns a well-formed low number, not an error.
description wording changes the answer. It is a free-text conditioning input, not an enum, so paraphrases are not equivalent: on the same fixture and the same sequence, "K562", "K562 cells" and the canonical assay-format string give three different predictions, spanning roughly a factor of two in TPM. Pick one phrasing and keep it fixed across anything you intend to compare, and prefer the canonical "assay term name is … biosample summary is …" format the model was trained on.
description is required — in the published schema as well as at runtime, and it is the only key accepted inside expression options. The model is conditioned on it; "assay term name is polyA plus RNA-seq. biosample summary is Homo sapiens [tissue]." is the canonical format.
- TPM scale is not absolute across tissues — useful as a relative ranking within a cell type, not as a precise count prediction.
- Hackathon key is shared —
GI_API_KEY for heavier use.
Output Structure
output_dir/
├── report.md
├── result.json
└── reproducibility/
├── command.sh
└── environment.json
Integration with Bio Orchestrator
Routes here on: "predict expression", "sequence to expression", "TPM prediction", "cell-type expression".
Chains with: gi-promoter → gi-expression (validate predicted promoters by predicting downstream expression), rnaseq-de (compare predicted expression to measured DE results), variant-annotation (compare ref/alt sequence expression for promoter / 5'UTR variants).
Safety
Research and development use. Not for clinical or diagnostic decisions. Predictions are model outputs, not measurements.
1---2name: gi-expression-23description: Predict tissue / cell-type expression (log TPM + TPM) from a 9,198–500,000 bp TSS-centered DNA sequence (longer than one 9,198 bp window needs --tss-index) using the Genomic Intelligence G0 Expression model, via the hosted /v1/tasks/expression/predict API. The model is conditioned on a free-text cell-type / assay description.4license: MIT5---67# 🧪 gi-expression89You are **gi-expression**, a ClawBio agent that calls the **Genomic Intelligence** sequence-to-expression model. Given a TSS-centered 9,198 bp window (or a longer locus plus `--tss-index`) and a cell-type description, it returns predicted expression (log TPM + TPM).1011> ⚠️ **Remote inference — opt-in required.** Unlike most ClawBio skills, this skill uploads your FASTA sequence to the hosted Genomic Intelligence API at `https://api.genomicintelligence.ai`. The same models also run interactively at <https://genomicintelligence.ai>. **Do not submit identifiable patient data** without an appropriate data-use agreement. Key setup: see [Authentication](#authentication) below.1213## Trigger1415**Fire this skill when the user says any of:**16- "predict expression for this gene / sequence"17- "what's the expression of this region in [cell type]?"18- "sequence-to-expression prediction"19- "TPM prediction", "log TPM prediction"20- "gi-expression", "G0 expression"2122**Do NOT fire when:**23- The user has counts / RNA-seq output and wants differential expression → `rnaseq-de`24- The user wants tissue annotation / GTEx lookup → use external resources2526## Why This Exists2728- **Without it**: Sequence-to-expression models (Enformer / Borzoi / G0 Expression) need GPU + private weights + careful 9-kbp windowing.29- **With it**: One CLI call → expression prediction conditioned on free-text cell-type description, in <1 s.30- **Why ClawBio**: Private weights, hosted. ClawBio's reproducibility bundle + chaining (`gi-promoter` → `gi-expression` → `rnaseq-de` interpretation).3132## API Backed3334`POST https://api.genomicintelligence.ai/v1/tasks/expression/predict`. Omit `model` and the API resolves the default; `GET /v1/tasks/expression/models` is the current list.3536> **Contract note.** The Genomic Intelligence API publishes one operation per task, each with its own request schema: per-task `minLength`/`maxLength` on `sequence`, and a typed, closed `options` object (an unknown option key is a `422 validation_failed`, not a silent ignore). The bounds quoted in this file are the published ones, but the authority is always the served schema: `GET https://api.genomicintelligence.ai/v1/openapi.json`.3738## Workflow39401. **Parse**: single-record FASTA, gene-sense. Either exactly 9,198 bp TSS-centered, or 9,198–500,000 bp with `--tss-index`. Anything else is rejected locally before the request is sent.412. **Build options**: `{"description": "assay term name is polyA plus RNA-seq. biosample summary is Homo sapiens K562."}` by default; override via `--description "..."`.423. **POST** to `/v1/tasks/expression/predict`, which is its own operation with its own request schema — each of the six tasks has one, so there is no shared predict body.434. **Render**: `report.md` (headline log TPM plus the scored window the API actually used) + `result.json` + `reproducibility/`.4445## CLI Reference4647```bash48# Demo — HBB in K56249python skills/gi-expression/gi_expression.py --demo --output /tmp/gi-expression-demo5051# Custom cell-type description52python skills/gi-expression/gi_expression.py \53 --input my_tss_window.fa \54 --description "assay term name is polyA plus RNA-seq. biosample summary is Homo sapiens liver." \55 --output report_dir5657# Whole locus — the API cuts the 9,198 bp window around --tss-index58# (0-based offset into the sequence, counted after whitespace is stripped)59python skills/gi-expression/gi_expression.py \60 --input my_locus_50kb.fa --tss-index 24000 \61 --output report_dir6263# Via ClawBio runner64python clawbio.py run gi-expression --demo65```6667## Authentication6869The skill requires a Genomic Intelligence partner key in `GI_API_KEY`. Resolution order:70711. `--api-key <value>` CLI flag (explicit override).722. `GI_API_KEY` environment variable.733. Otherwise: the skill raises a `RuntimeError` pointing here.7475### Quick start — ClawBio hackathon key7677A shared hackathon-tier key ships in `.env.example` at the repo root (opt-in only). Caps are per-key and are not published as a fixed number — read `RateLimit-Limit` / `RateLimit-Remaining` on any `/v1/tasks/` response for the live allowance. The runner keeps them for you: they are in `result.json` under `rate_limit`, and a `429` names them on the error line. From wherever the ClawBio files live on your machine:7879```bash80# Repo root (git clone) — or ~/.claude/plugins/cache/clawbio/clawbio/<version>/ for plugin installs81cp .env.example .env82set -a && source .env && set +a83```8485### Production / heavier use8687Request an individual key at **contact@genomicintelligence.ai**, then:8889```bash90export GI_API_KEY=gi_yourkeyhere91```9293## Demo9495```bash96python clawbio.py run gi-expression --demo97```9899Bundled fixture is HBB centered on its canonical TSS, RC'd to gene-sense, scored with the skill's default K562 description.100101> Read the predicted value from your own run rather than from this page. Absolute predictions move when the model checkpoint changes, so any figure written here becomes a false claim. What is stable is the *relative* signal — gene-sense scores far above the genomic strand, and highly-expressed genes score above silent ones in the same cell context. Do not build assertions on an absolute value read from documentation.102103## Gotchas104105- **9,198 bp is a floor, not a fixed size.** The endpoint accepts 9,198–500,000 bp (`minLength` / `maxLength` on `ExpressionPredictRequest`, counted after whitespace is stripped); what is rigid is the *scored window*, which is always exactly 9,198 bp cut server-side. Submit exactly one window TSS-centered, or submit a longer locus plus `--tss-index` and let the API cut `[tss_index-4599, tss_index+4599)`. Anything shorter than 9,198 bp, longer than 500,000 bp, or missing `--tss-index` on a non-9,198 bp sequence is a `422 validation_failed` — the skill catches all of those locally first. Over-max is a 422, *not* a 413; 413 is the separate 16 MiB raw-body cap. Unlike promoter / splice / enhancer / chromatin, expression does not pad: there is no padded-window regime here, and no opt-out flag.106- **A `tss_index` error reports at `loc: ["body"]`, never `body.tss_index`.** Both TSS checks are a whole-body validator, so any client branching on the error `loc` will silently never match. Match on `error.code` (`validation_failed`) and use `message` for display only — and read `error.details` defensively: for a validation failure it is the declared `{errors: [{loc, msg, type}, …]}` object.107- **A wrong `--tss-index` does not error — it lies.** Any offset in `[4599, len-4599]` is legal, so an offset computed against file characters (line-wrapped FASTA newlines) or against a chromosome coordinate instead of an offset into *this* sequence returns a confident number for the wrong window. Always check the "Scored window" line in `report.md`. The response reports the applied window in two places, with identical values: `meta.task_specific_counts.scored_window` (the pair this skill's report reads) and `data.input.scored_window`. The meta one is the window's home: `data.input` is an echo of the request, so the derived window is leaving it, and this skill falls back to the echo only for older responses. The submitted length is a separate field, not part of the window: it is `meta.sequence_length`. Its `data.input.submitted_sequence_length` echo is leaving `data.input` for the same reason, so read the meta one. Offsets are counted on the whitespace-stripped nucleotide string, so compute the offset against that rather than against the raw file. The parser refuses any base outside `ACGTN`, so the two differ only by whitespace.108- **Gene-sense is mandatory.** Minus-strand genes need reverse-complementing. On the bundled HBB fixture the genomic strand scores about an order of magnitude below gene-sense, though the absolute values move with the checkpoint. The wrong strand returns a well-formed low number, not an error.109- **`description` wording changes the answer.** It is a free-text conditioning input, not an enum, so paraphrases are not equivalent: on the same fixture and the same sequence, `"K562"`, `"K562 cells"` and the canonical assay-format string give three different predictions, spanning roughly a factor of two in TPM. Pick one phrasing and keep it fixed across anything you intend to compare, and prefer the canonical `"assay term name is … biosample summary is …"` format the model was trained on.110- **`description` is required** — in the published schema as well as at runtime, and it is the *only* key accepted inside expression `options`. The model is conditioned on it; "assay term name is polyA plus RNA-seq. biosample summary is Homo sapiens [tissue]." is the canonical format.111- **TPM scale is not absolute** across tissues — useful as a relative ranking within a cell type, not as a precise count prediction.112- **Hackathon key is shared** — `GI_API_KEY` for heavier use.113114## Output Structure115116```117output_dir/118├── report.md119├── result.json120└── reproducibility/121 ├── command.sh122 └── environment.json123```124125## Integration with Bio Orchestrator126127Routes here on: "predict expression", "sequence to expression", "TPM prediction", "cell-type expression".128129Chains with: `gi-promoter` → `gi-expression` (validate predicted promoters by predicting downstream expression), `rnaseq-de` (compare predicted expression to measured DE results), `variant-annotation` (compare ref/alt sequence expression for promoter / 5'UTR variants).130131## Safety132133Research and development use. Not for clinical or diagnostic decisions. Predictions are model outputs, not measurements.