Summary
- Problem: Many questions about the mouse brain need several datasets joined in one shared 3D atlas. Each crossing between datasets has a trap that gives a wrong answer without an error, and nobody can check what an agent joined.
- Design: A Python library translates each source, through its own adapter, into one model of atlas versions, cell-type taxonomies and observations. A join runs only between compatible versions. Every answer records what it read and every fix it applied.
- Agent surface: An MCP server and two Skills give agents tools that find data, plan joins, refuse invalid ones, and run code in a sandbox next to the data. They work in Claude Science and in Claude Code.
- Infrastructure: Batch work runs as Slurm jobs in Apptainer containers, which is how Claude Science computes on a cluster. The same job scripts run on the homelab's Slurm, on a Slurm cluster in AWS at the end, and on a partner's cluster. The MCP server runs as a container service.
- Evaluation: A pre-registered experiment runs four tool conditions in the Agent SDK, and subsets of them in Managed Agents and Claude Science, against gold answers from published sources. A component stays only if it measurably helps.
The problem
A question that spans datasets
Here is a question a neuroscientist might ask an agent:
Which cell types sit in the brain region under this recording probe, and how do the neurons there respond to what the animal sees?
No single dataset answers it. v1 answers two families of question. The first is the one above. The second starts from one traced neuron and asks which cell types sit where its axon ends, and how the neurons there respond. Four public datasets hold the parts of these two questions:
| Dataset | What it holds | Format and location |
|---|---|---|
| Visual Coding Neuropixels (Allen) | recordings from probes in the brain. Each channel has a 3D position | NWB files on DANDI |
| OpenScope Neuropixels (Allen) | more probe recordings, from experiments proposed by outside scientists | NWB files on DANDI |
| ABC Atlas MERFISH (Allen) | about 4 million cells from one mouse brain, each with a position and a cell type | tables and matrices in Allen's S3 bucket |
| MouseLight (Janelia) | whole traced neurons. Each traced point has a position and a region | JSON from Janelia's NeuronBrowser |
The Allen Common Coordinate Framework (CCF) links them. The CCF is a shared 3D reference atlas of the mouse brain. Each dataset places its observations in CCF coordinates and labels them with CCF regions. In software terms, the CCF is a coordinate reference system, like WGS84 for maps, and its annotation is a lookup table from a coordinate to a region id. Answering the question is a spatial join across datasets on that shared reference.
Where the joins go wrong
A spatial join is correct only when both sides agree on the axes, the units, the key and the version of the lookup table. GIS engineers know the failure: points geocoded against different datums land in the wrong place, and nothing errors. The v1 joins cross five traps of this kind. Each was checked in the public data on 2026-10-15 and 2026-10-16:
| Trap | Software analogue | Where it occurs |
|---|---|---|
| Broken and mirrored axes | one column copied over another, and an east-west axis flipped | In the Visual Coding NWB files on DANDI, the z column repeats y, and left-right is missing (AllenSDK issue 1796). Allen's own channel table has left-right, mirrored: the true value is 11,400 µm minus it (Allen forum) |
| Mixed units | one table in metres, the other in millimetres | The MERFISH coordinates are in millimetres (ABC Atlas tutorial). The probe coordinates are in micrometres |
| A key that looks right | joining on another table's surrogate key | MERFISH's parcellation_index looks like a region id. It is the value in an annotation volume, and it maps to region ids through a separate table (ABC Atlas tutorial) |
| Two versions of the lookup table | geocoding against two editions of a map | MouseLight stores each traced point's region under CCF 2.5 and under CCF 3, and each export carries one of them, on its own axes. For neuron AL0020 the two disagree on 296 of 466 dendrite points |
| Missing keys | nulls in a join column | In Allen's Visual Coding channel table, 29,311 of 123,224 channels have no region label. In one OpenScope session, 634 of 2,880 channels are labelled "void" because they sit above the brain (AIND) |
Why agents make it harder
- Size: The MERFISH brain's expression matrices take 15 GB as measured and 50 GB with imputed genes. An agent cannot read that. It calls tools or writes code, and each step can pick up a default it never sees.
- No signal: A trap returns a plausible result, so the agent has nothing to react to.
- No record: The answer does not say which files, versions and fixes it used, so a reviewer cannot rerun it.
What a trustworthy answer needs
A cross-dataset answer can be trusted only when four things hold:
- Every observation sits in one reference space, at a named atlas version, with known axes and units.
- Every label is an id in a named version of its ontology or taxonomy.
- Every join connects observations at compatible versions: the same version, or two versions linked by a recorded crosswalk. A crosswalk is a mapping table between two versions.
- The answer records what was read, every fix applied, and the code and environment that computed it, so a second person can rerun it.
The design enforces all four in code.
Constraints
| Constraint | Detail | Effect on the design |
|---|---|---|
| Data size | The MERFISH brain's expression matrices take 15 GB, or 50 GB with imputed genes. The Visual Coding dandiset holds 478 GB in 214 files | Data never passes through a tool response or a context window. Code runs next to the data and returns small tables |
| Licences | Each source sets its own terms. The ABC Atlas and MouseLight are CC BY-NC 4.0, and the Visual Coding files on DANDI are CC BY 4.0 | Nothing is re-hosted or published. Every answer names each source's licence |
| Open data only | Every v1 source answers anonymous reads | The system is read-only and holds no data credentials |
| Upstream release cadence | Each source releases on its own schedule | Versions are explicit inputs. Contract tests on small pinned metadata catch a change |
| Hosts call tools differently | Claude Science runs connector calls as code steps (docs). Claude Code calls tools by name | Tools return typed, structured results that a model and a script can both read |
| Claude Science has no API | Its beta runs as a desktop app | Its harness runs a 25-question subset, by hand |
| Claude Science computes through Slurm | It connects to an SSH host, such as an HPC login node. Where sbatch exists it submits jobs to Slurm, and it submits to no other scheduler. Its probe checks each host for Apptainer (docs) | Batch work is Slurm jobs in Apptainer containers |
| Homelab first | Development and the full experiment run on the homelab: Slurm through Slinky on its Kubernetes cluster (k3s), and the server on k3s. The public build moves to AWS at the end | Batch work ships as Slurm job scripts and Apptainer images, and the server as a container image |
| One part-time developer | v1 has to be finishable | v1 covers two question families and three sources |
Who it is for
| Stakeholder | Their problem today | What the design gives them | Requirements |
|---|---|---|---|
| A scientist asking Claude | They cannot tell whether an agent joined the datasets correctly | Answers that carry a record, and refusals that give the reason | R-1, R-7, R-14, R-15 |
| An agent answering the question | The data is too large for its context, and the traps raise no error | Tools that find data, plan joins, refuse invalid ones, and run code beside the data | R-10, R-11, R-14 |
| A reviewer, human or agent | They cannot rerun someone else's answer | The record, and a tool that reruns it and compares | R-13, R-16 |
| An engineer adding a source, at Allen or another institution | Each integration is written from scratch | One adapter against the capability ports, with contract tests | R-17 |
| Allen's teams building AI tools | Allen's partnership with Anthropic names "multi-omic data integration" as the agents' job (Anthropic, 2026-02-02), and each of their current tools covers one source | Results in Allen's own ids (CCF structure ids, taxonomy ids), and Skills and adapters they can adopt | R-3, R-4, R-19 |
| An operator running it on a partner institution's own HPC cluster | The system has to fit the partner's scheduler, container runtime, storage and accounts | Slurm job scripts and Apptainer images, with partitions, accounts and paths as settings | R-18 |
Goals and non-goals
The goals, in priority order:
- An agent answers v1's two question families with valid joins, or refuses and says why.
- A verifier reruns any answer from its record and gets the same result.
- A new source needs one adapter. The core and the agent surface stay as they are.
- An experiment measures what the MCP server, the Skills and the join rules each add. The results are published whatever they show.
- The system runs end to end on the homelab and on AWS, and its batch work runs unchanged on a partner's Slurm cluster.
v1 leaves these out:
- Patch-seq recordings: They use an older taxonomy with no crosswalk to the current one, and they have no CCF coordinates.
- MICrONS: It has no CCF registration.
- CELLxGENE Census: It excludes MERFISH, so neither v1 join needs it.
- Search over cell types in plain language: The Brain Knowledge Platform's AI helper already does this.
- Human or controlled-access data: Only open data is read.
- Re-hosting data: Data is read in place. The slice cache stays private to the cluster.
- Proposing findings: The system returns joined data, computed numbers and their records. It does not suggest biological conclusions.
- GPUs: No v1 step needs one.
Requirements
The 28 cases on the Evidence page motivate the provenance and identity requirements. The Evidence page also maps each case to its requirements.
Proposed design
Overview
The design follows the ports-and-adapters pattern. The core holds the shared model and every rule. It defines five ports, one per capability a source can offer: spatial observations, taxonomy, physiology, morphology and expression. Each source sits behind an adapter that implements the ports it can serve. On the other side, the MCP server, the Skills and the CLI call into the core.
The example question flows through the system like this:
- Claude calls
resolve_term, which turns the region's name into a region id in a named CCF version. - Claude calls
find_observationsfor the units recorded in that region. The DANDI adapter reads the session's units in place, takes channel positions from Allen's channel table, mirrors left-right back, and returns a handle and a count. - Claude calls
find_observationsfor the MERFISH cells in that region. The ABC Atlas adapter mapsparcellation_indexto region ids and converts millimetres to micrometres. - Claude calls
plan_joinwith the two handles. The planner checks that both sides use the same CCF version, or finds a crosswalk. It returns the plan and the code that runs it, or it refuses and says why. - Claude calls
run_plan. The code runs as a Slurm job, in an Apptainer container next to the data, and a small table comes back with a record id. - A reviewer, or Claude Science's Reviewer, calls
verifyon the record. The verifier reruns the plan and compares the result.
Components
| Component | Kind | What it does | Why it exists |
|---|---|---|---|
| Core | Python package mouse_brain_ccf_join | Holds the model, the join planner and its checks, the records and the verifier | Every interface and every experimental condition calls the same code |
| Source adapters | one module per source, in the package | Translate a source's formats, ids, axes, units and versions into the model | Each source's quirks stay in one module |
| Crosswalk tables | data files in the repository, with checksums | Map region ids between CCF versions, and taxa between taxonomy versions | A join across versions needs a reviewed mapping |
MCP server mouse-brain-ccf-join-mcp | container service over Streamable HTTP (k3s on the homelab), or a local process over stdio | Exposes seven typed, read-only tools over the core | Any MCP host can use the tools |
| Skills | folders of instructions and tested scripts | Carry one question family each, step by step | The multi-step workflow loads only when a task matches |
| CLI | a console command in the package | Runs the same functions from a shell, with JSON output | Contract tests, reference scripts and people use the core without an agent |
| Claude Science package | a connector, the imported Skills, a Specialist (Claude Science's bundle of connectors and Skills for one kind of work) and a Reviewer criterion | Installs the system in Claude Science | Claude Science is a target host and an agent harness in the experiment |
| Agent partition | a Slurm partition whose jobs run in Apptainer containers | Runs agent-written code and run_plan work next to the data | Agent code is untrusted, and the data is too large to move |
| Login node | a Slurm login node: a Slinky LoginSet on the homelab, the head node in AWS | Where Claude Science connects over SSH and submits with sbatch | Claude Science computes only through Slurm |
| Experiment runner | Slurm job arrays, accounted by slurmdbd | Runs and grades every question, condition and repeat | The sweep is thousands of attempts, and it has to resume after a failure |
| Images | Dockerfiles built in CI into OCI images, pushed to the homelab's Harbor registry. CI converts each batch image to one Apptainer image (SIF), once, from the OCI image's digest, and pushes the SIF to Harbor with oras:// | One build for every target. The server runs the OCI image, and every Slurm cluster runs the same SIF file | Jobs on every cluster run byte-identical files, so a record can name the exact environment by its sha256 |
| Slice cache | homelab storage | Keeps the data slices that questions reuse | Repeated reads in place are slow |
| Trace and run store | OpenTelemetry traces and run logs | Keeps every tool call and every attempt | The experiment's evidence, and the first place to debug |
Three external stores hold the data: Allen's S3 bucket, DANDI's S3 bucket and Janelia's NeuronBrowser.
How a join is kept valid
The model: The model has four kinds of thing.
- Reference spaces: each CCF version, with its axes, unit, resolution and region ontology.
- Taxonomies: each version of a cell-type taxonomy, with its levels.
- Genes: each gene at a named annotation release, with its symbol history.
- Observations: cells, units, channels and traced points. Each one has coordinates in a named reference space and labels at named versions.
Crosswalks link versions. The model is a schema. Adapters read observations on demand and return a handle to an Arrow table. No source is loaded whole.
The adapters: Each one fixes its source's traps on the way in and writes every fix to the record.
| Adapter | Source and format | Ports | What it normalizes |
|---|---|---|---|
| ABC Atlas | MERFISH cells, the taxonomy and CCF tables: CSV, Parquet and h5ad on S3 | spatial, taxonomy, expression | millimetres to micrometres. parcellation_index to structure ids. Measured or imputed, per gene |
| DANDI | Visual Coding and OpenScope NWB files, and Allen's channel table | spatial, physiology | Channel positions taken from Allen's channel table, since the NWB copy repeats y in z. Left-right mirrored back (11,400 µm minus the value). The QC filter stated. Unlabelled and "void" channels counted |
| MouseLight | traced neurons as JSON exports from NeuronBrowser | spatial, morphology | Both exports read, CCF 2.5 and CCF 3, each on its own axes. The two are kept apart, and mixing them needs a crosswalk |
The planner's rules: The join planner applies five rules before any join runs.
- Both sides must be in the same reference space version, or linked by a crosswalk in the crosswalk tables. Otherwise the join is refused.
- Labels joined at a taxonomy level must come from the same taxonomy version, or be crosswalked.
- Joins run on ids from the region ontology. A source's own index never reaches a join.
- Unlabelled observations are counted and reported on the record.
- Every fix an adapter applied is listed on the record.
What the rules miss: Adapters fix the axis and unit traps on the way in.
Rules 1, 3 and 4 catch the version, key and missing-label traps, and rule 2
does the same for taxonomy versions. The rules cannot judge whether a question
makes scientific sense, and they cannot catch a trap nobody has written a rule
for. Code that an agent writes without the
planner is also outside their view. The experiment counts the misses: an
attempt that fails on an unlisted trap gets the failure code missed_caveat,
and each such trap becomes a candidate rule with an adapter test.
Tools
| Tool | Takes | Returns | Never returns |
|---|---|---|---|
describe_sources | nothing | the sources, their pinned releases, the ports each serves, and their licences | file contents |
resolve_term | a region, cell-type or gene name, and optionally a version | the id at that version, its parents, and any crosswalks to other versions | data |
find_observations | a region or cell type, a kind of observation, and filters | a handle, a count, the unlabelled count, and the fields available | arrays of observations |
plan_join | two handles | a verdict (valid, valid through a crosswalk, or refused with the reason) and the code that runs the join | the joined data |
run_plan | a plan id | a small result table and a record id. The work runs as a job on the agent partition | arrays of data |
get_record | a record id | the full record | nothing else |
verify | a record id | a match, or the first difference found on rerun | nothing else |
Each tool declares input and output schemas and returns structured content,
so a code step in Claude Science and a model calling the tool by name read the
same fields. Each is marked readOnlyHint. A refused
join returns the reason and the crosswalk that would allow it. Tests hold each
response under a size budget.
Design principles
Anthropic's engineering guidance gives two principles for agent tools. The design accepts the cost of each and adds a third.
| Principle | Source | What it costs | How the design applies it |
|---|---|---|---|
| Build tools around the tasks an agent performs, and return compact, meaningful results | Writing effective tools for agents | A few task-shaped tools answer fewer questions directly than one tool per API endpoint, and they take more design work | Seven tools, one per step of a cross-dataset question, each under a size budget |
| Let the agent process large data in code, and keep intermediate results out of the model's context | Code execution with MCP | The agent needs a sandbox and takes an extra step, and running code adds a security surface | plan_join returns code. It runs in a sandbox beside the data, and only small tables come back |
| Anything that must happen on every answer happens in code | this design | A rule catches only what someone wrote a rule for | The planner's rules and the record live in the core |
Data model
Reference rows are keyed by id and version together, so the same region id in two CCF versions is two rows, and a crosswalk row links them. Each observation belongs to one release and one reference space. A record lists what an answer read, each join step with its verdict, and the code and environment. A record cites only releases in the source catalogue, which is the Sources group.
One question, end to end
The first family's Skill carries this workflow, and it is the template for that family's join questions.
Infrastructure
| Need | Design |
|---|---|
| Sandboxed execution | Agent code runs as Slurm jobs on the agent partition, each in an Apptainer container started with --containall --cleanenv, as an unprivileged user with no credentials. The nodes' egress allows the data buckets only: a network policy on the homelab, firewall rules in AWS. A step that needs no network adds --net --network none, which unprivileged users may use |
| Scheduled runs | A Slurm job array runs one task per question, condition and repeat. slurmdbd accounts every task, so sacct shows what ran, and a failed task requeues on its own. Each task writes its transcript and grade |
| Reads at scale | Adapters read objects in place with HTTPS range requests. The slice cache keeps the slices that questions reuse, on the cluster's shared filesystem |
| Serving | The MCP server runs as a container service behind HTTPS: a Kubernetes deployment on the homelab, on the tailnet only while in development. Each tool call is traced. Slurm runs batch work, and a long-lived server is not batch work |
The same job scripts and Apptainer images run on three Slurm clusters:
- The homelab: Slurm runs on k3s through Slinky, SchedMD's operator. No v1 step needs a GPU.
- AWS: a Slurm cluster built from infrastructure code, in P5.
- A partner's cluster: partitions, accounts and paths are settings.
Claude Science runs on a laptop and connects to a Slurm login node over SSH, so its data work runs as Slurm jobs too. In the Agent SDK and Claude Science, agent-written code runs on the agent partition, so the place code runs is the same in both harnesses.
Design decisions
| Decision | Chosen | Over | Because |
|---|---|---|---|
| How sources plug in | ports by capability | one interface per source | a source with several kinds of data implements several ports, and a new source of a known kind changes nothing in the core |
| Where data lives | a schema with handles, read in place | a warehouse loaded with copies | the licences, the size and upstream releases all rule out a copy |
| Where the join rules run | in the core | in a prompt or a Skill | the planner checks every join it plans without relying on the model |
| What tools return | typed, structured results | text | Claude Science reads results from code |
| How batch work is scheduled | Slurm, with jobs in Apptainer containers | Kueue jobs and gVisor pods on Kubernetes | Claude Science computes only through Slurm and checks hosts for Apptainer, and the same job scripts run on the homelab, in AWS and on a partner's cluster |
| Where the server runs | a container service | a Slurm job | the server is long-lived, and Slurm schedules work that ends |
| Where gold answers come from | published sources, each reproduced by a script | an expert panel | no panel is available, and a question with no published answer is labelled form-only |
Trade-offs
| The design gives up | In exchange for | How the cost is kept down |
|---|---|---|
| Breadth: two question families and three sources | joins that are correct and checkable | a new source is one adapter |
| Speed of a first answer: plan, then run | data stays out of the context window | the Skills script the common path |
| Effort up front: a shared model before any answer | adapters that hold every source's quirks | the model covers only what the two question families need |
| Some answers: joins without a crosswalk are refused | wrong joins become explicit errors | refusals carry the reason and the missing crosswalk, and the experiment counts them |
| Kernel isolation: Apptainer shares the host's kernel, where gVisor would intercept the agent's system calls | the container runtime Claude Science checks hosts for, so agent jobs run unchanged on a partner's cluster | the agent's user is unprivileged and holds no credentials, its egress reaches the data buckets only, and --containall hides the host's files and environment |
| Two substrates: Slurm for batch work, a container service for the server | each runs the work it was built for | on the homelab both run on the same k3s cluster, which already runs Slinky |
| Sample size in Claude Science: 25 questions, by hand | Claude Science is in the experiment at all | its results are reported with their own intervals and no decision rule |
Evaluation plan
This section is the pre-registration. The question set, the gold answers, the graders and this plan are tagged in the product repository before the first full run, and the results report links to that tag.
Hypotheses
- H1, the MCP server: On leg questions, and separately on join questions, Claude with code, Allen's libraries and the MCP server (T2) answers correctly more often than Claude with code and Allen's libraries alone (T1).
- H2, the Skills: On join questions, adding the Skills to the MCP server (T3 against T2) raises correctness.
- H3, the join rules: On trap questions, T2 and T3 each give the required fix or refusal more often than T1.
T0 is reported as a floor, with no hypothesis.
Three comparisons are exploratory. They are reported with intervals and carry no decision rule:
- E1, the harness: Claude Science against the Agent SDK, with the same tools, on the Claude Science subset.
- E2, the Reviewer: In Claude Science, whether the Reviewer criterion catches wrong joins.
- E3, a hosted agent: Managed Agents against the Agent SDK, with the same tools, in P5.
Conditions
| Condition | What Claude has | Agent SDK (full set) | Managed Agents (full set, P5) | Claude Science (subset) |
|---|---|---|---|---|
| T0, no tools | the question and its own knowledge | yes | ||
| T1, the baseline | a Python sandbox with Allen's libraries (AllenSDK, abc_atlas_access, pynwb) | yes | yes | |
| T2, plus the MCP server | T1 and the seven tools | yes | yes | |
| T3, plus the Skills | T2 and the two Skills | yes | yes | yes, with the Reviewer off and on |
T1 is the baseline. It gives Claude what a capable agent has today. Every condition uses one model and effort setting, named in the pre-registration tag, and the same system prompt apart from the tool description. Each answer ends with a JSON block with fixed fields, so every grader reads one format.
Question set
| Kind | Count | Gold answer | Example |
|---|---|---|---|
| Leg | 30 | a number from a published source, reproduced by a reference script at the pinned release | How many units does session 791319847 record in VISp under the AllenSDK's default QC filter? (93) |
| Join | 30 | form only: the join is valid, the record is complete, and a rerun reproduces the result | Which MERFISH subclasses sit in the region under this probe? |
| Trap | 20 | a specific fix, or a refusal | Join this MouseLight neuron's CCF 2.5 labels to MERFISH cells |
Leg questions check one dataset at a time against Allen's notebooks and two dataset papers: the AllenSDK Neuropixels tutorials, the abc_atlas_access MERFISH-to-CCF tables, Siegle et al. 2021 and Winnubst et al. 2019. No published source answers a join question, so join questions are graded on form. The report marks each form-only question as a place where expert review would go.
Size: The decision rules compare conditions within one kind, so the count per kind sets the precision. Each question is scored as its mean correctness over five runs, and conditions are compared question by question. If the per-question differences have a standard deviation near 0.5, then at 80% power and a 5% two-sided test, 30 questions detect a difference of about 25 percentage points, and 20 detect about 31. Each extra question costs a reference script or a sourced fix.
Pilot: A pilot of ten questions per kind checks the 0.5 assumption before the set is frozen. A larger spread adds questions. Questions that every condition gets right, or every condition gets wrong, are replaced. A leg question whose published number does not reproduce at the pinned release moves to form-only, and the report lists it.
Procedure and grading
Each question runs five times under each Agent SDK condition, for 1,600 attempts. Managed Agents adds 800 in P5. The Claude Science subset is 25 questions, stratified by kind and run once per cell by hand, for 75 attempts. Run order is randomised, and every transcript is stored with its token counts.
| Kind | Grader |
|---|---|
| Leg | the number must match the gold answer within the tolerance stated in the question's file |
| Join | the answer's JSON block must name both sides' versions, any crosswalk, every fix and the unlabelled count, and these must match the choices a reference script makes. Rerunning the answer's own code must reproduce its table |
| Trap | an LLM judge grades against a written rubric per question, and the author checks a random 20% of its verdicts |
The leg and trap graders follow the aind-data-mcp benchmark's two modes: a
match and an LLM judge. Every condition is graded from the same JSON block, so
no condition needs this system's tools to pass. Every wrong attempt also gets
one failure code:
wrong_version, wrong_axes_or_units, wrong_key, dropped_unlabelled,
wrong_level, ungrounded_number, fabricated_citation, missed_caveat or
tool_call_error.
Analysis and decision rules
The primary metric is correctness per kind and condition. Each comparison reports the paired difference with a 95% interval, from a bootstrap that resamples questions and keeps each question's runs together, following Adding Error Bars to Evals. Secondary metrics are the share of answerable questions refused, the count of each failure code, and tokens per question. The report leads with the failure codes.
A component stays only if the evidence shows it helps. An interval that includes zero counts as no help.
| Result | Decision |
|---|---|
| H1's interval is above zero on leg or on join questions | The MCP server stays the main agent surface |
| H1's interval includes zero on both kinds | The tools shrink to what the Skills and the Claude Science connector call |
| H2's interval is above zero | The Skills stay |
| H2's interval includes zero | The Skills are dropped, and agents use the tools directly |
| H3 fails in both tool conditions | The join rules are reworked before any other change |
| More than 20% of answerable questions are refused in a tool condition | The rules are revisited for over-refusal |
No target score is set in advance. The results are published with their intervals whatever they show.
Security, data handling and operations
The threat model maps every data flow and trust boundary, and records each STRIDE threat with its mitigations and status.
- Read-only: The system reads open data and holds no data credentials.
- Untrusted text: Free text from metadata and NWB descriptions comes back in quoted fields, and the tool descriptions mark it as data. Agent code runs only in the sandbox, so text that does steer an agent reaches no credentials.
- Sandboxed code: Agent code runs only as Slurm jobs on the agent partition, in Apptainer containers, as an unprivileged user whose network access is limited to the data buckets.
- Licences: Every record names the licence of each source. Anything beyond reading in place would need the data owner's agreement.
- Adopting an upstream release: A new release becomes a change to an adapter's pinned manifest in a pull request. The contract tests run against it, and a new crosswalk is a reviewed table.
- Contract tests: They read small pinned metadata files and run in CI on every change.
- Public endpoint: It runs only in the AWS build. It is read-only and rate-limited, and it depends on no homelab service.
- Hand-off: The project is done when someone new stands up the AWS build from its infrastructure code and reruns one condition from the documentation alone.
Milestones
| Phase | What happens | Exit |
|---|---|---|
| P0, frame | This review | the review is accepted |
| P1, spike | One reference script per v1 join that reproduces its trap and its fix. Claude Science loads a stub connector and an imported Skill, connects to a Slurm login node on the homelab, and submits a job. An Apptainer job on the agent partition reads a MERFISH slice in place | each script matches a hand-checked value; Claude Science's job runs through sbatch; the Apptainer job's isolation flags and read rate are recorded |
| P2, core and adapters | The repository mouse-brain-ccf-join is created. The model, the crosswalks, the three adapters and their contract tests | the P1 scripts' answers reproduce through the library |
| P3, agent surface | The MCP server, the Skills and the Claude Science package. The server deployed on k3s, and the agent partition on the homelab's Slurm | one v1 question answered end to end in Claude Code and in Claude Science, with a record the verifier reruns |
| P4, experiment | The pilot, the freeze, then the full sweep as Slurm job arrays on the homelab | results published, failures first |
| P5, AWS build and release | A Slurm cluster on AWS from infrastructure code, building on an earlier Terraform-built Slurm cluster that Claude Science has already driven, with the MCP server beside it. All of it in a public repository. The released package, the public endpoint, and the Managed Agents harness | someone new stands up the AWS build and reruns one condition from the documentation alone |
Risks
| Risk | How it would show | Mitigation |
|---|---|---|
| Claude Science's beta will not load the connector or the Skills, or will not run code on an SSH host | the P1 check fails | The rest of the experiment stands without it. The report says what did not load |
| A trap fix is itself wrong, for example a mirror applied to files that were already right | a region assigned by fixed coordinates disagrees with Allen's own channel labels | The P1 join spike checks the fix against Allen's labels, and each fix becomes an adapter test |
| A published number does not reproduce at the pinned release | a reference script disagrees with its source | Manifests are pinned. The question moves to form-only, and the report lists it |
| Agents call MCP tools less reliably than they run code | tool_call_error attempts in T2 and T3 | The failure code separates broken calls from wrong answers. H1 decides whether the tools stay |
| The question set does not separate the conditions | every condition scores near 0% or near 100% on a kind | The pilot replaces those questions before the freeze |
| Apptainer will not run unprivileged inside the homelab's Slurm pods, because user namespaces are refused or the node has no FUSE | the P1 sandbox check fails | A Slurm node image built with Apptainer, or a NodeSet on another node. In AWS and on a partner's cluster Apptainer runs on the host, so the risk is the homelab's alone |
| A source moves or changes access | contract tests fail on a missing or moved file | Paths come from pinned manifests, and every read goes through the adapter |
Harbor will not store SIF files pushed with oras://. Apptainer's docs show only ghcr.io | the P1 test push fails | SIF files go to the cluster's shared filesystem or an object store, keyed by their sha256, and the record names them the same way |
Questions for reviewers
- Crosswalks between atlas versions: For MouseLight, is a crosswalk between region labels enough, or must traced points be re-registered between CCF 2.5 and CCF 3?
- Join granularity: v1 joins units and cells that share a region. Should it also offer joins by distance, such as the cells within 100 µm of a channel, given the registration error of each dataset?
- Precision: Is detecting differences of about 25 points on leg and join questions, and 31 on trap questions, enough for these decisions?
- The AWS build: Should it run a Terraform-built Slurm cluster on EC2, a pattern Claude Science has already driven, or AWS Parallel Computing Service, AWS's managed Slurm?
- An instructions-only condition: Should the experiment add a condition in which Claude is told to state its versions but has no tools? It would separate the effect of the instruction from the effect of the tools, for a quarter more attempts.
Supporting material
- What an answer about the brain depends on: The versioned inputs behind an answer, in depth.
- What already exists: The MCP servers and the assistant that already work with Allen data.
- Same input, different answer: Documented version changes that moved results on identical inputs.
- Fluent, confident, unverifiable: AI deployments in science and medicine that failed on what could not be checked.
- Threat model: A data flow diagram with its trust boundaries, and the STRIDE threats against each element and crossing.
The full-screen data model and every verified case, with its source, are on the Data model and Evidence pages.