MaveraMavera Docs
Insight Miner
Checking…
Use or share this pageSend the page itself, print it, or open its complete context in your AI workspace.

Mining insights

Transcript → code-computed charts + steering signals.

2 min readDocs build Updated Jul 26, 2026

Endpoint: POST /api/v1/tools/mine_insights. Pure + deterministic by default (0 credits); the LLM layer (useLlm:true) runs the smallest model (Haiku) and meters a few credits.

What goes in

FieldTypeWhat it does
turns (required)arrayThe transcript: [{ speaker, text }]. Comes straight from a focus group, chat, debate, etc.
maxSignalsintegerCap on steering signals returned (default 2) — keeps it to the strongest.
minStrengthnumber 0–1Drop signals weaker than this (default ~0.5).
useLlmbooleanAdd the smallest-model analysis layer (subtext the keyword scan misses).
llmModemine·identify·findWhich question the LLM layer answers (below).
topicstringFocus hint for the LLM layer.
POST /api/v1/tools/mine_insights
{ "turns": [
    { "speaker": "Jamie", "text": "At $29 I'd switch today." },
    { "speaker": "Riley", "text": "For my 12-person team that price worries me — cheap won't scale." },
    { "speaker": "Sam",   "text": "I got burned at tax season once. I need to trust the numbers." }
  ],
  "maxSignals": 3, "minStrength": 0.4 }

What comes back — two layers, clearly separated

1. Charts (code-computed, basis: "code-computed-from-transcript")

kindShowsHow it's computed
share_bar (theme convergence)Share of speakers who raised each theme.Theme detection over the text, counted across participants.
diverging_bar (polarization)For-vs-against split on contested themes.Stance scoring per speaker per theme.
sentiment_arcSentiment trajectory across the conversation.Per-turn sentiment, ordered.
theme_distributionHow themes spread across the panel.Theme frequency distribution.
"charts": [
  { "kind": "share_bar", "title": "Theme convergence",
    "series": [ {"label":"Price","value":0.67}, {"label":"Trust","value":0.33}, {"label":"Scale","value":0.33} ],
    "computedFrom": "3 speakers, 3 turns" }
]

Charts are never drawn from model-invented numbers. The model may caption or theme, but the values come from counting/scoring the real transcript. That's the bright line.

2. Steering signals (rate-limited, ranked by strength)

kindMeaning
steerThe single highest-value follow-up question to ask next.
contradictionA speaker contradicted themselves — worth probing.
divergenceA genuine split in the room. Carries a ready-to-run branchPrompt you can hand to /api/v1/insights/branch.
branchAn explicit suggestion to fork a sub-conversation.
"signals": [
  { "kind": "divergence", "strength": 0.82,
    "summary": "Price reads as 'great value' to Jamie but 'won't scale' to Riley — opposite meanings of the same $29.",
    "branchPrompt": "Riley, you said $29 feels too cheap to scale — what price would actually signal it's built for a team your size?" }
]

The LLM layer — useLlm: true with three modes

The code miner is fast and deterministic but keyword-bounded. Flip useLlm:true and the smallest model reads the transcript for what a scan can't see. The output is returned under llm with basis: "model-analyzed" — kept strictly separate from the code charts.

llmMode: "mine" — deeper signals (subtext)

Surfaces implied objections, unprobed threads, and emotional undercurrents.

{ "useLlm": true, "llmMode": "mine", "topic": "$29 finance app" }
# → llm.signals: [
#   { kind:"steer", text:"Sam's tax-season burn is an unprobed trust wound — ask what evidence would rebuild it." } ]

llmMode: "identify" — where opinions diverge NOW

Maps the real fault lines present in this transcript, with a targeted probe per split.

{ "useLlm": true, "llmMode": "identify" }
# → llm.signals: [
#   { kind:"divergence", text:"Jamie optimizes price, Riley optimizes scale-fit, Sam optimizes trust — three different value hierarchies." } ]

llmMode: "find" — what would FLIP an opinion (hypotheses)

Generates counterfactual conditions to test. Stamped hypothesized: true — these are hypotheses to verify, not facts.

{ "useLlm": true, "llmMode": "find" }
# → llm: { basis:"model-analyzed", mode:"find", hypothesized:true, signals:[
#   { kind:"condition", text:"If there were a $99 team tier with SLAs, would Riley's 'won't scale' objection disappear?" } ] }

A find result is a question for the world, not an answer. The natural next step is to test it live: feed it to the flip-test loop, which branches the conversation, introduces the condition, and measures whether the opinion actually moved. See Branching & flip-tests.

The full loop: converse → mine → branch → verify

# 1. Run a focus group (or chat) → grab data.transcript
POST /api/v1/tools/focus_group { "audienceId":"aud_f1_1", "topic":"$29 finance app", "stimulus":"...", "panelSize":5, "rounds":2 }

# 2. Mine it for divergences (code + LLM "identify")
POST /api/v1/tools/mine_insights { "turns":[...transcript...], "useLlm":true, "llmMode":"identify" }
#    → a divergence signal with a branchPrompt

# 3. Explore that split live
POST /api/v1/insights/branch { "audienceId":"aud_f1_1", "branchPrompt":"<from step 2>", "depth":2 }

# 4. Or hypothesize + verify a flip-condition end to end
POST /api/v1/insights/flip-test { "audienceId":"aud_f1_1", "turns":[...], "topic":"price vs scale" }
#    → verdict: flipped | softened | unchanged | hardened (MEASURED from real stance text)

Why two layers instead of one

The code layer gives you defensible numbers (you can show a client the chart and explain exactly how it was computed). The LLM layer gives you interpretation and direction (what to ask next, what might change minds). Keeping them separate — with explicit basis labels — means you always know which is which, and you never accidentally present a model's guess as a measured result.

On this page