Reason8

reason8_ask

Overview

reason8_ask runs a fast, synchronous persona-panel reaction over a single artifact and returns the verdict in one round. Hand it a decision, a piece of copy, a PR summary, or a UI screenshot with a goal, and it answers in ~18–30s — no run_id, no polling.

Use it when you want an immediate read before you ship. For multi-method, human-in-the-loop deep research, use the async reason8_research_* track instead.

Contract. This page documents reason8_ask as the contract the MCP implementation matches. The response shapes are frozen by backend/src/backend/personas/contract.py (PanelResponse). Field names below are sourced field-for-field from that module.

Parameters

FieldTypeRequiredDescription
artifactobjectyesThe thing under review: content (the text, copy, plan, or PR summary) plus a goal (the decision this reaction must inform).
artifact.contentstringyesThe actual content to react to. Paste it — not a pointer to it.
artifact.goalstringyesThe decision this reaction informs (e.g. "decide whether this onboarding copy lands with first-time admins").
artifact.artifact_type"text" | "ui_image"noDefaults to "text". Set "ui_image" to react to a design.
artifact.image_b64stringnoBase64-encoded image, required when artifact_type is "ui_image".
audiencestringyesFree-text description of who the artifact is for (e.g. "mid-market ops leads evaluating procurement"). Auto-routes to a grounded persona set if one matches; otherwise the panel runs ungrounded.
grounding"auto" | "ungrounded" | "grounded"noThe grounding axis. Default "auto" — uses a matching grounded set when one exists, else ungrounded. "grounded" requires a matching set; "ungrounded" skips real evidence entirely.

The account is resolved from your API key — there is no account parameter. A request made without a key (or without a grounded set for the audience) reacts ungrounded only. There is no depth knob: reason8_ask is the fast, one-round path. Multi-round "thorough" research is the reason8_research_* workflow.

Behavior

reason8_ask is synchronous and returns a PanelResponse in a single round (~18–30s). Because the call can run longer than a default MCP client tool-timeout, the tool emits streaming progress while it works so compatible clients do not time out — treat any progress events as informational and wait for the final PanelResponse.

Two honesty distinctions run through every response, conveyed as labels (and an optional Material-Symbols icon), never by color alone:

  • Verified vs Inferred — the verified object carries only math and counts; the inferred object carries only prose and labels. They are kept structurally separate so a counted fact is never confused with a judgment.
  • supported vs speculative — a reaction's verified.is_speculative flag marks a persona that was grounded-but-thin, so the firewall surfaces it rather than presenting a thin read as solid.

Returns

reason8_ask returns a PanelResponse: a list of per-persona reactions plus a synthesis. Values below are illustrative; the shape is the contract.

{
  "reactions": [
    {
      "persona_id": "p_2",
      "persona_card": "Mid-market ops lead, evaluated three tools this quarter",
      "verified": {
        "evidence_count": 4,
        "coverage_score": 0.62,
        "grounding_refs": ["review#34", "ticket#12"],
        "is_speculative": false
      },
      "inferred": {
        "why": "Reads the pricing as per-seat and stalls on procurement approval.",
        "leaning": "edit",
        "trust_signal": "skeptical until ROI is explicit",
        "act_signal": "would forward to finance, not sign today",
        "what_id_do_next": "look for a usage-based tier"
      }
    }
  ],
  "synthesis": {
    "effective_n": 4.0,
    "reaction_summary": "3 of 5 stall at pricing clarity",
    "leaning": "edit",
    "why": "The value lands but the pricing model blocks self-serve.",
    "gaps": ["no signal from enterprise buyers"],
    "grounding": "grounded",
    "grounding_fell_back": false,
    "grounding_used": { "set_id": "set_abc", "name": "Ops buyers", "match_confidence": 0.81 },
    "alternatives": [{ "set_id": "set_def", "name": "Founders", "match_confidence": 0.55 }],
    "evidence_version": 7
  }
}

reactions[] — one entry per persona. Each entry holds:

  • verified (math / counts only): evidence_count (int), coverage_score (float | null), grounding_refs (string list of the evidence this reaction leaned on), is_speculative (bool — true means grounded-but-thin, flagged by the firewall).
  • inferred (prose / labels only): why, leaning ("ship" | "edit" | "rewrite"), trust_signal, act_signal, what_id_do_next.

synthesis — the panel-level read:

  • Verified side: effective_n (float) and reaction_summary.
  • Inferred side: leaning ("ship" | "edit" | "rewrite"), why, gaps (string list of what the evidence did not cover).
  • Routing / grounding metadata: grounding (which axis ran), grounding_fell_back (bool — true if a grounded request degraded to ungrounded), grounding_used (the set that was matched, or null), alternatives (other sets that could match), evidence_version (int | null — the grounding snapshot the read used).

The leaning enum is the machine-actionable verdict: ship, edit, or rewrite.

curl

curl -X POST https://api.reason8.io/mcp/tools/reason8_ask \
  -H "Authorization: Bearer $REASON8_MCP_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "artifact": {
      "content": "Onboarding copy: <paste here>",
      "goal": "Decide whether this lands with first-time admins",
      "artifact_type": "text"
    },
    "audience": "Mid-market ops leads evaluating procurement",
    "grounding": "auto"
  }'

TypeScript (via MCP SDK)

const result = await client.callTool({
  name: "reason8_ask",
  arguments: {
    artifact: {
      content: "...",
      goal: "Decide whether this lands with first-time admins",
      artifact_type: "text",
    },
    audience: "Mid-market ops leads evaluating procurement",
    grounding: "auto",
  },
});

For how grounding routing, the provenance ladder, and persona status work, see Grounding.