{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://parlane.ai/spec/action.schema.json",
  "title": "Action Request",
  "description": "The POST /action request body (REST fallback) or the equivalent MCP tool call. Fired when the user activates an interactive component carrying an action envelope. The root of this file validates the REQUEST; $defs.actionEnvelope and $defs.actionResponse describe the in-document envelope and the response shape. See docs/06-integration-kit.md §4 and §5.",
  "allOf": [{ "$ref": "#/$defs/actionRequest" }],

  "$defs": {
    "actionRequest": {
      "type": "object",
      "additionalProperties": false,
      "required": ["action_id", "tool"],
      "description": "Body of POST /action. The client resolves the component's action envelope plus any bound input values into this request.",
      "properties": {
        "action_id": {
          "type": "string",
          "minLength": 1,
          "description": "Client-generated correlation id for this invocation (idempotency + logging)."
        },
        "tool": {
          "type": "string",
          "minLength": 1,
          "description": "Backend tool name to invoke (copied from the action envelope's `tool`)."
        },
        "params": {
          "type": "object",
          "description": "Merged parameters: the envelope's static `params` overlaid with current values of bound input/toggle/slider/select components (keyed by their `bind`)."
        },
        "dashboard_id": {
          "type": "string",
          "description": "Optional id of the dashboard the action was fired from (context for the server; also the default refresh target)."
        }
      }
    },

    "actionEnvelope": {
      "type": "object",
      "additionalProperties": false,
      "required": ["tool"],
      "description": "The action envelope embedded on interactive components inside a UI document. Mirrors ui-document.schema.json#/$defs/action; kept in sync with it.",
      "properties": {
        "tool": {
          "type": "string",
          "minLength": 1,
          "description": "Backend tool name to invoke."
        },
        "params": {
          "type": "object",
          "description": "Static parameters merged with bound component values at invocation time."
        },
        "confirm": {
          "description": "If truthy, prompt before invoking. A string is the confirmation message; true uses a generic prompt.",
          "oneOf": [
            { "type": "boolean" },
            { "type": "string", "minLength": 1 }
          ]
        },
        "refresh": {
          "type": "string",
          "default": "self",
          "description": "Post-ack refresh target. Reserved: \"self\" (re-fetch current dashboard), \"none\" (do nothing); any other value is a dashboard id."
        }
      }
    },

    "actionResponse": {
      "type": "object",
      "additionalProperties": false,
      "description": "Response to POST /action (or the MCP tool result). Exactly one of `ui` (full-replace document, D13 — no patch format) or `ack` should be meaningful. If `ui` is present the client replaces the current document; otherwise it honors the envelope's `refresh`.",
      "properties": {
        "ui": {
          "$ref": "https://parlane.ai/spec/ui-document.schema.json",
          "description": "A full replacement UI document. Supersedes the current document entirely (renderer diffs by id)."
        },
        "ack": {
          "type": "boolean",
          "description": "True to acknowledge success with no UI change; the client then applies the envelope's `refresh`."
        },
        "error": {
          "type": "object",
          "additionalProperties": false,
          "required": ["message"],
          "description": "Present when the tool failed; the client surfaces it non-fatally.",
          "properties": {
            "code": { "type": "string", "description": "Machine-readable error code." },
            "message": { "type": "string", "description": "Human-readable error message." }
          }
        }
      }
    }
  }
}
