{
  "openapi": "3.1.1",
  "info": {
    "title": "AgentPrism HTTP API",
    "description": "The control plane AgentPrism maps into an ASP.NET Core application. Every path below is relative to the prefix passed to MapAgentPrism, which is '/agentprism' in this document. The AgentPrism packages do not generate this document themselves; it is produced by calling AddOpenApi in the host application, so the title, the version, and the server list in YOUR document come from YOUR application.",
    "version": "v1"
  },
  "servers": [
    {
      "url": "http://localhost:5081",
      "description": "The address the `dotnet new agentprism-api` template listens on by default."
    }
  ],
  "paths": {
    "/agentprism/api/meta": {
      "get": {
        "tags": [
          "AgentPrism",
          "Meta"
        ],
        "summary": "Reports the AgentPrism version, authentication method, active stores, and role authorizations.",
        "description": "Requires no authentication. Contains no secret, tenant data, or agent information.",
        "operationId": "AgentPrismMeta",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentPrismMetaResponse"
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/agentprism/api/agents": {
      "get": {
        "tags": [
          "AgentPrism",
          "Agents"
        ],
        "summary": "Lists all agents defined in code and in the database.",
        "description": "The list merges every registered agent source into a single view, ordered by name. When two sources hold the same name, the source with the higher priority wins and the other one is dropped from the list — code definitions win over database definitions. The response is not paged; the number of agents is bounded by the control plane, not by traffic. Each entry carries the origin, so a client can tell an editable definition from a code-defined one.",
        "operationId": "AgentPrismListAgents",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AgentDescriptor"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "AgentsRead"
      },
      "post": {
        "tags": [
          "AgentPrism",
          "Agents"
        ],
        "summary": "Creates a new agent definition.",
        "description": "The definition is fully validated before it is stored: the model binding, every tool, skill, and callable agent must already exist, and the call graph must be free of cycles. A failed check returns 400 and nothing is written. A name that another definition already uses returns 409; a name that a code-defined agent already uses also returns 409, because code wins name conflicts and the stored definition would never resolve. On success the response is 201 with the saved definition at version 1 and a Location header pointing at it.",
        "operationId": "AgentPrismCreateAgent",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentDefinitionRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentDefinition"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "AgentsAdmin"
      }
    },
    "/agentprism/api/agents/{name}": {
      "get": {
        "tags": [
          "AgentPrism",
          "Agents"
        ],
        "summary": "Returns an agent's catalog summary and its persisted definition, if any.",
        "description": "A code-defined agent resolves through the catalog but has no stored definition; for it 'definition' is null and 'isEditable' is false. 'isEditable' is the single field a client checks before offering an edit form — it is true only when the agent's origin is the database.",
        "operationId": "AgentPrismGetAgent",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentDetailResponse"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "AgentsRead"
      },
      "put": {
        "tags": [
          "AgentPrism",
          "Agents"
        ],
        "summary": "Updates an agent definition and produces a new version.",
        "description": "An agent's name is immutable: when the path name and the body name differ the response is 400. A code-defined name returns 409 — code definitions are validated at compile time and are changed by changing the application. The same existence and call-graph checks as create apply, and a failed check writes nothing. Every successful save appends a version rather than overwriting; the previous content stays readable through the version history.",
        "operationId": "AgentPrismUpdateAgent",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentDefinitionRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentDefinition"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "AgentsAdmin"
      },
      "delete": {
        "tags": [
          "AgentPrism",
          "Agents"
        ],
        "summary": "Deletes an agent definition and its version history.",
        "description": "The delete removes the current definition together with every stored version; it is not a soft delete and there is no rollback afterwards. A code-defined name returns 409. A name with no stored definition returns 404, so the call is not idempotent across repeats. Runs already recorded for the agent are kept — the run history does not depend on the definition still existing.",
        "operationId": "AgentPrismDeleteAgent",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "AgentsAdmin"
      }
    },
    "/agentprism/api/agents/validate": {
      "post": {
        "tags": [
          "AgentPrism",
          "Agents"
        ],
        "summary": "Compiles a definition without saving it and without calling any model.",
        "description": "A validation failure is NOT an HTTP error. When the body is well-formed the response is always 200 and the outcome is carried in the report's 'valid' field, with one message per finding. 400 is returned only when the body itself cannot be read or the required name/model fields are missing — that is the single case a pipeline needs in order to tell a transport error from a rejected definition. No model provider is contacted and nothing is written.",
        "operationId": "AgentPrismValidateAgent",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentDefinitionRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentValidationReport"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Operator",
        "x-agentprism-api-key-scope": "AgentsAdmin"
      }
    },
    "/agentprism/api/agents/{name}/versions": {
      "get": {
        "tags": [
          "AgentPrism",
          "Agents"
        ],
        "summary": "Lists a definition's version history, newest first.",
        "description": "Every entry is a full definition snapshot, not a delta, so a single entry is enough to inspect or restore a past state. The agent must have a current stored definition; a code-defined or deleted name returns 404. Code agents have no version history at all — their history is the application's source history.",
        "operationId": "AgentPrismListAgentVersions",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AgentDefinition"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "AgentsRead"
      }
    },
    "/agentprism/api/agents/{name}/rollback": {
      "post": {
        "tags": [
          "AgentPrism",
          "Agents"
        ],
        "summary": "Writes a definition as a new version with the content of a previous version.",
        "description": "A rollback moves forward, not backward: the old content is appended as a NEW version and the history is never rewritten, so the rollback itself stays auditable and can be rolled back in turn. An unknown version number returns 404; a code-defined name returns 409.",
        "operationId": "AgentPrismRollbackAgent",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentRollbackRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentDefinition"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "AgentsAdmin"
      }
    },
    "/agentprism/api/agents/{name}/versions/{a}/diff/{b}": {
      "get": {
        "tags": [
          "AgentPrism",
          "Agents"
        ],
        "summary": "Returns two definition versions as raw JSON; the diff is computed in the UI.",
        "description": "The server does no diffing and takes no position on how a change should be displayed; it returns both snapshots verbatim as 'left' and 'right' so the client chooses the presentation. The two version numbers may be given in any order. When either version is missing the response is 404 and names the one that was not found.",
        "operationId": "AgentPrismGetAgentVersionDiff",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "a",
            "in": "path",
            "required": true,
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "b",
            "in": "path",
            "required": true,
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentVersionDiffResponse"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "AgentsRead"
      }
    },
    "/agentprism/api/agents/{name}/run": {
      "post": {
        "tags": [
          "AgentPrism",
          "Agents"
        ],
        "summary": "Runs an agent for trial purposes and streams the response via SSE.",
        "description": "If the quota is exceeded, the run does not start and a 429 is returned; the ProblemDetails carries which quota was exceeded and when the counter resets. When the pre-flight context-window check is enabled (disabled by default) and the prompt is estimated to exceed the model's window, the run does not start and a 400 is returned with the estimated and allowed token counts; no call reaches the provider. A request carrying the 'Idempotency-Key' header runs with a single JSON response (non-streaming) instead of SSE, because a replayed response cannot be reconstructed from a stream. A request carrying the 'Prefer: respond-async' header queues the run and returns '202 Accepted' with a 'Location' header. If a registered IContentGuard blocks the content, the non-streaming response returns '422' and the run's error type becomes 'content_blocked'; in the STREAMING response the status code has already been sent, so the block arrives as an SSE 'error' event instead.",
        "operationId": "AgentPrismRunAgent",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentRunRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "202": {
            "description": "Accepted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcceptedRunResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Operator",
        "x-agentprism-api-key-scope": "RunsWrite"
      }
    },
    "/agentprism/api/agents/{name}/estimate": {
      "post": {
        "tags": [
          "AgentPrism",
          "Agents"
        ],
        "summary": "Estimates a prompt's token count against the agent's model, without calling the provider.",
        "description": "The diagnostic surface of the pre-flight context-window check: it returns the same numbers the check on 'POST /api/agents/{name}/run' would use, regardless of whether that check is enabled. No model provider is ever contacted. The estimate is approximate — it uses a fixed reference tokenizer, not the bound provider's own count. 'contextWindowTokens' and 'allowedPromptTokens' are null when the agent's model is not found in the catalog; in that case 'wouldBeRejected' is always false, since an unknown window can never be exceeded.",
        "operationId": "AgentPrismEstimateContextWindow",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentRunRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContextWindowEstimate"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "RunsRead"
      }
    },
    "/agentprism/api/attachments": {
      "post": {
        "tags": [
          "AgentPrism",
          "Attachments"
        ],
        "summary": "Uploads a new attachment.",
        "description": "The body must be 'multipart/form-data' and must carry a 'file' field. The type is validated by magic bytes, not by the Content-Type the client reports.",
        "operationId": "AgentPrismUploadAttachment",
        "parameters": [
          {
            "name": "sessionId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "required": [
                  "file"
                ],
                "type": "object",
                "properties": {
                  "file": {
                    "$ref": "#/components/schemas/IFormFile"
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AttachmentDescriptor"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Operator",
        "x-agentprism-api-key-scope": "RunsWrite"
      },
      "get": {
        "tags": [
          "AgentPrism",
          "Attachments"
        ],
        "summary": "Lists attachments.",
        "description": "Only descriptors are returned — file name, media type, size, and content hash — never the bytes; fetch those from the download endpoint. 'sessionId' narrows the list to one session, and attachments uploaded without a session are reachable only without that filter. Paging is offset based: 'skip' defaults to 0, 'take' to 50, and 'take' is clamped to 1..200 instead of being rejected.",
        "operationId": "AgentPrismListAttachments",
        "parameters": [
          {
            "name": "sessionId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "skip",
            "in": "query",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          },
          {
            "name": "take",
            "in": "query",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AttachmentDescriptor"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "RunsRead"
      }
    },
    "/agentprism/api/attachments/{id}": {
      "get": {
        "tags": [
          "AgentPrism",
          "Attachments"
        ],
        "summary": "Streams the raw content of an attachment.",
        "description": "The response carries the attachment's own stored media type, an ETag holding the content's SHA-256, and 'Content-Disposition: attachment' together with 'X-Content-Type-Options: nosniff' — a browser therefore downloads the bytes instead of rendering them, so uploaded HTML can never execute in the console's origin. The token travels in the Authorization header, so a browser cannot use this URL directly as an image or audio element source; fetch the bytes and wrap them in an object URL instead.",
        "operationId": "AgentPrismDownloadAttachment",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/octet-stream": {
                "schema": {
                  "$ref": "#/components/schemas/Stream"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "RunsRead"
      },
      "delete": {
        "tags": [
          "AgentPrism",
          "Attachments"
        ],
        "summary": "Deletes an attachment.",
        "description": "The bytes are removed immediately; there is no soft delete. Messages that already reference the attachment keep the reference and it stops resolving, so delete an attachment only when its conversation no longer needs to be replayed. Deleting the owning session removes its attachments as well, which is usually the call to reach for. An unknown id returns 404.",
        "operationId": "AgentPrismDeleteAttachment",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          }
        },
        "x-agentprism-role": "Operator",
        "x-agentprism-api-key-scope": "RunsWrite"
      }
    },
    "/agentprism/api/skills": {
      "get": {
        "tags": [
          "AgentPrism",
          "Skills"
        ],
        "summary": "Lists the tenant's skills.",
        "description": "Skills are scoped to the calling tenant; a skill defined for another tenant is never returned. Each entry is complete — instructions, resources, and scripts come with it, so a client does not need a second call per skill. The response is not paged.",
        "operationId": "AgentPrismListSkills",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AgentSkillDefinition"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "AgentsRead"
      }
    },
    "/agentprism/api/skills/{name}": {
      "get": {
        "tags": [
          "AgentPrism",
          "Skills"
        ],
        "summary": "Returns a single skill and its resources.",
        "description": "The response carries the skill's instructions together with every resource and script attached to it, including their content. Names are compared exactly, case included; an unknown name returns 404.",
        "operationId": "AgentPrismGetSkill",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentSkillDefinition"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "AgentsRead"
      },
      "put": {
        "tags": [
          "AgentPrism",
          "Skills"
        ],
        "summary": "Creates or updates a skill.",
        "description": "The call replaces the whole skill: resources and scripts that the body omits are removed. A first save answers 201, a later one 200. The path name and the body name must be identical (400 otherwise). Name, description, and compatibility follow the skill frontmatter rules, and instructions, resources, and scripts are each bounded by the configured size limits. A script may be SAVED even when script execution is turned off — saving and running are separate permissions — but an extension with no registered interpreter is rejected, because such a script could never run and would leave dead data behind.",
        "operationId": "AgentPrismSaveSkill",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentSkillRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentSkillDefinition"
                }
              }
            }
          },
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentSkillDefinition"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "AgentsAdmin"
      },
      "delete": {
        "tags": [
          "AgentPrism",
          "Skills"
        ],
        "summary": "Deletes a skill and its cascading resources.",
        "description": "Resources and scripts are removed with the skill. Agent definitions that still name the skill are NOT rewritten, and they stop resolving: compiling such an agent fails with 'the skill was not found' until the reference is removed or the skill is recreated. Check the agents that use a skill before deleting it. An unknown name returns 404.",
        "operationId": "AgentPrismDeleteSkill",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "AgentsAdmin"
      }
    },
    "/agentprism/api/skill-script-grants": {
      "get": {
        "tags": [
          "AgentPrism",
          "Governance"
        ],
        "summary": "Lists the tenant's script run grants.",
        "description": "A grant is permission to execute code on the server, so this list is the authoritative answer to 'what may run here'. A grant with no script name covers every script in that skill; one with a script name covers only that script. Entries may carry an expiry, and an expired grant no longer authorizes a run. Grants are also a retention target, so old ones are cleaned up.",
        "operationId": "AgentPrismListSkillScriptGrants",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SkillScriptGrant"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "SecurityAdmin"
      },
      "post": {
        "tags": [
          "AgentPrism",
          "Governance"
        ],
        "summary": "Grants run permission to a skill script.",
        "description": "Granting while script execution is switched off returns 409 rather than succeeding: a grant that reads as active but never allows a run would be misleading. Omit 'scriptName' to cover every script in the skill. 'expiresAt' is optional but must be in the future when given (400 otherwise); without it the grant does not expire. Every change is written to the audit trail.",
        "operationId": "AgentPrismGrantSkillScript",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SkillScriptGrantRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SkillScriptGrant"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "SecurityAdmin"
      }
    },
    "/agentprism/api/skill-script-grants/{skillName}": {
      "delete": {
        "tags": [
          "AgentPrism",
          "Governance"
        ],
        "summary": "Revokes a script run grant.",
        "description": "Revoking takes effect on the next run; a script already executing is not stopped. The optional '?scriptName=' must match how the grant was created — revoking one script does not remove a skill-wide grant, and the skill-wide grant keeps authorizing that script until it too is revoked. When no matching active grant exists the response is 404.",
        "operationId": "AgentPrismRevokeSkillScript",
        "parameters": [
          {
            "name": "skillName",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "scriptName",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "SecurityAdmin"
      }
    },
    "/agentprism/api/sessions": {
      "get": {
        "tags": [
          "AgentPrism",
          "Sessions"
        ],
        "summary": "Lists sessions from most recently updated to oldest.",
        "description": "Paging is offset based: 'skip' defaults to 0 and 'take' to 50, and 'take' is clamped to the 1..200 range rather than rejected, so an out-of-range value never fails the request. 'agentName' narrows the list to one agent. Because the order is by last update, a session that changes while a client pages can move between pages; use the session id, not the position, as the identity.",
        "operationId": "AgentPrismListSessions",
        "parameters": [
          {
            "name": "agentName",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "skip",
            "in": "query",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          },
          {
            "name": "take",
            "in": "query",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SessionRecord"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "RunsRead"
      }
    },
    "/agentprism/api/sessions/{sessionId}": {
      "get": {
        "tags": [
          "AgentPrism",
          "Sessions"
        ],
        "summary": "Returns a session's metadata and chat history.",
        "description": "'messages' is the readable chat history and is null when the configured session storage cannot expose one — with an in-memory setup the history lives inside an opaque state blob. 'state' always carries that raw provider state. Messages come back in sequence order, so the index of a message is the sequence number the branch endpoint expects.",
        "operationId": "AgentPrismGetSession",
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionDetailResponse"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "RunsRead"
      },
      "delete": {
        "tags": [
          "AgentPrism",
          "Sessions"
        ],
        "summary": "Deletes a session.",
        "description": "Attachments linked to the session are deleted with it, and this call is the only way they are cleaned up: an attachment may be uploaded before any session exists, so the link is deliberately not a database foreign key. The attachments are removed only after the session itself is found, so a 404 leaves no side effect. Runs recorded under the session are kept — run history does not depend on the session still existing.",
        "operationId": "AgentPrismDeleteSession",
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          }
        },
        "x-agentprism-role": "Operator",
        "x-agentprism-api-key-scope": "RunsWrite"
      }
    },
    "/agentprism/api/sessions/{sessionId}/branch": {
      "post": {
        "tags": [
          "AgentPrism",
          "Sessions"
        ],
        "summary": "Branches a conversation from a specific point and opens a new session.",
        "description": "Items up to and including 'upToSequence' are COPIED into a NEW conversation; the pointer is only provenance information. Writing to the branch does not change the parent conversation. Branching only works while a persistent SQL provider is enabled; in an in-memory setup, chat history lives in an opaque blob of session state and this returns 501.",
        "operationId": "AgentPrismBranchSession",
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SessionBranchRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionBranchResult"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Operator",
        "x-agentprism-api-key-scope": "RunsWrite"
      }
    },
    "/agentprism/api/runs": {
      "get": {
        "tags": [
          "AgentPrism",
          "Runs"
        ],
        "summary": "Lists runs from newest to oldest.",
        "description": "By default, ONLY root runs are returned. To also see child runs, use 'includeChildren=true'; pass 'rootRunId' for an entire tree, or 'parentRunId' for the direct children of a run. 'userId' narrows the list to one user's runs, and 'label' takes a 'key:value' pair ('label=team:payments'); a bare 'label=team' matches any value of that key. Both dimensions are recorded from the server-side IRunAttributionContext, never from the run request body.",
        "operationId": "AgentPrismListRuns",
        "parameters": [
          {
            "name": "agentName",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/RunStatus"
            }
          },
          {
            "name": "kind",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/RunKind"
            }
          },
          {
            "name": "sessionId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "errorType",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "userId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "label",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "startedAfter",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "includeChildren",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "parentRunId",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "rootRunId",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "skip",
            "in": "query",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          },
          {
            "name": "take",
            "in": "query",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/RunRecord"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "RunsRead"
      }
    },
    "/agentprism/api/runs/{runId}/tree": {
      "get": {
        "tags": [
          "AgentPrism",
          "Runs"
        ],
        "summary": "Returns the entire tree a run belongs to, starting from the root.",
        "description": "The tree is always resolved from the ROOT, whichever member is asked for: a request naming a child run still returns the whole tree, because without the sibling branches a client cannot tell where in the tree that run sits. Each entry carries its parent, so the shape is rebuilt on the client. At most 200 runs are returned; a tree larger than that is truncated rather than paged.",
        "operationId": "AgentPrismGetRunTree",
        "parameters": [
          {
            "name": "runId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/RunRecord"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "RunsRead"
      }
    },
    "/agentprism/api/runs/{runId}": {
      "get": {
        "tags": [
          "AgentPrism",
          "Runs"
        ],
        "summary": "Returns the summary of a single run.",
        "description": "The summary carries status, timings, token counts, and — when pricing is configured — cost; it does not carry the conversation. Read the messages from the events endpoint, and the recorded input from the input endpoint. A run row is written when the run starts, so a run that is still going is readable here with a non-terminal status.",
        "operationId": "AgentPrismGetRun",
        "parameters": [
          {
            "name": "runId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunRecord"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "RunsRead"
      }
    },
    "/agentprism/api/runs/{runId}/events": {
      "get": {
        "tags": [
          "AgentPrism",
          "Runs"
        ],
        "summary": "Streams a run's events over SSE; live and historical use the same path.",
        "description": "If the connection drops, the client resumes from its last sequence number using the 'Last-Event-ID' header. If the run is still in progress, the stream stays open until it completes.",
        "operationId": "AgentPrismStreamRunEvents",
        "parameters": [
          {
            "name": "runId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "RunsRead"
      }
    },
    "/agentprism/api/runs/{runId}/cancel": {
      "post": {
        "tags": [
          "AgentPrism",
          "Runs"
        ],
        "summary": "Requests cancellation of a running run.",
        "description": "202 only reports that cancellation was REQUESTED; the final status is read from 'GET /api/runs/{id}'. Returns 409 if the run is not executing on this instance (a different instance, or a restarted process). Canceling a root run also stops every child run in the tree; canceling a child run on its own does not affect the root.",
        "operationId": "AgentPrismCancelRun",
        "parameters": [
          {
            "name": "runId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunRecord"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Operator",
        "x-agentprism-api-key-scope": "RunsWrite"
      }
    },
    "/agentprism/api/runs/{runId}/feedback": {
      "post": {
        "tags": [
          "AgentPrism",
          "Runs"
        ],
        "summary": "Writes a score for a run or for a single message.",
        "description": "When the same author scores the same target (run or message) a second time, the row is UPDATED, not a new row opened. If 'messageId' is left blank, the score applies to the whole run.",
        "operationId": "AgentPrismSaveRunFeedback",
        "parameters": [
          {
            "name": "runId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RunFeedbackRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunScore"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Operator",
        "x-agentprism-api-key-scope": "RunsWrite"
      },
      "get": {
        "tags": [
          "AgentPrism",
          "Runs"
        ],
        "summary": "Lists all scores for a run.",
        "description": "Both human scores and scores written by automatic evaluators appear in one list; the source is a field on each entry, not a separate endpoint. A run belonging to another tenant is reported as 404 rather than 403, so the API does not confirm that the run exists. A run with no scores returns an empty list, not 404.",
        "operationId": "AgentPrismListRunFeedback",
        "parameters": [
          {
            "name": "runId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/RunScore"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "RunsRead"
      }
    },
    "/agentprism/api/runs/{runId}/feedback/{scoreId}": {
      "delete": {
        "tags": [
          "AgentPrism",
          "Runs"
        ],
        "summary": "Deletes a score.",
        "description": "The deletion is recorded in the audit trail, so removing a score is itself traceable. The run must belong to the calling tenant; otherwise the response is 404. An unknown score id also returns 404, so repeating the call is not idempotent. Aggregate statistics computed from scores are recalculated on the next read rather than adjusted here.",
        "operationId": "AgentPrismDeleteRunFeedback",
        "parameters": [
          {
            "name": "runId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "scoreId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          }
        },
        "x-agentprism-role": "Operator",
        "x-agentprism-api-key-scope": "RunsWrite"
      }
    },
    "/agentprism/api/runs/{runId}/input": {
      "get": {
        "tags": [
          "AgentPrism",
          "Runs"
        ],
        "summary": "Returns the recorded input messages for a run.",
        "description": "Returns 404 for a run that started while input recording was disabled (AgentPrism:RunRecording:RecordRunInput = false), or that was deleted by a retention policy; such a run cannot be replayed.",
        "operationId": "AgentPrismGetRunInput",
        "parameters": [
          {
            "name": "runId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunInputResponse"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "RunsRead"
      }
    },
    "/agentprism/api/runs/{a}/compare/{b}": {
      "get": {
        "tags": [
          "AgentPrism",
          "Runs"
        ],
        "summary": "Returns the summaries of two runs side by side.",
        "description": "The diff is NOT computed on the server; the endpoint returns the two summaries and the UI shows the comparison — the same pattern as the agent definition version diff.",
        "operationId": "AgentPrismCompareRuns",
        "parameters": [
          {
            "name": "a",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "b",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunComparisonResponse"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "RunsRead"
      }
    },
    "/agentprism/api/runs/{runId}/replay": {
      "post": {
        "tags": [
          "AgentPrism",
          "Runs"
        ],
        "summary": "Starts a new run with recorded input.",
        "description": "The input is preserved, the conditions change: 'agentVersion', 'modelId', and 'toolMode'. The default 'toolMode' value is 'ReplayTools', and NO tool actually runs — recorded results are replayed. Replaying a call with no recorded result STOPS the replay and returns 422. 'LiveTools' ACTUALLY runs tools, produces side effects, requires the Admin role, and returns 409 if a tool requires approval. Replay is sessionless: if the source run belongs to a session, only that TURN's input is replayed; the conversation history is not carried over.",
        "operationId": "AgentPrismReplayRun",
        "parameters": [
          {
            "name": "runId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RunReplayRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunReplayResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "502": {
            "description": "Bad Gateway",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Operator",
        "x-agentprism-api-key-scope": "RunsWrite"
      }
    },
    "/agentprism/api/workflows": {
      "get": {
        "tags": [
          "AgentPrism",
          "Workflows"
        ],
        "summary": "Lists workflows defined in code and stored in the database.",
        "description": "What the list contains depends on whether the workflow engine is registered. With the engine, both code-defined and stored workflows appear, because only the engine can see the ones built in code. Without it, only stored definitions are listed — managing definitions does not require the engine, but running them does.",
        "operationId": "AgentPrismListWorkflows",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WorkflowDescriptor"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "WorkflowsRead"
      }
    },
    "/agentprism/api/workflows/functions": {
      "get": {
        "tags": [
          "AgentPrism",
          "Workflows"
        ],
        "summary": "Lists function nodes registered in code.",
        "description": "Function nodes are defined only in code, with AddWorkflowFunction - the same code-only boundary AddTool draws for tools. This endpoint does not offer a write path; the UI lets users pick from this list when building a Sequential workflow's node list. An empty list means no function was registered, or the workflow engine was never turned on with UseWorkflows - either way, existing agent-only workflows are unaffected.",
        "operationId": "AgentPrismListWorkflowFunctions",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WorkflowFunctionResponse"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "WorkflowsRead"
      }
    },
    "/agentprism/api/workflows/{name}": {
      "get": {
        "tags": [
          "AgentPrism",
          "Workflows"
        ],
        "summary": "Returns a single workflow definition.",
        "description": "Only stored definitions are editable and only they are returned here. A code-defined workflow is listed and can be run but has no stored definition, so it answers 404 with a distinct 'No editable definition' title — different from the plain not-found title used for a name that does not exist at all. Read the structure of a code-defined workflow from the graph endpoint instead.",
        "operationId": "AgentPrismGetWorkflow",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowDefinition"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "WorkflowsRead"
      },
      "put": {
        "tags": [
          "AgentPrism",
          "Workflows"
        ],
        "summary": "Creates or updates a workflow definition.",
        "description": "The definition is validated at save time with the same rules the compiler applies, so a shape that could not run is rejected with 400 instead of failing on the first run. Which fields are required depends on the kind — a manager driven workflow needs its manager agent, for example. The call replaces the whole definition: omitted fields are cleared, not merged. The name comes from the path and is not taken from the body.",
        "operationId": "AgentPrismSaveWorkflow",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WorkflowSaveRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowDefinition"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "WorkflowsAdmin"
      },
      "delete": {
        "tags": [
          "AgentPrism",
          "Workflows"
        ],
        "summary": "Deletes a workflow definition.",
        "description": "Only a stored definition can be deleted; a code-defined workflow is removed by changing the application, and asking for one here returns 404. Runs and checkpoints already recorded are kept, so past executions stay readable, but a checkpoint cannot be resumed once the definition it needs is gone.",
        "operationId": "AgentPrismDeleteWorkflow",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "WorkflowsAdmin"
      }
    },
    "/agentprism/api/workflows/{name}/graph": {
      "get": {
        "tags": [
          "AgentPrism",
          "Workflows"
        ],
        "summary": "Returns the compiled graph of the workflow.",
        "description": "Node IDs are identical to the executor IDs in run events; this is how the UI colors nodes live. The response also carries the Mermaid text generated by Microsoft Agent Framework.",
        "operationId": "AgentPrismGetWorkflowGraph",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowGraph"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "WorkflowsRead"
      }
    },
    "/agentprism/api/workflows/{name}/run": {
      "post": {
        "tags": [
          "AgentPrism",
          "Workflows"
        ],
        "summary": "Runs the workflow and streams its events over SSE.",
        "description": "Each frame carries a RunEvent. The first frame reports the run ID; every agent invoked within the workflow opens its own runs row, viewable as a tree via GET /api/runs/{runId}/tree.",
        "operationId": "AgentPrismRunWorkflow",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WorkflowRunHttpRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Operator",
        "x-agentprism-api-key-scope": "RunsWrite"
      }
    },
    "/agentprism/api/workflows/runs/{runId}/checkpoints": {
      "get": {
        "tags": [
          "AgentPrism",
          "Workflows"
        ],
        "summary": "Lists the checkpoints of a workflow run.",
        "description": "Checkpoints are the points a run can be resumed from; each entry's id is what the resume endpoint takes. A run belonging to another tenant is reported as 404 rather than 403, so the API does not confirm that it exists. An empty list means the run wrote no checkpoint — checkpointing is a property of how the workflow was built, not something this endpoint can turn on. Checkpoints are subject to retention, so an old run may have none left.",
        "operationId": "AgentPrismListWorkflowCheckpoints",
        "parameters": [
          {
            "name": "runId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WorkflowCheckpointRecord"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "RunsRead"
      }
    },
    "/agentprism/api/workflows/runs/{runId}/resume": {
      "post": {
        "tags": [
          "AgentPrism",
          "Workflows"
        ],
        "summary": "Resumes from a checkpoint and streams events over SSE.",
        "description": "Resuming opens a NEW run rather than continuing the old one: the original run row is never rewritten, and the first streamed frame reports the new run id. The body is optional — without a checkpoint id the run resumes from its latest checkpoint. The engine must be registered; otherwise the response is 501. Because the status code is sent before the stream begins, a failure after that point arrives as an SSE error frame rather than an HTTP error.",
        "operationId": "AgentPrismResumeWorkflow",
        "parameters": [
          {
            "name": "runId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WorkflowResumeHttpRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Operator",
        "x-agentprism-api-key-scope": "RunsWrite"
      }
    },
    "/agentprism/api/workflows/runs/{runId}/requests": {
      "get": {
        "tags": [
          "AgentPrism",
          "Workflows"
        ],
        "summary": "Lists a run's pending human input requests.",
        "description": "Only a run in the 'AwaitingInput' state returns requests. Requests are read from the run's event stream; there is no separate table.",
        "operationId": "AgentPrismListWorkflowRequests",
        "parameters": [
          {
            "name": "runId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WorkflowPendingRequest"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "RunsRead"
      }
    },
    "/agentprism/api/workflows/runs/{runId}/respond": {
      "post": {
        "tags": [
          "AgentPrism",
          "Workflows"
        ],
        "summary": "Responds to a pending request and resumes the run.",
        "description": "The response is matched to the request re-published with the same ID in the execution resumed from the checkpoint. Resuming opens a NEW runs row; events stream over SSE.",
        "operationId": "AgentPrismRespondWorkflowRequest",
        "parameters": [
          {
            "name": "runId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WorkflowRespondHttpRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Operator",
        "x-agentprism-api-key-scope": "RunsWrite"
      }
    },
    "/agentprism/api/schedules": {
      "get": {
        "tags": [
          "AgentPrism",
          "Scheduling"
        ],
        "summary": "Lists a tenant's schedules.",
        "description": "Enabled and disabled schedules are returned together; 'enabled' tells them apart. Each entry carries 'nextRunAt' as computed at the last save and 'lastRunAt' from the last execution, which is the quickest way to see that a schedule has stopped firing. A schedule with no cron expression never fires on its own and exists only to be triggered by hand.",
        "operationId": "AgentPrismListSchedules",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/JobSchedule"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "PlatformRead"
      }
    },
    "/agentprism/api/schedules/{name}": {
      "get": {
        "tags": [
          "AgentPrism",
          "Scheduling"
        ],
        "summary": "Gets a single schedule.",
        "description": "The response is the definition, including the stored payload the schedule fires with; the jobs it produced are read from the job endpoints, filtered by this schedule's id. Names are scoped to the calling tenant, and an unknown name returns 404.",
        "operationId": "AgentPrismGetSchedule",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobSchedule"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "PlatformRead"
      },
      "put": {
        "tags": [
          "AgentPrism",
          "Scheduling"
        ],
        "summary": "Creates or updates a schedule.",
        "description": "The cron expression and time zone are validated here; the next run time is computed at save time. The payload cannot exceed the MaxItemsPerJob limit.",
        "operationId": "AgentPrismSaveSchedule",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JobScheduleSaveRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobSchedule"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "PlatformAdmin"
      },
      "delete": {
        "tags": [
          "AgentPrism",
          "Scheduling"
        ],
        "summary": "Deletes a schedule.",
        "description": "The schedule stops firing, but jobs it already queued are not withdrawn — cancel those individually if they must not run. Job history keeps pointing at the deleted schedule's id, so past executions stay traceable. To pause a schedule instead, save it with 'enabled: false'. An unknown name returns 404.",
        "operationId": "AgentPrismDeleteSchedule",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "PlatformAdmin"
      }
    },
    "/agentprism/api/schedules/{name}/trigger": {
      "post": {
        "tags": [
          "AgentPrism",
          "Scheduling"
        ],
        "summary": "Runs a schedule immediately, without waiting for the cron schedule.",
        "description": "The job is queued, not executed inline: the response is the queued job record, so poll the job endpoint for the outcome. The body is optional — without one the schedule's stored payload is used, and a body's payload overrides it for this run only without changing the schedule. A trigger fires even when the schedule is disabled, and it does not move 'nextRunAt'. The payload's item count is capped by the same limit that applies on save.",
        "operationId": "AgentPrismTriggerSchedule",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JobTriggerRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobRecord"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Operator",
        "x-agentprism-api-key-scope": "RunsWrite"
      }
    },
    "/agentprism/api/jobs": {
      "get": {
        "tags": [
          "AgentPrism",
          "Scheduling"
        ],
        "summary": "Lists jobs, filtered by kind, status, or schedule.",
        "description": "Every queued unit of work shares this queue — scheduled runs, retention cleanups, webhook deliveries, and queued agent runs — so filter by 'kind' to narrow it. 'scheduleId' returns the executions of one schedule. Job items are not included here; read them from the single-job endpoint. Paging is offset based, with 'skip' defaulting to 0 and 'take' to 50.",
        "operationId": "AgentPrismListJobs",
        "parameters": [
          {
            "name": "kind",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/JobKind"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/JobStatus"
            }
          },
          {
            "name": "scheduleId",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "skip",
            "in": "query",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          },
          {
            "name": "take",
            "in": "query",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/JobRecord"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "RunsRead"
      }
    },
    "/agentprism/api/jobs/{id}": {
      "get": {
        "tags": [
          "AgentPrism",
          "Scheduling"
        ],
        "summary": "Gets a job and its items.",
        "description": "This is the endpoint to poll after queuing work: it carries the job's status and attempt count together with its items, each with its own status, so partial progress is visible while the job is still running. A failed job keeps its error text here rather than only in the logs. An unknown id, or one belonging to another tenant, returns 404.",
        "operationId": "AgentPrismGetJob",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobDetailResponse"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "RunsRead"
      }
    },
    "/agentprism/api/jobs/{id}/cancel": {
      "post": {
        "tags": [
          "AgentPrism",
          "Scheduling"
        ],
        "summary": "Cancels a job.",
        "description": "Only a job in the Pending, Leased, or Running status can be canceled. The executing worker checks the cancellation request between items and stops cooperatively.",
        "operationId": "AgentPrismCancelJob",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          }
        },
        "x-agentprism-role": "Operator",
        "x-agentprism-api-key-scope": "RunsWrite"
      }
    },
    "/agentprism/api/evals": {
      "get": {
        "tags": [
          "AgentPrism",
          "Evals"
        ],
        "summary": "Lists a tenant's eval suites.",
        "description": "Each entry is a suite's definition — the agent under test and its check definitions — without the cases or the past runs; read those from the cases and runs endpoints. The response is not paged.",
        "operationId": "AgentPrismListEvalSuites",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/EvalSuite"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "EvalsRead"
      }
    },
    "/agentprism/api/evals/{name}": {
      "get": {
        "tags": [
          "AgentPrism",
          "Evals"
        ],
        "summary": "Gets a single eval suite.",
        "description": "The suite carries its checks, which are stored together with it rather than as separate rows, because a suite's checks are always read and written as one unit. Cases and runs are separate endpoints. Suites are scoped to the calling tenant, and an unknown name returns 404.",
        "operationId": "AgentPrismGetEvalSuite",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EvalSuite"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "EvalsRead"
      },
      "put": {
        "tags": [
          "AgentPrism",
          "Evals"
        ],
        "summary": "Creates or updates an eval suite.",
        "description": "Check definitions are declarative; an unknown check type turns into an error at run time.",
        "operationId": "AgentPrismSaveEvalSuite",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EvalSuiteSaveRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EvalSuite"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "EvalsAdmin"
      },
      "delete": {
        "tags": [
          "AgentPrism",
          "Evals"
        ],
        "summary": "Deletes an eval suite (together with its cases and runs).",
        "description": "The cases and every past eval run cascade with the suite, so the score history used to compare agent versions disappears with it — export it first if it matters. The agent runs those evals produced stay in the run history and are still readable there. An unknown name returns 404.",
        "operationId": "AgentPrismDeleteEvalSuite",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "EvalsAdmin"
      }
    },
    "/agentprism/api/evals/{name}/cases": {
      "get": {
        "tags": [
          "AgentPrism",
          "Evals"
        ],
        "summary": "Lists a suite's cases.",
        "description": "Cases come back in their stored order, and that order is their identity: a case is addressed by its sequence number, so reordering the list changes which case a past result refers to. An unknown suite name returns 404, while a suite with no cases returns an empty list.",
        "operationId": "AgentPrismListEvalCases",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/EvalCase"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "EvalsRead"
      },
      "put": {
        "tags": [
          "AgentPrism",
          "Evals"
        ],
        "summary": "Replaces all of a suite's cases with the given list.",
        "description": "This is a full replacement, not an append: cases missing from the body are removed, so send the complete list every time. Sequence numbers are assigned from the body's order, which means reordering the list re-numbers the cases and past results then line up with different cases. Every case needs a non-empty 'query'; one that does not fails the whole request with 400 and nothing is written. An unknown suite name returns 404.",
        "operationId": "AgentPrismSaveEvalCases",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/EvalCaseInput"
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/EvalCase"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "EvalsAdmin"
      },
      "delete": {
        "tags": [
          "AgentPrism",
          "Evals"
        ],
        "summary": "Deletes all of a suite's cases.",
        "description": "The suite itself survives with its checks intact; only the cases go. Past eval runs and their per-case results are kept, but they then point at cases that no longer exist. The call is idempotent — clearing an already empty suite still answers 204. An unknown suite name returns 404.",
        "operationId": "AgentPrismClearEvalCases",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "EvalsAdmin"
      }
    },
    "/agentprism/api/evals/{name}/cases/from-run/{runId}": {
      "post": {
        "tags": [
          "AgentPrism",
          "Evals"
        ],
        "summary": "Promotes a run to an eval case in a single request.",
        "description": "The query is read from the run's own session; runs without a session cannot be promoted. If the same run is promoted a second time, the existing case is returned (200, not 201).",
        "operationId": "AgentPrismPromoteRunToEvalCase",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "runId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EvalCasePromotionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EvalCase"
                }
              }
            }
          },
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EvalCase"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Operator",
        "x-agentprism-api-key-scope": "EvalsAdmin"
      }
    },
    "/agentprism/api/evals/{name}/run": {
      "post": {
        "tags": [
          "AgentPrism",
          "Evals"
        ],
        "summary": "Runs an eval suite now.",
        "description": "Each case runs in a new session on the agent being evaluated and produces its own 'runs' row. The run is queued as a job; results are processed in the background.",
        "operationId": "AgentPrismTriggerEvalRun",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EvalRunTriggerRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EvalRun"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Operator",
        "x-agentprism-api-key-scope": "RunsWrite"
      }
    },
    "/agentprism/api/evals/{name}/runs": {
      "get": {
        "tags": [
          "AgentPrism",
          "Evals"
        ],
        "summary": "Lists a suite's past runs.",
        "description": "Each entry is one execution of the whole suite with its aggregate outcome; the per-case results live behind the single eval-run endpoint. Comparing entries over time is how a regression between agent versions is spotted. Paging is offset based, with 'skip' defaulting to 0 and 'take' to 50. An unknown suite name returns 404.",
        "operationId": "AgentPrismListEvalRuns",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "skip",
            "in": "query",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          },
          {
            "name": "take",
            "in": "query",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/EvalRun"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "EvalsRead"
      }
    },
    "/agentprism/api/evals/runs/{id}": {
      "get": {
        "tags": [
          "AgentPrism",
          "Evals"
        ],
        "summary": "Gets a single eval run and its per-case results.",
        "description": "This is the endpoint to poll after triggering a suite: the eval run is queued and processed in the background, and its results fill in as cases complete. Each result names the agent run it came from, so a failing check can be traced to the exact conversation. Per-case results are a retention target, so an old eval run may keep its summary while its details are gone. An unknown id, or one belonging to another tenant, returns 404.",
        "operationId": "AgentPrismGetEvalRun",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EvalRunDetailResponse"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "EvalsRead"
      }
    },
    "/agentprism/api/evaluation/online": {
      "get": {
        "tags": [
          "AgentPrism",
          "Evals"
        ],
        "summary": "Returns a summary of the online evaluation window.",
        "description": "Returns the average judge score, sample count, and judge cost within the window. The summary is in-memory (it resets when the process restarts); for an authoritative result, the 'run_scores' table can be queried directly.",
        "operationId": "AgentPrismGetOnlineEvaluationSummary",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OnlineEvaluationSummary"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "EvalsRead"
      }
    },
    "/agentprism/api/runs/{runId}/judge": {
      "post": {
        "tags": [
          "AgentPrism",
          "Evals"
        ],
        "summary": "Manually has judge(s) score a run.",
        "description": "This SKIPS the sampling decision; it is for calibration and debugging. If no IRunJudge is registered, or the run's input/output cannot be read, an empty list is returned.",
        "operationId": "AgentPrismJudgeRun",
        "parameters": [
          {
            "name": "runId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/RunScore"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Operator",
        "x-agentprism-api-key-scope": "RunsWrite"
      }
    },
    "/agentprism/api/experiments": {
      "get": {
        "tags": [
          "AgentPrism",
          "Experiments"
        ],
        "summary": "Lists a tenant's A/B experiments.",
        "description": "Experiments in every state are returned — Draft, Running, and Stopped — because a stopped experiment is still the record its results are read from. At most one of them per agent can be Running. The entries carry the variant weights, so a client can show the traffic split without a second call.",
        "operationId": "AgentPrismListExperiments",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Experiment"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "ExperimentsRead"
      }
    },
    "/agentprism/api/experiments/{name}": {
      "get": {
        "tags": [
          "AgentPrism",
          "Experiments"
        ],
        "summary": "Gets a single A/B experiment.",
        "description": "The response is the experiment's definition — arms, weights, status — not its outcome; read the per-arm counts from the results endpoint and the canary rule from the canary endpoint. Experiments are scoped to the calling tenant, and a name that belongs to another tenant is reported as 404.",
        "operationId": "AgentPrismGetExperiment",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Experiment"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "ExperimentsRead"
      },
      "put": {
        "tags": [
          "AgentPrism",
          "Experiments"
        ],
        "summary": "Creates or updates an experiment.",
        "description": "An experiment can only be set up between versions of the same agent; code-sourced agents have no version history, so they are rejected. Variant weights must sum to 100.",
        "operationId": "AgentPrismSaveExperiment",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ExperimentSaveRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Experiment"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "ExperimentsAdmin"
      },
      "delete": {
        "tags": [
          "AgentPrism",
          "Experiments"
        ],
        "summary": "Deletes an experiment. A running experiment must be stopped first.",
        "description": "Deleting a Running experiment returns 409; stop it first, so traffic is never left splitting against a definition that no longer exists. Runs already assigned to an arm keep their assignment and stay readable, but the per-arm results endpoint disappears with the experiment — export the results before deleting. An unknown name returns 404.",
        "operationId": "AgentPrismDeleteExperiment",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "ExperimentsAdmin"
      }
    },
    "/agentprism/api/experiments/{name}/start": {
      "post": {
        "tags": [
          "AgentPrism",
          "Experiments"
        ],
        "summary": "Starts the experiment; traffic begins splitting according to the weights.",
        "description": "Only one experiment can run for the same agent at a time.",
        "operationId": "AgentPrismStartExperiment",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Experiment"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "ExperimentsAdmin"
      }
    },
    "/agentprism/api/experiments/{name}/stop": {
      "post": {
        "tags": [
          "AgentPrism",
          "Experiments"
        ],
        "summary": "Stops the experiment; new runs go to the current version.",
        "description": "Stopping affects only new runs: a run already in flight keeps the arm it was assigned, and the recorded results stay intact and readable afterwards. Stopping an experiment that is not Running returns 409, and so does an unknown name — this endpoint does not distinguish the two. Once stopped, the agent's own current version serves all traffic again, and the same agent becomes free for another experiment.",
        "operationId": "AgentPrismStopExperiment",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Experiment"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "ExperimentsAdmin"
      }
    },
    "/agentprism/api/experiments/{name}/results": {
      "get": {
        "tags": [
          "AgentPrism",
          "Experiments"
        ],
        "summary": "Gets a per-arm summary of count, error rate, tokens, and duration.",
        "description": "There is no statistical claim of a 'winner'; raw counts are shown.",
        "operationId": "AgentPrismGetExperimentResults",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExperimentResultsResponse"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "ExperimentsRead"
      }
    },
    "/agentprism/api/experiments/{name}/canary": {
      "put": {
        "tags": [
          "AgentPrism",
          "Experiments"
        ],
        "summary": "Defines or removes the canary rule (a 'null' body removes it).",
        "description": "Can only be defined on two-arm experiments: canaryVariant is the canary, and the single remaining arm counts as control. Works regardless of the experiment's status (Draft or Running).",
        "operationId": "AgentPrismSetExperimentCanary",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CanaryPolicy"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Experiment"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "ExperimentsAdmin"
      },
      "get": {
        "tags": [
          "AgentPrism",
          "Experiments"
        ],
        "summary": "Gets the canary rule and its current evaluation.",
        "description": "The evaluation is not persisted; it is recalculated on every call using current run results.",
        "operationId": "AgentPrismGetExperimentCanary",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExperimentCanaryResponse"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "ExperimentsRead"
      }
    },
    "/agentprism/api/tools": {
      "get": {
        "tags": [
          "AgentPrism",
          "Agents"
        ],
        "summary": "Lists registered tools and their JSON schemas.",
        "description": "Tools are defined only in code. This endpoint does not offer a write path; the UI lets users pick from this list when defining an agent.",
        "operationId": "AgentPrismListTools",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ToolDescriptor"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "AgentsRead"
      }
    },
    "/agentprism/api/models": {
      "get": {
        "tags": [
          "AgentPrism",
          "Agents"
        ],
        "summary": "Lists registered model providers and their models.",
        "description": "The model catalog comes from configuration; AgentPrism does not ship a built-in model list. An empty list is not an error. The catalog is also not a validation list: a model name that is not listed here can still be used. The `status` field comes FROM THE CACHE, and this endpoint makes no network call to the provider; use /api/models/health for an up-to-date check.",
        "operationId": "AgentPrismListModels",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ModelProviderDescriptor"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "AgentsRead"
      }
    },
    "/agentprism/api/stats": {
      "get": {
        "tags": [
          "AgentPrism",
          "Agents"
        ],
        "summary": "Returns run counts, token totals, and the error rate.",
        "description": "The summary is computed in the store itself. Cost is populated only when pricing is configured (model catalog or AgentPrism:Pricing); the count of models with undefined pricing is counted separately in the RunsWithUnknownPricing field — it is not written as zero. Every breakdown (byAgent, byModel, byVersion, byUser, byLabel) is ALWAYS returned; there is no groupBy switch. 'userId' and 'label' ('key:value') narrow the whole summary rather than choosing a breakdown. 🚨 byLabel rows do NOT sum to totalRuns: a run carrying three labels appears in three of them. cachedInputTokens and reasoningTokens are counted INSIDE inputTokens/outputTokens, so adding them double counts.",
        "operationId": "AgentPrismStats",
        "parameters": [
          {
            "name": "agentName",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "userId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "label",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "startedAfter",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "maxAgents",
            "in": "query",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunStatistics"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "RunsRead"
      }
    },
    "/agentprism/api/stats/timeseries": {
      "get": {
        "tags": [
          "AgentPrism",
          "Agents"
        ],
        "summary": "Per-bucket time series of runs, errors, tokens, and cost.",
        "description": "Empty buckets are returned too. The default range is the last 24 hours, the default bucket is an hour. At most 500 buckets; exceeding that returns 400. Unlike /api/stats, this endpoint does NOT exclude Eval/Workflow runs by default; it can be filtered with ?kind=.",
        "operationId": "AgentPrismStatsTimeSeries",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "bucket",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/TimeSeriesBucket"
            }
          },
          {
            "name": "agentName",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "modelId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "kind",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/RunKind"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TimeSeriesPoint"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "RunsRead"
      }
    },
    "/agentprism/api/stats/errors": {
      "get": {
        "tags": [
          "AgentPrism",
          "Agents"
        ],
        "summary": "Returns the breakdown by error class and each class's top three clusters.",
        "description": "This is a narrow slice of /api/stats: it returns only the ByErrorClass field (that field is also present in the /api/stats response). The default range is the last 24 hours, changed with ?hours=. Rows written before error classification existed appear in the Unknown bucket; a high Unknown share means the taxonomy is incomplete.",
        "operationId": "AgentPrismStatsErrors",
        "parameters": [
          {
            "name": "agentName",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
              "type": [
                "number",
                "string"
              ],
              "format": "double"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/RunErrorStatistics"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "RunsRead"
      }
    },
    "/agentprism/api/stats/recalculate-costs": {
      "post": {
        "tags": [
          "AgentPrism",
          "Agents"
        ],
        "summary": "Recalculates the cost of all runs based on the current pricing source.",
        "description": "This is a maintenance endpoint. It is used to refresh past runs when pricing is defined later. The provider is not kept on historical rows; if the same model name is defined for more than one provider, the first alphabetical match wins. Requires Admin; the call is written to the audit trail.",
        "operationId": "AgentPrismRecalculateCosts",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunCostRecalculationResult"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "RunsWrite"
      }
    },
    "/agentprism/api/quotas": {
      "get": {
        "tags": [
          "AgentPrism",
          "Governance"
        ],
        "summary": "Lists a tenant's quota rules.",
        "description": "Rules are definitions, not counters — read the counters from the usage endpoint. A rule with no agent name applies to the whole tenant, and a tenant-wide rule and an agent-specific rule can both be in force at once. A rule with 'enabled: false' is kept but not enforced. An agent with no matching rule is unlimited.",
        "operationId": "AgentPrismListQuotas",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/QuotaDefinition"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "PlatformRead"
      },
      "put": {
        "tags": [
          "AgentPrism",
          "Governance"
        ],
        "summary": "Creates or updates a quota rule.",
        "description": "The scope (tenant + agent + period) is unique: writing a second rule for the same scope overwrites the existing rule. Each limit can also be left empty; only the ones that are set are enforced.",
        "operationId": "AgentPrismSaveQuota",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QuotaSaveRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuotaDefinition"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "PlatformAdmin"
      }
    },
    "/agentprism/api/quotas/{id}": {
      "delete": {
        "tags": [
          "AgentPrism",
          "Governance"
        ],
        "summary": "Deletes a quota rule.",
        "description": "Removing the last rule that covers an agent makes it unlimited, which is why the removal is written to the audit trail with the rule's previous values. Usage counters already recorded are not deleted; they simply stop being enforced. To keep the limits but stop enforcing them, save the rule with 'enabled: false' instead. An unknown id returns 404.",
        "operationId": "AgentPrismDeleteQuota",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "PlatformAdmin"
      }
    },
    "/agentprism/api/quotas/usage": {
      "get": {
        "tags": [
          "AgentPrism",
          "Governance"
        ],
        "summary": "Returns the current period's quota usage.",
        "description": "An empty 'agentName' value shows the tenant-wide counter. Counters are approximate: the check happens before a run starts, and consumption is written after it finishes.",
        "operationId": "AgentPrismGetQuotaUsage",
        "parameters": [
          {
            "name": "agentName",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "period",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/QuotaPeriod"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuotaUsageResponse"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "PlatformRead"
      }
    },
    "/agentprism/api/webhooks": {
      "get": {
        "tags": [
          "AgentPrism",
          "Webhooks"
        ],
        "summary": "Lists a tenant's webhook subscriptions.",
        "description": "The response carries no secret; only the NAME of the signing key is returned.",
        "operationId": "AgentPrismListWebhooks",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebhookSubscription"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "PlatformRead"
      }
    },
    "/agentprism/api/webhooks/{name}": {
      "get": {
        "tags": [
          "AgentPrism",
          "Webhooks"
        ],
        "summary": "Gets a single subscription.",
        "description": "As in the list, no signing secret is returned — only the configuration key its value is read from at delivery time. A secret is never stored in the database and never leaves through this API. An unknown name returns 404.",
        "operationId": "AgentPrismGetWebhook",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookSubscription"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "PlatformRead"
      },
      "put": {
        "tags": [
          "AgentPrism",
          "Webhooks"
        ],
        "summary": "Creates or updates a webhook subscription.",
        "description": "The address passes an SSRF check: only https is accepted (http only when AllowInsecureHttp is enabled and only to loopback targets). Private network addresses are re-checked again at delivery time.",
        "operationId": "AgentPrismSaveWebhook",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookSaveRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookSubscription"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "PlatformAdmin"
      },
      "delete": {
        "tags": [
          "AgentPrism",
          "Webhooks"
        ],
        "summary": "Deletes a subscription and its delivery history.",
        "description": "The delivery history cascades with the subscription, so export it first if it is needed for an audit; there is no way to recover it afterwards. Events raised after the delete match no subscription and are simply not delivered. An unknown name returns 404.",
        "operationId": "AgentPrismDeleteWebhook",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "PlatformAdmin"
      }
    },
    "/agentprism/api/webhooks/{name}/test": {
      "post": {
        "tags": [
          "AgentPrism",
          "Webhooks"
        ],
        "summary": "Sends a test event to the subscription's endpoint.",
        "description": "The event is written to the queue and delivered by a background worker; the response reports that it was queued, not the delivery outcome.",
        "operationId": "AgentPrismTestWebhook",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookTestResponse"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "PlatformAdmin"
      }
    },
    "/agentprism/api/webhooks/{name}/deliveries": {
      "get": {
        "tags": [
          "AgentPrism",
          "Webhooks"
        ],
        "summary": "Lists a subscription's delivery history.",
        "description": "This is a history table, not a queue: scheduling and retry live in the job queue. There is one entry per event, carrying the latest status, the attempt count, and the endpoint's last response code — a retry updates that entry rather than adding another. Filter with '?status=' to find failures. Paging is offset based — 'skip' defaults to 0, 'take' to 50, and 'take' is clamped to 1..200 instead of being rejected. An unknown subscription name returns 404.",
        "operationId": "AgentPrismListWebhookDeliveries",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/WebhookDeliveryStatus"
            }
          },
          {
            "name": "skip",
            "in": "query",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          },
          {
            "name": "take",
            "in": "query",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebhookDelivery"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "PlatformRead"
      }
    },
    "/agentprism/api/api-keys": {
      "get": {
        "tags": [
          "AgentPrism",
          "ApiKeys"
        ],
        "summary": "Lists a tenant's API keys.",
        "description": "The response carries neither the raw value nor a hash.",
        "operationId": "AgentPrismListApiKeys",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ApiKeyRecord"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "SecurityAdmin"
      },
      "post": {
        "tags": [
          "AgentPrism",
          "ApiKeys"
        ],
        "summary": "Generates a new API key.",
        "description": "The raw value is returned in the response ONLY ON THIS CALL and cannot be produced again. The scope list is closed; an unknown scope is rejected. If the request was authenticated with an API key, a scope that key does NOT ITSELF CARRY cannot be requested (privilege extension/attenuation).",
        "operationId": "AgentPrismCreateApiKey",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApiKeyCreateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyCreationResult"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "SecurityAdmin"
      }
    },
    "/agentprism/api/api-keys/{id}": {
      "delete": {
        "tags": [
          "AgentPrism",
          "ApiKeys"
        ],
        "summary": "Revokes a key.",
        "description": "The row is NOT deleted; a revocation timestamp is written and stays in the audit trail.",
        "operationId": "AgentPrismRevokeApiKey",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "SecurityAdmin"
      }
    },
    "/agentprism/api/tenants/{tenantId}/providers": {
      "get": {
        "tags": [
          "AgentPrism",
          "TenantProviders"
        ],
        "summary": "Lists a tenant's model provider bindings.",
        "description": "The response carries neither the credential value nor its configuration key's value — only the key's NAME and whether it currently resolves ('resolved'). This is the diagnosis path for 'I set the key but it does not work'.",
        "operationId": "AgentPrismListTenantProviderBindings",
        "parameters": [
          {
            "name": "tenantId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TenantProviderBindingResponse"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "SecurityAdmin"
      }
    },
    "/agentprism/api/tenants/{tenantId}/providers/{provider}": {
      "put": {
        "tags": [
          "AgentPrism",
          "TenantProviders"
        ],
        "summary": "Creates or replaces a tenant's binding for a provider.",
        "description": "The body carries only the configuration key's NAME the value is read from at call time, never the value itself. The name must be under the configured allowed prefix (400 otherwise), and the provider must be allowed by the tenant's egress policy, if one is defined (400 otherwise).",
        "operationId": "AgentPrismSaveTenantProviderBinding",
        "parameters": [
          {
            "name": "tenantId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "provider",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TenantProviderBindingRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantProviderBindingResponse"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "SecurityAdmin"
      },
      "delete": {
        "tags": [
          "AgentPrism",
          "TenantProviders"
        ],
        "summary": "Deletes a tenant's binding for a provider.",
        "description": "After deletion, calls for that provider use the setup-time global credential again.",
        "operationId": "AgentPrismDeleteTenantProviderBinding",
        "parameters": [
          {
            "name": "tenantId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "provider",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "SecurityAdmin"
      }
    },
    "/agentprism/api/tenants/{tenantId}/egress": {
      "get": {
        "tags": [
          "AgentPrism",
          "TenantProviders"
        ],
        "summary": "Returns a tenant's model provider egress policy.",
        "description": "'allowedProviders: null' means the tenant is UNRESTRICTED (no policy saved); an empty or populated array means the tenant may call only those providers.",
        "operationId": "AgentPrismGetTenantEgressPolicy",
        "parameters": [
          {
            "name": "tenantId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantEgressPolicyResponse"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "SecurityAdmin"
      },
      "put": {
        "tags": [
          "AgentPrism",
          "TenantProviders"
        ],
        "summary": "Creates or replaces a tenant's egress policy.",
        "description": "Saving a policy is an ADDITIVE restriction: a tenant with no policy is unrestricted, and this call is the only way that changes. An agent definition naming a provider outside the saved list is rejected at compile time, not only at call time. An empty 'allowedProviders' array allows NO provider — it is not the same as having no policy; use DELETE to return to unrestricted.",
        "operationId": "AgentPrismSaveTenantEgressPolicy",
        "parameters": [
          {
            "name": "tenantId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TenantEgressPolicyRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantEgressPolicyResponse"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "SecurityAdmin"
      },
      "delete": {
        "tags": [
          "AgentPrism",
          "TenantProviders"
        ],
        "summary": "Deletes a tenant's egress policy.",
        "description": "After deletion the tenant is unrestricted again — the same state as before any policy was ever saved.",
        "operationId": "AgentPrismDeleteTenantEgressPolicy",
        "parameters": [
          {
            "name": "tenantId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "SecurityAdmin"
      }
    },
    "/agentprism/api/triggers": {
      "get": {
        "tags": [
          "AgentPrism",
          "Triggers"
        ],
        "summary": "Lists a tenant's inbound triggers.",
        "description": "The response carries no signing secret value, only the configuration key's NAME and whether it currently resolves ('resolved') — the diagnosis path for 'I set the secret but signatures still fail'.",
        "operationId": "AgentPrismListInboundTriggers",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/InboundTriggerResponse"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "PlatformRead"
      }
    },
    "/agentprism/api/triggers/{name}": {
      "get": {
        "tags": [
          "AgentPrism",
          "Triggers"
        ],
        "summary": "Gets a single inbound trigger.",
        "description": "An unknown name returns 404.",
        "operationId": "AgentPrismGetInboundTrigger",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InboundTriggerResponse"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "PlatformRead"
      },
      "put": {
        "tags": [
          "AgentPrism",
          "Triggers"
        ],
        "summary": "Creates or updates an inbound trigger.",
        "description": "'signingSecretConfigurationName' carries only the configuration key's NAME, never its value; the name must be under the configured allowed prefix (400 otherwise). 'payloadPath' is required when 'payloadMode' is 'path'.",
        "operationId": "AgentPrismSaveInboundTrigger",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InboundTriggerSaveRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InboundTriggerResponse"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "PlatformAdmin"
      },
      "delete": {
        "tags": [
          "AgentPrism",
          "Triggers"
        ],
        "summary": "Deletes an inbound trigger.",
        "description": "After deletion, the accept endpoint returns 404 for this name. An unknown name returns 404.",
        "operationId": "AgentPrismDeleteInboundTrigger",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "PlatformAdmin"
      }
    },
    "/agentprism/api/approvals/pending": {
      "get": {
        "tags": [
          "AgentPrism",
          "Approvals"
        ],
        "summary": "Lists the tenant's pending approval requests.",
        "description": "Only requests still awaiting a decision are returned; a decided request leaves the list and stays readable by id. A request appears here when a queued run ('Prefer: respond-async') stops on a tool call that needs approval — a run driven synchronously carries its approval in the response stream instead and never reaches this mailbox. Each entry carries an expiry, which is an absolute point in the future rather than an elapsed duration.",
        "operationId": "AgentPrismListPendingApprovals",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/PendingApproval"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Operator",
        "x-agentprism-api-key-scope": "RunsRead"
      }
    },
    "/agentprism/api/approvals/{id}": {
      "get": {
        "tags": [
          "AgentPrism",
          "Approvals"
        ],
        "summary": "Returns a single pending approval request.",
        "description": "Unlike the list, this reads a request in any state, so it is how a client polls the outcome after deciding: the response then carries who decided, when, and which way. The request holds the tool call's arguments as recorded, which is what an approver reviews before deciding. An unknown id returns 404.",
        "operationId": "AgentPrismGetPendingApproval",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PendingApproval"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Operator",
        "x-agentprism-api-key-scope": "RunsRead"
      }
    },
    "/agentprism/api/approvals/{id}/decide": {
      "post": {
        "tags": [
          "AgentPrism",
          "Approvals"
        ],
        "summary": "Decides a pending approval request.",
        "description": "The decision enqueues a NEW run (same sessionId, new RunId); the old run stays AwaitingApproval. A second decision on the same request gets 409.",
        "operationId": "AgentPrismDecideApproval",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApprovalDecisionRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PendingApproval"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Operator",
        "x-agentprism-api-key-scope": "RunsWrite"
      }
    },
    "/agentprism/api/retention": {
      "get": {
        "tags": [
          "AgentPrism",
          "Retention"
        ],
        "summary": "Lists a tenant's retention policies.",
        "description": "Only targets that have an explicit policy appear here. A target missing from the list is not cleaned up at all — absence means 'keep forever', not 'use a default'. A policy is also kept while switched off, so 'enabled: false' is a configured-but-paused policy and is different from having none.",
        "operationId": "AgentPrismListRetentionPolicies",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/RetentionPolicy"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "PlatformRead"
      }
    },
    "/agentprism/api/retention/preview": {
      "get": {
        "tags": [
          "AgentPrism",
          "Retention"
        ],
        "summary": "Shows how many rows would be deleted if run now. Does NOT delete.",
        "description": "Run this before every cleanup: it is the only way to see the size of a deletion before it happens. The counts are computed against the data as it is right now, so they are an estimate — rows written between the preview and the run are included by the run. Without '?target=' every configured target is previewed; an unknown target name returns 400. Nothing is written and no job is queued.",
        "operationId": "AgentPrismPreviewRetention",
        "parameters": [
          {
            "name": "target",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/RetentionPreview"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "PlatformRead"
      }
    },
    "/agentprism/api/retention/run": {
      "post": {
        "tags": [
          "AgentPrism",
          "Retention"
        ],
        "summary": "Runs the cleanup now.",
        "description": "Does not run synchronously: a JobKind.Retention job is enqueued and processed from the queue.",
        "operationId": "AgentPrismRunRetention",
        "parameters": [
          {
            "name": "target",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RetentionRunTriggerResponse"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "PlatformAdmin"
      }
    },
    "/agentprism/api/retention/history": {
      "get": {
        "tags": [
          "AgentPrism",
          "Retention"
        ],
        "summary": "Lists past cleanup runs.",
        "description": "Each entry records one executed cleanup — the target, when it ran, and how many rows it removed — which is how a deletion is accounted for after the fact. Filter to one target with '?target='. Paging is offset based: 'skip' defaults to 0, 'take' to 50, and 'take' is clamped to 1..200 instead of being rejected. This history is not itself cleaned up by any policy — it is the permanent record of what was deleted.",
        "operationId": "AgentPrismRetentionHistory",
        "parameters": [
          {
            "name": "target",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "skip",
            "in": "query",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          },
          {
            "name": "take",
            "in": "query",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/RetentionRun"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "PlatformRead"
      }
    },
    "/agentprism/api/retention/{target}": {
      "get": {
        "tags": [
          "AgentPrism",
          "Retention"
        ],
        "summary": "Gets the retention policy for a single target.",
        "description": "Two different failures are reported differently: an unrecognized target name returns 400 and lists the valid targets, while a valid target with no policy configured returns 404. Read that 404 as 'this data is never cleaned up'.",
        "operationId": "AgentPrismGetRetentionPolicy",
        "parameters": [
          {
            "name": "target",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RetentionPolicy"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "PlatformRead"
      },
      "put": {
        "tags": [
          "AgentPrism",
          "Retention"
        ],
        "summary": "Creates or updates the retention policy for a target.",
        "description": "'maxAgeDays' and 'maxRows' are independent limits and both may be set; each must be at least 1 when given, and leaving both unset means the policy removes nothing. Saving does not delete anything by itself — the cleanup runs from the queue, so preview first. Every save is written to the audit trail with the previous and the new values. An unrecognized target returns 400.",
        "operationId": "AgentPrismSaveRetentionPolicy",
        "parameters": [
          {
            "name": "target",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RetentionPolicySaveRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RetentionPolicy"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "PlatformAdmin"
      },
      "delete": {
        "tags": [
          "AgentPrism",
          "Retention"
        ],
        "summary": "Deletes the retention policy for a target.",
        "description": "Removing a policy stops the cleanup for that target; it deletes no data and restores none that was already deleted. To pause a cleanup while keeping the limits, save the policy with 'enabled: false' instead. The removal is written to the audit trail. An unrecognized target returns 400, a target with no policy returns 404.",
        "operationId": "AgentPrismDeleteRetentionPolicy",
        "parameters": [
          {
            "name": "target",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "PlatformAdmin"
      }
    },
    "/agentprism/api/knowledge/{collection}/documents": {
      "post": {
        "tags": [
          "AgentPrism",
          "Knowledge"
        ],
        "summary": "Uploads a document to the knowledge base.",
        "description": "The body carries either 'text' (the server chunks and embeds it) or 'chunks' (pre-chunked). PostgreSQL only: UsePostgreSql and an IEmbeddingGenerator must be registered.",
        "operationId": "AgentPrismUploadKnowledgeDocument",
        "parameters": [
          {
            "name": "collection",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UploadDocumentRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UploadDocumentResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Operator",
        "x-agentprism-api-key-scope": "KnowledgeAdmin"
      },
      "get": {
        "tags": [
          "AgentPrism",
          "Knowledge"
        ],
        "summary": "Lists the sources in a collection.",
        "description": "The response is a flat list of source identifiers, not the chunks or their text: a source is the unit a document was uploaded and is deleted as. An unknown collection is not an error — it simply has no sources and returns an empty list. Knowledge storage requires PostgreSQL; without it the response is 501.",
        "operationId": "AgentPrismListKnowledgeDocuments",
        "parameters": [
          {
            "name": "collection",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "KnowledgeRead"
      }
    },
    "/agentprism/api/knowledge/{collection}/documents/{sourceId}": {
      "delete": {
        "tags": [
          "AgentPrism",
          "Knowledge"
        ],
        "summary": "Deletes all chunks of a source.",
        "description": "Every chunk and embedding produced from the source is removed; re-uploading the document is the only way back, and it costs a fresh round of embedding calls. The call is idempotent: an unknown source id still answers 204, because the requested end state — no such source — already holds. Knowledge storage requires PostgreSQL; without it the response is 501.",
        "operationId": "AgentPrismDeleteKnowledgeDocument",
        "parameters": [
          {
            "name": "collection",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sourceId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "501": {
            "description": "Not Implemented",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Operator",
        "x-agentprism-api-key-scope": "KnowledgeAdmin"
      }
    },
    "/agentprism/api/knowledge/{collection}/search": {
      "post": {
        "tags": [
          "AgentPrism",
          "Knowledge"
        ],
        "summary": "Performs a semantic search in a collection (for diagnostics and calibration).",
        "description": "This runs the same retrieval an agent performs, so it is how a retrieval problem is separated from a prompt problem: if the right chunk does not come back here, the agent was never going to see it. The query is embedded, which costs one embedding call per request. Each hit carries its distance — smaller is closer — along with the chunk text and its metadata, so a relevance threshold can be calibrated from real values. Knowledge storage requires PostgreSQL; without it the response is 501.",
        "operationId": "AgentPrismSearchKnowledge",
        "parameters": [
          {
            "name": "collection",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SearchKnowledgeRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SearchKnowledgeHit"
                  }
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "KnowledgeRead"
      }
    },
    "/agentprism/api/models/health": {
      "get": {
        "tags": [
          "AgentPrism",
          "Models"
        ],
        "summary": "Returns the cached health status of all registered providers.",
        "description": "If a provider does not implement IModelProviderHealthCheck, its status is Unknown; this is not an error. A provider whose circuit is open shows as Unhealthy. The error detail does NOT include an API key or endpoint address.",
        "operationId": "AgentPrismModelsHealth",
        "parameters": [
          {
            "name": "refresh",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ModelProviderHealth"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "PlatformRead"
      }
    },
    "/agentprism/api/models/health/{provider}": {
      "get": {
        "tags": [
          "AgentPrism",
          "Models"
        ],
        "summary": "Returns the cached health status of a single provider.",
        "description": "The status is served from the cache; add '?refresh=true' to force a fresh check. A check reads the provider's model list and never runs a completion, so it costs nothing. An unregistered provider name returns 404 — which is different from a registered provider that reports Unknown because it implements no health check. Error details never carry an API key or an endpoint address.",
        "operationId": "AgentPrismModelHealth",
        "parameters": [
          {
            "name": "provider",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "refresh",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ModelProviderHealth"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "PlatformRead"
      }
    },
    "/agentprism/api/voice/health": {
      "get": {
        "tags": [
          "AgentPrism",
          "Voice"
        ],
        "summary": "Checks the voice provider's availability.",
        "description": "The check does not incur cost: no speech is generated, only the available voices are read.",
        "operationId": "AgentPrismVoiceHealth",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceHealth"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "PlatformRead"
      }
    },
    "/agentprism/api/voice/voices": {
      "get": {
        "tags": [
          "AgentPrism",
          "Voice"
        ],
        "summary": "Lists the available voices.",
        "description": "The list comes from the configured speech provider, not from AgentPrism; the identifiers it returns are the values the speak endpoint and the agent's 'speak' tool accept. When the speech layer was never enabled with UseVoice, the response is 501 rather than 404, so a missing configuration is not mistaken for a wrong address.",
        "operationId": "AgentPrismVoiceList",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/VoiceDescriptor"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "AgentsRead"
      }
    },
    "/agentprism/api/voice/sessions": {
      "get": {
        "tags": [
          "AgentPrism",
          "Voice"
        ],
        "summary": "Lists the summary record of real-time speech connections.",
        "description": "The record does NOT contain audio: it only carries duration, turn count, and metering. If the speech layer is not enabled, the list is empty.",
        "operationId": "AgentPrismVoiceSessions",
        "parameters": [
          {
            "name": "agentName",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sessionId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "skip",
            "in": "query",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          },
          {
            "name": "take",
            "in": "query",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/VoiceSessionRecord"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "RunsRead"
      }
    },
    "/agentprism/api/voice/speak": {
      "post": {
        "tags": [
          "AgentPrism",
          "Voice"
        ],
        "summary": "Synthesizes speech from text and saves it as an attachment.",
        "description": "This is an operator action and is NOT tied to a run; the metering is not written to tool_invocations, it is returned in the response. If persistent metering is required, use the agent's `speak` tool.",
        "operationId": "AgentPrismVoiceSpeak",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SpeakRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SpeakResponse"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Operator",
        "x-agentprism-api-key-scope": "RunsWrite"
      }
    },
    "/agentprism/api/runs/{runId}/trace": {
      "get": {
        "tags": [
          "AgentPrism",
          "Runs"
        ],
        "summary": "Returns a run's span tree.",
        "description": "Spans are written with sampling. Spans for failed runs are always recorded by default; successes are recorded at a configurable rate.",
        "operationId": "AgentPrismGetRunTrace",
        "parameters": [
          {
            "name": "runId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunTrace"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "RunsRead"
      }
    },
    "/agentprism/api/runs/{runId}/tools": {
      "get": {
        "tags": [
          "AgentPrism",
          "Runs"
        ],
        "summary": "Lists a run's tool calls in chronological order.",
        "description": "Duration is measured only for streaming runs: in a non-streaming run all messages arrive at once, so the true duration between call and result cannot be read.",
        "operationId": "AgentPrismListRunToolInvocations",
        "parameters": [
          {
            "name": "runId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ToolInvocationRecord"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "RunsRead"
      }
    },
    "/agentprism/api/tools/usage": {
      "get": {
        "tags": [
          "AgentPrism",
          "Runs"
        ],
        "summary": "Returns call count, error rate, and average duration per tool.",
        "description": "The summary is computed by the store itself; it is not a paginated subset.",
        "operationId": "AgentPrismToolUsage",
        "parameters": [
          {
            "name": "startedAfter",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "maxTools",
            "in": "query",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ToolUsage"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "RunsRead"
      }
    },
    "/agentprism/api/tenants/current": {
      "get": {
        "tags": [
          "AgentPrism",
          "Governance"
        ],
        "summary": "Returns the current request's tenant.",
        "description": "The tenant is resolved from the request. In a single-tenant setup, it always returns the default tenant. This endpoint is in the protected group; /api/meta does not carry tenant information.",
        "operationId": "AgentPrismCurrentTenant",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CurrentTenantResponse"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader"
      }
    },
    "/agentprism/api/tenants": {
      "get": {
        "tags": [
          "AgentPrism",
          "Governance"
        ],
        "summary": "Lists registered tenants.",
        "description": "A tenant record is NOT REQUIRED. The tenant_id in other tables is the same text as this record's slug value, but it is not connected by a foreign key; a tenant with no record does not produce an error at runtime.",
        "operationId": "AgentPrismListTenants",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TenantDescriptor"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "PlatformAdmin"
      }
    },
    "/agentprism/api/tenants/{slug}": {
      "put": {
        "tags": [
          "AgentPrism",
          "Governance"
        ],
        "summary": "Adds or updates a tenant record.",
        "description": "The record is a display name for a tenant key that already works without it; creating one does not create the tenant and deleting one does not remove its data. The slug comes from the path and must be at most 64 characters of letters, digits, dots, underscores, and hyphens (400 otherwise) — it is the same text stored as 'tenant_id' on every other row. An empty display name falls back to the slug.",
        "operationId": "AgentPrismSaveTenant",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TenantRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantDescriptor"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "PlatformAdmin"
      },
      "delete": {
        "tags": [
          "AgentPrism",
          "Governance"
        ],
        "summary": "Deletes a tenant record.",
        "description": "Only the record is deleted; the tenant's agents, sessions, and runs remain.",
        "operationId": "AgentPrismDeleteTenant",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "PlatformAdmin"
      }
    },
    "/agentprism/api/mcp-servers": {
      "get": {
        "tags": [
          "AgentPrism",
          "Governance"
        ],
        "summary": "Lists registered remote MCP servers.",
        "description": "The response CARRIES NO SECRETS: the authentication value is not stored; only the name of the configuration key from which the value will be read is returned.",
        "operationId": "AgentPrismListMcpServers",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/McpServerDefinition"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "AgentsRead"
      }
    },
    "/agentprism/api/mcp-servers/{name}": {
      "put": {
        "tags": [
          "AgentPrism",
          "Governance"
        ],
        "summary": "Adds or updates a remote MCP server.",
        "description": "SECURITY BOUNDARY. Adding an MCP server means accepting tool definitions from an external source. Only http/https addresses are accepted; local process (stdio) transport is not supported. Tools require approval by default.",
        "operationId": "AgentPrismSaveMcpServer",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/McpServerRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/McpServerDefinition"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "AgentsAdmin"
      },
      "delete": {
        "tags": [
          "AgentPrism",
          "Governance"
        ],
        "summary": "Deletes a remote MCP server.",
        "description": "The registration is removed, so the tools it contributed stop being offered to agents. Agent definitions that name those tools are not rewritten and will fail validation on their next save — check which agents use the server before removing it. No request is made to the remote server itself. An unknown name returns 404.",
        "operationId": "AgentPrismDeleteMcpServer",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "AgentsAdmin"
      }
    },
    "/agentprism/api/mcp-servers/refresh": {
      "post": {
        "tags": [
          "AgentPrism",
          "Governance"
        ],
        "summary": "Refreshes the tool list of remote MCP servers now.",
        "description": "The refresh normally happens in the background at fixed intervals. This endpoint lets the tools of a newly added server appear without waiting for the next scheduled refresh.",
        "operationId": "AgentPrismRefreshMcpTools",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "null"
                  },
                  {
                    "$ref": "#/components/schemas/IMcpToolRefresher"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/McpRefreshResponse"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "AgentsAdmin"
      }
    },
    "/agentprism/api/mcp-servers/{name}/prompts": {
      "get": {
        "tags": [
          "AgentPrism",
          "Governance"
        ],
        "summary": "Gets an MCP server's prompt list.",
        "description": "If the server does not advertise the 'prompts' capability, the request is never sent.",
        "operationId": "AgentPrismListMcpPrompts",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/McpPromptSummary"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "AgentsRead"
      }
    },
    "/agentprism/api/mcp-servers/{name}/prompts/{prompt}": {
      "post": {
        "tags": [
          "AgentPrism",
          "Governance"
        ],
        "summary": "Resolves an MCP prompt's content with arguments.",
        "description": "The returned content is a SNAPSHOT: it must be copied into the agent's instructions; it is not re-fetched at runtime. The 'hash' field is for tracking changes on the server.",
        "operationId": "AgentPrismGetMcpPrompt",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "prompt",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/McpPromptArgumentsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/McpPromptContent"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "AgentsRead"
      }
    },
    "/agentprism/api/mcp-servers/{name}/resources": {
      "get": {
        "tags": [
          "AgentPrism",
          "Governance"
        ],
        "summary": "Gets an MCP server's resource list.",
        "description": "If the server does not advertise the 'resources' capability, the request is never sent.",
        "operationId": "AgentPrismListMcpResources",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/McpResourceSummary"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Reader",
        "x-agentprism-api-key-scope": "AgentsRead"
      }
    },
    "/agentprism/api/mcp-servers/{name}/resources/read": {
      "get": {
        "tags": [
          "AgentPrism",
          "Governance"
        ],
        "summary": "Reads an MCP resource.",
        "description": "Only URIs advertised by the server's ListResourcesAsync are accepted; an arbitrary URI is rejected because it carries an SSRF risk.",
        "operationId": "AgentPrismReadMcpResource",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "uri",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/McpResourceContent"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Operator",
        "x-agentprism-api-key-scope": "AgentsRead"
      }
    },
    "/agentprism/api/mcp-servers/{name}/oauth/start": {
      "post": {
        "tags": [
          "AgentPrism",
          "Governance"
        ],
        "summary": "Starts the OAuth authorization flow for an MCP server.",
        "description": "The administrator is redirected to the returned 'authorizationUri'. After approval, the provider redirects back to the '/oauth/callback' endpoint; that endpoint uses the 'state' value for CSRF protection.",
        "operationId": "AgentPrismStartMcpOAuth",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/McpOAuthStartResponse"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "SecurityAdmin"
      }
    },
    "/agentprism/api/approvals/rules": {
      "get": {
        "tags": [
          "AgentPrism",
          "Governance"
        ],
        "summary": "Lists persistent 'don't ask again' approval rules.",
        "description": "Each rule pre-approves a tool call so it never reaches the approval mailbox again, which makes this list a standing grant worth reviewing. A rule with no agent name applies to every agent in the tenant. When it carries an arguments hash the rule matches only that exact call; without one it matches every call to that tool. Rules do not expire — remove one to start asking again.",
        "operationId": "AgentPrismListApprovalRules",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ToolApprovalRule"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "RunsRead"
      },
      "post": {
        "tags": [
          "AgentPrism",
          "Governance"
        ],
        "summary": "Creates a persistent, argument-conditioned approval rule.",
        "description": "Writes a standing 'don't ask again' rule with an admin-authored comparison (for example \"amount <= 100\"), evaluated on every call. There is no free-text expression field: the operator is a closed set and conditions combine with AND only. A code-defined policy (IAgentPrismBuilder.AddToolApprovalPolicy) always runs first and can override this rule in both directions.",
        "operationId": "AgentPrismCreateApprovalRule",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ToolApprovalRuleRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolApprovalRule"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "SecurityAdmin"
      }
    },
    "/agentprism/api/approvals/rules/{ruleId}": {
      "delete": {
        "tags": [
          "AgentPrism",
          "Governance"
        ],
        "summary": "Revokes a persistent approval rule.",
        "description": "After the rule is deleted, approval is asked again for that tool.",
        "operationId": "AgentPrismDeleteApprovalRule",
        "parameters": [
          {
            "name": "ruleId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "RunsWrite"
      }
    },
    "/agentprism/api/audit": {
      "get": {
        "tags": [
          "AgentPrism",
          "Governance"
        ],
        "summary": "Lists audit entries, filterable by actor, action, entity, and date range.",
        "description": "Filterable by actor, action, entity, and date range. Runs (an agent processing a message) are not written to this log; the runs table already keeps the full record. The one exception is the 'content.blocked' action: an IContentGuard's block decision is a GOVERNANCE decision, not a run detail, and must remain traceable even after the run record is deleted by retention policy. The entry carries only the guard and rule name, never the blocked TEXT.",
        "operationId": "AgentPrismListAudit",
        "parameters": [
          {
            "name": "actor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "action",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "entity",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "after",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "before",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AuditEntry"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "AuditRead"
      }
    },
    "/agentprism/api/audit/{entity}": {
      "get": {
        "tags": [
          "AgentPrism",
          "Governance"
        ],
        "summary": "Returns a single entity's change history, newest first.",
        "description": "The path segment is the full entity key as it was recorded, in the form '<type>:<id>' — for example 'quota:<guid>' or 'retention:runs'. It is matched as written, not as a prefix. Entries carry the before and the after state, so one request answers 'who changed this and to what'. There is no paging: '?limit=' defaults to 100 and is clamped to 1..500, and only the newest entries are returned. An entity with no history returns an empty list, not 404.",
        "operationId": "AgentPrismGetEntityAudit",
        "parameters": [
          {
            "name": "entity",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AuditEntry"
                  }
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "AuditRead"
      }
    },
    "/agentprism/api/audit/verify": {
      "get": {
        "tags": [
          "AgentPrism",
          "Governance"
        ],
        "summary": "Walks the tenant's audit trail hash chain and reports whether it is intact.",
        "description": "'Valid' means every entry's hash matches its content and links to the one before it. 'Broken' means an entry's stored hash no longer matches its content — it was altered after it was written. 'Gap' means a link between two entries is missing — a row was deleted, or a write never completed; 'firstFailingEntryId' names where. An entry written before this feature shipped carries no hash and is excluded from the walk, not misreported as broken. Without '?after='/'?before=' the whole tenant history is walked; a narrower range is cheaper but cannot judge a break exactly at its own edge, because the entry just before the range is not read.",
        "operationId": "AgentPrismVerifyAuditChain",
        "parameters": [
          {
            "name": "after",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "before",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuditChainVerification"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "AuditRead"
      }
    },
    "/agentprism/api/data-subjects/{id}/export": {
      "get": {
        "tags": [
          "AgentPrism",
          "Governance"
        ],
        "summary": "Exports a data subject's content as one JSON document.",
        "description": "'{id}' is resolved through IDataSubjectResolver, which is registered by the consumer — AgentPrism does not store personal identity. Without a registered resolver this returns 409, never an empty document. The document holds every column of every matching row, keyed by target table (session state, runs, run inputs, attachment METADATA only — no file bytes, voice session summaries, run scores, conversations, conversation items, and responses); a target with no matching rows is present as an empty array, not omitted.",
        "operationId": "AgentPrismExportDataSubject",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "SecurityAdmin"
      }
    },
    "/agentprism/api/data-subjects/{id}": {
      "delete": {
        "tags": [
          "AgentPrism",
          "Governance"
        ],
        "summary": "Deletes a data subject's content.",
        "description": "'{id}' is resolved through IDataSubjectResolver; without one this returns 409, never a silent no-op that could be read as 'already erased'. '?dryRun=' DEFAULTS TO TRUE: a bare call previews the row counts and deletes nothing; '?dryRun=false' deletes for real. The audit trail (audit_log) is never touched — it is deliberately outside a data subject's erasable content (by design: an audit record is 'who did what', not the subject's own data) — but the erasure ITSELF is written there, with the row count per target; if that write fails, every delete is rolled back and this call fails, the same rule Approval decisions follow.",
        "operationId": "AgentPrismEraseDataSubject",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "dryRun",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DataSubjectErasureResult"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Admin",
        "x-agentprism-api-key-scope": "SecurityAdmin"
      }
    },
    "/agentprism/v1/responses": {
      "post": {
        "tags": [
          "AgentPrism",
          "OpenAI"
        ],
        "summary": "Run endpoint compatible with the OpenAI Responses API.",
        "description": "The agent is selected from the 'model' field; if not found, 'metadata.entity_id' is tried. If 'conversation' is given the session is stored under that identifier; if not, under the generated response identifier, so chaining with 'previous_response_id' works.",
        "operationId": "AgentPrismOpenAIResponses",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonElement"
                }
              },
              "text/event-stream": {
                "schema": {
                  "$ref": "#/components/schemas/JsonElement"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OpenAIErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OpenAIErrorEnvelope"
                }
              }
            }
          },
          "502": {
            "description": "Bad Gateway",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OpenAIErrorEnvelope"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Operator",
        "x-agentprism-api-key-scope": "RunsWrite"
      }
    },
    "/agentprism/v1/chat/completions": {
      "post": {
        "tags": [
          "AgentPrism",
          "OpenAI"
        ],
        "summary": "Run endpoint compatible with the OpenAI Chat Completions API.",
        "description": "Stateless: the client carries history. The agent is selected from the 'model' field; if not found, 'metadata.entity_id' is tried.",
        "operationId": "AgentPrismOpenAIChatCompletions",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatCompletion"
                }
              },
              "text/event-stream": {
                "schema": {
                  "$ref": "#/components/schemas/ChatCompletion"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OpenAIErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OpenAIErrorEnvelope"
                }
              }
            }
          },
          "502": {
            "description": "Bad Gateway",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OpenAIErrorEnvelope"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Operator",
        "x-agentprism-api-key-scope": "RunsWrite"
      }
    },
    "/agentprism/v1/conversations": {
      "post": {
        "tags": [
          "AgentPrism",
          "OpenAI"
        ],
        "summary": "Generates a new conversation identifier.",
        "description": "An identifier reservation: the session is born on the first /v1/responses call. The returned identifier is used directly in the 'conversation' field.",
        "operationId": "AgentPrismOpenAICreateConversation",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationResource"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OpenAIErrorEnvelope"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Operator",
        "x-agentprism-api-key-scope": "RunsWrite"
      }
    },
    "/agentprism/v1/conversations/{conversationId}": {
      "get": {
        "tags": [
          "AgentPrism",
          "OpenAI"
        ],
        "summary": "Returns a conversation's metadata.",
        "description": "A conversation identifier is a reservation, so an id that has never carried a call is still valid and answers 200 with the current time as its creation time. 404 therefore means 'not yours', not 'never used': an identifier owned by another tenant is reported as missing rather than forbidden, so the API does not confirm that it exists.",
        "operationId": "AgentPrismOpenAIGetConversation",
        "parameters": [
          {
            "name": "conversationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationResource"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OpenAIErrorEnvelope"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Operator",
        "x-agentprism-api-key-scope": "RunsRead"
      },
      "delete": {
        "tags": [
          "AgentPrism",
          "OpenAI"
        ],
        "summary": "Deletes a conversation and the session underneath it.",
        "description": "Following the OpenAI shape, the response is 200 with a 'deleted' flag rather than 204: the flag is false when the identifier was valid but no session had been created for it yet, so a client can tell a real deletion from a no-op. An identifier owned by another tenant returns 404.",
        "operationId": "AgentPrismOpenAIDeleteConversation",
        "parameters": [
          {
            "name": "conversationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeletedResource"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OpenAIErrorEnvelope"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Operator",
        "x-agentprism-api-key-scope": "RunsWrite"
      }
    },
    "/agentprism/v1/conversations/{conversationId}/items": {
      "get": {
        "tags": [
          "AgentPrism",
          "OpenAI"
        ],
        "summary": "Lists a conversation's messages in the OpenAI item format.",
        "description": "Items come back oldest first, and one stored message can expand into several items — a reply plus its tool calls, for example. '?limit=' trims the list from the end and sets 'has_more' to true, which is computed from the real total before trimming, so a truncated list never looks complete. There is no cursor paging: 'first_id' and 'last_id' describe the returned window only. A conversation with no history returns an empty list, and an identifier owned by another tenant returns 404.",
        "operationId": "AgentPrismOpenAIListConversationItems",
        "parameters": [
          {
            "name": "conversationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ItemListResource"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OpenAIErrorEnvelope"
                }
              }
            }
          }
        },
        "x-agentprism-role": "Operator",
        "x-agentprism-api-key-scope": "RunsRead"
      }
    },
    "/agentprism/api/mcp-servers/{name}/oauth/callback": {
      "get": {
        "tags": [
          "AgentPrism",
          "Governance"
        ],
        "summary": "Processes the OAuth provider's callback request.",
        "description": "This endpoint is outside the access layers: the browser redirected by the provider cannot carry our bearer token. Security relies on the single-use 'state' value.",
        "operationId": "AgentPrismMcpOAuthCallback",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "code",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "state",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "iss",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "error",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "security": []
      }
    },
    "/agentprism/api/triggers/{tenantId}/{name}": {
      "post": {
        "tags": [
          "AgentPrism",
          "Triggers"
        ],
        "summary": "Accepts a signed external event and queues a run.",
        "description": "No bearer token: the caller authenticates with an HMAC signature over the raw body ('X-AgentPrism-Timestamp' + 'X-AgentPrism-Signature', the same headers outbound webhooks send, in the reverse direction). The event is ALWAYS queued and this ALWAYS returns 202 — there is no synchronous mode; a long model call would otherwise fail the caller's own webhook timeout. A missing or wrong signature, an unknown trigger, and a disabled trigger all return the SAME generic response so a caller cannot enumerate trigger names.",
        "operationId": "AgentPrismAcceptInboundTrigger",
        "parameters": [
          {
            "name": "tenantId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InboundTriggerAcceptedResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "413": {
            "description": "Payload Too Large",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": []
      }
    }
  },
  "components": {
    "schemas": {
      "AcceptedRunResponse": {
        "required": [
          "runId",
          "jobId",
          "location",
          "eventsLocation"
        ],
        "type": "object",
        "properties": {
          "runId": {
            "type": "string",
            "description": "Run identifier.",
            "format": "uuid"
          },
          "jobId": {
            "type": "string",
            "description": "Identifier of the queue record carrying the work.",
            "format": "uuid"
          },
          "location": {
            "type": "string",
            "description": "Address of the run record. Same as the `Location` header."
          },
          "eventsLocation": {
            "type": "string",
            "description": "Address of the event stream."
          }
        },
        "description": "`202 Accepted` response for a queued run."
      },
      "AgentDefinition": {
        "required": [
          "name",
          "model"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Gets the unique name of the agent, used as the key in the catalog and in API routes."
          },
          "displayName": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the name shown in the user interface. `Name` is used when it is empty."
          },
          "description": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets a short description of what the agent does."
          },
          "instructions": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the system instructions passed to the model."
          },
          "instructionsByCulture": {
            "type": [
              "null",
              "object"
            ],
            "additionalProperties": {
              "type": "string"
            },
            "description": "Gets culture-keyed instructions. The key is a BCP-47 tag (`\"en\"`, `\"tr\"`);\na region subtag (`\"tr-TR\"`) falls back to its parent (`\"tr\"`). A run's\nrequested culture that matches neither falls back to `Instructions` -\nresolution never fails."
          },
          "model": {
            "description": "Gets the provider and model binding to use.",
            "$ref": "#/components/schemas/ModelBinding"
          },
          "toolNames": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Gets the names of the tools this agent may use. Every name must match a tool\nregistered in code; otherwise building the agent fails."
          },
          "skillNames": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Gets the names of the skills this agent may load at run time. Every name must\nmatch an enabled skill found in code or in the skill store."
          },
          "callableAgentNames": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Gets the names of the other agents this agent may call."
          },
          "mcpResourceUris": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Gets the MCP resources added to the run context (mode A). Each item has the\nform `\"{server}:{uri}\"`. They are read at the start of the run and are\npredictable; every run receives the same resources."
          },
          "harness": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Gets the harness settings. When `null` a plain chat agent is\nproduced; when populated, harness capabilities such as context compaction and\ntodo tracking are enabled.",
                "$ref": "#/components/schemas/HarnessSettings"
              }
            ]
          },
          "compaction": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Gets the context compaction settings. When `null` no compaction\nis applied.",
                "$ref": "#/components/schemas/CompactionSettings"
              }
            ]
          },
          "memory": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Gets the memory provider settings. When `null` no memory provider\nis added.",
                "$ref": "#/components/schemas/MemorySettings"
              }
            ]
          },
          "origin": {
            "description": "Gets the origin of the definition: code or database.",
            "$ref": "#/components/schemas/AgentDefinitionOrigin"
          },
          "version": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Gets the definition version. Every save increments this value and so naturally\ninvalidates the compiled agent cache.",
            "format": "int32"
          },
          "tenantId": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the tenant this definition belongs to. A single-tenant setup uses the default value."
          },
          "updatedAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the time the definition last changed (UTC).",
            "format": "date-time"
          },
          "metadata": {
            "type": "object",
            "description": "Gets free-form, application-specific metadata."
          }
        },
        "description": "The full definition of an agent. The same type is used whether the agent is\ndeclared in code or stored in the database; AgentDefinitionOrigin AgentDefinition.Origin tells the two apart."
      },
      "AgentDefinitionOrigin": {
        "enum": [
          "Code",
          "Database"
        ],
        "description": "Tells where an agent definition came from."
      },
      "AgentDefinitionRequest": {
        "required": [
          "name",
          "model"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Agent name. Unique within the catalog."
          },
          "displayName": {
            "type": [
              "null",
              "string"
            ],
            "description": "Name shown in the UI."
          },
          "description": {
            "type": [
              "null",
              "string"
            ],
            "description": "Short description."
          },
          "instructions": {
            "type": [
              "null",
              "string"
            ],
            "description": "System instructions."
          },
          "instructionsByCulture": {
            "type": [
              "null",
              "object"
            ],
            "additionalProperties": {
              "type": "string"
            },
            "description": "Culture-keyed instructions. See IReadOnlyDictionary&lt;string, string&gt;? AgentDefinition.InstructionsByCulture."
          },
          "model": {
            "description": "Model binding: provider, model, and sampling settings.",
            "$ref": "#/components/schemas/ModelBinding"
          },
          "toolNames": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Names of tools to use. Tools are defined only in code; only the name of\nan already registered tool may be given here."
          },
          "skillNames": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Names of skills that can be loaded at runtime."
          },
          "callableAgentNames": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Names of other agents this agent may call."
          },
          "harness": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Harness settings. If left empty, a plain chat agent is compiled.",
                "$ref": "#/components/schemas/HarnessSettings"
              }
            ]
          },
          "compaction": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Context compaction settings. If left empty, no compaction is applied.",
                "$ref": "#/components/schemas/CompactionSettings"
              }
            ]
          },
          "memory": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Memory provider settings. If left empty, no memory provider is added.",
                "$ref": "#/components/schemas/MemorySettings"
              }
            ]
          }
        },
        "description": "Request to create or update an agent definition."
      },
      "AgentDescriptor": {
        "required": [
          "name",
          "origin",
          "sourceName"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Gets the unique name of the agent."
          },
          "displayName": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the name shown in the user interface."
          },
          "description": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the short description."
          },
          "origin": {
            "description": "Gets the origin of the definition.",
            "$ref": "#/components/schemas/AgentDefinitionOrigin"
          },
          "sourceName": {
            "type": "string",
            "description": "Gets the name of the source that supplies this agent, for example `code`\nor `database`. Several sources can share the same AgentDefinitionOrigin AgentDescriptor.Origin value."
          },
          "version": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Gets the definition version. It is always 1 for code agents.",
            "format": "int32"
          },
          "model": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Gets the bound model. It can be unknown for code agents.",
                "$ref": "#/components/schemas/ModelBinding"
              }
            ]
          },
          "toolNames": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Gets the names of the tools this agent may use."
          },
          "skillNames": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Gets the names of the skills this agent may load at run time."
          },
          "callableAgentNames": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Gets the names of the other agents this agent may call."
          },
          "usesHarness": {
            "type": "boolean",
            "description": "Gets whether the harness capabilities are enabled."
          },
          "updatedAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the time of the last change (UTC).",
            "format": "date-time"
          }
        },
        "description": "A summary view of an agent listed in the catalog. It carries everything the user\ninterface needs to draw the agent list, without having to build the agent."
      },
      "AgentDetailResponse": {
        "required": [
          "descriptor",
          "isEditable"
        ],
        "type": "object",
        "properties": {
          "descriptor": {
            "description": "Catalog summary.",
            "$ref": "#/components/schemas/AgentDescriptor"
          },
          "definition": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Persistent definition. `null` if the agent is defined only in code.",
                "$ref": "#/components/schemas/AgentDefinition"
              }
            ]
          },
          "isEditable": {
            "type": "boolean",
            "description": "Whether this agent can be modified through the management API."
          }
        },
        "description": "Detailed view of a single agent."
      },
      "AgentPrismAuthenticationMeta": {
        "required": [
          "allowRemoteAccess",
          "requiresBearerToken",
          "requiresAuthorizationPolicy"
        ],
        "type": "object",
        "properties": {
          "allowRemoteAccess": {
            "type": "boolean",
            "description": "Whether access from outside loopback is allowed."
          },
          "requiresBearerToken": {
            "type": "boolean",
            "description": "Whether an `Authorization: Bearer` header is expected."
          },
          "requiresAuthorizationPolicy": {
            "type": "boolean",
            "description": "Whether an ASP.NET Core authorization policy is applied."
          }
        },
        "description": "Reports which authentication layers are enabled."
      },
      "AgentPrismMetaResponse": {
        "required": [
          "version",
          "prefix",
          "authentication",
          "storage",
          "roles"
        ],
        "type": "object",
        "properties": {
          "version": {
            "type": "string",
            "description": "AgentPrism version."
          },
          "prefix": {
            "type": "string",
            "description": "Path prefix the endpoints are connected to. The UI builds its own calls from this."
          },
          "authentication": {
            "description": "Active authentication methods.",
            "$ref": "#/components/schemas/AgentPrismAuthenticationMeta"
          },
          "storage": {
            "description": "Active storage implementations.",
            "$ref": "#/components/schemas/AgentPrismStorageMeta"
          },
          "roles": {
            "description": "Role permissions of the current caller.",
            "$ref": "#/components/schemas/AgentPrismRoleMeta"
          }
        },
        "description": "Response for `{prefix}/api/meta`. Carries the minimum information the\nUI needs to configure itself."
      },
      "AgentPrismRoleMeta": {
        "required": [
          "canRead",
          "canOperate",
          "canAdminister"
        ],
        "type": "object",
        "properties": {
          "canRead": {
            "type": "boolean",
            "description": "Whether the caller may read agents, runs, sessions, traces, and statistics."
          },
          "canOperate": {
            "type": "boolean",
            "description": "Whether the caller may, in addition to Reader, start runs, give approvals, and delete sessions."
          },
          "canAdminister": {
            "type": "boolean",
            "description": "Whether the caller may write agent definitions, add MCP servers, and manage tenants and audit trails."
          }
        },
        "description": "Reports which role levels the current request's caller satisfies."
      },
      "AgentPrismStorageMeta": {
        "required": [
          "persistent",
          "agentDefinitionStore",
          "runStore",
          "sessionStore",
          "jobStore",
          "jobWorkerEnabled"
        ],
        "type": "object",
        "properties": {
          "persistent": {
            "type": "boolean",
            "description": "Whether all three stores are persistent. Returns\n`false` if any is in-memory."
          },
          "agentDefinitionStore": {
            "type": "string",
            "description": "Type name of the agent definition store."
          },
          "runStore": {
            "type": "string",
            "description": "Type name of the run store."
          },
          "sessionStore": {
            "type": "string",
            "description": "Type name of the session store."
          },
          "jobStore": {
            "type": "string",
            "description": "Type name of the job queue store."
          },
          "jobWorkerEnabled": {
            "type": "boolean",
            "description": "Whether the background job worker is running in this process. If\n`false`, the queue can still be written to and read\nfrom; only this process does not lease jobs."
          }
        },
        "description": "Reports which storage implementations are active."
      },
      "AgentResponseFormat": {
        "required": [
          "kind"
        ],
        "type": "object",
        "properties": {
          "kind": {
            "description": "Gets the requested format.",
            "$ref": "#/components/schemas/AgentResponseFormatKind"
          },
          "schema": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Gets the JSON schema. It is populated only for\nAgentResponseFormatKind.JsonSchema and must be a JSON\n<strong>object</strong>.",
                "$ref": "#/components/schemas/JsonElement"
              }
            ]
          },
          "schemaName": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the name of the schema. The provider can pass it on to the model."
          },
          "schemaDescription": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the description of the schema."
          }
        },
        "description": "The definition of a structured output."
      },
      "AgentResponseFormatKind": {
        "enum": [
          "Text",
          "Json",
          "JsonSchema"
        ],
        "description": "The requested format of an agent response."
      },
      "AgentRollbackRequest": {
        "required": [
          "version"
        ],
        "type": "object",
        "properties": {
          "version": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Version number to roll back to.",
            "format": "int32"
          }
        },
        "description": "Request to roll back a definition to a previous version."
      },
      "AgentRunRequest": {
        "type": "object",
        "properties": {
          "message": {
            "type": [
              "null",
              "string"
            ],
            "description": "User message. May be left empty only if IReadOnlyList&lt;ToolApprovalDecision&gt; AgentRunRequest.Approvals is sent."
          },
          "sessionId": {
            "type": [
              "null",
              "string"
            ],
            "description": "Session identifier. If not given, the run is sessionless and no history\nis carried."
          },
          "culture": {
            "type": [
              "null",
              "string"
            ],
            "description": "The culture to resolve the agent's instructions with (see\n`AgentDefinition.InstructionsByCulture`). `null` uses the\nagent's default instructions."
          },
          "approvals": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ToolApprovalDecision"
            },
            "description": "Approval decisions for pending tool calls."
          },
          "toolResults": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ClientToolResult"
            },
            "description": "Results of client-side tool calls."
          },
          "attachmentIds": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Identifiers of attachments previously uploaded via `POST /api/attachments`."
          }
        },
        "description": "Request for a trial run made from the UI."
      },
      "AgentSkillDefinition": {
        "required": [
          "tenantId",
          "name",
          "description",
          "instructions"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The skill's unique identifier.",
            "format": "uuid"
          },
          "tenantId": {
            "type": "string",
            "description": "The tenant the skill belongs to."
          },
          "name": {
            "type": "string",
            "description": "The skill name. Agent definitions bind to the skill with this name."
          },
          "description": {
            "type": "string",
            "description": "The skill's short description."
          },
          "instructions": {
            "type": "string",
            "description": "The markdown instructions given to the model."
          },
          "compatibility": {
            "type": [
              "null",
              "string"
            ],
            "description": "The skill's compatibility statement."
          },
          "license": {
            "type": [
              "null",
              "string"
            ],
            "description": "The skill license."
          },
          "allowedTools": {
            "type": [
              "null",
              "string"
            ],
            "description": "The allowed-tools declaration in the MAF frontmatter."
          },
          "metadata": {
            "type": "object",
            "description": "Application-specific free-form metadata."
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether the skill is included in compilation."
          },
          "version": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The skill record's version.",
            "format": "int32"
          },
          "resources": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AgentSkillResourceDefinition"
            },
            "description": "The skill's resources."
          },
          "scripts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AgentSkillScriptDefinition"
            },
            "description": "The skill's scripts stored in the database."
          },
          "createdAt": {
            "type": "string",
            "description": "The skill's creation time.",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "description": "The skill's last-updated time.",
            "format": "date-time"
          }
        },
        "description": "A markdown-based skill definition that can be loaded into an agent at run time."
      },
      "AgentSkillRequest": {
        "required": [
          "name",
          "description",
          "instructions"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Skill name."
          },
          "description": {
            "type": "string",
            "description": "Skill description."
          },
          "instructions": {
            "type": "string",
            "description": "Markdown instructions."
          },
          "compatibility": {
            "type": [
              "null",
              "string"
            ],
            "description": "Compatibility statement."
          },
          "license": {
            "type": [
              "null",
              "string"
            ],
            "description": "Skill license."
          },
          "allowedTools": {
            "type": [
              "null",
              "string"
            ],
            "description": "Allowed-tools declaration from the MAF frontmatter."
          },
          "metadata": {
            "type": "object",
            "description": "Application-specific metadata."
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether the skill is enabled."
          },
          "resources": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AgentSkillResourceDefinition"
            },
            "description": "Skill resources."
          },
          "scripts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AgentSkillScriptDefinition"
            },
            "description": "Skill scripts."
          }
        },
        "description": "Request to create or update a skill."
      },
      "AgentSkillResourceDefinition": {
        "required": [
          "name",
          "content"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "The resource name, unique within the skill."
          },
          "description": {
            "type": [
              "null",
              "string"
            ],
            "description": "The resource description."
          },
          "mediaType": {
            "type": "string",
            "description": "The resource media type."
          },
          "content": {
            "type": "string",
            "description": "The resource's text content."
          }
        },
        "description": "A readable resource carried with an AgentSkillDefinition."
      },
      "AgentSkillScriptDefinition": {
        "required": [
          "name",
          "extension",
          "content"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "The script name, unique within the skill."
          },
          "description": {
            "type": [
              "null",
              "string"
            ],
            "description": "A description telling the model what the script does."
          },
          "extension": {
            "type": "string",
            "description": "The file extension (without the dot, for example `py`). The\ninterpreter is selected from the allowlist through this value."
          },
          "content": {
            "type": "string",
            "description": "The script's source text."
          },
          "parametersSchema": {
            "type": [
              "null",
              "string"
            ],
            "description": "The argument schema reported to the model. Must be a valid JSON Schema\nobject; if `null`, the script is called with no arguments."
          }
        },
        "description": "A server-executable script stored together with an AgentSkillDefinition."
      },
      "AgentValidationReport": {
        "required": [
          "valid",
          "inconclusive",
          "messages"
        ],
        "type": "object",
        "properties": {
          "valid": {
            "type": "boolean",
            "description": "Gets a value that is `true` when the definition carries no ValidationSeverity.Error."
          },
          "inconclusive": {
            "type": "boolean",
            "description": "Gets a value that tells whether a check could not finish because a resource was\nunreachable, an MCP server for example. It does not affect `Valid`."
          },
          "messages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ValidationMessage"
            },
            "description": "Gets every message found. Validation does not stop at the first error."
          }
        },
        "description": "The result of a validation that builds an agent definition without saving it and\nwithout calling any model."
      },
      "AgentVersionDiffResponse": {
        "required": [
          "left",
          "right"
        ],
        "type": "object",
        "properties": {
          "left": {
            "description": "Left (usually older) side of the comparison.",
            "$ref": "#/components/schemas/AgentDefinition"
          },
          "right": {
            "description": "Right (usually newer) side of the comparison.",
            "$ref": "#/components/schemas/AgentDefinition"
          }
        },
        "description": "Raw JSON response for comparing two definition versions. The\ndiff is not computed on the server; the client compares the two raw\ndefinitions field by field."
      },
      "AIAnnotation": {
        "type": "object",
        "anyOf": [
          {
            "$ref": "#/components/schemas/AIAnnotationCitationAnnotation"
          },
          {
            "$ref": "#/components/schemas/AIAnnotationBase"
          }
        ]
      },
      "AIAnnotationBase": {
        "properties": {
          "annotatedRegions": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AnnotatedRegion"
            }
          },
          "additionalProperties": {
            "type": [
              "null",
              "object"
            ]
          }
        }
      },
      "AIAnnotationCitationAnnotation": {
        "required": [
          "$type"
        ],
        "properties": {
          "$type": {
            "enum": [
              "citation"
            ],
            "type": "string"
          },
          "title": {
            "type": [
              "null",
              "string"
            ]
          },
          "url": {
            "type": [
              "null",
              "string"
            ],
            "format": "uri"
          },
          "fileId": {
            "type": [
              "null",
              "string"
            ]
          },
          "toolName": {
            "type": [
              "null",
              "string"
            ]
          },
          "snippet": {
            "type": [
              "null",
              "string"
            ]
          },
          "annotatedRegions": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AnnotatedRegion"
            }
          },
          "additionalProperties": {
            "type": [
              "null",
              "object"
            ]
          }
        }
      },
      "AIContent": {
        "type": "object",
        "anyOf": [
          {
            "$ref": "#/components/schemas/AIContentDataContent"
          },
          {
            "$ref": "#/components/schemas/AIContentErrorContent"
          },
          {
            "$ref": "#/components/schemas/AIContentFunctionCallContent"
          },
          {
            "$ref": "#/components/schemas/AIContentFunctionResultContent"
          },
          {
            "$ref": "#/components/schemas/AIContentHostedFileContent"
          },
          {
            "$ref": "#/components/schemas/AIContentHostedVectorStoreContent"
          },
          {
            "$ref": "#/components/schemas/AIContentTextContent"
          },
          {
            "$ref": "#/components/schemas/AIContentTextReasoningContent"
          },
          {
            "$ref": "#/components/schemas/AIContentUriContent"
          },
          {
            "$ref": "#/components/schemas/AIContentUsageContent"
          },
          {
            "$ref": "#/components/schemas/AIContentToolCallContent"
          },
          {
            "$ref": "#/components/schemas/AIContentToolResultContent"
          },
          {
            "$ref": "#/components/schemas/AIContentInputRequestContent"
          },
          {
            "$ref": "#/components/schemas/AIContentInputResponseContent"
          },
          {
            "$ref": "#/components/schemas/AIContentToolApprovalRequestContent"
          },
          {
            "$ref": "#/components/schemas/AIContentToolApprovalResponseContent"
          },
          {
            "$ref": "#/components/schemas/AIContentMcpServerToolCallContent"
          },
          {
            "$ref": "#/components/schemas/AIContentMcpServerToolResultContent"
          },
          {
            "$ref": "#/components/schemas/AIContentImageGenerationToolCallContent"
          },
          {
            "$ref": "#/components/schemas/AIContentImageGenerationToolResultContent"
          },
          {
            "$ref": "#/components/schemas/AIContentCodeInterpreterToolCallContent"
          },
          {
            "$ref": "#/components/schemas/AIContentCodeInterpreterToolResultContent"
          },
          {
            "$ref": "#/components/schemas/AIContentWebSearchToolCallContent"
          },
          {
            "$ref": "#/components/schemas/AIContentWebSearchToolResultContent"
          },
          {
            "$ref": "#/components/schemas/AIContentBase"
          }
        ]
      },
      "AIContentBase": {
        "properties": {
          "annotations": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AIAnnotation"
            }
          },
          "additionalProperties": {
            "type": [
              "null",
              "object"
            ]
          }
        }
      },
      "AIContentCodeInterpreterToolCallContent": {
        "required": [
          "$type",
          "callId"
        ],
        "properties": {
          "$type": {
            "enum": [
              "codeInterpreterToolCall"
            ],
            "type": "string"
          },
          "inputs": {},
          "callId": {
            "type": "string"
          },
          "annotations": {},
          "additionalProperties": {}
        }
      },
      "AIContentCodeInterpreterToolResultContent": {
        "required": [
          "$type",
          "callId"
        ],
        "properties": {
          "$type": {
            "enum": [
              "codeInterpreterToolResult"
            ],
            "type": "string"
          },
          "outputs": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AIContent"
            }
          },
          "callId": {
            "type": "string"
          },
          "annotations": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AIAnnotation"
            }
          },
          "additionalProperties": {
            "type": [
              "null",
              "object"
            ]
          }
        }
      },
      "AIContentDataContent": {
        "required": [
          "$type",
          "uri"
        ],
        "properties": {
          "$type": {
            "enum": [
              "data"
            ],
            "type": "string"
          },
          "uri": {
            "type": "string",
            "description": "A data URI representing the content."
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "annotations": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AIAnnotation"
            }
          },
          "additionalProperties": {
            "type": [
              "null",
              "object"
            ]
          }
        }
      },
      "AIContentErrorContent": {
        "required": [
          "$type",
          "message"
        ],
        "properties": {
          "$type": {
            "enum": [
              "error"
            ],
            "type": "string"
          },
          "message": {
            "type": [
              "null",
              "string"
            ]
          },
          "errorCode": {
            "type": [
              "null",
              "string"
            ]
          },
          "details": {
            "type": [
              "null",
              "string"
            ]
          },
          "annotations": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AIAnnotation"
            }
          },
          "additionalProperties": {
            "type": [
              "null",
              "object"
            ]
          }
        }
      },
      "AIContentFunctionCallContent": {
        "required": [
          "$type",
          "name",
          "callId"
        ],
        "properties": {
          "$type": {
            "enum": [
              "functionCall"
            ],
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "arguments": {
            "type": [
              "null",
              "object"
            ]
          },
          "informationalOnly": {
            "type": "boolean"
          },
          "callId": {
            "type": "string"
          },
          "annotations": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AIAnnotation"
            }
          },
          "additionalProperties": {
            "type": [
              "null",
              "object"
            ]
          }
        }
      },
      "AIContentFunctionResultContent": {
        "required": [
          "$type",
          "result",
          "callId"
        ],
        "properties": {
          "$type": {
            "enum": [
              "functionResult"
            ],
            "type": "string"
          },
          "result": {},
          "callId": {
            "type": "string"
          },
          "annotations": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AIAnnotation"
            }
          },
          "additionalProperties": {
            "type": [
              "null",
              "object"
            ]
          }
        }
      },
      "AIContentHostedFileContent": {
        "required": [
          "$type",
          "fileId"
        ],
        "properties": {
          "$type": {
            "enum": [
              "hostedFile"
            ],
            "type": "string"
          },
          "fileId": {
            "type": "string"
          },
          "mediaType": {
            "type": [
              "null",
              "string"
            ]
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "sizeInBytes": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "createdAt": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "purpose": {
            "type": [
              "null",
              "string"
            ]
          },
          "scope": {
            "type": [
              "null",
              "string"
            ]
          },
          "annotations": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AIAnnotation"
            }
          },
          "additionalProperties": {
            "type": [
              "null",
              "object"
            ]
          }
        }
      },
      "AIContentHostedVectorStoreContent": {
        "required": [
          "$type",
          "vectorStoreId"
        ],
        "properties": {
          "$type": {
            "enum": [
              "hostedVectorStore"
            ],
            "type": "string"
          },
          "vectorStoreId": {
            "type": "string"
          },
          "annotations": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AIAnnotation"
            }
          },
          "additionalProperties": {
            "type": [
              "null",
              "object"
            ]
          }
        }
      },
      "AIContentImageGenerationToolCallContent": {
        "required": [
          "$type",
          "callId"
        ],
        "properties": {
          "$type": {
            "enum": [
              "imageGenerationToolCall"
            ],
            "type": "string"
          },
          "callId": {
            "type": "string"
          },
          "annotations": {},
          "additionalProperties": {}
        }
      },
      "AIContentImageGenerationToolResultContent": {
        "required": [
          "$type",
          "callId"
        ],
        "properties": {
          "$type": {
            "enum": [
              "imageGenerationToolResult"
            ],
            "type": "string"
          },
          "outputs": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AIContent"
            }
          },
          "callId": {
            "type": "string"
          },
          "annotations": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AIAnnotation"
            }
          },
          "additionalProperties": {
            "type": [
              "null",
              "object"
            ]
          }
        }
      },
      "AIContentInputRequestContent": {
        "required": [
          "$type"
        ],
        "properties": {
          "$type": {
            "enum": [
              "inputRequest"
            ],
            "type": "string"
          },
          "requestId": {
            "type": [
              "null",
              "string"
            ]
          },
          "annotations": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AIAnnotation"
            }
          },
          "additionalProperties": {
            "type": [
              "null",
              "object"
            ]
          }
        }
      },
      "AIContentInputResponseContent": {
        "required": [
          "$type"
        ],
        "properties": {
          "$type": {
            "enum": [
              "inputResponse"
            ],
            "type": "string"
          },
          "requestId": {
            "type": [
              "null",
              "string"
            ]
          },
          "annotations": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AIAnnotation"
            }
          },
          "additionalProperties": {
            "type": [
              "null",
              "object"
            ]
          }
        }
      },
      "AIContentMcpServerToolCallContent": {
        "required": [
          "$type",
          "name",
          "serverName",
          "callId"
        ],
        "properties": {
          "$type": {
            "enum": [
              "mcpServerToolCall"
            ],
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "serverName": {
            "type": [
              "null",
              "string"
            ]
          },
          "arguments": {},
          "callId": {
            "type": "string"
          },
          "annotations": {},
          "additionalProperties": {}
        }
      },
      "AIContentMcpServerToolResultContent": {
        "required": [
          "$type",
          "callId"
        ],
        "properties": {
          "$type": {
            "enum": [
              "mcpServerToolResult"
            ],
            "type": "string"
          },
          "outputs": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AIContent"
            }
          },
          "callId": {
            "type": "string"
          },
          "annotations": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AIAnnotation"
            }
          },
          "additionalProperties": {
            "type": [
              "null",
              "object"
            ]
          }
        }
      },
      "AIContentTextContent": {
        "required": [
          "$type",
          "text"
        ],
        "properties": {
          "$type": {
            "enum": [
              "text"
            ],
            "type": "string"
          },
          "text": {
            "type": [
              "null",
              "string"
            ]
          },
          "annotations": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AIAnnotation"
            }
          },
          "additionalProperties": {
            "type": [
              "null",
              "object"
            ]
          }
        }
      },
      "AIContentTextReasoningContent": {
        "required": [
          "$type",
          "text"
        ],
        "properties": {
          "$type": {
            "enum": [
              "reasoning"
            ],
            "type": "string"
          },
          "text": {
            "type": [
              "null",
              "string"
            ]
          },
          "protectedData": {
            "type": [
              "null",
              "string"
            ]
          },
          "annotations": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AIAnnotation"
            }
          },
          "additionalProperties": {
            "type": [
              "null",
              "object"
            ]
          }
        }
      },
      "AIContentToolApprovalRequestContent": {
        "required": [
          "$type",
          "toolCall",
          "requestId"
        ],
        "properties": {
          "$type": {
            "enum": [
              "toolApprovalRequest"
            ],
            "type": "string"
          },
          "toolCall": {
            "$ref": "#/components/schemas/ToolCallContent"
          },
          "requiresConfirmation": {
            "type": "boolean"
          },
          "requestId": {
            "type": "string"
          },
          "annotations": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AIAnnotation"
            }
          },
          "additionalProperties": {
            "type": [
              "null",
              "object"
            ]
          }
        }
      },
      "AIContentToolApprovalResponseContent": {
        "required": [
          "$type",
          "approved",
          "toolCall",
          "requestId"
        ],
        "properties": {
          "$type": {
            "enum": [
              "toolApprovalResponse"
            ],
            "type": "string"
          },
          "approved": {
            "type": "boolean"
          },
          "toolCall": {
            "$ref": "#/components/schemas/ToolCallContent"
          },
          "reason": {
            "type": [
              "null",
              "string"
            ]
          },
          "requestId": {
            "type": "string"
          },
          "annotations": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AIAnnotation"
            }
          },
          "additionalProperties": {
            "type": [
              "null",
              "object"
            ]
          }
        }
      },
      "AIContentToolCallContent": {
        "required": [
          "$type",
          "callId"
        ],
        "properties": {
          "$type": {
            "enum": [
              "toolCall"
            ],
            "type": "string"
          },
          "callId": {
            "type": "string"
          },
          "annotations": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AIAnnotation"
            }
          },
          "additionalProperties": {
            "type": [
              "null",
              "object"
            ]
          }
        }
      },
      "AIContentToolResultContent": {
        "required": [
          "$type",
          "callId"
        ],
        "properties": {
          "$type": {
            "enum": [
              "toolResult"
            ],
            "type": "string"
          },
          "callId": {
            "type": "string"
          },
          "annotations": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AIAnnotation"
            }
          },
          "additionalProperties": {
            "type": [
              "null",
              "object"
            ]
          }
        }
      },
      "AIContentUriContent": {
        "required": [
          "$type",
          "uri"
        ],
        "properties": {
          "$type": {
            "enum": [
              "uri"
            ],
            "type": "string"
          },
          "uri": {
            "type": "string",
            "format": "uri"
          },
          "mediaType": {
            "type": [
              "null",
              "string"
            ]
          },
          "annotations": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AIAnnotation"
            }
          },
          "additionalProperties": {
            "type": [
              "null",
              "object"
            ]
          }
        }
      },
      "AIContentUsageContent": {
        "required": [
          "$type",
          "details"
        ],
        "properties": {
          "$type": {
            "enum": [
              "usage"
            ],
            "type": "string"
          },
          "details": {
            "$ref": "#/components/schemas/UsageDetails"
          },
          "annotations": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AIAnnotation"
            }
          },
          "additionalProperties": {
            "type": [
              "null",
              "object"
            ]
          }
        }
      },
      "AIContentWebSearchToolCallContent": {
        "required": [
          "$type",
          "callId"
        ],
        "properties": {
          "$type": {
            "enum": [
              "webSearchToolCall"
            ],
            "type": "string"
          },
          "queries": {},
          "callId": {
            "type": "string"
          },
          "annotations": {},
          "additionalProperties": {}
        }
      },
      "AIContentWebSearchToolResultContent": {
        "required": [
          "$type",
          "callId"
        ],
        "properties": {
          "$type": {
            "enum": [
              "webSearchToolResult"
            ],
            "type": "string"
          },
          "outputs": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AIContent"
            }
          },
          "callId": {
            "type": "string"
          },
          "annotations": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AIAnnotation"
            }
          },
          "additionalProperties": {
            "type": [
              "null",
              "object"
            ]
          }
        }
      },
      "AnnotatedRegion": {
        "type": "object"
      },
      "ApiKeyCreateRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the name that lets the operator identify the key."
          },
          "scopes": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/ApiKeyScope"
            },
            "description": "Gets the set of scopes. Cannot be empty; an unknown value is rejected."
          },
          "expiresAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the expiration time. If not given, the key never expires.",
            "format": "date-time"
          }
        },
        "description": "The request body for creating an API key."
      },
      "ApiKeyCreationResult": {
        "required": [
          "record",
          "plaintextKey"
        ],
        "type": "object",
        "properties": {
          "record": {
            "description": "The saved view, which carries no raw value.",
            "$ref": "#/components/schemas/ApiKeyRecord"
          },
          "plaintextKey": {
            "type": "string",
            "description": "The raw key value. Cannot be produced again after this call; the\nconsumer must show it immediately and not store it."
          }
        },
        "description": "The result of a key creation operation."
      },
      "ApiKeyRecord": {
        "required": [
          "id",
          "tenantId",
          "name",
          "keyPrefix",
          "scopes",
          "createdAt"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The key identifier.",
            "format": "uuid"
          },
          "tenantId": {
            "type": "string",
            "description": "The tenant the key is bound to. On authentication, the tenant is resolved FROM HERE."
          },
          "name": {
            "type": "string",
            "description": "The name for the operator to recognize the key by."
          },
          "keyPrefix": {
            "type": "string",
            "description": "The raw value's first characters; used to distinguish the key in a list."
          },
          "scopes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApiKeyScope"
            },
            "description": "The scope set. The effective authority is `role ∩ scope`."
          },
          "expiresAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "The expiration. Never expires if `null`.",
            "format": "date-time"
          },
          "revokedAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "The revocation timestamp. The row is NOT DELETED; the audit trail is preserved through this field.",
            "format": "date-time"
          },
          "lastUsedAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "The last-used time. Used to spot an unused key.",
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "description": "The creation time (UTC).",
            "format": "date-time"
          },
          "isActive": {
            "type": "boolean",
            "description": "`true` if the key is not revoked and has not expired."
          }
        },
        "description": "An API key's database-stored view, WHICH CARRIES NO RAW VALUE."
      },
      "ApiKeyScope": {
        "enum": [
          "RunsRead",
          "RunsWrite",
          "AgentsRead",
          "AgentsAdmin",
          "ExternalInvoke",
          "KnowledgeRead",
          "KnowledgeAdmin",
          "WorkflowsRead",
          "WorkflowsAdmin",
          "EvalsRead",
          "EvalsAdmin",
          "ExperimentsRead",
          "ExperimentsAdmin",
          "PlatformRead",
          "PlatformAdmin",
          "SecurityAdmin",
          "AuditRead"
        ],
        "description": "An authority scope an API key may open."
      },
      "ApprovalDecisionRequest": {
        "required": [
          "approved"
        ],
        "type": "object",
        "properties": {
          "approved": {
            "type": "boolean",
            "description": "Gets whether the request was approved."
          }
        },
        "description": "Request body for deciding a pending approval request."
      },
      "ApprovalStatus": {
        "enum": [
          "Pending",
          "Approved",
          "Rejected",
          "Expired"
        ],
        "description": "The status of a pending approval request."
      },
      "AttachmentDescriptor": {
        "required": [
          "id",
          "tenantId",
          "fileName",
          "mediaType",
          "byteSize",
          "sha256",
          "createdAt"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Gets the attachment id.",
            "format": "uuid"
          },
          "tenantId": {
            "type": "string",
            "description": "Gets the tenant the attachment belongs to."
          },
          "sessionId": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the session the attachment was uploaded to. `null` for an\nupload without a session."
          },
          "runId": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the run that produced the attachment. `null` for a user upload.",
            "format": "uuid"
          },
          "fileName": {
            "type": "string",
            "description": "Gets the original file name."
          },
          "mediaType": {
            "type": "string",
            "description": "Gets the validated MIME type. It is the result of the magic-byte check, not the\n`Content-Type` the client sent."
          },
          "byteSize": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Gets the size of the content in bytes.",
            "format": "int64"
          },
          "sha256": {
            "type": "string",
            "description": "Gets the SHA-256 digest of the content (hexadecimal, upper case)."
          },
          "createdBy": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the actor that uploaded it, or `null` when it is unknown."
          },
          "createdAt": {
            "type": "string",
            "description": "Gets the upload time.",
            "format": "date-time"
          }
        },
        "description": "The metadata of an uploaded attachment."
      },
      "AuditChainStatus": {
        "enum": [
          "Valid",
          "Broken",
          "Gap"
        ],
        "description": "The result of walking a tenant's audit trail hash chain."
      },
      "AuditChainVerification": {
        "required": [
          "status",
          "entriesChecked"
        ],
        "type": "object",
        "properties": {
          "status": {
            "description": "Gets the overall chain status.",
            "$ref": "#/components/schemas/AuditChainStatus"
          },
          "entriesChecked": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Gets the number of entries walked.",
            "format": "int32"
          },
          "firstFailingEntryId": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the id of the first entry where the chain fails; `null`\nwhen AuditChainStatus AuditChainVerification.Status is `AuditChainStatus.Valid`.",
            "format": "uuid"
          }
        },
        "description": "The result of verifying one tenant's audit trail hash chain."
      },
      "AuditEntry": {
        "required": [
          "id",
          "tenantId",
          "action",
          "entity",
          "createdAt"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Gets the record id. A time-ordered UUID (v7).",
            "format": "uuid"
          },
          "tenantId": {
            "type": "string",
            "description": "Gets the tenant the change belongs to."
          },
          "actor": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the actor that made the change. It is `null` when there is no\nauthentication or the actor cannot be resolved; that state is not hidden."
          },
          "action": {
            "type": "string",
            "description": "Gets the action name, for example `agent.update`."
          },
          "entity": {
            "type": "string",
            "description": "Gets the affected entity, for example `agent:support`."
          },
          "before": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the state before the change, as JSON text. It has passed the secret filter."
          },
          "after": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the state after the change, as JSON text. It has passed the secret filter."
          },
          "createdAt": {
            "type": "string",
            "description": "Gets the time the record was written (UTC).",
            "format": "date-time"
          },
          "previousHash": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the hash of the previous entry of the same tenant.\n`null` for the first entry of a tenant."
          },
          "hash": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the hash of this entry, derived from its canonical form\n(see `AuditChainHasher` in `AgentPrism.Core`). The write path\ncomputes this value; a caller-supplied value is ignored."
          }
        },
        "description": "A row in the audit trail that records who changed which entity and when."
      },
      "CanaryDecisionKind": {
        "enum": [
          "InsufficientData",
          "Healthy",
          "RollBack"
        ],
        "description": "Defines the outcome of a canary evaluation."
      },
      "CanaryEvaluation": {
        "required": [
          "decision",
          "reason",
          "evaluatedAt"
        ],
        "type": "object",
        "properties": {
          "decision": {
            "description": "Gets the evaluation outcome.",
            "$ref": "#/components/schemas/CanaryDecisionKind"
          },
          "reason": {
            "type": "string",
            "description": "Gets the human-readable reason for the decision."
          },
          "canary": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Gets the current canary variant results. Returns `null` when no runs exist.",
                "$ref": "#/components/schemas/ExperimentVariantResult"
              }
            ]
          },
          "control": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Gets the current control variant results. Returns `null` when no runs exist.",
                "$ref": "#/components/schemas/ExperimentVariantResult"
              }
            ]
          },
          "evaluatedAt": {
            "type": "string",
            "description": "Gets the UTC time when the evaluation occurred.",
            "format": "date-time"
          }
        },
        "description": "Represents the result of evaluating a canary policy against the current results\nof the canary and control variants."
      },
      "CanaryPolicy": {
        "required": [
          "canaryVariant"
        ],
        "type": "object",
        "properties": {
          "canaryVariant": {
            "type": "string",
            "description": "Gets the canary variant name. It must exist in the experiment `Variants` list."
          },
          "maxErrorRateDelta": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "Gets the maximum absolute error-rate difference from the control, from 0.0\nthrough 1.0. The canary rolls back when its rate is higher. No error-rate\ncheck runs when this value is `null`.",
            "format": "double"
          },
          "minScore": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Gets the minimum average canary score from 0 through 100. The canary rolls\nback below this threshold. No score check runs when this value is\n`null`.",
            "format": "int32"
          },
          "minSampleSize": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Gets the minimum completed run count that both the canary and control\nvariants must reach before a decision is made.",
            "format": "int32"
          },
          "rampSteps": {
            "type": "array",
            "items": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            },
            "description": "Gets the canary-weight steps that increase over time, for example\n`[5, 25, 50, 100]`. An empty list disables gradual increases. The\ncanary weight stays at the value set through `SaveAsync` and only\nrollback is evaluated."
          },
          "rampInterval": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string",
            "description": "Gets the minimum time between steps."
          }
        },
        "description": "Defines automatic rollback and gradual traffic-increase rules for an experiment canary variant."
      },
      "ChatChoice": {
        "required": [
          "index",
          "message",
          "finish_reason"
        ],
        "type": "object",
        "properties": {
          "index": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "message": {
            "$ref": "#/components/schemas/ChatMessagePayload"
          },
          "finish_reason": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "ChatCompletion": {
        "required": [
          "id",
          "object",
          "created",
          "model",
          "choices",
          "usage"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "type": "string"
          },
          "created": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "model": {
            "type": "string"
          },
          "choices": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ChatChoice"
            }
          },
          "usage": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/ChatUsage"
              }
            ]
          }
        }
      },
      "ChatMessage": {
        "type": "object",
        "properties": {
          "authorName": {
            "type": [
              "null",
              "string"
            ]
          },
          "createdAt": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "role": {
            "$ref": "#/components/schemas/ChatRole"
          },
          "contents": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AIContent"
            }
          },
          "messageId": {
            "type": [
              "null",
              "string"
            ]
          },
          "additionalProperties": {
            "type": [
              "null",
              "object"
            ]
          }
        }
      },
      "ChatMessagePayload": {
        "required": [
          "role",
          "content"
        ],
        "type": "object",
        "properties": {
          "role": {
            "type": "string"
          },
          "content": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "ChatRole": {},
      "ChatUsage": {
        "required": [
          "prompt_tokens",
          "completion_tokens",
          "total_tokens"
        ],
        "type": "object",
        "properties": {
          "prompt_tokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "completion_tokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "total_tokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int64"
          }
        }
      },
      "ClientToolResult": {
        "required": [
          "callId"
        ],
        "type": "object",
        "properties": {
          "callId": {
            "type": "string",
            "description": "Identifier of the pending call this result answers. Matches the\n`FunctionCallContent.CallId` the run response carried."
          },
          "result": {
            "type": [
              "null",
              "string"
            ],
            "description": "The tool's result, given to the model as plain text. Required unless\n`ErrorMessage` is given."
          },
          "errorMessage": {
            "type": [
              "null",
              "string"
            ],
            "description": "A message describing why the client-side call failed, given to the\nmodel instead of `Result`."
          }
        },
        "description": "The result of a single client-side tool call, sent back so the run can\ncontinue."
      },
      "CompactionSettings": {
        "type": "object",
        "properties": {
          "strategy": {
            "description": "Gets the strategy to apply.",
            "$ref": "#/components/schemas/CompactionStrategyKind"
          },
          "triggerTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Gets the token count above which compaction is triggered.",
            "format": "int32"
          },
          "triggerMessages": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Gets the message count above which compaction is triggered.",
            "format": "int32"
          },
          "triggerTurns": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Gets the turn count above which compaction is triggered.",
            "format": "int32"
          },
          "minimumPreservedTurns": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Gets the minimum number of turns kept for\nCompactionStrategyKind.SlidingWindow. 2 is used when it is not given.",
            "format": "int32"
          },
          "minimumPreservedGroups": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Gets the minimum number of groups kept for CompactionStrategyKind.Truncation,\nCompactionStrategyKind.ToolResult and\nCompactionStrategyKind.Summarization. 4 is used when it is not given.",
            "format": "int32"
          },
          "maxContextWindowTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Gets the context window size. It is required for\nCompactionStrategyKind.ContextWindow and ignored by the other strategies.",
            "format": "int32"
          },
          "maxOutputTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Gets the upper output token limit for CompactionStrategyKind.ContextWindow.\nWhen it is not given, `ModelBinding.MaxOutputTokens` from the agent's own\nmodel binding is used, and 4096 when that is missing too.",
            "format": "int32"
          },
          "summarizationPrompt": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the extra instruction added to the summarization prompt for\nCompactionStrategyKind.Summarization and\nCompactionStrategyKind.Pipeline. When `null` the\ndefault prompt of MAF is used."
          },
          "summarizationModel": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Gets the model used for the summarization call. When it is empty the order is\nfollowed: the application-wide helper model setting, and the agent's own model\nwhen that is missing.",
                "$ref": "#/components/schemas/ModelBinding"
              }
            ]
          }
        },
        "description": "Determines how an agent compacts its conversation history."
      },
      "CompactionStrategyKind": {
        "enum": [
          "None",
          "SlidingWindow",
          "Truncation",
          "ToolResult",
          "Summarization",
          "ContextWindow",
          "Pipeline"
        ],
        "description": "The kind of context compaction strategy that can be bound to an agent definition."
      },
      "ContextWindowEstimate": {
        "required": [
          "promptTokens",
          "contextWindowTokens",
          "allowedPromptTokens",
          "wouldBeRejected"
        ],
        "type": "object",
        "properties": {
          "promptTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Gets the estimated token count of the prompt. The estimate is approximate.",
            "format": "int32"
          },
          "contextWindowTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Gets the model's context window size, taken from the model catalog's\n`ModelDescriptor.ContextWindowTokens`.\n`null` when the model is not found in the catalog.",
            "format": "int32"
          },
          "allowedPromptTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Gets the token budget kept for the prompt after\n`AgentPrismPreflightOptions.ReserveRatio` is set aside for\nthe answer. `null` when `ContextWindowTokens` is unknown.",
            "format": "int32"
          },
          "wouldBeRejected": {
            "type": "boolean",
            "description": "Gets whether a real run with this prompt would be rejected by the\npre-flight check. Always `false` when\n`ContextWindowTokens` is unknown — an unknown window can never\nbe exceeded."
          }
        },
        "description": "The result of a pre-flight context-window check, computed without calling\nthe model provider."
      },
      "ConversationResource": {
        "required": [
          "id",
          "object",
          "created_at",
          "metadata"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "type": "string"
          },
          "created_at": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "metadata": {
            "type": [
              "null",
              "object"
            ],
            "additionalProperties": {
              "type": "string"
            }
          }
        }
      },
      "CurrentTenantResponse": {
        "required": [
          "tenantId"
        ],
        "type": "object",
        "properties": {
          "tenantId": {
            "type": "string",
            "description": "Tenant identifier."
          }
        },
        "description": "Tenant of the current request."
      },
      "DataSubjectErasureResult": {
        "required": [
          "dryRun",
          "rowsByTarget"
        ],
        "type": "object",
        "properties": {
          "dryRun": {
            "type": "boolean",
            "description": "Gets whether this was a preview: `true` means\nIReadOnlyDictionary&lt;string, int&gt; DataSubjectErasureResult.RowsByTarget shows what WOULD be deleted and nothing was\nactually removed."
          },
          "rowsByTarget": {
            "type": "object",
            "additionalProperties": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            },
            "description": "Gets the number of rows removed (or, for a preview, that would be removed), by target table."
          }
        },
        "description": "The outcome of a data subject erasure request."
      },
      "DeletedResource": {
        "required": [
          "id",
          "object",
          "deleted"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "type": "string"
          },
          "deleted": {
            "type": "boolean"
          }
        }
      },
      "EvalCase": {
        "required": [
          "suiteId",
          "seq",
          "query"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The case identifier.",
            "format": "uuid"
          },
          "suiteId": {
            "type": "string",
            "description": "The identifier of the suite this case belongs to.",
            "format": "uuid"
          },
          "seq": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The sequence number within the suite (starts at 0).",
            "format": "int32"
          },
          "query": {
            "type": "string",
            "description": "The query text sent to the agent."
          },
          "expectedOutput": {
            "type": [
              "null",
              "string"
            ],
            "description": "The expected output. Referenced by the `containsExpected` check."
          },
          "expectedTools": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The tool names looked up by the `toolCalled` check. An empty list\ndoes not mean the check accepts any tool call — the check is still\ndefined separately in the suite's `checks` field."
          },
          "context": {
            "type": [
              "null",
              "string"
            ],
            "description": "Text given to the model as extra context."
          },
          "sourceRunId": {
            "type": [
              "null",
              "string"
            ],
            "description": "The run the case was generated from. `null` when hand-written.",
            "format": "uuid"
          },
          "sourceKind": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "The reason for promotion. `null` when hand-written.",
                "$ref": "#/components/schemas/EvalCaseSource"
              }
            ]
          },
          "promotedAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "The promotion time. `null` when hand-written.",
            "format": "date-time"
          }
        },
        "description": "A single test case inside an EvalSuite."
      },
      "EvalCaseInput": {
        "required": [
          "query"
        ],
        "type": "object",
        "properties": {
          "query": {
            "type": "string",
            "description": "Query text to send to the agent."
          },
          "expectedOutput": {
            "type": [
              "null",
              "string"
            ],
            "description": "Expected output."
          },
          "expectedTools": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Tool names looked for by the `toolCalled` check."
          },
          "context": {
            "type": [
              "null",
              "string"
            ],
            "description": "Text to give the model as extra context."
          }
        },
        "description": "Input shape of an eval case (in a request)."
      },
      "EvalCasePromotionRequest": {
        "type": "object",
        "properties": {
          "sourceKind": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Overrides the promotion reason. If not given, it is derived\nautomatically from the run's status and score.",
                "$ref": "#/components/schemas/EvalCaseSource"
              }
            ]
          }
        },
        "description": "Request to promote a run to a case."
      },
      "EvalCaseResult": {
        "required": [
          "evalRunId",
          "caseId",
          "passed"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The result record identifier.",
            "format": "uuid"
          },
          "evalRunId": {
            "type": "string",
            "description": "The identifier of the run this result belongs to.",
            "format": "uuid"
          },
          "caseId": {
            "type": "string",
            "description": "The identifier of the case being measured.",
            "format": "uuid"
          },
          "runId": {
            "type": [
              "null",
              "string"
            ],
            "description": "The identifier of the run record created while processing this case.\nThis lets an eval failure jump straight to its transcript and span tree.",
            "format": "uuid"
          },
          "passed": {
            "type": "boolean",
            "description": "Reports whether the case passed all of its checks."
          },
          "output": {
            "type": [
              "null",
              "string"
            ],
            "description": "The text output produced by the agent."
          },
          "scores": {
            "description": "Per-check score list (free-form JSON).",
            "$ref": "#/components/schemas/JsonElement"
          },
          "failureReason": {
            "type": [
              "null",
              "string"
            ],
            "description": "The failure reason. Populated only when `Passed` is `false`."
          }
        },
        "description": "The result of a single EvalCase within an EvalRun."
      },
      "EvalCaseSource": {
        "enum": [
          "FailedRun",
          "NegativeScore",
          "ReferenceRun",
          null
        ]
      },
      "EvalRun": {
        "required": [
          "id",
          "tenantId",
          "suiteId",
          "status",
          "startedAt"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The run identifier.",
            "format": "uuid"
          },
          "tenantId": {
            "type": "string",
            "description": "The tenant the run belongs to."
          },
          "suiteId": {
            "type": "string",
            "description": "The identifier of the suite being measured.",
            "format": "uuid"
          },
          "jobId": {
            "type": [
              "null",
              "string"
            ],
            "description": "The identifier of the job record responsible for executing this run. The\nrun is executed through the job queue (IJobStore).",
            "format": "uuid"
          },
          "agentVersion": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "The agent definition version being measured. `null` before the run starts.",
            "format": "int32"
          },
          "modelId": {
            "type": [
              "null",
              "string"
            ],
            "description": "The model identifier being measured. `null` before the run starts."
          },
          "status": {
            "description": "The current status of the run.",
            "$ref": "#/components/schemas/EvalRunStatus"
          },
          "total": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The total number of cases.",
            "format": "int32"
          },
          "passed": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The number of cases that passed.",
            "format": "int32"
          },
          "failed": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The number of remaining (failed) cases.",
            "format": "int32"
          },
          "inputTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "The total input token count.",
            "format": "int64"
          },
          "outputTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "The total output token count.",
            "format": "int64"
          },
          "startedAt": {
            "type": "string",
            "description": "The start time (UTC).",
            "format": "date-time"
          },
          "completedAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "The completion time (UTC). `null` while the run is in progress.",
            "format": "date-time"
          }
        },
        "description": "A single execution record and summary of an EvalSuite."
      },
      "EvalRunDetailResponse": {
        "required": [
          "run",
          "results"
        ],
        "type": "object",
        "properties": {
          "run": {
            "description": "Run summary.",
            "$ref": "#/components/schemas/EvalRun"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EvalCaseResult"
            },
            "description": "Per-case results."
          }
        },
        "description": "Detailed view of a single eval run: summary and case results together."
      },
      "EvalRunStatus": {
        "enum": [
          "Pending",
          "Running",
          "Completed",
          "Failed",
          "Cancelled"
        ],
        "description": "The status of an eval run."
      },
      "EvalRunTriggerRequest": {
        "type": "object",
        "properties": {
          "modelId": {
            "type": [
              "null",
              "string"
            ],
            "description": "Model identifier to record for this run. If not given, the model in\nthe agent's current definition is used."
          },
          "numRepetitions": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Number of times to repeat each case to measure its stability. If not\ngiven, 1.",
            "format": "int32"
          },
          "agentVersion": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Definition version to measure for this run. If not given, the agent's\ncurrent version is used. Rejected with 400 for code-sourced agents (no\nversion history).",
            "format": "int32"
          }
        },
        "description": "Request to trigger an eval run immediately."
      },
      "EvalSuite": {
        "required": [
          "tenantId",
          "name",
          "agentName"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The suite identifier.",
            "format": "uuid"
          },
          "tenantId": {
            "type": "string",
            "description": "The tenant the suite belongs to."
          },
          "name": {
            "type": "string",
            "description": "The suite name. Unique within the tenant."
          },
          "description": {
            "type": [
              "null",
              "string"
            ],
            "description": "A short description."
          },
          "agentName": {
            "type": "string",
            "description": "The name of the agent this suite measures."
          },
          "checks": {
            "description": "The check definitions. Example: `[{\"kind\":\"nonEmpty\",\"minLength\":10}]`.",
            "$ref": "#/components/schemas/JsonElement"
          },
          "createdAt": {
            "type": "string",
            "description": "The creation time (UTC).",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "description": "The last-updated time (UTC).",
            "format": "date-time"
          }
        },
        "description": "An evaluation (eval) suite defined for an agent: carries which agent is\nmeasured, with which checks."
      },
      "EvalSuiteSaveRequest": {
        "required": [
          "agentName"
        ],
        "type": "object",
        "properties": {
          "description": {
            "type": [
              "null",
              "string"
            ],
            "description": "Short description."
          },
          "agentName": {
            "type": "string",
            "description": "Name of the agent this suite measures."
          },
          "checks": {
            "description": "Check definitions. See `EvalSuite.Checks`.",
            "$ref": "#/components/schemas/JsonElement"
          }
        },
        "description": "Request to create/update an eval suite."
      },
      "Experiment": {
        "required": [
          "id",
          "tenantId",
          "name",
          "agentName",
          "variants"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Gets the experiment identifier.",
            "format": "uuid"
          },
          "tenantId": {
            "type": "string",
            "description": "Gets the tenant that owns the experiment."
          },
          "name": {
            "type": "string",
            "description": "Gets the experiment name. It is unique within the tenant and is used as an API route key."
          },
          "agentName": {
            "type": "string",
            "description": "Gets the name of the agent whose traffic is split."
          },
          "variants": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExperimentVariant"
            },
            "description": "Gets the experiment variants. Their weights must total 100."
          },
          "status": {
            "description": "Gets the current experiment status.",
            "$ref": "#/components/schemas/ExperimentStatus"
          },
          "assignmentKey": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets a reserved value. Runtime assignment does <strong>not read</strong> it\nin this phase. The assignment key is always the session identifier, or the\nrun identifier when no session exists. This property is reserved for future\nstrategies that assign outside a session."
          },
          "startedAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the time when the experiment entered ExperimentStatus.Running. Returns `null` while it is a\ndraft.",
            "format": "date-time"
          },
          "endedAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the time when the experiment stopped. Returns `null` when\nit runs or never started.",
            "format": "date-time"
          },
          "updatedAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the UTC time of the last update.",
            "format": "date-time"
          },
          "canary": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Gets the canary policy. `null` disables automatic decisions,\nso no background service evaluates this experiment.",
                "$ref": "#/components/schemas/CanaryPolicy"
              }
            ]
          },
          "rollbackReason": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the reason for an automatic rollback. Returns `null`\nwhen the experiment was stopped manually or was never stopped."
          }
        },
        "description": "Represents an A/B experiment that splits traffic between two or more definition versions of the same agent."
      },
      "ExperimentCanaryResponse": {
        "type": "object",
        "properties": {
          "policy": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "The defined canary rule. `null` if none has been defined.",
                "$ref": "#/components/schemas/CanaryPolicy"
              }
            ]
          },
          "evaluation": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Current evaluation of the rule. `null` if `Policy` is `null`.",
                "$ref": "#/components/schemas/CanaryEvaluation"
              }
            ]
          }
        },
        "description": "Response for `GET /api/experiments/{name}/canary` — the rule AND its\ncurrent evaluation together."
      },
      "ExperimentResultsResponse": {
        "required": [
          "experiment",
          "results"
        ],
        "type": "object",
        "properties": {
          "experiment": {
            "description": "The experiment itself.",
            "$ref": "#/components/schemas/Experiment"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExperimentVariantResult"
            },
            "description": "Per-arm results."
          }
        },
        "description": "Per-variant results view of an experiment."
      },
      "ExperimentSaveRequest": {
        "required": [
          "agentName",
          "variants"
        ],
        "type": "object",
        "properties": {
          "agentName": {
            "type": "string",
            "description": "Name of the agent whose traffic is split."
          },
          "variants": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExperimentVariant"
            },
            "description": "The experiment's arms. Weights must sum to 100."
          }
        },
        "description": "Request to create/update an experiment. The name comes from the path."
      },
      "ExperimentStatus": {
        "enum": [
          "Draft",
          "Running",
          "Stopped"
        ],
        "description": "Defines the lifecycle status of an A/B experiment."
      },
      "ExperimentVariant": {
        "required": [
          "name",
          "version",
          "weight"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Gets the variant name, for example `\"control\"` or `\"v3\"`. It must be\nunique within the experiment."
          },
          "version": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Gets the `AgentDefinition.Version` number to serve.",
            "format": "int32"
          },
          "weight": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Gets the traffic weight from 0 through 100. The weights of all experiment\nvariants must total exactly 100 or saving is rejected. See Experiment.",
            "format": "int32"
          }
        },
        "description": "Defines one experiment variant: its definition version and traffic weight."
      },
      "ExperimentVariantResult": {
        "required": [
          "variant",
          "version",
          "totalRuns",
          "completedRuns",
          "failedRuns",
          "canceledRuns"
        ],
        "type": "object",
        "properties": {
          "variant": {
            "type": "string",
            "description": "Gets the variant name."
          },
          "version": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Gets the definition version served by the variant.",
            "format": "int32"
          },
          "totalRuns": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Gets the total number of runs assigned to this variant.",
            "format": "int64"
          },
          "completedRuns": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Gets the number of successfully completed runs.",
            "format": "int64"
          },
          "failedRuns": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Gets the number of runs that ended with an error.",
            "format": "int64"
          },
          "canceledRuns": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Gets the number of cancelled runs.",
            "format": "int64"
          },
          "inputTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Gets the total input tokens.",
            "format": "int64"
          },
          "outputTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Gets the total output tokens.",
            "format": "int64"
          },
          "totalTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Gets the total tokens.",
            "format": "int64"
          },
          "totalCost": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "Gets the total cost for this variant. Returns `null` when pricing is undefined.",
            "format": "double"
          },
          "currency": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the currency. It is populated when `TotalCost` is populated."
          },
          "averageDurationMs": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "Gets the average duration of settled runs in milliseconds. Returns\n`null` when no run is settled.",
            "format": "double"
          },
          "errorRate": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "Gets the error rate among settled runs, from 0 through 1. It uses the same\ncalculation as `RunStatistics.ErrorRate`.",
            "format": "double"
          },
          "averageScore": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "Gets the average numeric score from 0 through 100 for runs assigned to this\nvariant. It uses the `RunScoreKind.Numeric` scores written by online evaluation.\nReturns `null` when no run is scored. This is not\n`0`; it means unknown, consistent with the existing `RunCost`\ncontract.",
            "format": "double"
          }
        },
        "description": "Summarizes run results for an experiment variant (calculated in the store)."
      },
      "HarnessSettings": {
        "type": "object",
        "properties": {
          "maxContextWindowTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Gets the token limit of the context window. Compaction starts once it is exceeded.",
            "format": "int32"
          },
          "maxOutputTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Gets the upper token limit produced in a single response.",
            "format": "int32"
          },
          "maximumIterationsPerRequest": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Gets the upper number of iterations allowed within a single request.",
            "format": "int32"
          },
          "harnessInstructions": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the extra instructions passed to the harness."
          },
          "disableCompaction": {
            "type": "boolean",
            "description": "Gets a value that turns off context compaction."
          },
          "disableTodoProvider": {
            "type": "boolean",
            "description": "Gets a value that turns off todo tracking."
          },
          "disableFileMemory": {
            "type": "boolean",
            "description": "Gets a value that turns off file memory."
          },
          "disableWebSearch": {
            "type": "boolean",
            "description": "Gets a value that turns off web search."
          },
          "disableToolAutoApproval": {
            "type": "boolean",
            "description": "Gets a value that turns off automatic tool approval. Once turned off, every tool\ncall waits for an explicit approval."
          },
          "disableAgentSkillsProvider": {
            "type": "boolean",
            "description": "Gets a value that turns off the agent skills provider."
          },
          "disableAgentModeProvider": {
            "type": "boolean",
            "description": "Gets a value that turns off the agent mode provider."
          }
        },
        "description": "Settings for the harness capabilities. It mirrors a safe subset of the\n`HarnessAgentOptions` structure of Microsoft Agent Framework."
      },
      "IFormFile": {
        "type": "string",
        "format": "binary"
      },
      "IMcpToolRefresher": {
        "type": "object",
        "description": "Refreshes the tool list of remote MCP servers on demand."
      },
      "InboundTriggerAcceptedResponse": {
        "required": [
          "jobId",
          "location"
        ],
        "type": "object",
        "properties": {
          "runId": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the identifier of the queued run, when the trigger targets an\nagent. `null` for a workflow target — a workflow job\nis not tied to a single run id until it is picked up from the queue.",
            "format": "uuid"
          },
          "jobId": {
            "type": "string",
            "description": "Gets the identifier of the queued job.",
            "format": "uuid"
          },
          "location": {
            "type": "string",
            "description": "Gets the address to poll for the outcome. Same as the `Location` header."
          },
          "eventsLocation": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the address of the run's event stream. `null` for a workflow target."
          }
        },
        "description": "The response for a successfully accepted inbound trigger event."
      },
      "InboundTriggerPayloadMode": {
        "enum": [
          "WholeBody",
          "Path"
        ],
        "description": "How an inbound trigger's request body becomes the agent/workflow message."
      },
      "InboundTriggerResponse": {
        "required": [
          "name",
          "targetKind",
          "targetName",
          "signingSecretConfigurationName",
          "resolved",
          "payloadMode",
          "enabled",
          "createdAt",
          "updatedAt"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Gets the trigger name."
          },
          "targetKind": {
            "description": "Gets the kind of target the trigger starts.",
            "$ref": "#/components/schemas/InboundTriggerTargetKind"
          },
          "targetName": {
            "type": "string",
            "description": "Gets the agent or workflow name the trigger starts."
          },
          "signingSecretConfigurationName": {
            "type": "string",
            "description": "Gets the configuration key name the signing secret is read from."
          },
          "resolved": {
            "type": "boolean",
            "description": "Gets whether `SigningSecretConfigurationName` currently resolves to a value."
          },
          "payloadMode": {
            "description": "Gets how the request body becomes the run's message.",
            "$ref": "#/components/schemas/InboundTriggerPayloadMode"
          },
          "payloadPath": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the dotted path used when InboundTriggerPayloadMode InboundTriggerResponse.PayloadMode is InboundTriggerPayloadMode.Path."
          },
          "enabled": {
            "type": "boolean",
            "description": "Gets whether the trigger accepts requests."
          },
          "createdAt": {
            "type": "string",
            "description": "Gets the creation time (UTC).",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "description": "Gets the last-updated time (UTC).",
            "format": "date-time"
          }
        },
        "description": "The response describing an inbound trigger definition."
      },
      "InboundTriggerSaveRequest": {
        "type": "object",
        "properties": {
          "targetKind": {
            "description": "Gets the kind of target the trigger starts. Default InboundTriggerTargetKind.Agent.",
            "$ref": "#/components/schemas/InboundTriggerTargetKind"
          },
          "targetName": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the agent or workflow name to run."
          },
          "signingSecretConfigurationName": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the configuration key name the signing secret is read from. Never a value."
          },
          "payloadMode": {
            "description": "Gets how the request body becomes the run's message. Default InboundTriggerPayloadMode.WholeBody.",
            "$ref": "#/components/schemas/InboundTriggerPayloadMode"
          },
          "payloadPath": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the dotted path used when InboundTriggerPayloadMode InboundTriggerSaveRequest.PayloadMode is InboundTriggerPayloadMode.Path."
          },
          "enabled": {
            "type": "boolean",
            "description": "Gets whether the trigger accepts requests. Default `true`."
          }
        },
        "description": "The request body for creating or replacing an inbound trigger."
      },
      "InboundTriggerTargetKind": {
        "enum": [
          "Agent",
          "Workflow"
        ],
        "description": "What kind of target an inbound trigger fires."
      },
      "ItemContent": {
        "required": [
          "type",
          "text"
        ],
        "type": "object",
        "properties": {
          "type": {
            "type": "string"
          },
          "text": {
            "type": "string"
          }
        }
      },
      "ItemListResource": {
        "required": [
          "object",
          "data",
          "first_id",
          "last_id",
          "has_more"
        ],
        "type": "object",
        "properties": {
          "object": {
            "type": "string"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ItemResource"
            }
          },
          "first_id": {
            "type": [
              "null",
              "string"
            ]
          },
          "last_id": {
            "type": [
              "null",
              "string"
            ]
          },
          "has_more": {
            "type": "boolean"
          }
        }
      },
      "ItemResource": {
        "required": [
          "id",
          "type",
          "status",
          "role",
          "content",
          "call_id",
          "name",
          "arguments",
          "output"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "status": {
            "type": [
              "null",
              "string"
            ]
          },
          "role": {
            "type": [
              "null",
              "string"
            ]
          },
          "content": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/ItemContent"
            }
          },
          "call_id": {
            "type": [
              "null",
              "string"
            ]
          },
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "arguments": {
            "type": [
              "null",
              "string"
            ]
          },
          "output": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "JobDetailResponse": {
        "required": [
          "job",
          "items"
        ],
        "type": "object",
        "properties": {
          "job": {
            "description": "Job record.",
            "$ref": "#/components/schemas/JobRecord"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/JobItemRecord"
            },
            "description": "The job's items, in sequence order."
          }
        },
        "description": "Detailed view of a single job: record and items together."
      },
      "JobItemRecord": {
        "required": [
          "id",
          "jobId",
          "seq",
          "input",
          "status"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The item identifier.",
            "format": "uuid"
          },
          "jobId": {
            "type": "string",
            "description": "The identifier of the job it belongs to.",
            "format": "uuid"
          },
          "seq": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The sequence number within the job (starts at 0).",
            "format": "int32"
          },
          "input": {
            "type": "string",
            "description": "This item's input text."
          },
          "runId": {
            "type": [
              "null",
              "string"
            ],
            "description": "The identifier of the run record created while processing this item.\n`null` if the item has not been processed yet.",
            "format": "uuid"
          },
          "status": {
            "description": "The item's processing status.",
            "$ref": "#/components/schemas/JobItemStatus"
          },
          "error": {
            "type": [
              "null",
              "string"
            ],
            "description": "The failure message. Populated only for JobItemStatus.Failed."
          }
        },
        "description": "A single input of a batch job and that input's processing result."
      },
      "JobItemStatus": {
        "enum": [
          "Pending",
          "Completed",
          "Failed"
        ],
        "description": "The status of a batch job item."
      },
      "JobKind": {
        "enum": [
          "AgentBatch",
          "Workflow",
          "Eval",
          "WebhookDelivery",
          "Retention",
          "AgentRun",
          "OnlineEval",
          "ApprovalResume"
        ],
        "description": "What target a job runs."
      },
      "JobRecord": {
        "required": [
          "id",
          "tenantId",
          "kind",
          "targetName",
          "status",
          "scheduledFor",
          "createdAt"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The job identifier.",
            "format": "uuid"
          },
          "tenantId": {
            "type": "string",
            "description": "The tenant the job belongs to."
          },
          "scheduleId": {
            "type": [
              "null",
              "string"
            ],
            "description": "The identifier of the schedule that produced this job.\n`null` for manually created (one-off) jobs.",
            "format": "uuid"
          },
          "kind": {
            "description": "The job's kind.",
            "$ref": "#/components/schemas/JobKind"
          },
          "targetName": {
            "type": "string",
            "description": "The agent or workflow name to run."
          },
          "status": {
            "description": "The job's current status.",
            "$ref": "#/components/schemas/JobStatus"
          },
          "payload": {
            "description": "The input set or parameters.",
            "$ref": "#/components/schemas/JsonElement"
          },
          "totalItems": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The total number of items.",
            "format": "int32"
          },
          "doneItems": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The number of items that completed successfully.",
            "format": "int32"
          },
          "failedItems": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The number of items that failed.",
            "format": "int32"
          },
          "attempt": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The number of lease attempts. Increments on every ValueTask&lt;JobRecord?&gt; IJobStore.LeaseAsync(string owner, TimeSpan leaseDuration, CancellationToken cancellationToken = default(CancellationToken)) call.",
            "format": "int32"
          },
          "maxAttempts": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "The maximum number of attempts specific to this job. If\n`null`, `AgentPrismSchedulingOptions.MaxAttempts` applies.",
            "format": "int32"
          },
          "leaseOwner": {
            "type": [
              "null",
              "string"
            ],
            "description": "The identifier of the worker currently leasing the job. `null` if not leased."
          },
          "leaseUntil": {
            "type": [
              "null",
              "string"
            ],
            "description": "The time the current lease expires (UTC). The job may be re-leased once it expires.",
            "format": "date-time"
          },
          "scheduledFor": {
            "type": "string",
            "description": "The earliest time the job is eligible to run (UTC).",
            "format": "date-time"
          },
          "startedAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "The time the first lease happened (UTC).",
            "format": "date-time"
          },
          "completedAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "The completion time (UTC). `null` while the job is in progress.",
            "format": "date-time"
          },
          "errorMessage": {
            "type": [
              "null",
              "string"
            ],
            "description": "The failure message. Populated only for JobStatus.Failed."
          },
          "createdAt": {
            "type": "string",
            "description": "The creation time (UTC).",
            "format": "date-time"
          }
        },
        "description": "The summary of a queued job. The header of its items (JobItemRecord)."
      },
      "JobSchedule": {
        "required": [
          "tenantId",
          "name",
          "kind",
          "targetName",
          "createdAt",
          "updatedAt"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The schedule identifier.",
            "format": "uuid"
          },
          "tenantId": {
            "type": "string",
            "description": "The tenant the schedule belongs to."
          },
          "name": {
            "type": "string",
            "description": "The schedule name, unique within the tenant."
          },
          "kind": {
            "description": "The kind of job this schedule produces.",
            "$ref": "#/components/schemas/JobKind"
          },
          "targetName": {
            "type": "string",
            "description": "The agent or workflow name to run."
          },
          "cron": {
            "type": [
              "null",
              "string"
            ],
            "description": "The five-field cron expression (`minute hour day-of-month month\nday-of-week`). If `null`, the schedule is triggered only manually."
          },
          "timeZone": {
            "type": "string",
            "description": "The time zone the `Cron` expression is interpreted in."
          },
          "payload": {
            "description": "The input set or parameters. Interpreted according to the job kind.",
            "$ref": "#/components/schemas/JsonElement"
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether the schedule is enabled. If disabled, it is not triggered automatically."
          },
          "nextRunAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "The next automatic run time (UTC). `null` if there is no cron.",
            "format": "date-time"
          },
          "lastRunAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "The last run time (UTC). `null` if it never ran.",
            "format": "date-time"
          },
          "createdBy": {
            "type": [
              "null",
              "string"
            ],
            "description": "The identifier of the user/service that created the schedule."
          },
          "createdAt": {
            "type": "string",
            "description": "The creation time (UTC).",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "description": "The last-updated time (UTC).",
            "format": "date-time"
          }
        },
        "description": "The schedule record defining when and how a job runs."
      },
      "JobScheduleSaveRequest": {
        "required": [
          "kind",
          "targetName"
        ],
        "type": "object",
        "properties": {
          "kind": {
            "description": "Kind of job this schedule produces.",
            "$ref": "#/components/schemas/JobKind"
          },
          "targetName": {
            "type": "string",
            "description": "Name of the agent or workflow to run."
          },
          "cron": {
            "type": [
              "null",
              "string"
            ],
            "description": "Five-field cron expression. If left empty, the schedule can only be\ntriggered manually (`POST .../trigger`)."
          },
          "timeZone": {
            "type": "string",
            "description": "Time zone the `Cron` expression is interpreted in."
          },
          "payload": {
            "description": "Input set or parameters.",
            "$ref": "#/components/schemas/JsonElement"
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether the schedule is enabled."
          }
        },
        "description": "Request to create/update a schedule."
      },
      "JobStatus": {
        "enum": [
          "Pending",
          "Leased",
          "Running",
          "Completed",
          "Failed",
          "Cancelled"
        ],
        "description": "The status of a queued job."
      },
      "JobTriggerRequest": {
        "type": "object",
        "properties": {
          "payload": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Payload to use for this run. If left empty, the schedule's own payload\nis used.",
                "$ref": "#/components/schemas/JsonElement"
              }
            ]
          }
        },
        "description": "Request to trigger a schedule immediately."
      },
      "JsonElement": {},
      "McpOAuthAuthorizationMode": {
        "enum": [
          "AuthorizationCode"
        ],
        "description": "The MCP OAuth authorization flow."
      },
      "McpOAuthStartResponse": {
        "required": [
          "authorizationUri",
          "state"
        ],
        "type": "object",
        "properties": {
          "authorizationUri": {
            "type": "string",
            "description": "Authorization address the admin is redirected to."
          },
          "state": {
            "type": "string",
            "description": "Single-use state value generated for CSRF protection."
          }
        },
        "description": "Response for starting OAuth Mode 1."
      },
      "McpPromptArgumentsRequest": {
        "type": "object",
        "properties": {
          "arguments": {
            "type": [
              "null",
              "object"
            ],
            "additionalProperties": {
              "type": "string"
            },
            "description": "Prompt arguments."
          }
        },
        "description": "Request to resolve an MCP prompt with arguments."
      },
      "McpPromptArgumentSummary": {
        "required": [
          "name"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "The argument name."
          },
          "description": {
            "type": [
              "null",
              "string"
            ],
            "description": "The description."
          },
          "required": {
            "type": "boolean",
            "description": "Whether the argument is required."
          }
        },
        "description": "The summary of an MCP prompt argument."
      },
      "McpPromptContent": {
        "required": [
          "text",
          "hash"
        ],
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The text concatenated from the prompt's messages."
          },
          "hash": {
            "type": "string",
            "description": "The content's SHA-256 digest (hex). The snapshot is stored in\n`AgentDefinition.Metadata` under the `mcp.prompt.hash` key;\nwhen the server's content changes, the UI compares this digest and\nshows a badge."
          }
        },
        "description": "The resolved content of a prompt."
      },
      "McpPromptSummary": {
        "required": [
          "name"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "The prompt name."
          },
          "title": {
            "type": [
              "null",
              "string"
            ],
            "description": "The title shown in the UI."
          },
          "description": {
            "type": [
              "null",
              "string"
            ],
            "description": "The description."
          },
          "arguments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/McpPromptArgumentSummary"
            },
            "description": "The arguments the prompt accepts."
          }
        },
        "description": "The summary of an MCP prompt."
      },
      "McpRefreshResponse": {
        "required": [
          "toolCount"
        ],
        "type": "object",
        "properties": {
          "toolCount": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Total number of tools available after the refresh.",
            "format": "int32"
          }
        },
        "description": "Result of an MCP tool refresh."
      },
      "McpResourceContent": {
        "required": [
          "uri"
        ],
        "type": "object",
        "properties": {
          "uri": {
            "type": "string",
            "description": "The resource URI."
          },
          "mimeType": {
            "type": [
              "null",
              "string"
            ],
            "description": "The MIME type."
          },
          "text": {
            "type": [
              "null",
              "string"
            ],
            "description": "The text content. `null` for binary resources."
          },
          "isBinary": {
            "type": "boolean",
            "description": "Whether the resource is binary (a blob)."
          },
          "byteSize": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The byte size of the raw content (before truncation).",
            "format": "int32"
          },
          "truncated": {
            "type": "boolean",
            "description": "Whether the content was truncated because it exceeded the size limit."
          }
        },
        "description": "The content of a resource that was read."
      },
      "McpResourceSummary": {
        "required": [
          "uri",
          "name"
        ],
        "type": "object",
        "properties": {
          "uri": {
            "type": "string",
            "description": "The resource URI."
          },
          "name": {
            "type": "string",
            "description": "The resource name."
          },
          "mimeType": {
            "type": [
              "null",
              "string"
            ],
            "description": "The MIME type."
          },
          "description": {
            "type": [
              "null",
              "string"
            ],
            "description": "The description."
          }
        },
        "description": "The summary of an MCP resource."
      },
      "McpServerDefinition": {
        "required": [
          "id",
          "tenantId",
          "name",
          "endpoint"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The server identifier. A time-ordered UUID (v7).",
            "format": "uuid"
          },
          "tenantId": {
            "type": "string",
            "description": "The tenant the server belongs to."
          },
          "name": {
            "type": "string",
            "description": "The server name. Discovered tools are named as `{name}.{tool}`, so\ntools with the same name on two servers never collide."
          },
          "description": {
            "type": [
              "null",
              "string"
            ],
            "description": "The description."
          },
          "endpoint": {
            "type": "string",
            "description": "The server address. Only `http` and `https` are accepted.",
            "format": "uri"
          },
          "transport": {
            "description": "The transport format.",
            "$ref": "#/components/schemas/McpTransportMode"
          },
          "authorizationConfigurationKey": {
            "type": [
              "null",
              "string"
            ],
            "description": "The configuration key the `Authorization` header's value is read\nfrom. Example: `AgentPrism:McpSecrets:GithubToken`. If left empty, the\nheader is not sent."
          },
          "headers": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Extra request headers. <strong>Must not carry a secret</strong> — these\nvalues are stored as-is and shown in the UI."
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether the server is enabled. Its tools are not discovered while disabled."
          },
          "oauthEnabled": {
            "type": "boolean",
            "description": "Whether OAuth authentication is on. When on, it cannot be used at the\nsame time as `AuthorizationConfigurationKey` — both would\ntry to manage the `Authorization` header."
          },
          "oauthClientId": {
            "type": [
              "null",
              "string"
            ],
            "description": "The OAuth client identifier. Not a secret, stored as-is."
          },
          "oauthClientSecretConfigurationKey": {
            "type": [
              "null",
              "string"
            ],
            "description": "The configuration key the OAuth client secret's value is read from.\nThe value is never written to the database, under the same rule\n as `AuthorizationConfigurationKey`."
          },
          "oauthScopes": {
            "type": [
              "null",
              "string"
            ],
            "description": "The space-separated OAuth scope list. Example: `\"repo read:user\"`."
          },
          "oauthAuthorizationMode": {
            "description": "The OAuth authorization flow.",
            "$ref": "#/components/schemas/McpOAuthAuthorizationMode"
          },
          "requiresApproval": {
            "type": "boolean",
            "description": "Whether this server's tools require explicit approval before each call.\n<strong>Defaults to `true`</strong>: the tool definition\ncomes from outside and is treated as untrusted."
          },
          "createdAt": {
            "type": "string",
            "description": "The creation time (UTC).",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "description": "The last-updated time (UTC).",
            "format": "date-time"
          }
        },
        "description": "A registered remote MCP server. Its tools are discovered at connection time and\nlisted alongside the tools registered in code."
      },
      "McpServerRequest": {
        "required": [
          "endpoint"
        ],
        "type": "object",
        "properties": {
          "description": {
            "type": [
              "null",
              "string"
            ],
            "description": "Description."
          },
          "endpoint": {
            "type": "string",
            "description": "Server address. Only `http` and `https` are accepted."
          },
          "transport": {
            "description": "Transport mode.",
            "$ref": "#/components/schemas/McpTransportMode"
          },
          "authorizationConfigurationKey": {
            "type": [
              "null",
              "string"
            ],
            "description": "Configuration key the `Authorization` header's value is read from.\nExample: `AgentPrism:McpSecrets:GithubToken`."
          },
          "headers": {
            "type": [
              "null",
              "object"
            ],
            "additionalProperties": {
              "type": "string"
            },
            "description": "Extra request headers. <strong>Must not carry secrets</strong> — these\nvalues are stored as-is and appear in the listing endpoint."
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether the server is enabled."
          },
          "requiresApproval": {
            "type": "boolean",
            "description": "Whether this server's tools require approval. Default `true`."
          },
          "oauthEnabled": {
            "type": "boolean",
            "description": "Whether OAuth authentication is enabled. While on,\n`AuthorizationConfigurationKey` must be empty."
          },
          "oauthClientId": {
            "type": [
              "null",
              "string"
            ],
            "description": "OAuth client identifier."
          },
          "oauthClientSecretConfigurationKey": {
            "type": [
              "null",
              "string"
            ],
            "description": "Configuration key the OAuth client secret's value is read from. The\nvalue itself is not sent; only the key's name is."
          },
          "oauthScopes": {
            "type": [
              "null",
              "string"
            ],
            "description": "Space-separated list of OAuth scopes."
          },
          "oauthAuthorizationMode": {
            "description": "OAuth authorization flow.",
            "$ref": "#/components/schemas/McpOAuthAuthorizationMode"
          }
        },
        "description": "Request to create/update an MCP server."
      },
      "McpTransportMode": {
        "enum": [
          "StreamableHttp",
          "Sse"
        ],
        "description": "The way a connection to an MCP server is made."
      },
      "MemorySettings": {
        "type": "object",
        "properties": {
          "enableFileMemory": {
            "type": "boolean",
            "description": "Gets a value that turns on file-based memory. In this phase it works only with\nthe in-memory store; the persistent version is left to a later phase."
          },
          "enableTodo": {
            "type": "boolean",
            "description": "Gets a value that turns on todo tracking."
          },
          "enableTextSearch": {
            "type": "boolean",
            "description": "Gets a value that turns on text search over the file store. The search runs over\nthe registered `AgentFileStore`, which in this phase is the in-memory store\nby default."
          },
          "enableVectorSearch": {
            "type": "boolean",
            "description": "Gets a value that turns on the `search_knowledge` tool.\nPostgreSQL only: the single concrete implementation of\nIVectorSearchStore lives in `AgentPrism.PostgreSql`. When this\nflag is turned on while another provider is registered, the build stops with\nAgentPrismCompilationException; it does not silently return an\nempty result."
          },
          "vectorCollection": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the name of the collection to search. The agent name is used when it is empty."
          }
        },
        "description": "Determines the memory providers bound to an agent."
      },
      "ModelBinding": {
        "required": [
          "provider",
          "model"
        ],
        "type": "object",
        "properties": {
          "provider": {
            "type": "string",
            "description": "Gets the provider name, for example `openai`."
          },
          "model": {
            "type": "string",
            "description": "Gets the model name, for example `gpt-5.4-mini`."
          },
          "temperature": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "Gets the sampling temperature. The provider default is used when it is `null`.",
            "format": "float"
          },
          "maxOutputTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Gets the upper output token limit. The provider default is used when it is `null`.",
            "format": "int32"
          },
          "topP": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "Gets the nucleus sampling threshold. The provider default is used when it is `null`.",
            "format": "float"
          },
          "reasoningEffort": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the reasoning effort level. Models that support it use the value; the other\nproviders ignore it."
          },
          "providerSettings": {
            "type": "object",
            "description": "Gets the provider-specific extra settings. A key has the form `{provider}.{setting}`."
          },
          "responseFormat": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Gets the requested output format. When it is `null` today's\nbehaviour does not change: no format constraint is sent to the provider.",
                "$ref": "#/components/schemas/AgentResponseFormat"
              }
            ]
          },
          "fallbacks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ModelFallback"
            },
            "description": "Gets the ordered fallback chain tried when the primary provider is\nunavailable. Empty by default."
          }
        },
        "description": "Determines the provider and the model an agent runs with. It carries\n<em>no</em> credentials; the API key is resolved from configuration."
      },
      "ModelDescriptor": {
        "required": [
          "name"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "The model name. `ModelBinding.Model` matches this value."
          },
          "displayName": {
            "type": [
              "null",
              "string"
            ],
            "description": "The name shown in the UI."
          },
          "contextWindowTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "The context window's token capacity.",
            "format": "int32"
          },
          "maxOutputTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "The maximum number of tokens producible in a single response.",
            "format": "int32"
          },
          "supportsStreaming": {
            "type": "boolean",
            "description": "Whether streaming responses are supported."
          },
          "supportsTools": {
            "type": "boolean",
            "description": "Whether tool calling is supported."
          },
          "supportsReasoning": {
            "type": "boolean",
            "description": "Whether the reasoning-effort setting is supported."
          },
          "supportsStructuredOutput": {
            "type": "boolean",
            "description": "Whether output conforming to a JSON schema can be produced."
          },
          "inputCostPerMillionTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "The cost per million input tokens. For reporting only.",
            "format": "double"
          },
          "outputCostPerMillionTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "The cost per million output tokens. For reporting only.",
            "format": "double"
          },
          "cachedInputCostPerMillionTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "The cost per million input tokens that were served from the provider's\nprompt cache. For reporting only.",
            "format": "double"
          }
        },
        "description": "A model's capabilities and limits."
      },
      "ModelFallback": {
        "required": [
          "provider",
          "model"
        ],
        "type": "object",
        "properties": {
          "provider": {
            "type": "string",
            "description": "Gets the provider name, for example `anthropic`."
          },
          "model": {
            "type": "string",
            "description": "Gets the model name, for example `claude-opus-5`."
          }
        },
        "description": "One link of a IReadOnlyList&lt;ModelFallback&gt; ModelBinding.Fallbacks chain."
      },
      "ModelProviderDescriptor": {
        "required": [
          "name"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "The provider name."
          },
          "displayName": {
            "type": [
              "null",
              "string"
            ],
            "description": "The name shown in the UI."
          },
          "models": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ModelDescriptor"
            },
            "description": "The models this provider offers."
          },
          "status": {
            "description": "The provider's last known health status.",
            "$ref": "#/components/schemas/ModelProviderHealthStatus"
          }
        },
        "description": "A provider's definition as shown in the UI."
      },
      "ModelProviderHealth": {
        "required": [
          "providerName",
          "status"
        ],
        "type": "object",
        "properties": {
          "providerName": {
            "type": "string",
            "description": "The provider name."
          },
          "status": {
            "description": "The check result.",
            "$ref": "#/components/schemas/ModelProviderHealthStatus"
          },
          "detail": {
            "type": [
              "null",
              "string"
            ],
            "description": "A short failure reason. <strong>Carries no secret</strong>: the\nresponse body, headers, or API key are never written here under any\ncondition — only the HTTP status code and a short description."
          },
          "latency": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": [
              "null",
              "string"
            ],
            "description": "How long the check request took."
          },
          "checkedAt": {
            "type": "string",
            "description": "The time the check was performed.",
            "format": "date-time"
          },
          "models": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The model names the server reported. Empty if the check failed."
          }
        },
        "description": "A model provider's status at the last check."
      },
      "ModelProviderHealthStatus": {
        "enum": [
          "Unknown",
          "Healthy",
          "Degraded",
          "Unhealthy"
        ],
        "description": "A provider's checked reachability status."
      },
      "OnlineEvaluationSummary": {
        "required": [
          "windowStart",
          "windowEnd",
          "sampleCount",
          "lowScoreThreshold",
          "minSampleSize",
          "belowThreshold"
        ],
        "type": "object",
        "properties": {
          "windowStart": {
            "type": "string",
            "description": "Gets the window start in UTC.",
            "format": "date-time"
          },
          "windowEnd": {
            "type": "string",
            "description": "Gets the window end in UTC.",
            "format": "date-time"
          },
          "sampleCount": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Gets the sample count, which is the number of scored runs in the window.",
            "format": "int64"
          },
          "averageScore": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "Gets the average score in the window, from 0 to 100, or `null` with no samples.",
            "format": "double"
          },
          "lowScoreThreshold": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Gets the configured low-score threshold.",
            "format": "int32"
          },
          "minSampleSize": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Gets the minimum sample count required for an alarm.",
            "format": "int32"
          },
          "belowThreshold": {
            "type": "boolean",
            "description": "Gets `true` when the average is below the threshold and\nthe sample count meets the minimum."
          },
          "judgeCost": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "Gets the total judge cost in the window, or `null` when unknown.",
            "format": "double"
          },
          "judgeCostCurrency": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the judge-cost currency."
          }
        },
        "description": "Summarizes the online evaluation window (`GET /api/evaluation/online`)."
      },
      "OpenAIErrorBody": {
        "required": [
          "message",
          "type"
        ],
        "type": "object",
        "properties": {
          "message": {
            "type": "string"
          },
          "type": {
            "type": "string"
          }
        }
      },
      "OpenAIErrorEnvelope": {
        "required": [
          "error"
        ],
        "type": "object",
        "properties": {
          "error": {
            "$ref": "#/components/schemas/OpenAIErrorBody"
          }
        }
      },
      "PendingApproval": {
        "required": [
          "id",
          "tenantId",
          "runId",
          "sessionId",
          "requestId",
          "toolName",
          "status",
          "expiresAt",
          "createdAt"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Gets the record id.",
            "format": "uuid"
          },
          "tenantId": {
            "type": "string",
            "description": "Gets the tenant id."
          },
          "runId": {
            "type": "string",
            "description": "Gets the run that produced this request and closed with RunStatus.AwaitingApproval.",
            "format": "uuid"
          },
          "sessionId": {
            "type": "string",
            "description": "Gets the session of the run. While the decision is applied, the continuing run is\nput on the queue with this session."
          },
          "requestId": {
            "type": "string",
            "description": "Gets the `ToolApprovalRequestContent.RequestId` value produced by MAF."
          },
          "toolName": {
            "type": "string",
            "description": "Gets the name of the tool that asks for approval."
          },
          "arguments": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the arguments of the tool call as `key=value` pairs (reflection-based\nJSON serialization is NOT USED, to stay AOT compatible). It stays\n`null` when `RecordToolPayloads` is turned off in the\nrecording settings."
          },
          "status": {
            "description": "Gets the status of the request.",
            "$ref": "#/components/schemas/ApprovalStatus"
          },
          "decidedBy": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the actor that made the decision, or `null` when no decision was made."
          },
          "decidedAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the time of the decision, or `null` when no decision was made.",
            "format": "date-time"
          },
          "expiresAt": {
            "type": "string",
            "description": "Gets the time after which the request counts as ApprovalStatus.Expired.",
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "description": "Gets the creation time.",
            "format": "date-time"
          }
        },
        "description": "The pending tool approval request of a run that executes from the queue."
      },
      "PricingSource": {
        "enum": [
          "Catalog",
          "Configuration",
          "Unknown"
        ],
        "description": "Reports where a run's cost pricing came from."
      },
      "ProblemDetails": {
        "type": "object",
        "properties": {
          "type": {
            "type": [
              "null",
              "string"
            ]
          },
          "title": {
            "type": [
              "null",
              "string"
            ]
          },
          "status": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "detail": {
            "type": [
              "null",
              "string"
            ]
          },
          "instance": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "QuotaDefinition": {
        "required": [
          "id",
          "tenantId",
          "period",
          "createdAt",
          "updatedAt"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The rule identifier.",
            "format": "uuid"
          },
          "tenantId": {
            "type": "string",
            "description": "The tenant the rule belongs to."
          },
          "agentName": {
            "type": [
              "null",
              "string"
            ],
            "description": "The agent the rule is bound to. If `null`, the rule\napplies to all of the tenant's runs."
          },
          "period": {
            "description": "The counter's reset interval.",
            "$ref": "#/components/schemas/QuotaPeriod"
          },
          "maxRuns": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "The maximum number of runs per period. Unlimited if `null`.",
            "format": "int64"
          },
          "maxTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "The maximum tokens per period. Unlimited if `null`.",
            "format": "int64"
          },
          "maxCost": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "The maximum monetary amount per period. Unlimited if `null`.",
            "format": "double"
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether the rule is enabled."
          },
          "createdAt": {
            "type": "string",
            "description": "The creation time (UTC).",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "description": "The last-updated time (UTC).",
            "format": "date-time"
          }
        },
        "description": "A quota rule defined for a tenant or an agent."
      },
      "QuotaPeriod": {
        "enum": [
          "Daily",
          "Monthly"
        ],
        "description": "The interval at which a quota's counter resets."
      },
      "QuotaSaveRequest": {
        "type": "object",
        "properties": {
          "agentName": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the agent the rule is bound to. If left empty, the rule applies to all\nof the tenant's runs."
          },
          "period": {
            "description": "Gets the counter's reset interval.",
            "$ref": "#/components/schemas/QuotaPeriod"
          },
          "maxRuns": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Gets the maximum number of runs per period.",
            "format": "int64"
          },
          "maxTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Gets the maximum number of tokens per period.",
            "format": "int64"
          },
          "maxCost": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "Gets the maximum monetary amount per period.",
            "format": "double"
          },
          "enabled": {
            "type": "boolean",
            "description": "Gets whether the rule is enabled."
          }
        },
        "description": "Request body for saving a quota rule."
      },
      "QuotaUsageRecord": {
        "required": [
          "tenantId",
          "agentName",
          "period",
          "periodStart",
          "updatedAt"
        ],
        "type": "object",
        "properties": {
          "tenantId": {
            "type": "string",
            "description": "The tenant identifier."
          },
          "agentName": {
            "type": "string",
            "description": "The agent name. An empty string (`\"\"`) means the tenant-wide counter."
          },
          "period": {
            "description": "The counter's interval.",
            "$ref": "#/components/schemas/QuotaPeriod"
          },
          "periodStart": {
            "type": "string",
            "description": "The first day of the period (in local time).",
            "format": "date"
          },
          "runs": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The number of runs completed in the period.",
            "format": "int64"
          },
          "tokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The total tokens spent in the period.",
            "format": "int64"
          },
          "cost": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "description": "The total amount spent in the period. Runs with undefined pricing are\n<strong>not included</strong> in this total (not even added as zero).",
            "format": "double"
          },
          "updatedAt": {
            "type": "string",
            "description": "The last-updated time (UTC).",
            "format": "date-time"
          }
        },
        "description": "A scope's consumption in the current period."
      },
      "QuotaUsageResponse": {
        "required": [
          "tenantId",
          "timeZone",
          "usage",
          "definitions",
          "dailyResetsAt",
          "monthlyResetsAt"
        ],
        "type": "object",
        "properties": {
          "tenantId": {
            "type": "string",
            "description": "Gets the tenant identifier."
          },
          "timeZone": {
            "type": "string",
            "description": "Gets the time zone the period boundaries are computed in."
          },
          "usage": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/QuotaUsageRecord"
            },
            "description": "Gets the current period's counters."
          },
          "definitions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/QuotaDefinition"
            },
            "description": "Gets the defined quota rules. The UI computes the percentage from these."
          },
          "dailyResetsAt": {
            "type": "string",
            "description": "Gets the moment (UTC) the daily counters reset.",
            "format": "date-time"
          },
          "monthlyResetsAt": {
            "type": "string",
            "description": "Gets the moment (UTC) the monthly counters reset.",
            "format": "date-time"
          }
        },
        "description": "Response for the quota usage endpoint."
      },
      "ReplayToolMode": {
        "enum": [
          "NoTools",
          "ReplayTools",
          "LiveTools"
        ],
        "description": "How tools are handled during replay."
      },
      "RetentionPolicy": {
        "required": [
          "id",
          "tenantId",
          "target",
          "createdAt",
          "updatedAt"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The policy identifier.",
            "format": "uuid"
          },
          "tenantId": {
            "type": "string",
            "description": "The tenant identifier. `\"*\"` means the default for all tenants."
          },
          "target": {
            "type": "string",
            "description": "The target table name. See RetentionTargets."
          },
          "maxAgeDays": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Rows older than this age are candidates for deletion. If\n`null`, age-based deletion does not apply (only\n`MaxRows`, if set, applies).",
            "format": "int32"
          },
          "maxRows": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "The maximum number of rows to keep in the target table. The oldest\nrows over the limit are deleted. If `null`,\nvolume-based deletion does not apply (only `MaxAgeDays`,\nif set, applies).",
            "format": "int64"
          },
          "archive": {
            "type": "boolean",
            "description": "Whether to archive with `IArchiveSink` before deleting. If no\nsink is registered, no row is deleted even if this field is\n`true`."
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether the policy is enabled."
          },
          "createdAt": {
            "type": "string",
            "description": "The creation time (UTC).",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "description": "The last-updated time (UTC).",
            "format": "date-time"
          }
        },
        "description": "An age- and volume-based retention rule for a target."
      },
      "RetentionPolicySaveRequest": {
        "type": "object",
        "properties": {
          "maxAgeDays": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Rows older than this age are candidates for deletion.",
            "format": "int32"
          },
          "maxRows": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "The maximum number of rows to keep for the target. The oldest rows are deleted.",
            "format": "int64"
          },
          "archive": {
            "type": "boolean",
            "description": "Whether to archive rows before deleting them."
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether the policy is enabled."
          }
        },
        "description": "Request body for saving a retention policy."
      },
      "RetentionPreview": {
        "required": [
          "target"
        ],
        "type": "object",
        "properties": {
          "target": {
            "type": "string",
            "description": "The previewed target."
          },
          "maxAgeDays": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "`null` if no policy was found (nothing would be deleted).",
            "format": "int32"
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether the policy is enabled."
          },
          "cutoff": {
            "type": [
              "null",
              "string"
            ],
            "description": "The computed cutoff date (UTC). `null` if there is no policy.",
            "format": "date-time"
          },
          "matchingRows": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The number of rows currently older than the cutoff date.",
            "format": "int64"
          }
        },
        "description": "A preview of \"how many rows would be deleted if run now\" for a target."
      },
      "RetentionRun": {
        "required": [
          "id",
          "tenantId",
          "target",
          "startedAt"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The run identifier.",
            "format": "uuid"
          },
          "tenantId": {
            "type": "string",
            "description": "The tenant identifier."
          },
          "target": {
            "type": "string",
            "description": "The target processed."
          },
          "deletedRows": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The number of rows deleted so far.",
            "format": "int64"
          },
          "archivedRows": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The number of rows archived so far.",
            "format": "int64"
          },
          "startedAt": {
            "type": "string",
            "description": "The start time (UTC).",
            "format": "date-time"
          },
          "completedAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "The completion time (UTC). `null` while the run is in progress.",
            "format": "date-time"
          },
          "error": {
            "type": [
              "null",
              "string"
            ],
            "description": "The error message. Populated only for failed runs."
          }
        },
        "description": "The history record of a cleanup run."
      },
      "RetentionRunTriggerResponse": {
        "required": [
          "jobId",
          "target"
        ],
        "type": "object",
        "properties": {
          "jobId": {
            "type": "string",
            "description": "The id of the enqueued job.",
            "format": "uuid"
          },
          "target": {
            "type": "string",
            "description": "The target to process; `\"*\"` for all targets."
          }
        },
        "description": "Response to a \"run now\" request."
      },
      "RunAgentStatistics": {
        "required": [
          "agentName",
          "totalRuns",
          "failedRuns"
        ],
        "type": "object",
        "properties": {
          "agentName": {
            "type": "string",
            "description": "The agent name."
          },
          "totalRuns": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "This agent's total number of runs.",
            "format": "int64"
          },
          "failedRuns": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "This agent's number of runs that ended in an error.",
            "format": "int64"
          },
          "totalTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "This agent's total token usage.",
            "format": "int64"
          }
        },
        "description": "An agent's run summary."
      },
      "RunComparisonResponse": {
        "required": [
          "left",
          "right"
        ],
        "type": "object",
        "properties": {
          "left": {
            "description": "The left-hand run.",
            "$ref": "#/components/schemas/RunComparisonSide"
          },
          "right": {
            "description": "The right-hand run.",
            "$ref": "#/components/schemas/RunComparisonSide"
          }
        },
        "description": "Side-by-side summary of two runs."
      },
      "RunComparisonSide": {
        "required": [
          "runId",
          "agentName",
          "status",
          "toolCallCount"
        ],
        "type": "object",
        "properties": {
          "runId": {
            "type": "string",
            "description": "Run identifier.",
            "format": "uuid"
          },
          "agentName": {
            "type": "string",
            "description": "Agent name."
          },
          "agentVersion": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Definition version. `null` if unknown.",
            "format": "int32"
          },
          "modelId": {
            "type": [
              "null",
              "string"
            ],
            "description": "Model used."
          },
          "status": {
            "description": "Final status.",
            "$ref": "#/components/schemas/RunStatus"
          },
          "durationMs": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Duration (milliseconds). `null` if the run has not finished.",
            "format": "int64"
          },
          "usage": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Token usage.",
                "$ref": "#/components/schemas/RunUsage"
              }
            ]
          },
          "cost": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Cost.",
                "$ref": "#/components/schemas/RunCost"
              }
            ]
          },
          "toolCallCount": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Number of tool calls.",
            "format": "int32"
          },
          "errorClass": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Error class. `null` for a successful run.",
                "$ref": "#/components/schemas/RunErrorClass"
              }
            ]
          },
          "errorMessage": {
            "type": [
              "null",
              "string"
            ],
            "description": "Error message. `null` for a successful run."
          },
          "replayOfRunId": {
            "type": [
              "null",
              "string"
            ],
            "description": "Source of this run, if it is a replay.",
            "format": "uuid"
          },
          "output": {
            "type": [
              "null",
              "string"
            ],
            "description": "Text produced by the model."
          },
          "scores": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RunScore"
            },
            "description": "Scores written against this run."
          }
        },
        "description": "One side of the comparison."
      },
      "RunCost": {
        "required": [
          "source"
        ],
        "type": "object",
        "properties": {
          "inputCost": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "Gets the input token cost, or `null` when the price is unknown.",
            "format": "double"
          },
          "outputCost": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "Gets the output token cost, or `null` when the price is unknown.",
            "format": "double"
          },
          "cachedInputCost": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "Gets the cost of the input tokens that were served from the prompt\ncache, or `null` when no cache read was priced.",
            "format": "double"
          },
          "currency": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the currency, taken from `AgentPrism:Pricing:Currency`."
          },
          "source": {
            "description": "Gets where the price came from.",
            "$ref": "#/components/schemas/PricingSource"
          }
        },
        "description": "Cost of a run. It is computed and written once when the run ends (a price\nsnapshot) — a later change to the price list does not change past values."
      },
      "RunCostRecalculationResult": {
        "required": [
          "runsConsidered",
          "runsUpdated",
          "runsStillUnknown"
        ],
        "type": "object",
        "properties": {
          "runsConsidered": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Gets the number of runs considered, that is those with a model and usage.",
            "format": "int64"
          },
          "runsUpdated": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Gets the number of runs whose price resolved and was updated.",
            "format": "int64"
          },
          "runsStillUnknown": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Gets the number of runs whose price is still unknown afterwards.",
            "format": "int64"
          }
        },
        "description": "Result of a cost recalculation."
      },
      "RunError": {
        "required": [
          "type",
          "message"
        ],
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "description": "Gets the name of the exception type."
          },
          "message": {
            "type": "string",
            "description": "Gets the error message."
          },
          "class": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Gets the class chosen by IRunErrorClassifier. Rows written\nBEFORE the error class was introduced hold `null`, which\nthe user interface shows in the `Unknown` bucket.",
                "$ref": "#/components/schemas/RunErrorClass"
              }
            ]
          },
          "fingerprint": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the digest of the normalized message, used to cluster repetitions of\nthe same fault. `null` when no classifier ran, as for\n`Class`."
          }
        },
        "description": "Error information for a failed run."
      },
      "RunErrorClass": {
        "enum": [
          "Unknown",
          "ProviderError",
          "ProviderUnavailable",
          "RateLimited",
          "QuotaExceeded",
          "ContentFiltered",
          "ToolError",
          "Timeout",
          "CompilationFailed",
          "BudgetExceeded",
          "Canceled",
          "ContentBlocked",
          "Infrastructure",
          "ToolTimeout",
          null
        ]
      },
      "RunErrorCluster": {
        "required": [
          "fingerprint",
          "count",
          "sampleMessage",
          "sampleRunId",
          "lastSeenAt"
        ],
        "type": "object",
        "properties": {
          "fingerprint": {
            "type": "string",
            "description": "The digest of the normalized message."
          },
          "count": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The number of runs in this cluster.",
            "format": "int64"
          },
          "sampleMessage": {
            "type": "string",
            "description": "The raw error message of the most recent occurrence in the cluster."
          },
          "sampleRunId": {
            "type": "string",
            "description": "The run identifier of the most recent occurrence in the cluster.",
            "format": "uuid"
          },
          "lastSeenAt": {
            "type": "string",
            "description": "The moment this cluster was last seen (UTC).",
            "format": "date-time"
          }
        },
        "description": "The summary of runs sharing the same fingerprint."
      },
      "RunErrorStatistics": {
        "required": [
          "class",
          "totalRuns"
        ],
        "type": "object",
        "properties": {
          "class": {
            "description": "The error class.",
            "$ref": "#/components/schemas/RunErrorClass"
          },
          "totalRuns": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The total number of runs falling into this class.",
            "format": "int64"
          },
          "topClusters": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RunErrorCluster"
            },
            "description": "This class's most frequent clusters, in descending order of count."
          }
        },
        "description": "An error class's summary."
      },
      "RunFeedbackRequest": {
        "required": [
          "kind",
          "value"
        ],
        "type": "object",
        "properties": {
          "kind": {
            "description": "The format of the score.",
            "$ref": "#/components/schemas/RunScoreKind"
          },
          "value": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "0/1 for RunScoreKind.Binary, 1.5 for RunScoreKind.Stars.",
            "format": "int32"
          },
          "messageId": {
            "type": [
              "null",
              "string"
            ],
            "description": "The id of the scored message. If left blank, the score applies to the whole run."
          },
          "comment": {
            "type": [
              "null",
              "string"
            ],
            "description": "Free-text comment."
          }
        },
        "description": "Request body for writing a run/message score."
      },
      "RunInputResponse": {
        "required": [
          "runId",
          "createdAt",
          "messages"
        ],
        "type": "object",
        "properties": {
          "runId": {
            "type": "string",
            "description": "Run identifier.",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "description": "Creation time of the record (UTC).",
            "format": "date-time"
          },
          "messages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ChatMessage"
            },
            "description": "Input messages, with their polymorphic content, exactly as recorded."
          }
        },
        "description": "HTTP response for a run's recorded input."
      },
      "RunKind": {
        "enum": [
          "Agent",
          "Workflow",
          "Eval"
        ],
        "description": "Reports what a `runs` row records."
      },
      "RunLabelStatistics": {
        "required": [
          "key",
          "value",
          "totalRuns",
          "failedRuns"
        ],
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "description": "The label key."
          },
          "value": {
            "type": "string",
            "description": "The label value."
          },
          "totalRuns": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The number of runs carrying this exact key/value pair.",
            "format": "int64"
          },
          "failedRuns": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "This label's number of runs that ended in an error.",
            "format": "int64"
          },
          "totalTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "This label's total token usage.",
            "format": "int64"
          },
          "totalCost": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "This label's total cost. `null` if no run carrying it was ever priced.",
            "format": "double"
          }
        },
        "description": "A label's run summary; one entry per distinct key/value pair."
      },
      "RunModelStatistics": {
        "required": [
          "modelId",
          "totalRuns"
        ],
        "type": "object",
        "properties": {
          "modelId": {
            "type": "string",
            "description": "The model name."
          },
          "totalRuns": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The total number of runs made with this model.",
            "format": "int64"
          },
          "inputTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The total input tokens.",
            "format": "int64"
          },
          "outputTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The total output tokens.",
            "format": "int64"
          },
          "totalTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The total tokens.",
            "format": "int64"
          },
          "totalCost": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "The total cost of runs made with this model. `null` if pricing is undefined.",
            "format": "double"
          }
        },
        "description": "A model's run summary. The input to cost computation."
      },
      "RunRecord": {
        "required": [
          "id",
          "agentName",
          "status",
          "startedAt"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Gets the run id. A time-ordered UUID (v7).",
            "format": "uuid"
          },
          "agentName": {
            "type": "string",
            "description": "Gets the name of the agent that ran. For workflow runs this is the workflow\nname: the existing lists, statistics and user interface read this column, and\nleaving it empty would show workflow rows without a name."
          },
          "kind": {
            "description": "Gets whether this row records an agent or a workflow.",
            "$ref": "#/components/schemas/RunKind"
          },
          "workflowName": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the name of the workflow. Populated only on\nRunKind.Workflow rows."
          },
          "status": {
            "description": "Gets the current status of the run.",
            "$ref": "#/components/schemas/RunStatus"
          },
          "startedAt": {
            "type": "string",
            "description": "Gets the start time (UTC).",
            "format": "date-time"
          },
          "completedAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the completion time (UTC), or `null` while the run is in flight.",
            "format": "date-time"
          },
          "tenantId": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the tenant the run belongs to."
          },
          "userId": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the user the run belongs to, or `null` when it was\nnot known."
          },
          "labels": {
            "type": [
              "null",
              "object"
            ],
            "additionalProperties": {
              "type": "string"
            },
            "description": "Gets the labels the run carries, or `null` when it\ncarries none."
          },
          "sessionId": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the id of the session that was used."
          },
          "modelId": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the model used by the run. Cost and per-model reports need it. It is\n`null` when the agent definition carries no model."
          },
          "isStreaming": {
            "type": "boolean",
            "description": "Gets whether the run streamed."
          },
          "usage": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Gets the token usage, or `null` when the provider reported none.",
                "$ref": "#/components/schemas/RunUsage"
              }
            ]
          },
          "error": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Gets the error information. Populated only for RunStatus.Failed.",
                "$ref": "#/components/schemas/RunError"
              }
            ]
          },
          "eventCount": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Gets the number of events written for this run.",
            "format": "int64"
          },
          "parentRunId": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the id of the run that started this one, or `null` for a\nroot run.",
            "format": "uuid"
          },
          "rootRunId": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the id of the run at the root of the tree. `null` for a\nroot run and always populated for a child run.",
            "format": "uuid"
          },
          "depth": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Gets the depth in the tree. The root run is 0.",
            "format": "int32"
          },
          "agentVersion": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Gets the definition version this run measured, or `null` when unknown.",
            "format": "int32"
          },
          "experimentId": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the experiment this run belongs to, or `null` outside an experiment.",
            "format": "uuid"
          },
          "variant": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the experiment variant this run was assigned to, or `null` outside an experiment."
          },
          "childRunCount": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Gets the number of <em>direct</em> child runs.",
            "format": "int32"
          },
          "treeUsage": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Gets the total token usage of this run and every run below it.",
                "$ref": "#/components/schemas/RunUsage"
              }
            ]
          },
          "cost": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Gets the run's own cost. `null` when the model is unknown;\nwhen the model is known the value is populated even if the price is not.",
                "$ref": "#/components/schemas/RunCost"
              }
            ]
          },
          "treeCost": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Gets the total cost of this run and every run below it.",
                "$ref": "#/components/schemas/RunTreeCost"
              }
            ]
          },
          "replayOfRunId": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the source run id when this run is a replay, otherwise\n`null`.",
            "format": "uuid"
          }
        },
        "description": "Summary of a run. It acts as the header of the event stream."
      },
      "RunReplayRequest": {
        "type": "object",
        "properties": {
          "agentVersion": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "The agent definition version to use. The currently active version if not given.",
            "format": "int32"
          },
          "modelId": {
            "type": [
              "null",
              "string"
            ],
            "description": "The model name to override with. The definition's own model is used if not given."
          },
          "toolMode": {
            "description": "The tool behavior. Defaults to ReplayToolMode.ReplayTools.",
            "$ref": "#/components/schemas/ReplayToolMode"
          }
        },
        "description": "A replay request."
      },
      "RunReplayResponse": {
        "required": [
          "runId",
          "sourceRunId",
          "toolMode",
          "compareLocation"
        ],
        "type": "object",
        "properties": {
          "runId": {
            "type": "string",
            "description": "Identifier of the newly started run.",
            "format": "uuid"
          },
          "sourceRunId": {
            "type": "string",
            "description": "Identifier of the source run. Same as `runs.replay_of_run_id`.",
            "format": "uuid"
          },
          "toolMode": {
            "description": "Tool mode applied.",
            "$ref": "#/components/schemas/ReplayToolMode"
          },
          "agentVersion": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Definition version used. `null` for a code agent.",
            "format": "int32"
          },
          "modelId": {
            "type": [
              "null",
              "string"
            ],
            "description": "Model used."
          },
          "output": {
            "type": [
              "null",
              "string"
            ],
            "description": "Text produced by the model."
          },
          "compareLocation": {
            "type": "string",
            "description": "Address of the endpoint that places the two runs side by side."
          }
        },
        "description": "Result of a replay."
      },
      "RunScore": {
        "required": [
          "tenantId",
          "runId",
          "kind",
          "value",
          "source"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The score's identifier.",
            "format": "uuid"
          },
          "tenantId": {
            "type": "string",
            "description": "The tenant."
          },
          "runId": {
            "type": "string",
            "description": "The identifier of the run being scored.",
            "format": "uuid"
          },
          "messageId": {
            "type": [
              "null",
              "string"
            ],
            "description": "The identifier of the message being scored. If empty, the score belongs to the whole run."
          },
          "kind": {
            "description": "The shape of `Value`.",
            "$ref": "#/components/schemas/RunScoreKind"
          },
          "value": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The score value. 0/1 for RunScoreKind.Binary, 1.5 for RunScoreKind.Stars.",
            "format": "int32"
          },
          "comment": {
            "type": [
              "null",
              "string"
            ],
            "description": "A free-text comment."
          },
          "source": {
            "type": "string",
            "description": "The score's source: `human`, `api`, or `judge`. Today\nonly `human` is used; the column is set up from the start so\nonline evaluation can write a judge score into the same table as-is."
          },
          "author": {
            "type": [
              "null",
              "string"
            ],
            "description": "The actor who gave the score. `null` in an identity-less setup."
          },
          "createdAt": {
            "type": "string",
            "description": "The creation/last-updated time.",
            "format": "date-time"
          }
        },
        "description": "A human (or judge) score for a run or for a single message within a run."
      },
      "RunScoreKind": {
        "enum": [
          "Binary",
          "Stars",
          "Numeric"
        ],
        "description": "The shape of the value a RunScore carries."
      },
      "RunStatistics": {
        "required": [
          "totalRuns",
          "completedRuns",
          "failedRuns",
          "canceledRuns",
          "runningRuns"
        ],
        "type": "object",
        "properties": {
          "totalRuns": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The total number of runs matching the filter.",
            "format": "int64"
          },
          "completedRuns": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The number of runs that completed successfully.",
            "format": "int64"
          },
          "failedRuns": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The number of runs that ended in an error.",
            "format": "int64"
          },
          "canceledRuns": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The number of cancelled runs.",
            "format": "int64"
          },
          "runningRuns": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The number of runs still running.",
            "format": "int64"
          },
          "awaitingInputRuns": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The number of runs awaiting human input.",
            "format": "int64"
          },
          "inputTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The total input tokens.",
            "format": "int64"
          },
          "outputTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The total output tokens.",
            "format": "int64"
          },
          "totalTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The total tokens.",
            "format": "int64"
          },
          "cachedInputTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The input tokens that were served from the prompt cache. Counted INSIDE\n`InputTokens`, so the two must not be added together.",
            "format": "int64"
          },
          "reasoningTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The tokens spent on reasoning. Counted INSIDE `OutputTokens`.",
            "format": "int64"
          },
          "audioInputTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The audio input tokens. Counted INSIDE `InputTokens`.",
            "format": "int64"
          },
          "audioOutputTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The audio output tokens. Counted INSIDE `OutputTokens`.",
            "format": "int64"
          },
          "byAgent": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RunAgentStatistics"
            },
            "description": "The breakdown by agent."
          },
          "byModel": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RunModelStatistics"
            },
            "description": "The breakdown by model. Runs with an unknown model name do not appear\nin this list; they are still counted in the totals."
          },
          "byVersion": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RunVersionStatistics"
            },
            "description": "The breakdown by definition version. Runs with an unknown version do not appear in this list."
          },
          "byUser": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RunUserStatistics"
            },
            "description": "The breakdown by user. Runs that carry no user identity do not appear\nin this list; they are still counted in the totals."
          },
          "byLabel": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RunLabelStatistics"
            },
            "description": "The breakdown by label. One entry per distinct key/value pair, so a run\ncarrying three labels contributes to three entries."
          },
          "byErrorClass": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RunErrorStatistics"
            },
            "description": "The breakdown by error class. Only runs that ended in an error are\ncounted. Rows written before the error class was added appear in the\n`Unknown` bucket (past rows are not backfilled)."
          },
          "totalCost": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "The total cost. If a model has undefined pricing, that model's run\ncosts are <strong>not included</strong> in this total (only runs with\nknown pricing are summed); the number of runs excluded appears in\n`RunsWithUnknownPricing`. `null` if no run\nwas ever priced.",
            "format": "double"
          },
          "currency": {
            "type": [
              "null",
              "string"
            ],
            "description": "The currency. Populated when `TotalCost` is populated."
          },
          "runsWithUnknownPricing": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The number of runs whose model is known but whose pricing is undefined.",
            "format": "int64"
          },
          "errorRate": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "The error rate among settled runs (0–1). `null` if no\nrun has settled.",
            "format": "double"
          },
          "scoredRuns": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The number of runs that received at least one RunScore\n(at the run or message level). Eval runs (RunKind.Eval)\nare excluded for the same reason as `TotalRuns`.",
            "format": "int64"
          },
          "positiveRate": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "The positive rate among RunScoreKind.Binary scores (0–1).\nStar ratings are not included in this rate — averaging the two kinds\nwould be meaningless. `null` if there is no binary score.",
            "format": "double"
          }
        },
        "description": "A summary of the runs in a time range."
      },
      "RunStatus": {
        "enum": [
          "Running",
          "Completed",
          "Failed",
          "Canceled",
          "AwaitingInput",
          "Queued",
          "AwaitingApproval"
        ],
        "description": "Status of a run."
      },
      "RunTrace": {
        "required": [
          "id",
          "traceId",
          "tenantId",
          "startedAt"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The database identifier.",
            "format": "uuid"
          },
          "traceId": {
            "type": "string",
            "description": "The W3C trace identifier (32-character hex)."
          },
          "runId": {
            "type": [
              "null",
              "string"
            ],
            "description": "The associated run. `null` for spans without a run.",
            "format": "uuid"
          },
          "tenantId": {
            "type": "string",
            "description": "The tenant identifier."
          },
          "startedAt": {
            "type": "string",
            "description": "The first span's start (UTC).",
            "format": "date-time"
          },
          "endedAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "The last span's end (UTC).",
            "format": "date-time"
          },
          "spans": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TraceSpan"
            },
            "description": "The spans, ordered by start time."
          }
        },
        "description": "A run's span tree. The waterfall view is built on top of this."
      },
      "RunTreeCost": {
        "type": "object",
        "properties": {
          "inputCost": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "Gets the total input cost across the tree.",
            "format": "double"
          },
          "outputCost": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "Gets the total output cost across the tree.",
            "format": "double"
          },
          "cachedInputCost": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "Gets the total cached-input cost across the tree.",
            "format": "double"
          },
          "currency": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the currency."
          },
          "runsWithUnknownPricing": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Gets how many runs in the tree have an unknown price.",
            "format": "int64"
          }
        },
        "description": "Total cost of a run tree (the root plus every child run)."
      },
      "RunUsage": {
        "type": "object",
        "properties": {
          "inputTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Gets the number of input tokens.",
            "format": "int64"
          },
          "outputTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Gets the number of output tokens.",
            "format": "int64"
          },
          "totalTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Gets the total number of tokens.",
            "format": "int64"
          },
          "cachedInputTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Gets the input tokens that were served from the provider's prompt\ncache. Counted INSIDE `InputTokens`.",
            "format": "int64"
          },
          "reasoningTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Gets the tokens the model spent on reasoning. Counted INSIDE\n`OutputTokens`.",
            "format": "int64"
          },
          "audioInputTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Gets the audio input tokens. Counted INSIDE `InputTokens`.",
            "format": "int64"
          },
          "audioOutputTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Gets the audio output tokens. Counted INSIDE `OutputTokens`.",
            "format": "int64"
          }
        },
        "description": "Token usage of a run."
      },
      "RunUserStatistics": {
        "required": [
          "userId",
          "totalRuns",
          "failedRuns"
        ],
        "type": "object",
        "properties": {
          "userId": {
            "type": "string",
            "description": "The user identity."
          },
          "totalRuns": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "This user's total number of runs.",
            "format": "int64"
          },
          "failedRuns": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "This user's number of runs that ended in an error.",
            "format": "int64"
          },
          "totalTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "This user's total token usage.",
            "format": "int64"
          },
          "totalCost": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "This user's total cost. `null` if no run of theirs was ever priced.",
            "format": "double"
          }
        },
        "description": "A user's run summary."
      },
      "RunVersionStatistics": {
        "required": [
          "agentName",
          "version",
          "totalRuns",
          "failedRuns"
        ],
        "type": "object",
        "properties": {
          "agentName": {
            "type": "string",
            "description": "The agent name this breakdown belongs to."
          },
          "version": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The definition version.",
            "format": "int32"
          },
          "totalRuns": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The total number of runs made with this version.",
            "format": "int64"
          },
          "failedRuns": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "This version's number of runs that ended in an error.",
            "format": "int64"
          },
          "totalTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "This version's total token usage.",
            "format": "int64"
          }
        },
        "description": "A definition version's run summary."
      },
      "SearchKnowledgeHit": {
        "required": [
          "sourceId",
          "chunkIndex",
          "content",
          "distance"
        ],
        "type": "object",
        "properties": {
          "sourceId": {
            "type": "string",
            "description": "Identifier of the source the chunk belongs to."
          },
          "chunkIndex": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Sequence number within the source.",
            "format": "int32"
          },
          "content": {
            "type": "string",
            "description": "The chunk's text."
          },
          "distance": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "description": "Cosine distance. A smaller value means closer.",
            "format": "double"
          },
          "metadata": {
            "type": [
              "null",
              "object"
            ],
            "additionalProperties": {
              "type": "string"
            },
            "description": "Optional metadata given at write time."
          }
        },
        "description": "A semantic search hit."
      },
      "SearchKnowledgeRequest": {
        "required": [
          "query"
        ],
        "type": "object",
        "properties": {
          "query": {
            "type": "string",
            "description": "Natural language query to search."
          },
          "top": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Number of results to return. If not given, the default in configuration is used.",
            "format": "int32"
          }
        },
        "description": "A semantic search request."
      },
      "SessionBranchRequest": {
        "type": "object",
        "properties": {
          "upToSequence": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "The sequence number of the last item to include (inclusive). If not\ngiven, the whole conversation is copied.",
            "format": "int64"
          },
          "newSessionId": {
            "type": [
              "null",
              "string"
            ],
            "description": "The identifier of the new session to open. Generated if not given."
          }
        },
        "description": "A request to branch a conversation from a specific point."
      },
      "SessionBranchResult": {
        "required": [
          "sessionId",
          "conversationId",
          "parentSessionId",
          "parentConversationId",
          "branchFromSequence",
          "copiedItemCount"
        ],
        "type": "object",
        "properties": {
          "sessionId": {
            "type": "string",
            "description": "The new session's identifier."
          },
          "conversationId": {
            "type": "string",
            "description": "The new conversation's identifier.",
            "format": "uuid"
          },
          "parentSessionId": {
            "type": "string",
            "description": "The source session's identifier."
          },
          "parentConversationId": {
            "type": "string",
            "description": "The source conversation's identifier.",
            "format": "uuid"
          },
          "branchFromSequence": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The branch point: the sequence number of the last item copied to the\nnew conversation. `-1` if no item was copied.",
            "format": "int64"
          },
          "copiedItemCount": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The number of items copied.",
            "format": "int32"
          }
        },
        "description": "The result of branching."
      },
      "SessionDetailResponse": {
        "required": [
          "id",
          "agentName",
          "createdAt",
          "updatedAt",
          "state"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Session identifier."
          },
          "agentName": {
            "type": "string",
            "description": "Agent the session belongs to."
          },
          "tenantId": {
            "type": [
              "null",
              "string"
            ],
            "description": "Tenant identifier."
          },
          "createdAt": {
            "type": "string",
            "description": "Creation time.",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "description": "Last update time.",
            "format": "date-time"
          },
          "messages": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Chat history. Returns `null` if the history could not\nbe read (e.g. the agent is no longer in the catalog).",
                "$ref": "#/components/schemas/JsonElement"
              }
            ]
          },
          "state": {
            "description": "Serialized session state.",
            "$ref": "#/components/schemas/JsonElement"
          }
        },
        "description": "Detailed view of a single session: metadata and chat history."
      },
      "SessionRecord": {
        "required": [
          "id",
          "agentName",
          "state",
          "createdAt",
          "updatedAt"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The session identifier."
          },
          "agentName": {
            "type": "string",
            "description": "The agent the session belongs to."
          },
          "state": {
            "description": "The serialized session state. Microsoft Agent Framework's\n`SerializeSessionAsync` output, treated as opaque.",
            "$ref": "#/components/schemas/JsonElement"
          },
          "createdAt": {
            "type": "string",
            "description": "The creation time (UTC).",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "description": "The last-updated time (UTC).",
            "format": "date-time"
          },
          "tenantId": {
            "type": [
              "null",
              "string"
            ],
            "description": "The tenant identifier."
          }
        },
        "description": "A stored session."
      },
      "SkillScriptGrant": {
        "required": [
          "tenantId",
          "skillName"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The grant record identifier. A time-ordered UUID (v7).",
            "format": "uuid"
          },
          "tenantId": {
            "type": "string",
            "description": "The tenant the grant belongs to."
          },
          "skillName": {
            "type": "string",
            "description": "The name of the skill granted."
          },
          "scriptName": {
            "type": [
              "null",
              "string"
            ],
            "description": "The name of the script granted. If `null`, all of the\nskill's scripts are covered."
          },
          "grantedBy": {
            "type": [
              "null",
              "string"
            ],
            "description": "The actor who gave the grant."
          },
          "grantedAt": {
            "type": "string",
            "description": "The moment the grant was given (UTC).",
            "format": "date-time"
          },
          "expiresAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "The moment the grant expires. Never expires if `null`.",
            "format": "date-time"
          },
          "revokedAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "The moment the grant was revoked. Active if `null`.",
            "format": "date-time"
          }
        },
        "description": "The record carrying permission to execute a skill script."
      },
      "SkillScriptGrantRequest": {
        "required": [
          "skillName"
        ],
        "type": "object",
        "properties": {
          "skillName": {
            "type": "string",
            "description": "Name of the skill being granted permission."
          },
          "scriptName": {
            "type": [
              "null",
              "string"
            ],
            "description": "Name of the script being granted permission. If `null`,\nevery script of the skill is covered."
          },
          "expiresAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "Expiration time of the grant. If `null`, it is unlimited.",
            "format": "date-time"
          }
        },
        "description": "Request to grant script execution permission."
      },
      "SpeakRequest": {
        "required": [
          "text"
        ],
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The text to speak."
          },
          "sessionId": {
            "type": [
              "null",
              "string"
            ],
            "description": "The session the attachment is bound to. If left empty, the\nattachment is considered orphaned and deleted by the retention policy."
          },
          "voiceId": {
            "type": [
              "null",
              "string"
            ],
            "description": "The identifier of the voice to use. The default voice if empty."
          },
          "includeTimestamps": {
            "type": "boolean",
            "description": "Requests character-level timing alongside the audio. Default `false`."
          }
        },
        "description": "A speech synthesis request as an operator action."
      },
      "SpeakResponse": {
        "required": [
          "attachment",
          "characters",
          "isEstimated"
        ],
        "type": "object",
        "properties": {
          "attachment": {
            "description": "The saved attachment.",
            "$ref": "#/components/schemas/AttachmentDescriptor"
          },
          "characters": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The billed character count.",
            "format": "int32"
          },
          "isEstimated": {
            "type": "boolean",
            "description": "Whether the character count is estimated."
          },
          "cost": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "The computed amount. `null` if pricing is undefined.",
            "format": "double"
          },
          "currency": {
            "type": [
              "null",
              "string"
            ],
            "description": "The currency label."
          },
          "alignment": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/SpeechAlignment"
            },
            "description": "Character-level timing. `null` when not requested via\n`SpeakRequest.IncludeTimestamps`, or when the provider does not support it."
          }
        },
        "description": "The result of speech synthesis."
      },
      "SpeechAlignment": {
        "required": [
          "character",
          "start",
          "end"
        ],
        "type": "object",
        "properties": {
          "character": {
            "type": "string",
            "description": "The character, as sent in the request text."
          },
          "start": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string",
            "description": "When the character starts, relative to the start of the audio."
          },
          "end": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string",
            "description": "When the character ends, relative to the start of the audio."
          }
        },
        "description": "One character's position in the generated audio."
      },
      "Stream": {
        "type": "string",
        "format": "binary"
      },
      "TenantDescriptor": {
        "required": [
          "id",
          "slug",
          "displayName"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The tenant identifier. A time-ordered UUID (v7).",
            "format": "uuid"
          },
          "slug": {
            "type": "string",
            "description": "The tenant key. The same text as the `tenant_id` column in other\ntables, and `ITenantContext.TenantId` returns this value."
          },
          "displayName": {
            "type": "string",
            "description": "The name shown in the UI."
          },
          "createdAt": {
            "type": "string",
            "description": "The creation time (UTC).",
            "format": "date-time"
          }
        },
        "description": "A registered tenant."
      },
      "TenantEgressPolicyRequest": {
        "type": "object",
        "properties": {
          "allowedProviders": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "type": "string"
            },
            "description": "Gets the closed set of allowed provider names. An empty list allows no provider."
          }
        },
        "description": "The request body for creating or replacing a tenant's egress policy."
      },
      "TenantEgressPolicyResponse": {
        "required": [
          "tenantId"
        ],
        "type": "object",
        "properties": {
          "tenantId": {
            "type": "string",
            "description": "Gets the tenant this policy belongs to."
          },
          "allowedProviders": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "type": "string"
            },
            "description": "Gets the closed set of allowed provider names, or `null`\nwhen the tenant is unrestricted (no policy saved)."
          },
          "updatedAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the time the policy was last written; `null` when unrestricted.",
            "format": "date-time"
          }
        },
        "description": "The response describing a tenant's egress policy."
      },
      "TenantProviderBindingRequest": {
        "type": "object",
        "properties": {
          "apiKeyConfigurationName": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the configuration key name the credential is read from. Never a value."
          },
          "endpoint": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the optional endpoint override."
          }
        },
        "description": "The request body for creating or replacing a tenant provider binding."
      },
      "TenantProviderBindingResponse": {
        "required": [
          "providerName",
          "apiKeyConfigurationName",
          "resolved",
          "updatedAt"
        ],
        "type": "object",
        "properties": {
          "providerName": {
            "type": "string",
            "description": "Gets the provider name."
          },
          "apiKeyConfigurationName": {
            "type": "string",
            "description": "Gets the configuration key name the credential is read from."
          },
          "endpoint": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the optional endpoint override."
          },
          "resolved": {
            "type": "boolean",
            "description": "Gets whether `ApiKeyConfigurationName` currently resolves to a value."
          },
          "updatedAt": {
            "type": "string",
            "description": "Gets the time this binding was last written.",
            "format": "date-time"
          }
        },
        "description": "The response describing a tenant provider binding."
      },
      "TenantRequest": {
        "type": "object",
        "properties": {
          "displayName": {
            "type": [
              "null",
              "string"
            ],
            "description": "Name shown in the UI. If left empty, the key is used."
          }
        },
        "description": "Request to create/update a tenant record."
      },
      "TimeSeriesBucket": {
        "enum": [
          "Hour",
          "Day",
          null
        ]
      },
      "TimeSeriesPoint": {
        "required": [
          "bucket"
        ],
        "type": "object",
        "properties": {
          "bucket": {
            "type": "string",
            "description": "The bucket's start time (UTC).",
            "format": "date-time"
          },
          "runs": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The number of runs that started in this bucket.",
            "format": "int64"
          },
          "failedRuns": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The number of runs that ended in an error in this bucket.",
            "format": "int64"
          },
          "inputTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The total input tokens.",
            "format": "int64"
          },
          "outputTokens": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The total output tokens.",
            "format": "int64"
          },
          "cost": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "The total cost. `null` if no run was ever priced.",
            "format": "double"
          },
          "averageDurationMs": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "The average duration of settled runs (milliseconds).",
            "format": "double"
          }
        },
        "description": "A summary of the runs in a time bucket. The result unit of\n`/api/stats/timeseries`; empty buckets are also returned (with zero events)."
      },
      "ToolApprovalDecision": {
        "required": [
          "requestId",
          "approved"
        ],
        "type": "object",
        "properties": {
          "requestId": {
            "type": "string",
            "description": "Identifier of the approved request. This is the\n`ToolApprovalRequestContent.RequestId` value received in the stream."
          },
          "approved": {
            "type": "boolean",
            "description": "Whether the call is approved."
          },
          "reason": {
            "type": [
              "null",
              "string"
            ],
            "description": "Reason for the decision. Passed on to the model."
          },
          "remember": {
            "type": "boolean",
            "description": "Whether the decision should be saved as a permanent rule (\"don't ask\nagain\"). Meaningful only while `Approved` is `true`."
          },
          "rememberArgumentsOnly": {
            "type": "boolean",
            "description": "Whether the permanent rule covers only a call with the same arguments.\nIf `false`, it covers every call to the tool."
          }
        },
        "description": "Tool approval decision sent from the UI."
      },
      "ToolApprovalRule": {
        "required": [
          "id",
          "tenantId",
          "toolName",
          "createdAt"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Gets the rule id. A time-ordered UUID (v7).",
            "format": "uuid"
          },
          "tenantId": {
            "type": "string",
            "description": "Gets the tenant the rule holds in."
          },
          "agentName": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the agent the rule holds for. When `null` it covers every\nagent of the tenant."
          },
          "toolName": {
            "type": "string",
            "description": "Gets the tool the rule holds for."
          },
          "argumentsHash": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the argument fingerprint. When it is populated the rule covers only a call\nmade with the same arguments."
          },
          "argumentConditions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ToolArgumentCondition"
            },
            "description": "Gets the argument conditions. All conditions must match for the rule to apply\n(`AND`); an empty list matches every call of the tool. Mutually exclusive\nwith `ArgumentsHash` — a rule carries one or the other, never both."
          },
          "createdBy": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets who created the rule, or `null` when there is no authentication."
          },
          "createdAt": {
            "type": "string",
            "description": "Gets the creation time (UTC).",
            "format": "date-time"
          }
        },
        "description": "A persistent approval rule for a tool call the user said \"do not ask again\" for."
      },
      "ToolApprovalRuleRequest": {
        "required": [
          "toolName"
        ],
        "type": "object",
        "properties": {
          "agentName": {
            "type": [
              "null",
              "string"
            ],
            "description": "The agent the rule holds for. When empty it covers every agent of the tenant."
          },
          "toolName": {
            "type": "string",
            "description": "The tool the rule holds for."
          },
          "argumentConditions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ToolArgumentCondition"
            },
            "description": "All conditions must match for the rule to apply (`AND`). An empty list\n(the default) matches every call of the tool."
          }
        },
        "description": "Request to create a persistent, argument-conditioned approval rule."
      },
      "ToolArgumentCondition": {
        "required": [
          "path",
          "operator",
          "value"
        ],
        "type": "object",
        "properties": {
          "path": {
            "type": "string",
            "description": "Gets the dotted path into the argument object, for example `order.amount`.\nNo array index is accepted."
          },
          "operator": {
            "description": "Gets the comparison operator.",
            "$ref": "#/components/schemas/ToolArgumentOperator"
          },
          "value": {
            "description": "Gets the value compared against. For ToolArgumentOperator.In and\nToolArgumentOperator.NotIn this is a JSON array of text or numbers;\nfor every other operator it is a single text, number, or boolean.",
            "$ref": "#/components/schemas/JsonElement"
          }
        },
        "description": "One comparison against a tool call argument: <em>path · operator · value</em>."
      },
      "ToolArgumentOperator": {
        "enum": [
          "Equals",
          "NotEquals",
          "GreaterThan",
          "GreaterThanOrEqual",
          "LessThan",
          "LessThanOrEqual",
          "In",
          "NotIn"
        ],
        "description": "A comparison operator for a ToolArgumentCondition."
      },
      "ToolCallContent": {
        "type": "object",
        "anyOf": [
          {
            "$ref": "#/components/schemas/ToolCallContentFunctionCallContent"
          },
          {
            "$ref": "#/components/schemas/ToolCallContentMcpServerToolCallContent"
          },
          {
            "$ref": "#/components/schemas/ToolCallContentImageGenerationToolCallContent"
          },
          {
            "$ref": "#/components/schemas/ToolCallContentCodeInterpreterToolCallContent"
          },
          {
            "$ref": "#/components/schemas/ToolCallContentWebSearchToolCallContent"
          },
          {
            "$ref": "#/components/schemas/ToolCallContentBase"
          }
        ]
      },
      "ToolCallContentBase": {
        "required": [
          "callId"
        ],
        "properties": {
          "callId": {
            "type": "string"
          },
          "annotations": {},
          "additionalProperties": {}
        }
      },
      "ToolCallContentCodeInterpreterToolCallContent": {
        "required": [
          "$type",
          "callId"
        ],
        "properties": {
          "$type": {
            "enum": [
              "codeInterpreterToolCall"
            ],
            "type": "string"
          },
          "inputs": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AIContent"
            }
          },
          "callId": {
            "type": "string"
          },
          "annotations": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AIAnnotation"
            }
          },
          "additionalProperties": {
            "type": [
              "null",
              "object"
            ]
          }
        }
      },
      "ToolCallContentFunctionCallContent": {
        "required": [
          "$type",
          "name",
          "callId"
        ],
        "properties": {
          "$type": {
            "enum": [
              "functionCall"
            ],
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "arguments": {},
          "informationalOnly": {
            "type": "boolean"
          },
          "callId": {
            "type": "string"
          },
          "annotations": {},
          "additionalProperties": {}
        }
      },
      "ToolCallContentImageGenerationToolCallContent": {
        "required": [
          "$type",
          "callId"
        ],
        "properties": {
          "$type": {
            "enum": [
              "imageGenerationToolCall"
            ],
            "type": "string"
          },
          "callId": {
            "type": "string"
          },
          "annotations": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AIAnnotation"
            }
          },
          "additionalProperties": {
            "type": [
              "null",
              "object"
            ]
          }
        }
      },
      "ToolCallContentMcpServerToolCallContent": {
        "required": [
          "$type",
          "name",
          "serverName",
          "callId"
        ],
        "properties": {
          "$type": {
            "enum": [
              "mcpServerToolCall"
            ],
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "serverName": {
            "type": [
              "null",
              "string"
            ]
          },
          "arguments": {
            "type": [
              "null",
              "object"
            ]
          },
          "callId": {
            "type": "string"
          },
          "annotations": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AIAnnotation"
            }
          },
          "additionalProperties": {
            "type": [
              "null",
              "object"
            ]
          }
        }
      },
      "ToolCallContentWebSearchToolCallContent": {
        "required": [
          "$type",
          "callId"
        ],
        "properties": {
          "$type": {
            "enum": [
              "webSearchToolCall"
            ],
            "type": "string"
          },
          "queries": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "type": "string"
            }
          },
          "callId": {
            "type": "string"
          },
          "annotations": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/AIAnnotation"
            }
          },
          "additionalProperties": {
            "type": [
              "null",
              "object"
            ]
          }
        }
      },
      "ToolCallUsage": {
        "required": [
          "unit",
          "quantity"
        ],
        "type": "object",
        "properties": {
          "unit": {
            "type": "string",
            "description": "The measurement unit. See ToolUsageUnits for known values."
          },
          "quantity": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "description": "The billed quantity.",
            "format": "double"
          },
          "cost": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "The computed amount. Stays `null` if the\nconfiguration has no price for this tool — <strong>not</strong> zero.",
            "format": "double"
          },
          "currency": {
            "type": [
              "null",
              "string"
            ],
            "description": "The currency. Comes from `AgentPrism:Pricing:Currency`."
          },
          "isEstimated": {
            "type": "boolean",
            "description": "Whether the quantity was measured or estimated."
          }
        },
        "description": "A single tool call's non-token measurement and cost."
      },
      "ToolDescriptor": {
        "required": [
          "name"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "The tool name. Used in agent definitions."
          },
          "description": {
            "type": [
              "null",
              "string"
            ],
            "description": "The description that lets the model understand when to call the tool."
          },
          "jsonSchema": {
            "type": [
              "null",
              "string"
            ],
            "description": "The arguments' JSON schema."
          },
          "requiresApproval": {
            "type": "boolean",
            "description": "Whether explicit approval is required before the call."
          },
          "source": {
            "type": [
              "null",
              "string"
            ],
            "description": "The tool's source. `null` for tools defined in code;\nthe server name for tools coming from a remote MCP server."
          },
          "runsOnClient": {
            "type": "boolean",
            "description": "Whether the tool's body runs on the caller (typically a browser)\ninstead of on the server."
          },
          "effect": {
            "description": "The tool's effect class. Defaults to ToolEffect.Read.",
            "$ref": "#/components/schemas/ToolEffect"
          },
          "requiredPermission": {
            "type": [
              "null",
              "string"
            ],
            "description": "The permission name a caller must hold to call this tool, or\n`null` when the tool declares none."
          },
          "timeout": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": [
              "null",
              "string"
            ],
            "description": "The longest duration this tool's call may run, or `null`\nto use the installation default (`AgentPrismOptions.Tools.DefaultTimeout`)."
          }
        },
        "description": "The UI-facing definition of a tool registered in code. The agent editor\nshows a selection from this list; it does not accept free-text input."
      },
      "ToolEffect": {
        "enum": [
          "Read",
          "Write",
          "Destructive",
          "External"
        ],
        "description": "Classifies the blast radius of a tool call."
      },
      "ToolInvocationRecord": {
        "required": [
          "id",
          "runId",
          "toolName",
          "createdAt"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The record identifier. A time-ordered UUID (v7).",
            "format": "uuid"
          },
          "runId": {
            "type": "string",
            "description": "The run that made the call.",
            "format": "uuid"
          },
          "toolName": {
            "type": "string",
            "description": "The name of the tool called."
          },
          "toolCallId": {
            "type": [
              "null",
              "string"
            ],
            "description": "The call identifier generated by the model. Distinguishes multiple calls of the same kind."
          },
          "source": {
            "type": [
              "null",
              "string"
            ],
            "description": "The tool's source. `null` for tools defined in code;\nthe server name for MCP tools."
          },
          "arguments": {
            "type": [
              "null",
              "string"
            ],
            "description": "The call arguments. Raw text; may not be valid JSON."
          },
          "result": {
            "type": [
              "null",
              "string"
            ],
            "description": "The call result. Raw text; may not be valid JSON."
          },
          "duration": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": [
              "null",
              "string"
            ],
            "description": "The call's duration. `null` if the event pair did not match."
          },
          "error": {
            "type": [
              "null",
              "string"
            ],
            "description": "The error message. Populated only if the call errored."
          },
          "createdAt": {
            "type": "string",
            "description": "The moment the call settled (UTC).",
            "format": "date-time"
          },
          "usage": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "The call's non-token measurement and cost. `null` if\nthe tool reported no measurement — which is empty for the vast\nmajority of calls.",
                "$ref": "#/components/schemas/ToolCallUsage"
              }
            ]
          },
          "authorizationDenied": {
            "type": "boolean",
            "description": "Whether IToolAuthorizationHandler denied this call before it ran."
          },
          "timedOut": {
            "type": "boolean",
            "description": "Whether the call ended because its execution timeout elapsed\n(AgentPrismToolTimeoutException)."
          },
          "succeeded": {
            "type": "boolean",
            "description": "Whether the call finished successfully."
          }
        },
        "description": "The summary of a single completed tool call."
      },
      "ToolUsage": {
        "required": [
          "toolName",
          "totalCalls",
          "failedCalls"
        ],
        "type": "object",
        "properties": {
          "toolName": {
            "type": "string",
            "description": "The tool name."
          },
          "totalCalls": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The total number of calls.",
            "format": "int64"
          },
          "failedCalls": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The number of calls that errored.",
            "format": "int64"
          },
          "averageDurationMs": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "The average duration (milliseconds). `null` if no call carries a duration.",
            "format": "double"
          },
          "lastCalledAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "The moment it was last called (UTC).",
            "format": "date-time"
          },
          "errorRate": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "The error rate among settled calls (0–1). `null` if there is no call.",
            "format": "double"
          }
        },
        "description": "A tool's usage summary. Shown by the UI's Tools screen."
      },
      "TraceSpan": {
        "required": [
          "id",
          "spanId",
          "name",
          "startedAt"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The database identifier. Derived from the W3C identifiers.",
            "format": "uuid"
          },
          "parentId": {
            "type": [
              "null",
              "string"
            ],
            "description": "The parent span's database identifier. `null` for the root span.",
            "format": "uuid"
          },
          "spanId": {
            "type": "string",
            "description": "The W3C span identifier (16-character hex)."
          },
          "name": {
            "type": "string",
            "description": "The span name. Example: `chat gpt-5.4-mini`, `invoke_agent support`."
          },
          "kind": {
            "description": "The span kind.",
            "$ref": "#/components/schemas/TraceSpanKind"
          },
          "startedAt": {
            "type": "string",
            "description": "The start time (UTC).",
            "format": "date-time"
          },
          "endedAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "The end time (UTC).",
            "format": "date-time"
          },
          "status": {
            "description": "The result status.",
            "$ref": "#/components/schemas/TraceSpanStatus"
          },
          "attributes": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "The span attributes. GenAI semantic convention keys\n(`gen_ai.request.model`, `gen_ai.usage.input_tokens`) go here."
          }
        },
        "description": "A single persisted OpenTelemetry span."
      },
      "TraceSpanKind": {
        "enum": [
          "Internal",
          "Server",
          "Client",
          "Producer",
          "Consumer"
        ],
        "description": "A span's OpenTelemetry kind. Values are stored in the database as\n`smallint`; the numbers are stable."
      },
      "TraceSpanStatus": {
        "enum": [
          "Unset",
          "Ok",
          "Error"
        ],
        "description": "A span's result status. `smallint` in the database."
      },
      "UploadDocumentChunk": {
        "required": [
          "index",
          "content"
        ],
        "type": "object",
        "properties": {
          "index": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Sequence number within the source.",
            "format": "int32"
          },
          "content": {
            "type": "string",
            "description": "The chunk's text."
          },
          "embedding": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
              "type": [
                "number",
                "string"
              ],
              "format": "float"
            },
            "description": "The chunk's embedding. If empty, the server embeds it; if filled in, it\nis written as is and returns 400 if it does not match the store's dimension."
          },
          "metadata": {
            "type": [
              "null",
              "object"
            ],
            "additionalProperties": {
              "type": "string"
            },
            "description": "Optional metadata."
          }
        },
        "description": "A single ready-made chunk in an upload request."
      },
      "UploadDocumentRequest": {
        "required": [
          "sourceId"
        ],
        "type": "object",
        "properties": {
          "sourceId": {
            "type": "string",
            "description": "Source identifier. Uploading again with the same identifier replaces the old one."
          },
          "text": {
            "type": [
              "null",
              "string"
            ],
            "description": "Raw text. If given, the server chunks and embeds it."
          },
          "chunks": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/UploadDocumentChunk"
            },
            "description": "Ready-made chunks. If `UploadDocumentChunk.Embedding` is\nleft empty, the server embeds it; if it is filled in, it is written as is."
          }
        },
        "description": "Request to upload a document."
      },
      "UploadDocumentResponse": {
        "required": [
          "sourceId",
          "chunkCount"
        ],
        "type": "object",
        "properties": {
          "sourceId": {
            "type": "string",
            "description": "Identifier of the uploaded source."
          },
          "chunkCount": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Number of chunks written.",
            "format": "int32"
          }
        },
        "description": "Result of a document upload request."
      },
      "UsageDetails": {
        "type": "object",
        "properties": {
          "inputTokenCount": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "outputTokenCount": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "totalTokenCount": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "cachedInputTokenCount": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "reasoningTokenCount": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "inputAudioTokenCount": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "inputTextTokenCount": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "outputAudioTokenCount": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "outputTextTokenCount": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "additionalCounts": {
            "type": [
              "null",
              "object"
            ],
            "additionalProperties": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int64"
            }
          }
        }
      },
      "ValidationMessage": {
        "required": [
          "severity",
          "code",
          "message"
        ],
        "type": "object",
        "properties": {
          "severity": {
            "description": "Gets the severity of the finding.",
            "$ref": "#/components/schemas/ValidationSeverity"
          },
          "code": {
            "type": "string",
            "description": "Gets the stable machine-readable code, for example `unknown_tool` or `cycle`."
          },
          "message": {
            "type": "string",
            "description": "Gets the human-readable description. It is not translated."
          },
          "path": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the path of the offending field inside the definition, for example\n`toolNames[2]`. It is `null` when the finding points at no field."
          }
        },
        "description": "A single finding produced by the validation of an agent definition."
      },
      "ValidationSeverity": {
        "enum": [
          "Error",
          "Warning"
        ],
        "description": "The severity of a ValidationMessage."
      },
      "VoiceDescriptor": {
        "required": [
          "voiceId",
          "name"
        ],
        "type": "object",
        "properties": {
          "voiceId": {
            "type": "string",
            "description": "The voice identifier. Used in agent definitions and requests."
          },
          "name": {
            "type": "string",
            "description": "The human-readable name."
          },
          "category": {
            "type": [
              "null",
              "string"
            ],
            "description": "The category given by the provider (for example, `premade`)."
          }
        },
        "description": "The definition of an available voice."
      },
      "VoiceHealth": {
        "required": [
          "providerName",
          "isHealthy",
          "latency",
          "checkedAt"
        ],
        "type": "object",
        "properties": {
          "providerName": {
            "type": "string",
            "description": "The provider name."
          },
          "isHealthy": {
            "type": "boolean",
            "description": "Whether the provider is reachable."
          },
          "latency": {
            "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$",
            "type": "string",
            "description": "The check's duration."
          },
          "checkedAt": {
            "type": "string",
            "description": "The moment the check was performed (UTC).",
            "format": "date-time"
          },
          "detail": {
            "type": [
              "null",
              "string"
            ],
            "description": "The reason, if failed. The text carries neither an API key nor an address."
          },
          "voiceCount": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "The number of voices seen during the check.",
            "format": "int32"
          }
        },
        "description": "The voice provider's reachability status."
      },
      "VoiceSessionEndReason": {
        "enum": [
          "Client",
          "IdleTimeout",
          "DurationLimit",
          "Error",
          "ServerShutdown",
          null
        ]
      },
      "VoiceSessionRecord": {
        "required": [
          "id",
          "tenantId",
          "sessionId",
          "agentName",
          "startedAt"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The connection's identifier.",
            "format": "uuid"
          },
          "tenantId": {
            "type": "string",
            "description": "The tenant. Resolved when the connection is established and\n<strong>fixed</strong> for the connection's lifetime."
          },
          "sessionId": {
            "type": "string",
            "description": "The identifier of the agent session the conversation runs in."
          },
          "agentName": {
            "type": "string",
            "description": "The name of the agent being talked to."
          },
          "startedAt": {
            "type": "string",
            "description": "The moment the connection opened.",
            "format": "date-time"
          },
          "endedAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "The moment the connection closed; `null` while still open.",
            "format": "date-time"
          },
          "turns": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The number of completed conversation turns.",
            "format": "int32"
          },
          "inputSeconds": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "description": "The total resolved audio duration (seconds). Stays\n`null` if the provider does not report duration —\nAgentPrism does not fabricate a duration.",
            "format": "double"
          },
          "outputChars": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "The total characters synthesized to speech.",
            "format": "int64"
          },
          "endReason": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Why the connection closed.",
                "$ref": "#/components/schemas/VoiceSessionEndReason"
              }
            ]
          },
          "createdBy": {
            "type": [
              "null",
              "string"
            ],
            "description": "The actor who opened the connection."
          }
        },
        "description": "The summary record of a real-time voice connection."
      },
      "WebhookDelivery": {
        "required": [
          "id",
          "subscriptionId",
          "tenantId",
          "eventType",
          "payload",
          "status",
          "createdAt"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The delivery identifier. Sent in the request as the `X-AgentPrism-Delivery` header.",
            "format": "uuid"
          },
          "subscriptionId": {
            "type": "string",
            "description": "The subscription identifier.",
            "format": "uuid"
          },
          "tenantId": {
            "type": "string",
            "description": "The tenant identifier."
          },
          "eventType": {
            "type": "string",
            "description": "The event name."
          },
          "payload": {
            "type": "string",
            "description": "The JSON body sent."
          },
          "status": {
            "description": "The delivery's status.",
            "$ref": "#/components/schemas/WebhookDeliveryStatus"
          },
          "attempt": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The number of attempts made.",
            "format": "int32"
          },
          "responseCode": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "The HTTP status code the recipient returned. `null` if a\nconnection could not be established.",
            "format": "int32"
          },
          "error": {
            "type": [
              "null",
              "string"
            ],
            "description": "The most recent error message."
          },
          "createdAt": {
            "type": "string",
            "description": "The creation time (UTC).",
            "format": "date-time"
          },
          "deliveredAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "The successful delivery time (UTC).",
            "format": "date-time"
          }
        },
        "description": "A single delivery record."
      },
      "WebhookDeliveryStatus": {
        "enum": [
          "Pending",
          "Delivered",
          "Failed",
          "Dropped"
        ],
        "description": "The status of a webhook delivery attempt."
      },
      "WebhookSaveRequest": {
        "type": "object",
        "properties": {
          "url": {
            "type": [
              "null",
              "string"
            ],
            "description": "The address events are sent to. Only `https` (or loopback `http`)."
          },
          "events": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "type": "string"
            },
            "description": "The names of the subscribed events. See WebhookEvents."
          },
          "secretConfigurationKey": {
            "type": [
              "null",
              "string"
            ],
            "description": "The <strong>name</strong> of the configuration key from which the signing secret is read.\nNot the secret itself."
          },
          "headers": {
            "type": [
              "null",
              "object"
            ],
            "additionalProperties": {
              "type": "string"
            },
            "description": "Additional headers to add to every request."
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether the subscription is enabled."
          }
        },
        "description": "The request body for saving a webhook subscription."
      },
      "WebhookSubscription": {
        "required": [
          "id",
          "tenantId",
          "name",
          "url",
          "events",
          "createdAt",
          "updatedAt"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The subscription identifier.",
            "format": "uuid"
          },
          "tenantId": {
            "type": "string",
            "description": "The tenant the subscription belongs to."
          },
          "name": {
            "type": "string",
            "description": "The name, unique within the tenant."
          },
          "url": {
            "type": "string",
            "description": "The address events are sent to."
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The subscribed event names. See WebhookEvents."
          },
          "secretConfigurationKey": {
            "type": [
              "null",
              "string"
            ],
            "description": "The <strong>name</strong> of the configuration key the signing secret\nis read from. Not the secret itself."
          },
          "headers": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Extra headers added to every request."
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether the subscription is enabled."
          },
          "consecutiveFailures": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The consecutive-failure count. Once the threshold is exceeded, the\nsubscription disables itself and is written to the audit trail.",
            "format": "int32"
          },
          "createdAt": {
            "type": "string",
            "description": "The creation time (UTC).",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "description": "The last-updated time (UTC).",
            "format": "date-time"
          }
        },
        "description": "An external system's event subscription."
      },
      "WebhookTestResponse": {
        "required": [
          "name",
          "queued",
          "message"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "The subscription name."
          },
          "queued": {
            "type": "boolean",
            "description": "Whether the event was written to the queue."
          },
          "message": {
            "type": "string",
            "description": "The description shown to the user."
          }
        },
        "description": "The response for the test event."
      },
      "WorkflowCheckpointRecord": {
        "required": [
          "id",
          "tenantId",
          "sessionId",
          "checkpointId",
          "createdAt",
          "state"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Gets the record identifier. A time-ordered UUID (v7).",
            "format": "uuid"
          },
          "tenantId": {
            "type": "string",
            "description": "Gets the tenant the record belongs to."
          },
          "sessionId": {
            "type": "string",
            "description": "Gets the identifier of the run session. Microsoft Agent Framework\ngroups checkpoints under this value."
          },
          "checkpointId": {
            "type": "string",
            "description": "Gets the checkpoint identifier. The value belongs to AgentPrism, not\nto Microsoft Agent Framework: `CreateAsync` generates it and\nhands it back to MAF."
          },
          "parentCheckpointId": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the identifier of the previous checkpoint. `null` for the first checkpoint."
          },
          "runId": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the identifier of the run that produced this checkpoint.\n`null` if no run was in progress when the checkpoint\nwas written.",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "description": "Gets the creation time (UTC).",
            "format": "date-time"
          },
          "state": {
            "description": "Gets the opaque run state.",
            "$ref": "#/components/schemas/JsonElement"
          }
        },
        "description": "Represents a single checkpoint of a workflow run."
      },
      "WorkflowDefinition": {
        "required": [
          "name",
          "kind"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Gets the workflow's unique name. Serves as the key in the catalog and in API routes."
          },
          "displayName": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the display name shown in the UI. `Name` is used if left empty."
          },
          "description": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the short description of what the workflow does."
          },
          "kind": {
            "description": "Gets the built-in pattern to use.",
            "$ref": "#/components/schemas/WorkflowKind"
          },
          "agentNames": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Gets the agent names to enter the graph. Order is meaningful for\nWorkflowKind.Sequential; for other kinds it defines the\nparticipant set."
          },
          "managerAgentName": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the manager agent's name. Required for\nWorkflowKind.Magentic, unused in other patterns."
          },
          "nodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WorkflowNodeReference"
            },
            "description": "Gets the ordered node list for a WorkflowKind.Sequential\nworkflow that mixes agent and function nodes."
          },
          "maxIterations": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Gets the maximum number of turns. The only guard against an infinite\nloop in the WorkflowKind.GroupChat,\nWorkflowKind.Handoff, and WorkflowKind.Magentic\npatterns.",
            "format": "int32"
          },
          "handoffInstructions": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the extra instruction that tells the model how to decide on a\nhandoff. Used only for WorkflowKind.Handoff."
          },
          "requirePlanApproval": {
            "type": "boolean",
            "description": "Gets whether the plan the manager agent builds must be approved by a\nhuman before execution starts. Applies only to\nWorkflowKind.Magentic."
          },
          "tenantId": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the tenant the definition belongs to. `null` for workflows defined in code."
          },
          "version": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Gets the definition version. Increments by one on every save.",
            "format": "int32"
          },
          "updatedAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the last modification time (UTC).",
            "format": "date-time"
          }
        },
        "description": "Represents the full definition of a workflow, whether defined through the\nUI or in code."
      },
      "WorkflowDescriptor": {
        "required": [
          "name",
          "origin"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Gets the workflow's unique name."
          },
          "displayName": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the display name shown in the UI."
          },
          "description": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the short description."
          },
          "origin": {
            "description": "Gets the source of the definition.",
            "$ref": "#/components/schemas/AgentDefinitionOrigin"
          },
          "kind": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Gets the built-in pattern. `null` for workflows\ndefined by a factory in code: a free-form graph does not correspond\nto a pattern.",
                "$ref": "#/components/schemas/WorkflowKind"
              }
            ]
          },
          "agentNames": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Gets the agent names entering the graph. Can be empty for code-defined workflows."
          },
          "nodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WorkflowNodeReference"
            },
            "description": "Gets the mixed agent/function node list for a Sequential workflow that\nuses function nodes. Empty for every other definition."
          },
          "version": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Gets the definition version. Always 1 for code-defined workflows.",
            "format": "int32"
          },
          "updatedAt": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the last modification time (UTC).",
            "format": "date-time"
          }
        },
        "description": "Represents a summary view of a workflow listed in the catalog."
      },
      "WorkflowEdgeKind": {
        "enum": [
          "Direct",
          "FanOut",
          "FanIn"
        ],
        "description": "Represents the kind of an edge."
      },
      "WorkflowFunctionResponse": {
        "required": [
          "name",
          "inputType",
          "outputType"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "The function's unique name."
          },
          "description": {
            "type": [
              "null",
              "string"
            ],
            "description": "The short description of what the function does."
          },
          "inputType": {
            "type": "string",
            "description": "The display name of the CLR type the function accepts."
          },
          "outputType": {
            "type": "string",
            "description": "The display name of the CLR type the function returns."
          }
        },
        "description": "Wire-safe view of a registered function node."
      },
      "WorkflowGraph": {
        "required": [
          "name",
          "startExecutorId",
          "mermaid"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Gets the name of the workflow the graph belongs to."
          },
          "startExecutorId": {
            "type": "string",
            "description": "Gets the identifier of the node that receives the input message first."
          },
          "nodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WorkflowGraphNode"
            },
            "description": "Gets the nodes in the graph."
          },
          "edges": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WorkflowGraphEdge"
            },
            "description": "Gets the edges between nodes."
          },
          "mermaid": {
            "type": "string",
            "description": "Gets the Mermaid text produced by Microsoft Agent Framework."
          }
        },
        "description": "Represents a workflow's compiled graph: nodes, edges, and external\nrequest ports."
      },
      "WorkflowGraphEdge": {
        "required": [
          "from",
          "to",
          "kind"
        ],
        "type": "object",
        "properties": {
          "from": {
            "type": "string",
            "description": "Gets the source node's identifier."
          },
          "to": {
            "type": "string",
            "description": "Gets the target node's identifier."
          },
          "kind": {
            "description": "Gets the edge's kind.",
            "$ref": "#/components/schemas/WorkflowEdgeKind"
          }
        },
        "description": "Represents the connection between two nodes."
      },
      "WorkflowGraphNode": {
        "required": [
          "id",
          "label",
          "kind"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Gets the executor identifier."
          },
          "label": {
            "type": "string",
            "description": "Gets the short label shown in the UI."
          },
          "kind": {
            "description": "Gets the node's role.",
            "$ref": "#/components/schemas/WorkflowNodeKind"
          },
          "agentName": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the agent's name if the node represents an agent; otherwise\n`null`."
          },
          "executorType": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the Microsoft Agent Framework executor type. For debugging."
          }
        },
        "description": "Represents a node in the graph."
      },
      "WorkflowKind": {
        "enum": [
          "Sequential",
          "Concurrent",
          "Handoff",
          "GroupChat",
          "Magentic",
          null
        ]
      },
      "WorkflowNodeKind": {
        "enum": [
          "Unknown",
          "Agent",
          "Orchestration",
          "RequestPort",
          "Output",
          "Function"
        ],
        "description": "Represents the role of a graph node."
      },
      "WorkflowNodeReference": {
        "required": [
          "name",
          "kind"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Gets the referenced name: an agent name from the catalog when\nWorkflowNodeKind WorkflowNodeReference.Kind is WorkflowNodeKind.Agent, or a\nfunction name from the code registry when it is\nWorkflowNodeKind.Function."
          },
          "kind": {
            "description": "Gets which registry `Name` is looked up in.",
            "$ref": "#/components/schemas/WorkflowNodeKind"
          }
        },
        "description": "Points to a single node entering a workflow's graph: an agent from the\ncatalog, or a function registered in code."
      },
      "WorkflowPendingRequest": {
        "required": [
          "runId",
          "requestId",
          "portId",
          "form"
        ],
        "type": "object",
        "properties": {
          "runId": {
            "type": "string",
            "description": "Gets the identifier of the run that produced the request.",
            "format": "uuid"
          },
          "requestId": {
            "type": "string",
            "description": "Gets the request identifier. Send this value when responding; the\nresumed execution matches it to the request published with the same id."
          },
          "portId": {
            "type": "string",
            "description": "Gets the identifier of the port that published the request. It maps to a graph node."
          },
          "requestType": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the request data type name."
          },
          "responseType": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the expected response type name."
          },
          "prompt": {
            "type": [
              "null",
              "string"
            ],
            "description": "Gets the request text shown to the user. For plan approval, this is the plan itself."
          },
          "form": {
            "description": "Gets the input field the UI should display.",
            "$ref": "#/components/schemas/WorkflowRequestForm"
          },
          "requestedAt": {
            "type": "string",
            "description": "Gets the UTC time when the request was published.",
            "format": "date-time"
          }
        },
        "description": "Represents human input awaited by a workflow run."
      },
      "WorkflowRequestForm": {
        "enum": [
          "Json",
          "Text",
          "Boolean",
          "PlanReview"
        ],
        "description": "Defines how the UI presents a pending request."
      },
      "WorkflowRespondHttpRequest": {
        "required": [
          "requestId"
        ],
        "type": "object",
        "properties": {
          "requestId": {
            "type": "string",
            "description": "Identifier of the request being answered."
          },
          "approved": {
            "type": [
              "null",
              "boolean"
            ],
            "description": "Yes/no response. In a plan approval, `true` approves\nthe plan; `false` sends it back with the correction in\nthe `Text` field."
          },
          "text": {
            "type": [
              "null",
              "string"
            ],
            "description": "Text response; in a plan approval this is the correction instruction."
          },
          "data": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Free-form response body. Resolved against the port's response type.",
                "$ref": "#/components/schemas/JsonElement"
              }
            ]
          },
          "checkpointId": {
            "type": [
              "null",
              "string"
            ],
            "description": "Identifier of the checkpoint to resume. If left empty, the run's most\nrecent checkpoint is used."
          }
        },
        "description": "Response to a pending human input request."
      },
      "WorkflowResumeHttpRequest": {
        "type": "object",
        "properties": {
          "checkpointId": {
            "type": [
              "null",
              "string"
            ],
            "description": "Identifier of the checkpoint to resume from. If left empty, the run's\nmost recent checkpoint is used."
          }
        },
        "description": "Request to resume a workflow from a checkpoint."
      },
      "WorkflowRunHttpRequest": {
        "type": "object",
        "properties": {
          "message": {
            "type": [
              "null",
              "string"
            ],
            "description": "User message to feed into the graph."
          },
          "sessionId": {
            "type": [
              "null",
              "string"
            ],
            "description": "Identifier of the execution session. If left empty, one is generated.\nCheckpoints are grouped under this value."
          }
        },
        "description": "Request to run a workflow."
      },
      "WorkflowSaveRequest": {
        "type": "object",
        "properties": {
          "displayName": {
            "type": [
              "null",
              "string"
            ],
            "description": "Name shown in the UI."
          },
          "description": {
            "type": [
              "null",
              "string"
            ],
            "description": "Short description of what the workflow does."
          },
          "kind": {
            "description": "Built-in pattern to use.",
            "$ref": "#/components/schemas/WorkflowKind"
          },
          "agentNames": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "type": "string"
            },
            "description": "Names of agents to add to the graph."
          },
          "nodes": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "$ref": "#/components/schemas/WorkflowNodeReference"
            },
            "description": "Ordered agent/function node list for a Sequential workflow that mixes\nfunction nodes in with agents. Mutually exclusive with\nIReadOnlyList&lt;string&gt;? WorkflowSaveRequest.AgentNames; leave both empty or set only one."
          },
          "managerAgentName": {
            "type": [
              "null",
              "string"
            ],
            "description": "Name of the manager agent. Only for WorkflowKind.Magentic."
          },
          "maxIterations": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "Maximum number of turns.",
            "format": "int32"
          },
          "handoffInstructions": {
            "type": [
              "null",
              "string"
            ],
            "description": "Handoff instructions. Only for WorkflowKind.Handoff."
          },
          "requirePlanApproval": {
            "type": "boolean",
            "description": "Whether the manager agent's plan must be approved by a human. Only for\nWorkflowKind.Magentic."
          }
        },
        "description": "Request to save a workflow definition."
      }
    },
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "description": "The token configured through AgentPrismEndpointOptions, or an API key issued from /api/api-keys. The header is compared in constant time. When no token is configured the endpoints are reachable from loopback only, so an unauthenticated local run still works.",
        "scheme": "bearer"
      }
    }
  },
  "security": [
    {
      "bearer": []
    }
  ],
  "tags": [
    {
      "name": "AgentPrism"
    },
    {
      "name": "Meta"
    },
    {
      "name": "Agents"
    },
    {
      "name": "Attachments"
    },
    {
      "name": "Skills"
    },
    {
      "name": "Governance"
    },
    {
      "name": "Sessions"
    },
    {
      "name": "Runs"
    },
    {
      "name": "Workflows"
    },
    {
      "name": "Scheduling"
    },
    {
      "name": "Evals"
    },
    {
      "name": "Experiments"
    },
    {
      "name": "Webhooks"
    },
    {
      "name": "ApiKeys"
    },
    {
      "name": "TenantProviders"
    },
    {
      "name": "Triggers"
    },
    {
      "name": "Approvals"
    },
    {
      "name": "Retention"
    },
    {
      "name": "Knowledge"
    },
    {
      "name": "Models"
    },
    {
      "name": "Voice"
    },
    {
      "name": "OpenAI"
    }
  ]
}
