> ## Documentation Index
> Fetch the complete documentation index at: https://docs.biomni.phylo.bio/llms.txt
> Use this file to discover all available pages before exploring further.

# Reviewing a gene list

> Send a gene list for a first-pass review, then hand what it flags to a scientist to check

This recipe sends a gene list to Biomni for a first-pass review and turns the
genes it flags into a checklist for a scientist. The checklist links back to
the task, so the scientist can open it in Biomni and keep the conversation
going.

The example list is 15 hits from a genome-wide CRISPR knockout screen for
vemurafenib resistance in A375 melanoma cells. For each gene, the agent checks
whether its symbol is current, whether it is expressed in melanoma lines,
whether there is published evidence linking its loss to MAPK-inhibitor
resistance, and whether it could be a screen artifact. It returns a verdict of
`plausible` or `flag` for each gene, with reasons and sources.

## Prerequisites

* [An API key](https://docs.biomni.phylo.bio/api/authentication.md)
* Python 3.10 or later with the `requests` package
* `phylo_client.py` from [Building a Python client](https://docs.biomni.phylo.bio/api/recipes/wrapping-the-api-in-python.md),
  saved beside your script

Install `requests`, then set your API key:

```bash theme={null}
python -m pip install requests
export PHYLO_API_KEY="<your-api-key>"
```

The script uses `https://api.phylo.bio/v1`. If you're an Enterprise customer,
set the `PHYLO_BASE_URL` environment variable to the API base URL shared by your
Phylo representative.

By default, the script creates a project called "API demo". To use an existing
project instead, set `PHYLO_PROJECT_ID` to its ID.

## How it works

`main()` creates the review task with `auto_mode=True`, waits for it to
finish, and downloads `review.json`. It then writes every flagged gene, with
the agent's reasons and sources, to `scientist_checklist.md`.

```python theme={null}
def main():
    phylo = PhyloClient()
    project_id = (
        os.getenv("PHYLO_PROJECT_ID")
        or phylo.create_project(title="API demo")["id"]
    )

    task = phylo.create_task(
        project_id=project_id,
        title="Gene list review: vemurafenib resistance screen",
        initial_messages=[
            {"role": "user", "content": REVIEW_PROMPT.format(genes=", ".join(GENES))}
        ],
        auto_mode=True,
    )
    print(f"Review task: {task['id']}")
    phylo.wait_for_task(task["id"], poll_interval_seconds=60)

    results_dir = phylo.download_results(task["id"], Path("gene-review") / task["id"])
    review = json.loads((results_dir / "review.json").read_text())
    flagged = [entry for entry in review if entry["verdict"] == "flag"]

    task_url = f"{WEB_BASE}/projects/{project_id}/tasks/{task['id']}"
    checklist = results_dir / "scientist_checklist.md"
    write_checklist(checklist, task_url, flagged)
    print(f"{len(flagged)} of {len(review)} genes flagged for a scientist to check.")
    print(f"Checklist: {checklist}")
    print(f"Task: {task_url}")
```

`write_checklist()` turns the flagged genes into a Markdown checklist with a
link to the task:

```python theme={null}
def write_checklist(path, task_url, flagged):
    lines = [
        "# Gene list review: genes to check",
        "",
        f"Biomni's first-pass review: {task_url}",
        "Reply in that task to ask Biomni follow-up questions about any gene.",
        "",
    ]
    for entry in flagged:
        lines.append(f"- [ ] **{entry['gene']}**: {entry['reason']}")
        lines.extend(f"  - {source}" for source in entry["evidence"])
    path.write_text("\n".join(lines) + "\n")
```

The link uses `https://biomni.phylo.bio`. If you're an Enterprise customer,
set `WEB_BASE` to your Biomni URL.

With Auto mode on, the task does not stop to wait for a person. Biomni answers
its own clarification questions and approves its own plan, and marks both in
the task.

![Gene list review task showing an auto-answered clarification and an auto-approved first-pass review plan](https://mintcdn.com/phylo/liKXOE1vbHNl7uvD/images/api-recipe-gene-review-auto-mode.png?fit=max\&auto=format\&n=liKXOE1vbHNl7uvD\&q=85\&s=361defb4c1ec1a746d6007e9d74ed399)

Auto mode in the review task: the clarification question was answered automatically and the plan was approved automatically.

## Run the script

Save the [full script](#full-script) as `gene_list_review.py` beside
`phylo_client.py`, then run:

```bash theme={null}
python gene_list_review.py
```

The script prints how many genes were flagged, and the paths to the checklist
and the task. Results are saved under `gene-review/<task-id>/`.

## Example results

The review found 10 genes plausible (NF1, MED12, NF2, CUL3, TADA2B, TADA1, CIC,
KEAP1, PTEN, DUSP4) and flagged 5:

| Gene | Why it was flagged |
| - | - |
| SEPT2 | Outdated symbol: the guide library must map it to SEPTIN2. |
| MARCH5 | Outdated symbol, and no established direction of effect on resistance. |
| OR4F5 | Not expressed in A375 or other melanoma lines; guides may also hit related olfactory receptors. |
| TTN | Only trace expression in A375, and below 1 TPM in every melanoma line measured. |
| LINC00473 | Noncoding RNA: there is no protein-coding frame to knock out. |

![Summary of the gene list review with 10 plausible genes and 5 flagged genes](https://mintcdn.com/phylo/liKXOE1vbHNl7uvD/images/api-recipe-gene-review-summary.png?fit=max\&auto=format\&n=liKXOE1vbHNl7uvD\&q=85\&s=493a99cd59a184f0fef32829098c5430)

The finished review: 10 genes plausible and 5 flagged, saved as review\.json.

Each checklist entry includes the agent's full reasoning and sources:

```markdown scientist_checklist.md theme={null}
# Gene list review: genes to check

Biomni's first-pass review: https://biomni.phylo.bio/projects/<project-id>/tasks/<task-id>
Reply in that task to ask Biomni follow-up questions about any gene.

- [ ] **SEPT2**: Not the current approved symbol: SEPT2 is a previous symbol of SEPTIN2 (HGNC:7729); ...
```

## Adapting this for your gene list

* Replace `GENES` with your list, and edit `REVIEW_PROMPT` to describe your
  screen and the checks you want.
* Keep a fixed verdict field, like `plausible` or `flag`, so your code can
  route results without reading the agent's prose.

## Full script

```python gene_list_review.py theme={null}
"""Gene list review: send a gene list for a first-pass review, then hand what
it flags to a scientist to check."""

import json
import os
from pathlib import Path

from phylo_client import PhyloClient

WEB_BASE = "https://biomni.phylo.bio"

# Top positively selected genes from a genome-wide CRISPR knockout screen for
# vemurafenib resistance in A375 melanoma cells.
GENES = [
    "NF1", "MED12", "NF2", "CUL3", "TADA2B", "TADA1", "CIC", "KEAP1",
    "SEPT2", "MARCH5", "OR4F5", "TTN", "PTEN", "DUSP4", "LINC00473",
]

REVIEW_PROMPT = """
These genes are the top hits from a genome-wide CRISPR knockout screen for
vemurafenib resistance in A375 BRAF V600E melanoma cells:

{genes}

Do a first-pass review of each gene before we spend bench time on it:
- Is the symbol current HGNC, and is it a protein-coding gene a CRISPR knockout
  can hit?
- Is it expressed in A375 or melanoma lines (DepMap/CCLE)?
- Is there published evidence linking its loss to BRAF or MAPK inhibitor
  resistance?
- Could it be a screen artifact (not expressed, very long gene, copy-number
  effect)?

Save raw JSON (no code fence) at /mnt/results/review.json, one entry per gene:
[{{"gene": "NF1", "verdict": "plausible" or "flag", "reason": "...",
   "evidence": ["PMID or source", "..."]}}]
""".strip()


def write_checklist(path, task_url, flagged):
    lines = [
        "# Gene list review: genes to check",
        "",
        f"Biomni's first-pass review: {task_url}",
        "Reply in that task to ask Biomni follow-up questions about any gene.",
        "",
    ]
    for entry in flagged:
        lines.append(f"- [ ] **{entry['gene']}**: {entry['reason']}")
        lines.extend(f"  - {source}" for source in entry["evidence"])
    path.write_text("\n".join(lines) + "\n")


def main():
    phylo = PhyloClient()
    project_id = (
        os.getenv("PHYLO_PROJECT_ID")
        or phylo.create_project(title="API demo")["id"]
    )

    task = phylo.create_task(
        project_id=project_id,
        title="Gene list review: vemurafenib resistance screen",
        initial_messages=[
            {"role": "user", "content": REVIEW_PROMPT.format(genes=", ".join(GENES))}
        ],
        auto_mode=True,
    )
    print(f"Review task: {task['id']}")
    phylo.wait_for_task(task["id"], poll_interval_seconds=60)

    results_dir = phylo.download_results(task["id"], Path("gene-review") / task["id"])
    review = json.loads((results_dir / "review.json").read_text())
    flagged = [entry for entry in review if entry["verdict"] == "flag"]

    task_url = f"{WEB_BASE}/projects/{project_id}/tasks/{task['id']}"
    checklist = results_dir / "scientist_checklist.md"
    write_checklist(checklist, task_url, flagged)
    print(f"{len(flagged)} of {len(review)} genes flagged for a scientist to check.")
    print(f"Checklist: {checklist}")
    print(f"Task: {task_url}")


if __name__ == "__main__":
    main()
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.