Analyze a dataset and re-check every figure
Numbers from a model are easy to believe and hard to trust. This graph profiles the data, writes cleaning rules, answers the questions and runs sanity checks in parallel, and a verifier keeps a figure only when it says how it was computed and matches the data on a spot check.
7 steps in 4 stages · 7 subagents · a kit of 12 files
Free. Built in your browser; nothing is uploaded. No API key, no account.
How it runs
Steps in the same stage start at the same time. Each subagent gets only what its incoming edges carry, and a step in a fresh context never sees the reasoning of the steps before it. A gate decides whether the work passes, and a failed gate re-runs the work it checks.
- Stage 1
Split · Planner
sonnet · Read
- Stage 24 in parallel
Profile · Worker
haiku · Read, Grep, Glob, Bash
Cleaning Rules · Worker
haiku · Read, Grep, Glob, Bash
Analysis · Worker
haiku · Read, Grep, Glob, Bash
Sanity Checks · Worker
haiku · Read, Grep, Glob, Bash
- Stage 3
VERIFIER (Fresh Context) · Checker
opus · Read, Grep, Glob · fresh context
Gate: Every kept figure says how it was computed and matches the data on a spot check.
- Stage 4
Final answer · Writer
sonnet · Read
Use it when
- You have a CSV or spreadsheet and questions about it.
- You need to know how each number was computed.
- The data is messy and needs cleaning rules first.
Change these first
- The workers can run Python or SQL through Bash; narrow it to the commands you allow.
- List the questions you care about in the request.
Need a workflow built for your team? Fixed-price packages
What you get
An orchestrating SKILL.md, one Claude Code subagent per step with its own tools and model, and the same skill as a Cursor rule. Your agent runs it with its own subagents; nothing on this site calls a model.
- .claude/skills/analyze-a-dataset/SKILL.mdorchestrator
- .claude/skills/analyze-a-dataset/graph.skill.mdgraph source
- .claude/agents/analyze-a-dataset-splitter.mdsubagent
- .claude/agents/analyze-a-dataset-profile.mdsubagent
- .claude/agents/analyze-a-dataset-cleaning.mdsubagent
- .claude/agents/analyze-a-dataset-analysis.mdsubagent
- .skill-graph/.gitignoresupport
- .cursor/rules/analyze-a-dataset.mdcCursor rule
- README.mdreadme
- + 3 more subagents
---
name: analyze-a-dataset
description: "Analyzes a CSV or table: profiling, cleaning rules, answers and sanity checks run in parallel, every figure is re-checked in a fresh context, then a data report."
---
# analyze-a-dataset
Analyzes a CSV or table: profiling, cleaning rules, answers and sanity checks run in parallel, every figure is re-checked in a fresh context, then a data report.
This skill is a graph: each step has its own prompt and context, and only the payloads named below move between steps.
## Plan
Run the stages in order. Every model step runs in its own subagent; do not do a step's work yourself. Only command steps and approvals are yours to run. Steps in the same stage do not depend on each other: start them together, in one message with several subagent calls.
The input (`goal`) is the user's goal: their request, word for word, handed on under `### goal`. Ask for it if the user has not given one.
### Stage 1 · 1 step
- **SPLIT** (`splitter`) → subagent `analyze-a-dataset-splitter`
- Hand it: the user's goal.
- Expect: `subtask_json` (json).
- Contract check (`subtask_json`): save its output to `.skill-graph/analyze-a-dataset/splitter.json`, then run `node -e "const fs=require('fs');const d=JSON.parse(fs.readFileSync(process.argv[1],'utf8'));const k=['profile','cleaning','analysis','sanity'];const ok=d!==null&&typeof d==='object'&&Array.isArray(d)===false;const m=ok?k.filter((x)=>Object.hasOwn(d,x)===false):k;if(m.length>0){console.error('Missing keys: '+m.join(', '));process.exit(1)}" .skill-graph/analyze-a-dataset/splitter.json` with Bash. Exit code 0 passes.
- If a contract check fails: re-run this step once with its previous answer and the error output. If it fails again, stop and show the user the output.
### Stage 2 · 4 steps in parallel
- **Profile** (`profile`) → subagent `analyze-a-dataset-profile`
- Hand it: only the `profile` value from the JSON of SPLIT (`splitter`).
- Expect: `data_findings` (markdown).
- **Cleaning Rules** (`cleaning`) → subagent `analyze-a-dataset-cleaning`
- Hand it: only the `cleaning` value from the JSON of SPLIT (`splitter`).
- Expect: `data_findings` (markdown).
- **Analysis** (`analysis`) → subagent `analyze-a-dataset-analysis`
- Hand it: only the `analysis` value from the JSON of SPLIT (`splitter`).
- Expect: `data_findings` (markdown).
- **Sanity Checks** (`sanity`) → subagent `analyze-a-dataset-sanity`
- Hand it: only the `sanity` value from the JSON of SPLIT (`splitter`).
- Expect: `data_findings` (markdown).
… 37 more lines in the kitOr let Claude adapt it
Add Skill Graph to Claude Code as a connector, then ask. Claude loads this starter, changes it for your project, checks it and hands you the kit.
Set up the connectorAsk Claude
Use Skill Graph: get the analyze-a-dataset template, adapt it to this project, validate it until it has no errors, and compile it for Claude Code.The graph file
The whole workflow is one Markdown file, graph.skill.md: the steps and edges in the frontmatter, one prompt per step below it. The guide explains every field.
graph.skill.md · 154 lines
---
name: analyze-a-dataset
description: "Analyzes a CSV or table: profiling, cleaning rules, answers and sanity checks run in parallel, every figure is re-checked in a fresh context, then a data report."
spec: skill-graph/1
topology:
nodes:
- id: goal
type: input
label: DATA FILE + QUESTIONS
- id: splitter
type: orchestrator
label: SPLIT
model: sonnet
tools:
- Read
- id: profile
type: worker
label: Profile
model: haiku
tools:
- Read
- Grep
- Glob
- Bash
- id: cleaning
type: worker
label: Cleaning Rules
model: haiku
tools:
- Read
- Grep
- Glob
- Bash
- id: analysis
type: worker
label: Analysis
model: haiku
tools:
- Read
- Grep
- Glob
- Bash
- id: sanity
type: worker
label: Sanity Checks
model: haiku
tools:
- Read
- Grep
- Glob
- Bash
- id: verifier
type: verifier
label: VERIFIER (Fresh Context)
isolated_context: true
model: opus
tools:
- Read
- Grep
- Glob
gate: Every kept figure says how it was computed and matches the data on a spot check.
on_fail: retry
max_retries: 1
- id: merger
type: synthesizer
label: FINAL ANSWER
model: sonnet
tools:
- Read
edges:
- from: goal
to: splitter
- from: splitter
to:
- profile
- cleaning
- analysis
- sanity
contract: subtask_json
- from:
- profile
- cleaning
- analysis
- sanity
to: verifier
contract: data_findings
- from: verifier
to: merger
contract: checked_figures
contracts:
subtask_json:
format: json
description: One key per worker id; each value is that worker's task.
data_findings:
format: markdown
description: A numbered list; every figure has how it was computed and a confidence of high, medium or low.
checked_figures:
format: markdown
description: Only the figures that matched the data on a spot check, then the rejected ones with the reason.
---
# Node Prompts & Edge Contracts
## @node: splitter
You are the analysis lead. Read the file path and the questions, and give each analyst their part of the work on that file.
Input:
{{goal}}
Output strictly as JSON with one key per worker: `profile`, `cleaning`, `analysis`, `sanity`. Each value is the exact task for that worker.
## @node: profile
Profile ONLY the data: columns, types, row count, missing values, duplicates and outliers. Compute every figure; never estimate it.
Your task: {{splitter.profile}}
Return findings as a numbered list. For each one give the figure, how you got it (the command, formula or rows it rests on) and a confidence of high, medium or low. Never change the data file.
## @node: cleaning
Propose ONLY cleaning rules: how to fix types, missing values, duplicates and bad rows, with how many rows each rule touches.
Your task: {{splitter.cleaning}}
Return findings as a numbered list. For each one give the figure, how you got it (the command, formula or rows it rests on) and a confidence of high, medium or low. Never change the data file.
## @node: analysis
Answer ONLY the questions in the task with the data: each figure, and the command or formula that produced it.
Your task: {{splitter.analysis}}
Return findings as a numbered list. For each one give the figure, how you got it (the command, formula or rows it rests on) and a confidence of high, medium or low. Never change the data file.
## @node: sanity
Check ONLY whether the data can be trusted: totals that should add up, impossible values, and gaps in time or coverage.
Your task: {{splitter.sanity}}
Return findings as a numbered list. For each one give the figure, how you got it (the command, formula or rows it rests on) and a confidence of high, medium or low. Never change the data file.
## @node: verifier
You are a data reviewer. Spot-check each figure against the file itself; reject figures you cannot trace back to the data.
You only see the raw worker outputs below, not their reasoning. Drop any claim without concrete evidence, merge duplicates, and mark what you rejected and why.
Original input: {{goal}}
Worker outputs:
{{workers.output}}
## @node: merger
Write the data report: the answers with their figures, the cleaning steps to apply in order, and the caveats a reader must know.
{{verifier.output}}
More starter graphs
- PR reviewSecurity, performance, architecture and test coverage reviewers
- Bug triageStack trace, logs, recent commits and a minimal repro
- RFC discoveryFeasibility, prior art, interface design and failure modes
- Ship a changeEdit until tests pass, review the diff in parallel, approve once before the PR
- Review each fileOne fresh-context review per changed file, however many there are, then merge and gate
- Parallel auditResearch, compare, check and find gaps, then verify in a fresh context
- Research reportSources, figures, counterpoints and open questions, fact-checked in a fresh context
- Write an articleAngle, outline, facts and reader in parallel, then an editor check before the draft
- Design an appUsers, features, screens and data model in parallel, then a product review before the spec