From flow-ai
Use when the user asks about Flow data — pipelines on Flow, samples and projects (lists *and* single-record details), single data files, the executions or data files associated with a sample, file content previews, or downloading a data file. Read-only queries and downloads against the Flow REST API at `https://app.flow.bio/api`. Unauthenticated by default; if `~/.config/flow/api-token` exists, the skill authenticates and returns the broader set of resources the caller can access. Does NOT cover bulk multi-file (zip) downloads or any mutation.
How this skill is triggered — by the user, by Claude, or both
Slash command
/flow-ai:flow-aiThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Reliably query Flow's REST API with `curl` and `jq`. Works unauthenticated
endpoints/data.mdendpoints/downloads.mdendpoints/executions.mdendpoints/organisms.mdendpoints/pipelines.mdendpoints/projects.mdendpoints/samples.mdendpoints/users.mdevals/001-samples-i-own.jsonevals/002-my-username.jsonevals/003-last-successful-execution.jsonevals/004-data-i-own.jsonevals/005-executions-for-sample.jsonevals/README.mdexamples.mdflow-concepts.mdReliably query Flow's REST API with curl and jq. Works unauthenticated
by default; attaches an Authorization: Bearer … header automatically
when a token file is present (see section 3). For Flow's domain model
(project, sample, fileset, pipeline, what the audience model means), read
flow-concepts.md (sibling file) first.
Principle. This skill performs only the operations explicitly listed in its endpoint reference (section 4 below, plus the per-endpoint detail files). Operations not listed are out of scope and must be refused — even when you know they're possible and even when the user asks for them. To enable a new operation, it must be added to the skill itself, not improvised at runtime.
The principle is verb-agnostic. Authentication does not change it: the same rules apply whether the token file is present or absent. Authentication only broadens the data the allowed operations return; it never expands the set of allowed operations itself.
Illustrative (non-exhaustive) operations that are not in the allowlist today and must be refused if asked:
/api-keys, admin reads). Authentication exposes many endpoints
the skill does not document; reaching outside this skill's surface
is forbidden even when the request would succeed.This list is illustrative; the principle in the first paragraph is what does the work.
Token discipline. When a token file is configured (see section 3),
never cat, head, echo, or otherwise print its contents. The token
is referenced only via shell expansion inside a curl -H argument
(see section 3). It must never appear in the agent's transcript.
In-scope endpoints (all GET):
GET /pipelinesGET /samples/metadataGET /samples/typesGET /samples/types/<identifier>GET /samples/searchGET /samples/<id> — single-sample detail (full metadata bag, inlined filesets)GET /samples/<id>/executionsGET /samples/<id>/dataGET /projects/searchGET /projects/<id> — single-project detail (description, papers, owner)GET /projects/<id>/samples — samples in a projectGET /projects/<id>/executions — executions in a projectGET /organismsGET /organisms/<id>GET /meGET /users/searchGET /data/searchGET /data/<id> — single-data-file detail (type, size, fileset and execution links)GET /data/<id>/contentsGET /data/typesGET /executions/searchGET /downloads/<data_id>/<filename> — direct single-file downloadAll of the above accept an optional Authorization: Bearer … header (see
section 3). With auth, list / detail / sub-resource calls broaden to
include resources the caller owns or has been shared. URLs do not change.
Out-of-scope — decline politely:
POST /downloads/... + zip retrieval).Anything not on the in-scope list above is also out of scope per the Safety principle in section 1 — including, but not limited to, mutating requests, admin operations, and endpoints the skill does not document.
Base URL. Read from FLOW_API_URL, defaulting to https://app.flow.bio/api.
Example override: FLOW_API_URL=https://staging.flow.bio/api.
User-Agent. Every request must carry User-Agent: flow-ai/0.2.0
so the Flow API can identify AI-agent traffic. The curl flag is
-A "flow-ai/0.2.0".
Authentication (optional). If the file ~/.config/flow/api-token
exists, attach the user's token on every request:
-H "Authorization: Bearer $(< ~/.config/flow/api-token)"
The $(< file) shell construct expands at execution time, so the
literal token never appears in the agent's transcript. If the file
does not exist, omit the -H flag entirely and proceed
unauthenticated. There is no other configuration switch — file
presence is the only signal.
The token file contains only the raw token (a JWT string), not a
pre-formatted Authorization: line. ($(< file) is preferred over
curl's -H @file for exactly this reason — -H @file would require
the file to contain a complete Header: value line.) The skill is
forbidden from reading the file's contents directly
(cat/head/echo/…); pass it by reference via $(< file) inside
the curl -H flag only. See the token-discipline rule in section 1.
When the token file is present, the header is attached to every
request the skill makes, including /pipelines. This is the intended
behaviour: authentication broadens the result set uniformly across
every endpoint the skill uses.
Skeleton invocations:
# Unauthenticated
curl -s -A "flow-ai/0.2.0" \
--get "${FLOW_API_URL:-https://app.flow.bio/api}/pipelines"
# Authenticated (when ~/.config/flow/api-token exists)
curl -s -A "flow-ai/0.2.0" \
-H "Authorization: Bearer $(< ~/.config/flow/api-token)" \
--get "${FLOW_API_URL:-https://app.flow.bio/api}/pipelines"
This file does NOT contain endpoint parameter or response details. Before issuing a request to any endpoint, Read the matching file below. Do not guess query params, response shapes, or visibility rules — they vary non-obviously across endpoints (e.g. timestamp encoding, envelope keys, private-sample reachability).
| User question is about… | Read this file before answering |
|---|---|
Pipeline catalog (/pipelines) | endpoints/pipelines.md |
Samples or sample-related discovery — list, detail, executions, data, plus what metadata attributes / sample types exist on this instance (/samples/search, /samples/<id>, /samples/<id>/executions, /samples/<id>/data, /samples/metadata, /samples/types) | endpoints/samples.md |
Projects list, single project detail, or a project's samples / executions (/projects/search, /projects/<id>, /projects/<id>/samples, /projects/<id>/executions) | endpoints/projects.md |
Resolving an organism name to a pk (/organisms) | endpoints/organisms.md |
The authenticated caller's identity / memberships, or resolving a user name to a pk (/me, /users/search) | endpoints/users.md |
Cross-sample executions search (/executions/search) | endpoints/executions.md |
Data file detail / contents / cross-sample search, plus data-type discovery (/data/<id>, /data/<id>/contents, /data/search, /data/types) | endpoints/data.md |
Downloading the bytes of a file (/downloads/<data_id>/<filename>) | endpoints/downloads.md |
| End-to-end recipes that chain endpoints | examples.md |
Cross-cutting rules (sections 5–7 below) apply to every endpoint and stay inline.
Always include -A "flow-ai/0.2.0" so requests identify as AI traffic.
For paginated endpoints, set count explicitly — never rely on the
implicit default of 10. Cap at 100; the API rejects >100 with HTTP 400
(not silent clamp).
URL-encode every user-supplied filter value with
--data-urlencode "<param>=<value>" (e.g. name=rna-seq); never
string-interpolate user input into the URL.
Discover before filtering. When a user names a resource ("the rna-seq
pipeline"), list the catalog first, identify the right item by name,
then use the id. The list endpoints don't accept names as exact-match
filter values directly — at best they accept a substring on name,
which can over-match.
Trust only the documented response envelope per endpoint. /pipelines
is a bare array. List endpoints use {count, page, <resource>: [...]}
where the envelope count is total matches, not page size. Detail
endpoints return a bare object. Read the relevant endpoints/*.md
before assuming a shape.
One endpoint per question. To answer a multi-resource question, make sequential calls. Do not invent combined endpoints or query params.
Never invent query params. If a user asks for a filter that isn't in
the table for that endpoint (in endpoints/*.md), say so honestly.
Do not send unknown params.
Discover before filtering on metadata or controlled-vocab entities. When a user's question involves a domain concept (organism, tissue, treatment, sample type, etc.), do not guess at filter identifiers or values. Call the relevant discovery endpoint first:
GET /organisms → match by name/latin_name,
pass id to /samples/search?organism=<id>.GET /samples/types → pass identifier to
/samples/search?sample_types=<identifier>.GET /data/types → match by name or identifier,
pass identifier to /data/search?data_types=<identifier>.GET /samples/metadata → confirm the
identifier exists on this instance, then use it on
/samples/search?<identifier>=<value>.Discovery costs one extra round-trip and removes the entire class of "filter silently ignored" bugs from your query path. Metadata attributes vary per Flow instance — do not assume specific identifiers exist.
jq to project to the fields the user actually asked for,
then summarise.jq; never paste raw curl output verbatim into the
user's view if it's longer than ~20 lines.endpoints/samples.md before answering any "what
metadata does sample X have?" question.| Status | Meaning | What to do |
|---|---|---|
| 400 | Wrong filter, wrong type, malformed value, or count > 100 | Report the message verbatim. Suggest the closest valid filter from the relevant endpoints/*.md. For count, lower it. |
| 404 | Wrong path or non-public ID | Verify path against endpoints/*.md. If filtering by ID, fall back to discovery via the list endpoint. |
| 500 | Likely a non-integer page/count value (the API doesn't catch ValueError) | Confirm both are integers. If they are, report as a server-side issue and stop. |
| 5xx (other) | Server-side | Report once. Do not retry — the user retries manually. |
| Network failure | DNS, timeout | Report FLOW_API_URL and the failure to the user. Ask whether the URL is reachable. |
| 200 with empty list | No resources visible to this caller match | Not a failure. Tell the user "no matches found". If the request was unauthenticated, remind them many resources on Flow are private and an authenticated caller may see more. |
| 200 but result count unchanged after adding a filter | Filter likely silently ignored — unknown identifier on this instance | Confirm the identifier exists via GET /samples/metadata (or the relevant discovery endpoint). The API does not currently reject unknown filter params. |
Never silently swallow an error. If curl exits non-zero or the body
contains an error, report and stop — do not fabricate a result.
POST /downloads/... →
GET /downloads/<job_id> zip flow is auth-gated and tracked separately.<base>/openapi.json and use
it." Reliability tactics, output discipline, and error handling stay;
they're operational, not endpoint-specific.Provides CDSS development patterns for drug interaction checking, dose validation, clinical scoring (NEWS2, qSOFA), and alert classification integrated into EMR workflows.
npx claudepluginhub goodwright/flow-skills --plugin flow-ai