{
  "type": "object",
  "properties": {
    "queryId": {
      "type": "string",
      "description": "Server-side ID of this council query. With async=true, pass it to council_result."
    },
    "status": {
      "type": "string",
      "enum": [
        "running",
        "complete",
        "failed"
      ],
      "description": "Only present on async queries: \"running\" means poll council_result with the queryId."
    },
    "synthesis": {
      "type": "string",
      "description": "Moderator-synthesized consensus answer across all models. Empty when synthesize=false; absent while an async query is still running."
    },
    "consensusScore": {
      "type": [
        "number",
        "null"
      ],
      "description": "Cross-model agreement score on the 0-100 scale. Null when synthesize=false; absent while an async query is still running."
    },
    "agreementType": {
      "anyOf": [
        {
          "type": "string",
          "enum": [
            "high",
            "divergent"
          ]
        },
        {
          "type": "null"
        }
      ],
      "description": "Agreement classification from the moderator's analysis. Null when synthesize=false."
    },
    "keyDisagreement": {
      "type": [
        "string",
        "null"
      ],
      "description": "The main point the models disagreed on, when one was identified. Often more decision-relevant than the consensus itself \u2014 inspect it before acting on a low consensusScore. Null on high agreement or when synthesize=false."
    },
    "perModelResponses": {
      "type": "object",
      "additionalProperties": {
        "type": "string"
      },
      "description": "Each model's independent response, keyed by model name. Absent while an async query is still running."
    },
    "modelMapping": {
      "type": "object",
      "additionalProperties": {
        "type": "string"
      },
      "description": "Anonymous reviewer label (M1..Mn) to model name mapping used during synthesis."
    },
    "totalTokens": {
      "type": "object",
      "properties": {
        "input": {
          "type": "number",
          "description": "Prompt tokens across all council models."
        },
        "output": {
          "type": "number",
          "description": "Completion tokens across all council models."
        }
      },
      "required": [
        "input",
        "output"
      ],
      "additionalProperties": false,
      "description": "Aggregate token usage for this query across the whole council."
    },
    "durationMs": {
      "type": "number",
      "description": "Wall-clock duration of the council run (fan-out + synthesis), in milliseconds."
    },
    "budgetPercentUsed": {
      "type": [
        "number",
        "null"
      ],
      "description": "The user's monthly Council budget consumption after this query, as a percentage (0-100+). Use it to decide whether another query is affordable. Council never reports budget in dollar amounts \u2014 always reason and communicate in percentages."
    },
    "errors": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "modelId": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "modelId",
          "message"
        ],
        "additionalProperties": false
      },
      "description": "Per-model failures, if any. The synthesis covers the models that responded."
    },
    "droppedModelIds": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Requested model IDs that were skipped (unknown or retired). Call council_models for current IDs."
    },
    "timedOutModelIds": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Council members that failed by exceeding the per-model timeout. On a synchronous run (90s per model) this is recoverable: re-run the same query with async=true, which allows 300s. Slow reasoning models will time out on EVERY synchronous call."
    },
    "wasSyncRun": {
      "type": "boolean",
      "description": "True when this ran synchronously \u2014 the path with the tight per-model timeout."
    },
    "consensusUnavailable": {
      "type": "boolean",
      "description": "True when the moderator's agreement verdict could not be parsed, so this run has no consensus score at all. Do not substitute a number \u2014 report agreement as unknown."
    },
    "synthesisError": {
      "type": [
        "string",
        "null"
      ],
      "description": "Set when moderator synthesis failed and the response degraded to raw per-model output."
    }
  },
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}