| name | analyst |
| description | Use when researching a question that serves a decision, running market/competitive/internal research, verifying AI-generated research, or aggregating multi-model consensus on contested claims |
| triggers | ["research this / look into / find out about (with a decision at stake)","market research / competitive analysis / landscape scan","start a research mission / brief the analyst","verify these findings / fact-check this research","consensus across models / wisdom of the crowd","three-question gate / is this research trustworthy"] |
| read_strategy | On first use: read Quick Start + The Workflow.
When briefing/interviewing: read Workflow steps 1-3.
When fanning out runs: read Workflow steps 4-5 (parallel runs, findings).
When aggregating/verifying: read Workflow steps 6-7 (consensus, fresh-thread verification).
When delivering: read Workflow steps 8-9 (gate, deliverable formats).
Full command reference / data model: read those sections on demand.
|
Analyst โ the research analyst you always wanted
Use this skill to run research the way an executive briefs an analyst, not the way
people query a search engine. Every mission is framed by a decision, constrained
by time horizon / source policy / exclusions, and executed by commissioning the
research engines declared in engines.yaml: the analyst frames
the questions, dispatches them to an engine, reads the reports back in the
decision's context, aggregates consensus, verifies in a fresh thread, and
passes everything through the three-question gate before it touches a decision.
Division of labour (explicit, configured): the analyst does NOT discover or
ingest โ the engines do. engines.yaml is the analystโengine contract; the
dispatch command validates against it, and its output echoes the engine's
invoke/ingest instructions. The analyst owns what no engine does: decision
framing, question setting, claim-level consensus and verification bookkeeping,
and the operator's sign-off gate โ feeding decisions managed by the personal
assistant suite (advisor, career, ops, surfaced by chief-of-staff).
Key principle: the script stores and queries; Claude does the sensemaking
(interviewing, question-framing, reading reports, matching claims across
engines, verifying, synthesizing).
This skill operationalizes the repo's operating principles:
primer notes (speak, don't type), interview-first, plan/execute split, explicit
โธ OPERATOR CHECKPOINT moments, wisdom-of-the-crowd, and the three-question gate.
Routing โ when to use the analyst vs. an engine directly
| The ask | Route |
|---|
| Research that informs a decision in flight (advisor/career/ops) | analyst mission โ it commissions engines and books the evidence |
| "Compare tools / evaluate X / survey a tech space" with no decision record needed | tech-recon directly |
| "What does the literature say about X" standalone | scientific-literature directly |
| Quick one-off web question | /deep-research skill or an ad-hoc thread |
If a mission's question is technology-shaped, the analyst still doesn't do the
work โ it dispatches to tech-recon and reads the investigation back. Run
analyst.py list-engines for the live contract.
Quick Start
Prerequisites
- TypeDB running with the
alh_personal database (provisioned by this skill's
SessionStart hook when installed as a plugin)
uv available; run commands from the skill directory or with --project
Environment Variables
TYPEDB_HOST: TypeDB server (default: localhost)
TYPEDB_PORT: TypeDB port (default: 1729)
TYPEDB_DATABASE: Database name (default: alh_personal)
Essential Commands
uv run python skills/analyst/analyst.py create-mission \
--name "EU battery market entry" \
--decision-context "Whether to open an EU manufacturing line in 2027" \
--time-horizon "2026-2029" --priority high \
--primer "Voice-dictated brain dump, unedited..."
uv run python skills/analyst/analyst.py add-run --mission mission-abc123 --model "claude-opus"
uv run python skills/analyst/analyst.py add-finding --run run-def456 \
--claim "EU battery demand grows ~30% CAGR through 2028" --confidence high
uv run python skills/analyst/analyst.py record-consensus \
--findings finding-a1 finding-b2 finding-c3 --agree 3
uv run python skills/analyst/analyst.py list-findings --divergent
uv run python skills/analyst/analyst.py report-mission --id mission-abc123
Command Output Pattern
uv run emits a VIRTUAL_ENV warning to stderr. Always use 2>/dev/null when
piping output to a JSON parser -- never 2>&1, which merges the warning into
stdout and breaks JSON parsing.
The Workflow
Everything between checkpoints is agent work. The operator steps in only at the
โธ OPERATOR CHECKPOINT moments.
1. Brief โ capture the primer โธ OPERATOR CHECKPOINT
Ask the operator for their messy, unstructured brain dump (voice dictation is
ideal): what decision is at stake, what they already believe, hunches, constraints,
politics, prior attempts. Do NOT ask them to structure it โ you structure it.
analyst.py create-mission --name "..." --decision-context "..." --primer "<verbatim dump>"
A mission without --decision-context triggers a warning: research without a
decision in mind is a search-engine query, not an analyst brief.
2. Interview โ surface unknown-unknowns โธ OPERATOR CHECKPOINT
Before planning, interview the operator like a senior analyst taking a brief:
- What decision will this research change, and when is it made?
- Time horizon? Which sources count (and which are banned)? What is out of scope?
- What assumptions are you already making? What would change your mind?
- What haven't you considered? What context should you give me that I can't find?
Record the full Q&A: analyst.py add-interview --mission <id> --content-file qa.md,
then analyst.py update-mission --id <id> --status planning.
3. Plan โ separate planning from execution โธ OPERATOR CHECKPOINT (approve plan)
Draft the research plan: questions to answer, source strategy, how many parallel
runs (minimum 3), what a "finding" looks like, success criteria. Present it to the
operator; iterate until approved. Only then execute.
analyst.py add-plan --mission <id> --content-file plan.md
analyst.py update-mission --id <id> --status running
4. Frame the questions โธ OPERATOR CHECKPOINT (approve questions)
Decompose the plan into discrete, decision-linked research questions. A good
question names what the decision needs to know, not a topic:
analyst.py add-question --mission <id> --text "What is TypeDB's production adoption vs Neo4j in 2025-2026?"
analyst.py add-question --mission <id> --text "What are the licensing/cost implications at our scale?"
analyst.py list-questions --mission <id>
analyst.py update-question --id <question-id> --status approved
The operator approves the question set before anything is dispatched.
5. Dispatch to the research engines
Route each approved question to the engine that owns its shape โ the engines and
their invoke/ingest contracts are declared in engines.yaml
(list-engines to inspect):
| Question shape | Engine |
|---|
| General / market / org web research | deep-research (the Claude skill: fan-out search, adversarial verification, cited report) |
| Technology comparison / evaluation / survey / monitoring | tech-recon (in alh_deep_research) |
| Academic literature | scientific-literature (in alh_deep_research) |
| Tiny lookup no engine covers | ad-hoc (the exception, not the rule) |
analyst.py dispatch --mission <id> --engine tech-recon --questions q-1 q-2
Then commission the engine exactly as the dispatch output says (e.g. invoke
the /deep-research skill with the question as its brief, or
tech_recon.py start-investigation with goal + success criteria from the
mission's decision context). For independent multi-engine consensus on a
load-bearing question, dispatch the SAME question to more than one engine.
6. Ingest the reports and extract findings in decision context
When an engine finishes, capture its report verbatim and close out the dispatch:
analyst.py ingest-report --run <run-id> --content-file /tmp/report.md \
--external-ref "investigation-abc123"
Now read the report against the mission's decision-context โ not as a
summary exercise. Extract only the claims that bear on the decision, one
add-finding per claim, sourced from the report and the citations inside it:
analyst.py add-finding --run <run-id> --claim "..." --confidence high --content "what the report says + where"
analyst.py link-source --finding <finding-id> --url "https://..." --kind academic --reliability high
Then analyst.py update-mission --id <id> --status aggregating.
7. Consensus aggregation
You (the agent) match claims across engine reports semantically โ the script just stores your
groupings. For each claim group, call record-consensus with all the finding ids
that assert the same claim and how many runs agree:
analyst.py record-consensus --findings f-a1 f-b2 f-c3 --agree 3
analyst.py record-consensus --findings f-a9 --agree 1
Interpretation:
- 100% consensus โ likely factual โ still verify the load-bearing ones.
- Single-thread claims are marked divergent โ investigate or re-research them
(a targeted follow-up dispatch) before they appear in any deliverable.
Write the cross-run synthesis as a synthesis note (--type is implicit in the
command): store it via a deliverable draft or attach with the notebook's note
tooling; the consensus narrative belongs in the mission record. Then
update-mission --status verifying.
8. Verification โ in a FRESH thread
AI verifies better than it generates, but never in the thread that generated the
claims (it will defend its own work). Open a fresh session/subagent with no
generation context, hand it only the claims + sources, and ask it to confirm,
refute, or flag each:
analyst.py list-findings --mission <id> --unverified
analyst.py verify-finding --finding <id> --status confirmed --content "checked against primary source X"
analyst.py verify-finding --finding <id> --status refuted --content "source does not say this"
Refuted findings never reach the deliverable. needs-work findings go back to
step 7 (re-research).
9. Three-question gate โธ OPERATOR CHECKPOINT
Before acting on or delivering ANY research, the operator answers the gate:
- Is this grounded in real sources, or is it pattern-matching?
- What's missing that I didn't think to ask?
- Would I put my name on this?
analyst.py record-gate --mission <id> \
--grounded "All load-bearing claims verified against primary sources" \
--missing "No pricing data from APAC competitors - flagged as open question" \
--name-on-it "Yes, with the APAC caveat stated" \
--passed
A passing gate moves the mission to gated. A failing gate (--failed) leaves
status unchanged โ go back to the step the answers point at.
10. Deliverable โธ OPERATOR CHECKPOINT (choose format)
Don't default to a wall of text. Ask what would actually get used:
| Format | When |
|---|
brief | Operator wants a tight written summary |
dashboard | Ongoing decision โ numbers that update |
infographic | Sharing with others; one-glance story |
interactive-page | Exploration โ let the operator drill in |
audio-summary | Operator consumes on the move |
analyst.py add-deliverable --mission <id> --name "EU entry brief" --format infographic --uri "path/or/url"
analyst.py update-mission --id <id> --status delivered
Command Reference
All commands: uv run python skills/analyst/analyst.py <command> --flags.
JSON to stdout (except report-mission, which prints Markdown).
| Command | Purpose | Key flags |
|---|
create-mission | Open a research mission | --name (req), --decision-context, --primer, --time-horizon, --source-policy, --exclusions, --priority, --deadline, --decision-ref |
add-interview | Store operator interview note | --mission (req), --content/--content-file |
add-plan | Store approved plan note | --mission (req), --content/--content-file |
update-mission | Update status/framing | --id (req), --status, --priority, --decision-context, --time-horizon, --source-policy, --exclusions, --deadline, --decision-ref |
list-missions | List missions + rollups | --status |
show-mission | Full detail (runs, findings, gate, deliverables) | --id (req) |
add-run | Register a research thread | --mission (req), --model (req) |
list-engines | The declared engine contract (engines.yaml) | |
add-question | Frame a decision-linked research question | --mission (req), --text (req), --status |
list-questions | Questions with status + answering dispatches | --mission (req) |
update-question | Approve / edit a question | --id (req), --status, --text |
dispatch | Send questions to an engine; echoes its invoke/ingest contract | --mission, --engine (req), --questions, --external-ref |
ingest-report | Capture engine report verbatim, close the dispatch | --run (req), --content/-file, --external-ref, --url |
complete-run | Finish a run | --run (req), --status completed|failed |
add-finding | One discrete claim from a run | --run (req), --claim (req), --confidence, --content |
link-source | Evidence for a finding | --finding (req), --url/--source, --name, --kind, --reliability |
list-findings | Query findings | --mission, --divergent, --unverified |
record-consensus | Store one claim group | --findings id... (req), --agree N, --divergent/--not-divergent |
verify-finding | Fresh-thread verification | --finding (req), --status confirmed|refuted|needs-work (req), --content |
record-gate | Three answers + pass/fail | --mission (req), --grounded, --missing, --name-on-it (all req), --passed/--failed (req) |
add-deliverable | Attach output | --mission (req), --name (req), --format (req), --content/--content-file, --uri |
report-mission | Markdown mission report | --id (req) |
audit | Run quality-checks.yaml | --severity |
Data Model
Namespace anlst-, subtypes of the alh-* core types. IDs are <type>-<hash12>.
Notes attach to subjects via alh-aboutness.
Entities
| Type | Sub | Key attributes |
|---|
anlst-mission | alh-domain-thing | anlst-decision-context, anlst-time-horizon, anlst-source-policy, anlst-exclusions, anlst-mission-status, anlst-priority-level, anlst-deadline, anlst-decision-ref (soft ref to an advisor decision) |
anlst-question | Decision-linked research question commissioned to an engine (anlst-question-text, anlst-question-status) | |
anlst-run | alh-domain-thing | anlst-model-name, anlst-run-status, anlst-started-at, anlst-completed-at |
anlst-finding | alh-fragment | anlst-claim, anlst-confidence-level, anlst-consensus-count, anlst-divergent, anlst-verification-status |
anlst-source | alh-artifact | anlst-source-url, anlst-source-kind, anlst-reliability |
anlst-deliverable | alh-artifact | anlst-deliverable-format |
Notes (all sub alh-note, attached via alh-aboutness)
| Type | Holds |
|---|
anlst-primer-note | Operator's messy initial brain dump |
anlst-interview-note | The agent-interviews-operator Q&A |
anlst-plan-note | The approved research plan |
anlst-verification-note | Fresh-thread verification rationale (about a finding) |
anlst-gate-note | anlst-gate-grounded, anlst-gate-missing, anlst-gate-name-on-it, anlst-gate-passed |
anlst-synthesis-note | Cross-run consensus narrative |
Relations
| Relation | Roles |
|---|
anlst-mission-run | mission, run |
anlst-run-yielded | run, finding |
anlst-finding-source | finding, source |
anlst-mission-deliverable | mission, deliverable |
Status values
- Mission:
briefing โ planning โ running โ aggregating โ verifying โ gated โ delivered
- Run:
running | completed | failed
- Verification:
unverified | confirmed | refuted | needs-work
- Deliverable format:
brief | dashboard | infographic | interactive-page | audio-summary
Quality checklist
Before calling a mission done, confirm (or just run analyst.py audit):
Common Mistakes
- Asking like a search engine instead of briefing an analyst. "What's the EU
battery market like?" is a query. A brief has a decision, a time horizon, a
source policy, and exclusions. If the operator gives you a query, interview
them until it becomes a brief.
- Trusting one thread. A single run's output is one sample, not an answer.
Always fan out 3+ independent runs and aggregate. A confident single-thread
claim is exactly the thing most likely to be confabulated.
- Verifying in the same thread that generated. The generating thread will
rationalize its own claims. Verification gets a fresh session with no
generation context โ claims and sources only.
- Skipping the gate. "Looks good" is not a gate. The three questions are
answered explicitly and stored (
record-gate); delivered without a gate note
is an audit violation.