{
  "components": {
    "schemas": {
      "APITokenLog": {
        "description": "Serializer for APITokenLog model, providing read-only access to log entries.",
        "properties": {
          "id": {
            "description": "Unique identifier of the log entry.",
            "readOnly": true,
            "type": "integer"
          },
          "timestamp": {
            "description": "When the call was made.",
            "format": "date-time",
            "readOnly": true,
            "type": "string"
          },
          "api_key_prefix": {
            "description": "Prefix of the API key that made the call; null for calls made with a login token or by a cloud run.",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "user_username": {
            "description": "Username of the user the call was made for.",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "organization_name": {
            "description": "Name of the organization charged for the call.",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "model_id_used": {
            "description": "The HackAgent model the call was made to.",
            "readOnly": true,
            "type": "string"
          },
          "api_endpoint": {
            "description": "The role of the model called: `generator` for `hackagent/attacker-v1`, `judge` for `hackagent/judge-v1`.",
            "readOnly": true,
            "type": "string"
          },
          "input_tokens": {
            "description": "Prompt tokens of the call.",
            "readOnly": true,
            "type": "integer"
          },
          "output_tokens": {
            "description": "Completion tokens of the call.",
            "readOnly": true,
            "type": "integer"
          },
          "credits_deducted": {
            "description": "Credits (US dollars) charged for the call.",
            "format": "decimal",
            "pattern": "^-?\\d{0,4}(?:\\.\\d{0,6})?$",
            "readOnly": true,
            "type": "string"
          },
          "request_payload_preview": {
            "description": "The first characters of the request body.",
            "nullable": true,
            "readOnly": true,
            "title": "Request Preview",
            "type": "string"
          },
          "response_payload_preview": {
            "description": "The first characters of the response body.",
            "nullable": true,
            "readOnly": true,
            "title": "Response Preview",
            "type": "string"
          }
        },
        "required": [
          "api_endpoint",
          "api_key_prefix",
          "credits_deducted",
          "id",
          "input_tokens",
          "model_id_used",
          "organization_name",
          "output_tokens",
          "request_payload_preview",
          "response_payload_preview",
          "timestamp",
          "user_username"
        ],
        "type": "object"
      },
      "AdhocLaunchRequest": {
        "description": "A new campaign, saved when it is launched.",
        "example": {
          "agent": "3f2b8c1e-5d4a-4e6b-9c7d-1a2b3c4d5e6f",
          "executor": "local",
          "name": "Weekly jailbreak sweep",
          "spec": {
            "attacks": [
              {
                "name": "baseline"
              },
              {
                "name": "pair",
                "parameters": {
                  "iterations": 3
                },
                "roles": {
                  "attacker": {
                    "connection": {
                      "provider": "hackagent",
                      "type": "OPENAI"
                    },
                    "name": "hackagent/attacker-v1"
                  }
                }
              }
            ],
            "campaign": {
              "description": "Baseline and PAIR on HarmBench",
              "name": "Weekly jailbreak sweep"
            },
            "dataset": {
              "source": {
                "name": "harmbench",
                "type": "preset"
              }
            },
            "evaluation": {
              "judges": [
                {
                  "connection": {
                    "provider": "hackagent",
                    "type": "OPENAI"
                  },
                  "name": "hackagent/judge-v1"
                }
              ]
            },
            "version": 1
          }
        },
        "properties": {
          "name": {
            "description": "Display name of the campaign.",
            "maxLength": 200,
            "minLength": 1,
            "type": "string"
          },
          "description": {
            "description": "Free-text description.",
            "type": "string"
          },
          "agent": {
            "description": "Id of the agent the campaign targets, in the caller's organization.",
            "format": "uuid",
            "type": "string"
          },
          "spec": {
            "description": "The campaign spec, as the hackagent SDK reads it, without `target` and `execution`: `version`, `campaign` (name, description), `dataset` (where the goals come from), `attacks` (techniques with their `parameters` and model `roles`) and optionally `evaluation` (judges) and other sections; see `GET /campaign/schema`. Model keys must be `${VARIABLE}` references to organization secrets; HackAgent's own models are named `hackagent/attacker-v1` and `hackagent/judge-v1` with provider `hackagent` and no endpoint or key."
          },
          "executor": {
            "allOf": [
              {
                "$ref": "#/components/schemas/LaunchExecutorEnum"
              }
            ],
            "description": "Where the run executes. Left out, the deployment decides: its cloud worker when it has one, otherwise a local machine. ``hackagent web`` sets ``local``, as it runs what it launches.\n\n* `cloud` - cloud\n* `local` - local",
            "writeOnly": true
          }
        },
        "required": [
          "agent",
          "name",
          "spec"
        ],
        "type": "object"
      },
      "Agent": {
        "description": "Serializes Agent model instances to JSON and validates data for creating\nor updating Agent instances.\n\nThis serializer provides a comprehensive representation of an Agent,\nincluding its type, endpoint, and nested details for related 'organization'\nand 'owner' for read operations, while allowing 'organization' and 'owner' IDs\nfor write operations.\n\nAttributes:\n    organization_detail (OrganizationMinimalSerializer): Read-only nested\n        serializer for the agent's organization. Displays minimal details.\n    owner_detail (UserProfileMinimalSerializer): Read-only nested serializer\n        for the agent's owner's user profile. Displays minimal details.\n        Can be null if the agent has no owner or the owner has no profile.\n    agent_type (CharField): The type of the agent as a string\n                      (e.g., LITELLM, OPENAI_SDK, GOOGLE_ADK).\n\nMeta:\n    model (Agent): The model class that this serializer works with.\n    fields (tuple): The fields to include in the serialized output.\n        Includes standard Agent fields like 'endpoint', 'type',\n        and the read-only nested details.\n    read_only_fields (tuple): Fields that are read-only and cannot be\n        set during create/update operations through this serializer.\n        This includes 'id', 'created_at', 'updated_at', and the\n        nested detail fields.",
        "properties": {
          "id": {
            "description": "Unique identifier of the agent.",
            "format": "uuid",
            "readOnly": true,
            "type": "string"
          },
          "name": {
            "description": "Display name, unique within the organization.",
            "maxLength": 200,
            "title": "Agent Name",
            "type": "string"
          },
          "endpoint": {
            "description": "Copy of `config.connection.endpoint`; empty when it has none.",
            "readOnly": true,
            "title": "Endpoint URL",
            "type": "string"
          },
          "agent_type": {
            "description": "Copy of `config.connection.type`, e.g. `OPENAI`, `LITELLM` or `GOOGLE_ADK`.",
            "readOnly": true,
            "title": "Agent SDK/ADK Type",
            "type": "string"
          },
          "description": {
            "description": "Free-text description of the agent.",
            "type": "string"
          },
          "config": {
            "description": "The agent's model configuration, as the hackagent SDK reads it: `name` (the model), `connection` (`provider`, `type`, and optionally `endpoint`, `api_key`, `headers`, `timeout`) and optionally `generation` and `options`. `connection.api_key` must be a `${VARIABLE}` reference to an organization secret; literal credentials are refused."
          },
          "organization": {
            "description": "Id of the agent's organization.",
            "format": "uuid",
            "readOnly": true,
            "type": "string"
          },
          "organization_detail": {
            "allOf": [
              {
                "$ref": "#/components/schemas/OrganizationMinimal"
              }
            ],
            "description": "The organization the agent belongs to.",
            "readOnly": true
          },
          "owner": {
            "description": "Id of the user who created the agent.",
            "nullable": true,
            "readOnly": true,
            "type": "integer"
          },
          "owner_detail": {
            "allOf": [
              {
                "$ref": "#/components/schemas/UserProfileMinimal"
              }
            ],
            "description": "The user who created the agent; null if unknown.",
            "nullable": true,
            "readOnly": true
          },
          "created_at": {
            "description": "When the agent was created.",
            "format": "date-time",
            "readOnly": true,
            "type": "string"
          },
          "updated_at": {
            "description": "When the agent was last changed.",
            "format": "date-time",
            "readOnly": true,
            "type": "string"
          }
        },
        "required": [
          "agent_type",
          "config",
          "created_at",
          "endpoint",
          "id",
          "name",
          "organization",
          "organization_detail",
          "owner",
          "owner_detail",
          "updated_at"
        ],
        "type": "object"
      },
      "AgentRequest": {
        "description": "Serializes Agent model instances to JSON and validates data for creating\nor updating Agent instances.\n\nThis serializer provides a comprehensive representation of an Agent,\nincluding its type, endpoint, and nested details for related 'organization'\nand 'owner' for read operations, while allowing 'organization' and 'owner' IDs\nfor write operations.\n\nAttributes:\n    organization_detail (OrganizationMinimalSerializer): Read-only nested\n        serializer for the agent's organization. Displays minimal details.\n    owner_detail (UserProfileMinimalSerializer): Read-only nested serializer\n        for the agent's owner's user profile. Displays minimal details.\n        Can be null if the agent has no owner or the owner has no profile.\n    agent_type (CharField): The type of the agent as a string\n                      (e.g., LITELLM, OPENAI_SDK, GOOGLE_ADK).\n\nMeta:\n    model (Agent): The model class that this serializer works with.\n    fields (tuple): The fields to include in the serialized output.\n        Includes standard Agent fields like 'endpoint', 'type',\n        and the read-only nested details.\n    read_only_fields (tuple): Fields that are read-only and cannot be\n        set during create/update operations through this serializer.\n        This includes 'id', 'created_at', 'updated_at', and the\n        nested detail fields.",
        "example": {
          "config": {
            "connection": {
              "api_key": "${SUPPORT_BOT_API_KEY}",
              "endpoint": "https://agent.example.com/v1",
              "provider": "openai",
              "type": "OPENAI"
            },
            "name": "gpt-4o-mini"
          },
          "description": "Customer support assistant, staging deployment.",
          "name": "Support bot"
        },
        "properties": {
          "name": {
            "description": "Display name, unique within the organization.",
            "maxLength": 200,
            "minLength": 1,
            "title": "Agent Name",
            "type": "string"
          },
          "description": {
            "description": "Free-text description of the agent.",
            "type": "string"
          },
          "config": {
            "description": "The agent's model configuration, as the hackagent SDK reads it: `name` (the model), `connection` (`provider`, `type`, and optionally `endpoint`, `api_key`, `headers`, `timeout`) and optionally `generation` and `options`. `connection.api_key` must be a `${VARIABLE}` reference to an organization secret; literal credentials are refused."
          }
        },
        "required": [
          "config",
          "name"
        ],
        "type": "object"
      },
      "AnalyticsConsentEnum": {
        "description": "* `unset` - Unset\n* `accepted` - Accepted\n* `declined` - Declined",
        "enum": [
          "unset",
          "accepted",
          "declined"
        ],
        "type": "string"
      },
      "Attack": {
        "description": "Serializer for the Attack model, which represents an Attack configuration.\n\nHandles the conversion of Attack configuration instances to JSON (and vice-versa)\nfor API requests and responses. It includes read-only fields for related\nobject names (like agent_name, owner_username) for convenience in API outputs.",
        "properties": {
          "id": {
            "description": "Unique identifier of the attack configuration.",
            "format": "uuid",
            "readOnly": true,
            "type": "string"
          },
          "type": {
            "description": "The attack technique, as the SDK names it (e.g. `pair`, `baseline`, `tap`; see `GET /campaign/techniques`).",
            "maxLength": 100,
            "title": "Attack Type",
            "type": "string"
          },
          "agent": {
            "description": "Id of the target agent.",
            "format": "uuid",
            "title": "Target Agent",
            "type": "string"
          },
          "agent_name": {
            "description": "Name of the target agent.",
            "readOnly": true,
            "type": "string"
          },
          "owner": {
            "description": "Id of the user who created the configuration.",
            "nullable": true,
            "readOnly": true,
            "title": "Defined By",
            "type": "integer"
          },
          "owner_username": {
            "description": "Username of the user who created the configuration.",
            "readOnly": true,
            "type": "string"
          },
          "organization": {
            "description": "Id of the organization.",
            "format": "uuid",
            "readOnly": true,
            "type": "string"
          },
          "organization_name": {
            "description": "Name of the organization.",
            "readOnly": true,
            "type": "string"
          },
          "configuration": {
            "description": "The technique's parameters and settings, as the client recorded them (free-form JSON).",
            "title": "Attack Configuration"
          },
          "created_at": {
            "description": "When the configuration was created.",
            "format": "date-time",
            "readOnly": true,
            "type": "string"
          },
          "updated_at": {
            "description": "When the configuration was last changed.",
            "format": "date-time",
            "readOnly": true,
            "type": "string"
          }
        },
        "required": [
          "agent",
          "agent_name",
          "configuration",
          "created_at",
          "id",
          "organization",
          "organization_name",
          "owner",
          "owner_username",
          "type",
          "updated_at"
        ],
        "type": "object"
      },
      "AttackCategoryOutcome": {
        "properties": {
          "recorded_goals": {
            "description": "Goals with at least one recorded attempt.",
            "type": "integer"
          },
          "jailbroken": {
            "description": "Goals with at least one successful jailbreak.",
            "type": "integer"
          },
          "mitigated": {
            "description": "Goals every attempt of which was mitigated, once the scope is complete.",
            "type": "integer"
          },
          "unresolved": {
            "description": "Goals neither jailbroken nor (yet) mitigated: still running, pending evaluation or errored.",
            "type": "integer"
          },
          "category": {
            "description": "The goal category (`Unknown` when the goals carry none).",
            "type": "string"
          },
          "subcategories": {
            "description": "The category's outcomes per subcategory.",
            "items": {
              "$ref": "#/components/schemas/SubcategoryOutcomes"
            },
            "type": "array"
          },
          "run_id": {
            "description": "The attack run these category outcomes are for.",
            "format": "uuid",
            "type": "string"
          }
        },
        "required": [
          "category",
          "jailbroken",
          "mitigated",
          "recorded_goals",
          "run_id",
          "subcategories",
          "unresolved"
        ],
        "type": "object"
      },
      "AttackOutcome": {
        "properties": {
          "run_id": {
            "description": "The attack run.",
            "format": "uuid",
            "type": "string"
          },
          "verdict": {
            "allOf": [
              {
                "$ref": "#/components/schemas/AttackVerdictEnum"
              }
            ],
            "description": "The attack run's verdict on the goal; `error` when every attempt errored.\n\n* `jailbroken` - jailbroken\n* `mitigated` - mitigated\n* `unresolved` - unresolved\n* `error` - error"
          },
          "attempts": {
            "description": "Attempts the attack run made on the goal.",
            "type": "integer"
          }
        },
        "required": [
          "attempts",
          "run_id",
          "verdict"
        ],
        "type": "object"
      },
      "AttackRequest": {
        "description": "Serializer for the Attack model, which represents an Attack configuration.\n\nHandles the conversion of Attack configuration instances to JSON (and vice-versa)\nfor API requests and responses. It includes read-only fields for related\nobject names (like agent_name, owner_username) for convenience in API outputs.",
        "properties": {
          "type": {
            "description": "The attack technique, as the SDK names it (e.g. `pair`, `baseline`, `tap`; see `GET /campaign/techniques`).",
            "maxLength": 100,
            "minLength": 1,
            "title": "Attack Type",
            "type": "string"
          },
          "agent": {
            "description": "Id of the target agent.",
            "format": "uuid",
            "title": "Target Agent",
            "type": "string"
          },
          "configuration": {
            "description": "The technique's parameters and settings, as the client recorded them (free-form JSON).",
            "title": "Attack Configuration"
          }
        },
        "required": [
          "agent",
          "configuration",
          "type"
        ],
        "type": "object"
      },
      "AttackStructure": {
        "properties": {
          "attempts": {
            "description": "The goal's attempts in the attack run, in order.",
            "items": {
              "$ref": "#/components/schemas/StructureAttempt"
            },
            "type": "array"
          },
          "traces": {
            "description": "Their trace steps.",
            "items": {
              "$ref": "#/components/schemas/StructureTrace"
            },
            "type": "array"
          },
          "results": {
            "description": "Their results.",
            "items": {
              "$ref": "#/components/schemas/StructureResult"
            },
            "type": "array"
          }
        },
        "required": [
          "attempts",
          "results",
          "traces"
        ],
        "type": "object"
      },
      "AttackVerdictEnum": {
        "description": "* `jailbroken` - jailbroken\n* `mitigated` - mitigated\n* `unresolved` - unresolved\n* `error` - error",
        "enum": [
          "jailbroken",
          "mitigated",
          "unresolved",
          "error"
        ],
        "type": "string"
      },
      "Attempt": {
        "properties": {
          "id": {
            "description": "Id of the attempt's result.",
            "format": "uuid",
            "type": "string"
          },
          "run_id": {
            "description": "The attack run that made it.",
            "format": "uuid",
            "type": "string"
          },
          "ordinal": {
            "description": "Position of the attempt among the goal's attempts, from 1.",
            "type": "integer"
          },
          "bucket": {
            "allOf": [
              {
                "$ref": "#/components/schemas/BucketEnum"
              }
            ],
            "description": "How the attempt was judged: `jailbreak`, `mitigated`, `error` or `pending` (not evaluated yet).\n\n* `jailbreak` - jailbreak\n* `mitigated` - mitigated\n* `error` - error\n* `pending` - pending"
          },
          "notes": {
            "description": "The judges' notes, if any.",
            "nullable": true,
            "type": "string"
          },
          "created_at": {
            "description": "When the attempt was recorded.",
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "bucket",
          "created_at",
          "id",
          "notes",
          "ordinal",
          "run_id"
        ],
        "type": "object"
      },
      "AttemptPage": {
        "properties": {
          "count": {
            "description": "Total number of items across all pages.",
            "type": "integer"
          },
          "next": {
            "description": "URL of the next page, or null on the last page.",
            "nullable": true,
            "type": "string"
          },
          "previous": {
            "description": "URL of the previous page, or null on the first page.",
            "nullable": true,
            "type": "string"
          },
          "results": {
            "description": "The attempts of this page.",
            "items": {
              "$ref": "#/components/schemas/Attempt"
            },
            "type": "array"
          },
          "first_success": {
            "allOf": [
              {
                "$ref": "#/components/schemas/FirstSuccess"
              }
            ],
            "description": "Where the goal's first jailbreak is; null when there is none.",
            "nullable": true
          }
        },
        "required": [
          "count",
          "first_success",
          "next",
          "previous",
          "results"
        ],
        "type": "object"
      },
      "BlankEnum": {
        "enum": [
          ""
        ]
      },
      "BucketEnum": {
        "description": "* `jailbreak` - jailbreak\n* `mitigated` - mitigated\n* `error` - error\n* `pending` - pending",
        "enum": [
          "jailbreak",
          "mitigated",
          "error",
          "pending"
        ],
        "type": "string"
      },
      "Calls": {
        "properties": {
          "target": {
            "description": "Calls to the target agent.",
            "type": "integer"
          },
          "attacker": {
            "description": "Calls to attacker models; null when not traced.",
            "nullable": true,
            "type": "integer"
          },
          "judge": {
            "description": "Calls to judge models; null when not traced.",
            "nullable": true,
            "type": "integer"
          }
        },
        "required": [
          "attacker",
          "judge",
          "target"
        ],
        "type": "object"
      },
      "Campaign": {
        "properties": {
          "id": {
            "description": "Unique identifier of the campaign.",
            "format": "uuid",
            "readOnly": true,
            "type": "string"
          },
          "name": {
            "description": "Display name of the campaign.",
            "maxLength": 200,
            "type": "string"
          },
          "description": {
            "description": "Free-text description.",
            "type": "string"
          },
          "agent": {
            "description": "Id of the agent the campaign targets, in the caller's organization.",
            "format": "uuid",
            "type": "string"
          },
          "spec": {
            "description": "The campaign spec, as the hackagent SDK reads it, without `target` and `execution`: `version`, `campaign` (name, description), `dataset` (where the goals come from), `attacks` (techniques with their `parameters` and model `roles`) and optionally `evaluation` (judges) and other sections; see `GET /campaign/schema`. Model keys must be `${VARIABLE}` references to organization secrets; HackAgent's own models are named `hackagent/attacker-v1` and `hackagent/judge-v1` with provider `hackagent` and no endpoint or key."
          },
          "origin": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CampaignOriginEnum"
              }
            ],
            "description": "Where the campaign was saved: `dashboard` (the dashboard or this API) or `cli` (`hackagent campaign run FILE`).\n\n* `dashboard` - Dashboard\n* `cli` - CLI",
            "readOnly": true
          },
          "organization": {
            "description": "Id of the campaign's organization.",
            "format": "uuid",
            "readOnly": true,
            "type": "string"
          },
          "owner": {
            "description": "Id of the user who created the campaign.",
            "nullable": true,
            "readOnly": true,
            "type": "integer"
          },
          "created_at": {
            "description": "When the campaign was created.",
            "format": "date-time",
            "readOnly": true,
            "type": "string"
          },
          "updated_at": {
            "description": "When the campaign was last changed.",
            "format": "date-time",
            "readOnly": true,
            "type": "string"
          }
        },
        "required": [
          "agent",
          "created_at",
          "id",
          "name",
          "organization",
          "origin",
          "owner",
          "spec",
          "updated_at"
        ],
        "type": "object"
      },
      "CampaignOriginEnum": {
        "description": "* `dashboard` - Dashboard\n* `cli` - CLI",
        "enum": [
          "dashboard",
          "cli"
        ],
        "type": "string"
      },
      "CampaignRequest": {
        "example": {
          "agent": "3f2b8c1e-5d4a-4e6b-9c7d-1a2b3c4d5e6f",
          "description": "Baseline and PAIR on HarmBench",
          "name": "Weekly jailbreak sweep",
          "spec": {
            "attacks": [
              {
                "name": "baseline"
              },
              {
                "name": "pair",
                "parameters": {
                  "iterations": 3
                },
                "roles": {
                  "attacker": {
                    "connection": {
                      "provider": "hackagent",
                      "type": "OPENAI"
                    },
                    "name": "hackagent/attacker-v1"
                  }
                }
              }
            ],
            "campaign": {
              "description": "Baseline and PAIR on HarmBench",
              "name": "Weekly jailbreak sweep"
            },
            "dataset": {
              "source": {
                "name": "harmbench",
                "type": "preset"
              }
            },
            "evaluation": {
              "judges": [
                {
                  "connection": {
                    "provider": "hackagent",
                    "type": "OPENAI"
                  },
                  "name": "hackagent/judge-v1"
                }
              ]
            },
            "version": 1
          }
        },
        "properties": {
          "name": {
            "description": "Display name of the campaign.",
            "maxLength": 200,
            "minLength": 1,
            "type": "string"
          },
          "description": {
            "description": "Free-text description.",
            "type": "string"
          },
          "agent": {
            "description": "Id of the agent the campaign targets, in the caller's organization.",
            "format": "uuid",
            "type": "string"
          },
          "spec": {
            "description": "The campaign spec, as the hackagent SDK reads it, without `target` and `execution`: `version`, `campaign` (name, description), `dataset` (where the goals come from), `attacks` (techniques with their `parameters` and model `roles`) and optionally `evaluation` (judges) and other sections; see `GET /campaign/schema`. Model keys must be `${VARIABLE}` references to organization secrets; HackAgent's own models are named `hackagent/attacker-v1` and `hackagent/judge-v1` with provider `hackagent` and no endpoint or key."
          }
        },
        "required": [
          "agent",
          "name",
          "spec"
        ],
        "type": "object"
      },
      "CampaignRunReport": {
        "description": "A campaign run and its goal verdicts over every attack run.",
        "properties": {
          "recorded_goals": {
            "description": "Goals with at least one recorded attempt.",
            "type": "integer"
          },
          "jailbroken": {
            "description": "Goals with at least one successful jailbreak.",
            "type": "integer"
          },
          "mitigated": {
            "description": "Goals every attempt of which was mitigated, once the scope is complete.",
            "type": "integer"
          },
          "unresolved": {
            "description": "Goals neither jailbroken nor (yet) mitigated: still running, pending evaluation or errored.",
            "type": "integer"
          },
          "id": {
            "description": "Id of the campaign run.",
            "format": "uuid",
            "type": "string"
          },
          "name": {
            "description": "The campaign's name.",
            "type": "string"
          },
          "campaign": {
            "description": "Id of the saved campaign it was launched from, if any.",
            "format": "uuid",
            "nullable": true,
            "type": "string"
          },
          "agent": {
            "description": "Id of the agent.",
            "format": "uuid",
            "type": "string"
          },
          "target": {
            "description": "The agent's name.",
            "type": "string"
          },
          "status": {
            "allOf": [
              {
                "$ref": "#/components/schemas/StatusEnum"
              }
            ],
            "description": "The run's status.\n\n* `PENDING` - Pending\n* `RUNNING` - Running\n* `COMPLETED` - Completed\n* `FAILED` - Failed\n* `CANCELLED` - Cancelled"
          },
          "executor": {
            "allOf": [
              {
                "$ref": "#/components/schemas/RunExecutorEnum"
              }
            ],
            "description": "Who executes the run.\n\n* `cloud` - HackAgent cloud\n* `local` - Local machine\n* `cli` - Command line"
          },
          "created_at": {
            "description": "When the run was created.",
            "format": "date-time",
            "type": "string"
          },
          "updated_at": {
            "description": "When the run's reports last changed.",
            "format": "date-time",
            "type": "string"
          },
          "finished_at": {
            "description": "When the run finished; null while it is active.",
            "format": "date-time",
            "nullable": true,
            "type": "string"
          },
          "attack_runs": {
            "description": "Number of attack runs.",
            "type": "integer"
          },
          "attempts": {
            "description": "Attempts recorded across all attack runs.",
            "type": "integer"
          },
          "revision": {
            "description": "Goes up with every write that changes this campaign run's reports: poll the summary and refetch the rest when it moves.",
            "type": "integer"
          },
          "configuration": {
            "additionalProperties": {},
            "description": "The campaign spec.",
            "type": "object"
          },
          "audit": {
            "additionalProperties": {},
            "description": "The judge audit of the campaign run.",
            "nullable": true,
            "type": "object"
          },
          "notes": {
            "description": "The campaign run's notes, if any.",
            "nullable": true,
            "type": "string"
          },
          "scope_run_id": {
            "description": "The attack run the outcomes are limited to (`run_id`), or null.",
            "format": "uuid",
            "nullable": true,
            "type": "string"
          },
          "runs": {
            "description": "The attack runs, oldest first.",
            "items": {
              "$ref": "#/components/schemas/HistoryRun"
            },
            "type": "array"
          },
          "technique_outcomes": {
            "description": "Goal outcomes per attack technique.",
            "items": {
              "$ref": "#/components/schemas/TechniqueOutcomes"
            },
            "type": "array"
          },
          "category_outcomes": {
            "description": "Goal outcomes per goal category and subcategory.",
            "items": {
              "$ref": "#/components/schemas/CategoryOutcomes"
            },
            "type": "array"
          },
          "attack_category_outcomes": {
            "description": "Goal outcomes per category, for each attack run.",
            "items": {
              "$ref": "#/components/schemas/AttackCategoryOutcome"
            },
            "type": "array"
          },
          "previous": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PreviousRun"
              }
            ],
            "description": "The latest completed earlier run of the same campaign.",
            "nullable": true
          }
        },
        "required": [
          "agent",
          "attack_category_outcomes",
          "attack_runs",
          "attempts",
          "audit",
          "campaign",
          "category_outcomes",
          "configuration",
          "created_at",
          "executor",
          "finished_at",
          "id",
          "jailbroken",
          "mitigated",
          "name",
          "notes",
          "previous",
          "recorded_goals",
          "revision",
          "runs",
          "scope_run_id",
          "status",
          "target",
          "technique_outcomes",
          "unresolved",
          "updated_at"
        ],
        "type": "object"
      },
      "CampaignRunSelectionRequest": {
        "example": {
          "ids": [
            "c7d8e9f0-1a2b-4c3d-9e4f-5a6b7c8d9e0f",
            "0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d"
          ]
        },
        "properties": {
          "ids": {
            "description": "Ids of the campaign runs (1 to 100).",
            "items": {
              "format": "uuid",
              "type": "string"
            },
            "maxItems": 100,
            "minItems": 1,
            "type": "array"
          }
        },
        "required": [
          "ids"
        ],
        "type": "object"
      },
      "CampaignRunSummary": {
        "description": "A campaign run and its goal verdicts over every attack run.",
        "properties": {
          "recorded_goals": {
            "description": "Goals with at least one recorded attempt.",
            "type": "integer"
          },
          "jailbroken": {
            "description": "Goals with at least one successful jailbreak.",
            "type": "integer"
          },
          "mitigated": {
            "description": "Goals every attempt of which was mitigated, once the scope is complete.",
            "type": "integer"
          },
          "unresolved": {
            "description": "Goals neither jailbroken nor (yet) mitigated: still running, pending evaluation or errored.",
            "type": "integer"
          },
          "id": {
            "description": "Id of the campaign run.",
            "format": "uuid",
            "type": "string"
          },
          "name": {
            "description": "The campaign's name.",
            "type": "string"
          },
          "campaign": {
            "description": "Id of the saved campaign it was launched from, if any.",
            "format": "uuid",
            "nullable": true,
            "type": "string"
          },
          "agent": {
            "description": "Id of the agent.",
            "format": "uuid",
            "type": "string"
          },
          "target": {
            "description": "The agent's name.",
            "type": "string"
          },
          "status": {
            "allOf": [
              {
                "$ref": "#/components/schemas/StatusEnum"
              }
            ],
            "description": "The run's status.\n\n* `PENDING` - Pending\n* `RUNNING` - Running\n* `COMPLETED` - Completed\n* `FAILED` - Failed\n* `CANCELLED` - Cancelled"
          },
          "executor": {
            "allOf": [
              {
                "$ref": "#/components/schemas/RunExecutorEnum"
              }
            ],
            "description": "Who executes the run.\n\n* `cloud` - HackAgent cloud\n* `local` - Local machine\n* `cli` - Command line"
          },
          "created_at": {
            "description": "When the run was created.",
            "format": "date-time",
            "type": "string"
          },
          "updated_at": {
            "description": "When the run's reports last changed.",
            "format": "date-time",
            "type": "string"
          },
          "finished_at": {
            "description": "When the run finished; null while it is active.",
            "format": "date-time",
            "nullable": true,
            "type": "string"
          },
          "attack_runs": {
            "description": "Number of attack runs.",
            "type": "integer"
          },
          "attempts": {
            "description": "Attempts recorded across all attack runs.",
            "type": "integer"
          },
          "revision": {
            "description": "Goes up with every write that changes this campaign run's reports: poll the summary and refetch the rest when it moves.",
            "type": "integer"
          }
        },
        "required": [
          "agent",
          "attack_runs",
          "attempts",
          "campaign",
          "created_at",
          "executor",
          "finished_at",
          "id",
          "jailbroken",
          "mitigated",
          "name",
          "recorded_goals",
          "revision",
          "status",
          "target",
          "unresolved",
          "updated_at"
        ],
        "type": "object"
      },
      "CampaignRunSummaryPage": {
        "properties": {
          "count": {
            "description": "Total number of items across all pages.",
            "type": "integer"
          },
          "next": {
            "description": "URL of the next page, or null on the last page.",
            "nullable": true,
            "type": "string"
          },
          "previous": {
            "description": "URL of the previous page, or null on the first page.",
            "nullable": true,
            "type": "string"
          },
          "results": {
            "description": "The campaign runs of this page.",
            "items": {
              "$ref": "#/components/schemas/CampaignRunSummary"
            },
            "type": "array"
          }
        },
        "required": [
          "count",
          "next",
          "previous",
          "results"
        ],
        "type": "object"
      },
      "CampaignSchema": {
        "properties": {
          "schema": {
            "additionalProperties": {},
            "description": "JSON Schema of a campaign spec.",
            "type": "object"
          },
          "dataset_presets": {
            "description": "The built-in datasets, by name.",
            "items": {
              "$ref": "#/components/schemas/DatasetPreset"
            },
            "type": "array"
          }
        },
        "required": [
          "dataset_presets",
          "schema"
        ],
        "type": "object"
      },
      "CampaignStartRequest": {
        "description": "A campaign started by ``hackagent campaign run FILE``: the SDK's\nrecorded spec, whose ``target`` and ``execution`` are the client's own and\nare not stored.",
        "properties": {
          "agent": {
            "description": "Id of the agent the campaign runs against.",
            "format": "uuid",
            "type": "string"
          },
          "spec": {
            "description": "The campaign spec the CLI runs. Its `target` and `execution` are dropped; the rest is validated and saved as the campaign."
          },
          "claimed_by": {
            "description": "Free-text description of the executor; defaults to `cli`.",
            "maxLength": 200,
            "type": "string"
          }
        },
        "required": [
          "agent",
          "spec"
        ],
        "type": "object"
      },
      "CategoryOutcomes": {
        "properties": {
          "recorded_goals": {
            "description": "Goals with at least one recorded attempt.",
            "type": "integer"
          },
          "jailbroken": {
            "description": "Goals with at least one successful jailbreak.",
            "type": "integer"
          },
          "mitigated": {
            "description": "Goals every attempt of which was mitigated, once the scope is complete.",
            "type": "integer"
          },
          "unresolved": {
            "description": "Goals neither jailbroken nor (yet) mitigated: still running, pending evaluation or errored.",
            "type": "integer"
          },
          "category": {
            "description": "The goal category (`Unknown` when the goals carry none).",
            "type": "string"
          },
          "subcategories": {
            "description": "The category's outcomes per subcategory.",
            "items": {
              "$ref": "#/components/schemas/SubcategoryOutcomes"
            },
            "type": "array"
          }
        },
        "required": [
          "category",
          "jailbroken",
          "mitigated",
          "recorded_goals",
          "subcategories",
          "unresolved"
        ],
        "type": "object"
      },
      "CategorySourceEnum": {
        "description": "* `recorded` - recorded\n* `unknown` - unknown",
        "enum": [
          "recorded",
          "unknown"
        ],
        "type": "string"
      },
      "ChangeCounts": {
        "properties": {
          "regressed": {
            "description": "Goals jailbroken now but not in the baseline.",
            "type": "integer"
          },
          "fixed": {
            "description": "Goals jailbroken in the baseline but not now.",
            "type": "integer"
          },
          "unchanged": {
            "description": "Goals whose jailbroken-or-not outcome did not change.",
            "type": "integer"
          },
          "new": {
            "description": "Goals only in this run.",
            "type": "integer"
          },
          "dropped": {
            "description": "Goals only in the baseline.",
            "type": "integer"
          }
        },
        "required": [
          "dropped",
          "fixed",
          "new",
          "regressed",
          "unchanged"
        ],
        "type": "object"
      },
      "ChangeEnum": {
        "description": "* `regressed` - regressed\n* `fixed` - fixed\n* `unchanged` - unchanged\n* `new` - new\n* `dropped` - dropped",
        "enum": [
          "regressed",
          "fixed",
          "unchanged",
          "new",
          "dropped"
        ],
        "type": "string"
      },
      "ChildRunRequest": {
        "description": "A child run of a campaign run: one attack. The agent defaults to the\ncampaign run's.",
        "properties": {
          "attack": {
            "description": "Id of the attack configuration the child run executes.",
            "format": "uuid",
            "nullable": true,
            "type": "string"
          },
          "agent": {
            "description": "Id of the agent; defaults to the campaign run's.",
            "format": "uuid",
            "type": "string"
          },
          "run_config": {
            "additionalProperties": {},
            "description": "The attack run's configuration (credentials as `${VARIABLE}` references only).",
            "nullable": true,
            "type": "object"
          }
        },
        "type": "object"
      },
      "Choice": {
        "properties": {
          "index": {
            "description": "Index of the choice",
            "type": "integer"
          },
          "message": {
            "allOf": [
              {
                "$ref": "#/components/schemas/ChoiceMessage"
              }
            ],
            "description": "Message object"
          },
          "finish_reason": {
            "description": "Reason for completion (stop, length, etc.)",
            "type": "string"
          }
        },
        "required": [
          "finish_reason",
          "index",
          "message"
        ],
        "type": "object"
      },
      "ChoiceMessage": {
        "properties": {
          "role": {
            "description": "Role of the message sender",
            "type": "string"
          },
          "content": {
            "description": "Generated content",
            "type": "string"
          }
        },
        "required": [
          "content",
          "role"
        ],
        "type": "object"
      },
      "ClaimRequest": {
        "properties": {
          "claimed_by": {
            "description": "Free-text description of the executor, e.g. local:<hostname>.",
            "maxLength": 200,
            "type": "string"
          }
        },
        "type": "object"
      },
      "ClaimedRun": {
        "description": "A claimed run; for a cloud run, also the credentials it runs with\n(set on the instance by the claim; absent for local runs).",
        "properties": {
          "id": {
            "description": "Unique identifier of the run.",
            "format": "uuid",
            "readOnly": true,
            "type": "string"
          },
          "agent": {
            "description": "Id of the agent the run targets.",
            "format": "uuid",
            "readOnly": true,
            "type": "string"
          },
          "agent_name": {
            "description": "Name of the agent.",
            "readOnly": true,
            "type": "string"
          },
          "attack": {
            "description": "Id of the attack configuration an attack run executes; null for campaign runs.",
            "format": "uuid",
            "nullable": true,
            "readOnly": true,
            "title": "Associated Attack",
            "type": "string"
          },
          "owner": {
            "description": "Id of the user who launched the run.",
            "nullable": true,
            "readOnly": true,
            "title": "Initiated By",
            "type": "integer"
          },
          "owner_username": {
            "description": "Username of the user who launched the run.",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "organization": {
            "description": "Id of the run's organization.",
            "format": "uuid",
            "readOnly": true,
            "type": "string"
          },
          "organization_name": {
            "description": "Name of the run's organization.",
            "readOnly": true,
            "type": "string"
          },
          "run_config": {
            "description": "The run's configuration. For a campaign run: `campaign_config` (the resolved campaign spec, with the agent as `target`), `campaign_id`, `campaign_name` and the `sdk_version` it runs with; for an attack run, what its executor recorded.",
            "nullable": true,
            "readOnly": true,
            "title": "Run Configuration"
          },
          "timestamp": {
            "description": "When the run was created.",
            "format": "date-time",
            "readOnly": true,
            "type": "string"
          },
          "status": {
            "allOf": [
              {
                "$ref": "#/components/schemas/StatusEnum"
              }
            ],
            "description": "`PENDING` (queued), `RUNNING`, then `COMPLETED`, `FAILED` or `CANCELLED`.\n\n* `PENDING` - Pending\n* `RUNNING` - Running\n* `COMPLETED` - Completed\n* `FAILED` - Failed\n* `CANCELLED` - Cancelled",
            "readOnly": true
          },
          "run_notes": {
            "description": "Notes on the run, e.g. why it failed or was cancelled.",
            "readOnly": true,
            "type": "string"
          },
          "executor": {
            "allOf": [
              {
                "$ref": "#/components/schemas/RunExecutorEnum"
              }
            ],
            "description": "Who executes the run: HackAgent cloud, a local machine or the CLI.\n\n* `cloud` - HackAgent cloud\n* `local` - Local machine\n* `cli` - Command line",
            "readOnly": true
          },
          "campaign": {
            "description": "Id of the saved campaign the run was launched from, if any.",
            "format": "uuid",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "parent": {
            "description": "Id of the campaign run an attack run belongs to; null for a campaign run.",
            "format": "uuid",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "claimed_at": {
            "description": "When an executor claimed the run.",
            "format": "date-time",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "claimed_by": {
            "description": "Free-text description of the executor that claimed the run.",
            "readOnly": true,
            "type": "string"
          },
          "heartbeat_at": {
            "description": "The executor's last heartbeat.",
            "format": "date-time",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "cancel_requested_at": {
            "description": "When a cancel was requested; the executor then stops the run.",
            "format": "date-time",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "finished_at": {
            "description": "When the run reached COMPLETED, FAILED or CANCELLED.",
            "format": "date-time",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "results": {
            "description": "The run's results with their traces. Left out by `GET /run/{id}?include_results=false`.",
            "items": {
              "$ref": "#/components/schemas/Result"
            },
            "readOnly": true,
            "type": "array"
          },
          "run_token": {
            "description": "Cloud runs: the run's token, valid until the run finishes.",
            "readOnly": true,
            "type": "string"
          },
          "env": {
            "additionalProperties": {
              "type": "string"
            },
            "description": "Cloud runs: the secrets the spec's API-key references read, by name.",
            "readOnly": true,
            "type": "object"
          }
        },
        "required": [
          "agent",
          "agent_name",
          "attack",
          "campaign",
          "cancel_requested_at",
          "claimed_at",
          "claimed_by",
          "executor",
          "finished_at",
          "heartbeat_at",
          "id",
          "organization",
          "organization_name",
          "owner",
          "owner_username",
          "parent",
          "results",
          "run_config",
          "run_notes",
          "status",
          "timestamp"
        ],
        "type": "object"
      },
      "ComparedGoal": {
        "properties": {
          "goal": {
            "description": "The goal text, by which goals are matched.",
            "type": "string"
          },
          "category": {
            "description": "The goal's category.",
            "type": "string"
          },
          "subcategory": {
            "description": "The goal's subcategory; empty when none.",
            "type": "string"
          },
          "current": {
            "description": "Its verdict in this run; null when absent.\n\n* `jailbroken` - jailbroken\n* `mitigated` - mitigated\n* `unresolved` - unresolved",
            "nullable": true,
            "oneOf": [
              {
                "$ref": "#/components/schemas/GoalVerdictEnum"
              },
              {
                "$ref": "#/components/schemas/NullEnum"
              }
            ]
          },
          "baseline": {
            "description": "Its verdict in the baseline run; null when absent.\n\n* `jailbroken` - jailbroken\n* `mitigated` - mitigated\n* `unresolved` - unresolved",
            "nullable": true,
            "oneOf": [
              {
                "$ref": "#/components/schemas/GoalVerdictEnum"
              },
              {
                "$ref": "#/components/schemas/NullEnum"
              }
            ]
          },
          "change": {
            "allOf": [
              {
                "$ref": "#/components/schemas/ChangeEnum"
              }
            ],
            "description": "How the outcome changed.\n\n* `regressed` - regressed\n* `fixed` - fixed\n* `unchanged` - unchanged\n* `new` - new\n* `dropped` - dropped"
          }
        },
        "required": [
          "baseline",
          "category",
          "change",
          "current",
          "goal",
          "subcategory"
        ],
        "type": "object"
      },
      "ComparedRun": {
        "properties": {
          "id": {
            "description": "Id of the campaign run.",
            "format": "uuid",
            "type": "string"
          },
          "name": {
            "description": "The campaign's name.",
            "type": "string"
          },
          "created_at": {
            "description": "When the run was created.",
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "created_at",
          "id",
          "name"
        ],
        "type": "object"
      },
      "CreditRequestRequest": {
        "example": {
          "amount": "50.00",
          "reason": "Nightly cloud campaigns."
        },
        "properties": {
          "amount": {
            "description": "Requested credit amount in USD (optional).",
            "format": "decimal",
            "pattern": "^-?\\d{0,13}(?:\\.\\d{0,6})?$",
            "type": "string"
          },
          "reason": {
            "description": "Why the credits are needed (optional).",
            "maxLength": 2000,
            "type": "string"
          }
        },
        "type": "object"
      },
      "CreditRequestResponse": {
        "properties": {
          "status": {
            "description": "`sent` once the request was emailed.",
            "type": "string"
          }
        },
        "required": [
          "status"
        ],
        "type": "object"
      },
      "DatasetPreset": {
        "description": "A built-in goal dataset.",
        "properties": {
          "name": {
            "description": "The preset's name, for `dataset.source.name` (with `type: preset`).",
            "type": "string"
          },
          "description": {
            "description": "What the dataset contains.",
            "type": "string"
          }
        },
        "required": [
          "description",
          "name"
        ],
        "type": "object"
      },
      "ErrorDetail": {
        "description": "An error with a human-readable ``detail``: authentication, permission,\nnot found and rate-limit errors, and the license limits. Some errors add\nother keys (a license error adds ``error``, its verification code).",
        "properties": {
          "detail": {
            "description": "What went wrong, for people.",
            "type": "string"
          },
          "code": {
            "description": "Machine-readable cause, when there is one: `license_read_only` (writes refused until a valid license is installed), `license_run_limit` (the monthly runs of the license are used up).",
            "type": "string"
          }
        },
        "required": [
          "detail"
        ],
        "type": "object"
      },
      "EvaluationStatusEnum": {
        "description": "* `NOT_EVALUATED` - Not Evaluated\n* `SUCCESSFUL_JAILBREAK` - Successful Jailbreak\n* `FAILED_JAILBREAK` - Failed Jailbreak (Mitigated/Refused)\n* `ERROR_AGENT_RESPONSE` - Error in Agent Response\n* `ERROR_TEST_FRAMEWORK` - Error in Test Framework\n* `PASSED_CRITERIA` - Passed Criteria (Not Jailbreak)\n* `FAILED_CRITERIA` - Failed Criteria (Not Jailbreak)",
        "enum": [
          "NOT_EVALUATED",
          "SUCCESSFUL_JAILBREAK",
          "FAILED_JAILBREAK",
          "ERROR_AGENT_RESPONSE",
          "ERROR_TEST_FRAMEWORK",
          "PASSED_CRITERIA",
          "FAILED_CRITERIA"
        ],
        "type": "string"
      },
      "FinishRequest": {
        "properties": {
          "status": {
            "allOf": [
              {
                "$ref": "#/components/schemas/FinishStatusEnum"
              }
            ],
            "description": "How the run ended.\n\n* `COMPLETED` - COMPLETED\n* `FAILED` - FAILED\n* `CANCELLED` - CANCELLED"
          },
          "note": {
            "default": "",
            "description": "Stored as the run's `run_notes`, e.g. the error that failed it.",
            "type": "string"
          }
        },
        "required": [
          "status"
        ],
        "type": "object"
      },
      "FinishStatusEnum": {
        "description": "* `COMPLETED` - COMPLETED\n* `FAILED` - FAILED\n* `CANCELLED` - CANCELLED",
        "enum": [
          "COMPLETED",
          "FAILED",
          "CANCELLED"
        ],
        "type": "string"
      },
      "FirstSuccess": {
        "properties": {
          "id": {
            "description": "Id of the first successful attempt.",
            "format": "uuid",
            "type": "string"
          },
          "page": {
            "description": "The page (with the requested `page_size`) that holds it.",
            "type": "integer"
          }
        },
        "required": [
          "id",
          "page"
        ],
        "type": "object"
      },
      "GatewayModel": {
        "properties": {
          "id": {
            "description": "The name to send as ``model``",
            "type": "string"
          },
          "object": {
            "description": "Always 'model'",
            "type": "string"
          },
          "owned_by": {
            "description": "Always 'hackagent'",
            "type": "string"
          }
        },
        "required": [
          "id",
          "object",
          "owned_by"
        ],
        "type": "object"
      },
      "GatewayModelList": {
        "properties": {
          "object": {
            "description": "Always 'list'",
            "type": "string"
          },
          "data": {
            "description": "The models served.",
            "items": {
              "$ref": "#/components/schemas/GatewayModel"
            },
            "type": "array"
          }
        },
        "required": [
          "data",
          "object"
        ],
        "type": "object"
      },
      "GenerateErrorResponse": {
        "description": "An LLM gateway error. Most also carry a machine-readable ``code``\n(``UNKNOWN_MODEL``, ``INVALID_MAX_TOKENS``, ``INSUFFICIENT_CREDITS``,\n``STREAMING_DISABLED``, ``PROVIDER_RATE_LIMITED``, ``ORG_CONTEXT_MISSING``)\nand sometimes ``details``; an unknown model also lists the ``models``.",
        "properties": {
          "error": {
            "description": "Description of the error that occurred.",
            "type": "string"
          }
        },
        "required": [
          "error"
        ],
        "type": "object"
      },
      "GenerateRequestRequest": {
        "example": {
          "max_tokens": 256,
          "messages": [
            {
              "content": "Answer JAILBROKEN or MITIGATED.",
              "role": "system"
            },
            {
              "content": "Goal: <goal>\nResponse: <agent response>",
              "role": "user"
            }
          ],
          "model": "hackagent/judge-v1",
          "temperature": 0
        },
        "properties": {
          "model": {
            "allOf": [
              {
                "$ref": "#/components/schemas/ModelEnum"
              }
            ],
            "description": "The HackAgent model to use (GET /v1/models)\n\n* `hackagent/attacker-v1` - hackagent/attacker-v1\n* `hackagent/judge-v1` - hackagent/judge-v1"
          },
          "messages": {
            "description": "Array of conversation messages",
            "items": {
              "$ref": "#/components/schemas/MessageRequest"
            },
            "type": "array"
          },
          "stream": {
            "default": false,
            "description": "Whether to stream the response",
            "type": "boolean"
          },
          "temperature": {
            "description": "Sampling temperature (0-2)",
            "format": "double",
            "type": "number"
          },
          "max_tokens": {
            "description": "Maximum tokens to generate",
            "type": "integer"
          },
          "top_p": {
            "description": "Nucleus sampling threshold",
            "format": "double",
            "type": "number"
          },
          "frequency_penalty": {
            "description": "Frequency penalty (-2.0 to 2.0)",
            "format": "double",
            "type": "number"
          },
          "presence_penalty": {
            "description": "Presence penalty (-2.0 to 2.0)",
            "format": "double",
            "type": "number"
          },
          "stop": {
            "description": "Sequences where the API will stop generating",
            "items": {
              "minLength": 1,
              "type": "string"
            },
            "type": "array"
          }
        },
        "required": [
          "messages",
          "model"
        ],
        "type": "object"
      },
      "GenerateSuccessResponse": {
        "properties": {
          "id": {
            "description": "Unique identifier for the completion",
            "type": "string"
          },
          "object": {
            "description": "Object type (chat.completion)",
            "type": "string"
          },
          "created": {
            "description": "Unix timestamp of creation",
            "type": "integer"
          },
          "model": {
            "description": "The HackAgent model that answered",
            "type": "string"
          },
          "choices": {
            "description": "Array of completion choices",
            "items": {
              "$ref": "#/components/schemas/Choice"
            },
            "type": "array"
          },
          "usage": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Usage"
              }
            ],
            "description": "Token usage information"
          }
        },
        "required": [
          "choices",
          "created",
          "id",
          "model",
          "object",
          "usage"
        ],
        "type": "object"
      },
      "GoalMatrix": {
        "properties": {
          "runs": {
            "description": "The attack runs: the columns of `cells` and `attempts`.",
            "items": {
              "format": "uuid",
              "type": "string"
            },
            "type": "array"
          },
          "goals": {
            "description": "The goals: the rows of `cells` and `attempts`.",
            "items": {
              "$ref": "#/components/schemas/MatrixGoal"
            },
            "type": "array"
          },
          "cells": {
            "description": "cells[goal][run]: 0 unresolved, 1 mitigated, 2 error, 3 jailbroken; null when the attack run recorded nothing for the goal.",
            "items": {
              "items": {
                "nullable": true,
                "type": "integer"
              },
              "type": "array"
            },
            "type": "array"
          },
          "attempts": {
            "description": "attempts[goal][run], null like cells.",
            "items": {
              "items": {
                "nullable": true,
                "type": "integer"
              },
              "type": "array"
            },
            "type": "array"
          }
        },
        "required": [
          "attempts",
          "cells",
          "goals",
          "runs"
        ],
        "type": "object"
      },
      "GoalSample": {
        "properties": {
          "goal_index": {
            "description": "The goal.",
            "type": "integer"
          },
          "first_jailbreak_attempt": {
            "description": "The attempt (from 1) that first jailbroke the agent; null when none did.",
            "nullable": true,
            "type": "integer"
          },
          "first_jailbreak_elapsed_s": {
            "description": "Seconds from the goal's first attempt to its first jailbreak; null when unknown.",
            "format": "double",
            "nullable": true,
            "type": "number"
          },
          "attempts": {
            "description": "Attempts made on the goal.",
            "type": "integer"
          },
          "calls": {
            "description": "Model calls made for the goal; null when not fully traced.",
            "nullable": true,
            "type": "integer"
          },
          "target_tokens": {
            "description": "Target tokens spent on the goal; null when not fully recorded.",
            "nullable": true,
            "type": "integer"
          },
          "elapsed_s": {
            "description": "Seconds between the goal's first and last recorded attempt.",
            "format": "double",
            "type": "number"
          }
        },
        "required": [
          "attempts",
          "calls",
          "elapsed_s",
          "first_jailbreak_attempt",
          "first_jailbreak_elapsed_s",
          "goal_index",
          "target_tokens"
        ],
        "type": "object"
      },
      "GoalVerdictEnum": {
        "description": "* `jailbroken` - jailbroken\n* `mitigated` - mitigated\n* `unresolved` - unresolved",
        "enum": [
          "jailbroken",
          "mitigated",
          "unresolved"
        ],
        "type": "string"
      },
      "Heartbeat": {
        "properties": {
          "cancel_requested": {
            "description": "Whether a cancel was requested: the executor should stop and finish the run as `CANCELLED`.",
            "type": "boolean"
          }
        },
        "required": [
          "cancel_requested"
        ],
        "type": "object"
      },
      "HistoryGoal": {
        "properties": {
          "index": {
            "description": "The goal's index in the dataset.",
            "type": "integer"
          },
          "category": {
            "description": "The goal's category (`Unknown` when none was recorded).",
            "type": "string"
          },
          "subcategory": {
            "description": "The goal's subcategory; empty when none.",
            "type": "string"
          },
          "category_source": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CategorySourceEnum"
              }
            ],
            "description": "`recorded` when an attack run recorded the category, `unknown` otherwise.\n\n* `recorded` - recorded\n* `unknown` - unknown"
          },
          "goal": {
            "description": "The goal text.",
            "type": "string"
          },
          "verdict": {
            "allOf": [
              {
                "$ref": "#/components/schemas/GoalVerdictEnum"
              }
            ],
            "description": "The goal's verdict over the attack runs in scope.\n\n* `jailbroken` - jailbroken\n* `mitigated` - mitigated\n* `unresolved` - unresolved"
          },
          "attempts": {
            "description": "Attempts made on the goal.",
            "type": "integer"
          },
          "successful_attempts": {
            "description": "Attempts that jailbroke the agent.",
            "type": "integer"
          },
          "errors": {
            "description": "Attempts that errored.",
            "type": "integer"
          },
          "pending": {
            "description": "Attempts not evaluated yet.",
            "type": "integer"
          },
          "run_ids": {
            "description": "The attack runs that recorded the goal.",
            "items": {
              "format": "uuid",
              "type": "string"
            },
            "type": "array"
          },
          "attack_outcomes": {
            "description": "Each attack run's outcome on the goal.",
            "items": {
              "$ref": "#/components/schemas/AttackOutcome"
            },
            "type": "array"
          }
        },
        "required": [
          "attack_outcomes",
          "attempts",
          "category",
          "category_source",
          "errors",
          "goal",
          "index",
          "pending",
          "run_ids",
          "subcategory",
          "successful_attempts",
          "verdict"
        ],
        "type": "object"
      },
      "HistoryGoalPage": {
        "properties": {
          "count": {
            "description": "Total number of items across all pages.",
            "type": "integer"
          },
          "next": {
            "description": "URL of the next page, or null on the last page.",
            "nullable": true,
            "type": "string"
          },
          "previous": {
            "description": "URL of the previous page, or null on the first page.",
            "nullable": true,
            "type": "string"
          },
          "results": {
            "description": "The goals of this page.",
            "items": {
              "$ref": "#/components/schemas/HistoryGoal"
            },
            "type": "array"
          }
        },
        "required": [
          "count",
          "next",
          "previous",
          "results"
        ],
        "type": "object"
      },
      "HistoryRun": {
        "description": "An attack run of the campaign run.",
        "properties": {
          "id": {
            "description": "Id of the attack run.",
            "format": "uuid",
            "type": "string"
          },
          "attack_id": {
            "description": "Id of its attack configuration, if any.",
            "format": "uuid",
            "nullable": true,
            "type": "string"
          },
          "technique": {
            "description": "The attack technique.",
            "type": "string"
          },
          "family": {
            "description": "The technique's family, if known.",
            "nullable": true,
            "type": "string"
          },
          "status": {
            "allOf": [
              {
                "$ref": "#/components/schemas/StatusEnum"
              }
            ],
            "description": "The attack run's status.\n\n* `PENDING` - Pending\n* `RUNNING` - Running\n* `COMPLETED` - Completed\n* `FAILED` - Failed\n* `CANCELLED` - Cancelled"
          },
          "notes": {
            "description": "The attack run's notes, if any.",
            "nullable": true,
            "type": "string"
          },
          "created_at": {
            "description": "When the attack run was created.",
            "format": "date-time",
            "type": "string"
          },
          "configuration": {
            "additionalProperties": {},
            "description": "The attack run's run_config.",
            "type": "object"
          },
          "attack_configuration": {
            "additionalProperties": {},
            "description": "The attack's configuration, credentials redacted.",
            "nullable": true,
            "type": "object"
          },
          "outcomes": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CampaignRunSummary"
              }
            ],
            "description": "This attack run's own summary; null outside the scope.",
            "nullable": true
          }
        },
        "required": [
          "attack_configuration",
          "attack_id",
          "configuration",
          "created_at",
          "family",
          "id",
          "notes",
          "outcomes",
          "status",
          "technique"
        ],
        "type": "object"
      },
      "Latency": {
        "properties": {
          "median": {
            "description": "Median latency, in milliseconds.",
            "format": "double",
            "type": "number"
          },
          "p90": {
            "description": "90th percentile latency, in milliseconds.",
            "format": "double",
            "type": "number"
          },
          "samples": {
            "description": "Number of measured calls.",
            "type": "integer"
          }
        },
        "required": [
          "median",
          "p90",
          "samples"
        ],
        "type": "object"
      },
      "LaunchError": {
        "additionalProperties": {},
        "description": "400 body of a refused launch: preflight ``problems``, or ``spec`` when\nthe saved spec no longer validates. A request that fails validation\nanswers with a map of field name to errors instead (``additionalProperties``).",
        "properties": {
          "problems": {
            "description": "The preflight checks that failed; nothing was queued.",
            "items": {
              "$ref": "#/components/schemas/PreflightProblem"
            },
            "type": "array"
          },
          "spec": {
            "additionalProperties": {
              "type": "string"
            },
            "description": "The saved spec no longer validates (e.g. after an SDK upgrade): error messages by dotted path. Edit and save the campaign.",
            "type": "object"
          }
        },
        "type": "object"
      },
      "LaunchExecutorEnum": {
        "description": "* `cloud` - cloud\n* `local` - local",
        "enum": [
          "cloud",
          "local"
        ],
        "type": "string"
      },
      "LaunchRequest": {
        "example": {
          "executor": "cloud"
        },
        "properties": {
          "executor": {
            "allOf": [
              {
                "$ref": "#/components/schemas/LaunchExecutorEnum"
              }
            ],
            "description": "Where the run executes. Left out, the deployment decides: its cloud worker when it has one, otherwise a local machine. ``hackagent web`` sets ``local``, as it runs what it launches.\n\n* `cloud` - cloud\n* `local` - local"
          }
        },
        "type": "object"
      },
      "LaunchedRun": {
        "description": "A queued campaign run; local runs also carry the command that starts it.",
        "properties": {
          "id": {
            "description": "Unique identifier of the run.",
            "format": "uuid",
            "readOnly": true,
            "type": "string"
          },
          "agent": {
            "description": "Id of the agent the run targets.",
            "format": "uuid",
            "readOnly": true,
            "type": "string"
          },
          "agent_name": {
            "description": "Name of the agent.",
            "readOnly": true,
            "type": "string"
          },
          "attack": {
            "description": "Id of the attack configuration an attack run executes; null for campaign runs.",
            "format": "uuid",
            "nullable": true,
            "readOnly": true,
            "title": "Associated Attack",
            "type": "string"
          },
          "owner": {
            "description": "Id of the user who launched the run.",
            "nullable": true,
            "readOnly": true,
            "title": "Initiated By",
            "type": "integer"
          },
          "owner_username": {
            "description": "Username of the user who launched the run.",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "organization": {
            "description": "Id of the run's organization.",
            "format": "uuid",
            "readOnly": true,
            "type": "string"
          },
          "organization_name": {
            "description": "Name of the run's organization.",
            "readOnly": true,
            "type": "string"
          },
          "run_config": {
            "description": "The run's configuration. For a campaign run: `campaign_config` (the resolved campaign spec, with the agent as `target`), `campaign_id`, `campaign_name` and the `sdk_version` it runs with; for an attack run, what its executor recorded.",
            "nullable": true,
            "readOnly": true,
            "title": "Run Configuration"
          },
          "timestamp": {
            "description": "When the run was created.",
            "format": "date-time",
            "readOnly": true,
            "type": "string"
          },
          "status": {
            "allOf": [
              {
                "$ref": "#/components/schemas/StatusEnum"
              }
            ],
            "description": "`PENDING` (queued), `RUNNING`, then `COMPLETED`, `FAILED` or `CANCELLED`.\n\n* `PENDING` - Pending\n* `RUNNING` - Running\n* `COMPLETED` - Completed\n* `FAILED` - Failed\n* `CANCELLED` - Cancelled",
            "readOnly": true
          },
          "run_notes": {
            "description": "Notes on the run, e.g. why it failed or was cancelled.",
            "readOnly": true,
            "type": "string"
          },
          "executor": {
            "allOf": [
              {
                "$ref": "#/components/schemas/RunExecutorEnum"
              }
            ],
            "description": "Who executes the run: HackAgent cloud, a local machine or the CLI.\n\n* `cloud` - HackAgent cloud\n* `local` - Local machine\n* `cli` - Command line",
            "readOnly": true
          },
          "campaign": {
            "description": "Id of the saved campaign the run was launched from, if any.",
            "format": "uuid",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "parent": {
            "description": "Id of the campaign run an attack run belongs to; null for a campaign run.",
            "format": "uuid",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "claimed_at": {
            "description": "When an executor claimed the run.",
            "format": "date-time",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "claimed_by": {
            "description": "Free-text description of the executor that claimed the run.",
            "readOnly": true,
            "type": "string"
          },
          "heartbeat_at": {
            "description": "The executor's last heartbeat.",
            "format": "date-time",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "cancel_requested_at": {
            "description": "When a cancel was requested; the executor then stops the run.",
            "format": "date-time",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "finished_at": {
            "description": "When the run reached COMPLETED, FAILED or CANCELLED.",
            "format": "date-time",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "results": {
            "description": "The run's results with their traces. Left out by `GET /run/{id}?include_results=false`.",
            "items": {
              "$ref": "#/components/schemas/Result"
            },
            "readOnly": true,
            "type": "array"
          },
          "command": {
            "description": "Local runs: the command to run, ``hackagent run <id>``.",
            "readOnly": true,
            "type": "string"
          }
        },
        "required": [
          "agent",
          "agent_name",
          "attack",
          "campaign",
          "cancel_requested_at",
          "claimed_at",
          "claimed_by",
          "executor",
          "finished_at",
          "heartbeat_at",
          "id",
          "organization",
          "organization_name",
          "owner",
          "owner_username",
          "parent",
          "results",
          "run_config",
          "run_notes",
          "status",
          "timestamp"
        ],
        "type": "object"
      },
      "LicenseStatus": {
        "properties": {
          "enforcement": {
            "description": "Whether license limits and read-only mode are enforced.",
            "type": "boolean"
          },
          "state": {
            "allOf": [
              {
                "$ref": "#/components/schemas/StateEnum"
              }
            ],
            "description": "`valid`; `warning` (valid, but see `warnings`); `grace` (expired, still working until `grace_ends_at`); `read_only` or `invalid`.\n\n* `valid` - valid\n* `warning` - warning\n* `grace` - grace\n* `read_only` - read_only\n* `invalid` - invalid"
          },
          "read_only": {
            "description": "Whether writes are refused until a valid license is installed.",
            "type": "boolean"
          },
          "error": {
            "description": "Why the license is not valid (a verification error code), or null.",
            "nullable": true,
            "type": "string"
          },
          "installation_id": {
            "description": "This installation's id, which licenses bind to.",
            "type": "string"
          },
          "license": {
            "allOf": [
              {
                "$ref": "#/components/schemas/LicenseSummary"
              }
            ],
            "description": "The license in force; null without one.",
            "nullable": true
          },
          "grace_ends_at": {
            "description": "When the grace period ends, in `grace`.",
            "format": "date-time",
            "nullable": true,
            "type": "string"
          },
          "usage": {
            "allOf": [
              {
                "$ref": "#/components/schemas/LicenseUsage"
              }
            ],
            "description": "Usage against the limits; null without a license.",
            "nullable": true
          },
          "warnings": {
            "description": "Conditions to act on: the license expires soon, seats are full, runs reached 80% or 100% of the monthly limit.",
            "items": {
              "$ref": "#/components/schemas/WarningsEnum"
            },
            "type": "array"
          }
        },
        "required": [
          "enforcement",
          "error",
          "grace_ends_at",
          "installation_id",
          "license",
          "read_only",
          "state",
          "usage",
          "warnings"
        ],
        "type": "object"
      },
      "LicenseSummary": {
        "description": "The license in force, as issued.",
        "properties": {
          "license_id": {
            "description": "Identifier of the license.",
            "type": "string"
          },
          "customer": {
            "additionalProperties": {},
            "description": "Who the license was issued to.",
            "type": "object"
          },
          "mode": {
            "description": "How the installation reports to HackAgent, e.g. `connected`.",
            "type": "string"
          },
          "issued_at": {
            "description": "When it was issued (ISO 8601).",
            "type": "string"
          },
          "not_before": {
            "description": "When it starts to be valid (ISO 8601).",
            "type": "string"
          },
          "expires_at": {
            "description": "When it expires (ISO 8601).",
            "type": "string"
          },
          "limits": {
            "additionalProperties": {},
            "description": "Licensed limits: `seats` and `runs_per_month`.",
            "type": "object"
          },
          "features": {
            "description": "Features the license enables.",
            "items": {
              "type": "string"
            },
            "type": "array"
          }
        },
        "required": [
          "customer",
          "expires_at",
          "features",
          "issued_at",
          "license_id",
          "limits",
          "mode",
          "not_before"
        ],
        "type": "object"
      },
      "LicenseUploadRequest": {
        "properties": {
          "token": {
            "description": "The signed license, as issued (the content of the license file).",
            "minLength": 1,
            "type": "string"
          }
        },
        "required": [
          "token"
        ],
        "type": "object"
      },
      "LicenseUsage": {
        "properties": {
          "seats_active_30d": {
            "description": "Users active on any of the last 30 days (UTC), today included.",
            "type": "integer"
          },
          "seats_limit": {
            "description": "Licensed seats.",
            "type": "integer"
          },
          "runs_this_month": {
            "description": "Runs started this calendar month (UTC), on the whole installation.",
            "type": "integer"
          },
          "runs_per_month_limit": {
            "description": "Licensed runs per month.",
            "type": "integer"
          },
          "runs_hard_limit": {
            "description": "Runs a month may reach (110% of the limit); then refused.",
            "type": "integer"
          }
        },
        "required": [
          "runs_hard_limit",
          "runs_per_month_limit",
          "runs_this_month",
          "seats_active_30d",
          "seats_limit"
        ],
        "type": "object"
      },
      "MatrixGoal": {
        "properties": {
          "index": {
            "description": "The goal's index in the dataset.",
            "type": "integer"
          },
          "goal": {
            "description": "The goal text.",
            "type": "string"
          },
          "category": {
            "description": "The goal's category.",
            "type": "string"
          },
          "subcategory": {
            "description": "The goal's subcategory; empty when none.",
            "type": "string"
          },
          "verdict": {
            "allOf": [
              {
                "$ref": "#/components/schemas/GoalVerdictEnum"
              }
            ],
            "description": "The goal's verdict over all attack runs.\n\n* `jailbroken` - jailbroken\n* `mitigated` - mitigated\n* `unresolved` - unresolved"
          }
        },
        "required": [
          "category",
          "goal",
          "index",
          "subcategory",
          "verdict"
        ],
        "type": "object"
      },
      "MessageRequest": {
        "properties": {
          "role": {
            "description": "Role of the message sender (system, user, assistant)",
            "minLength": 1,
            "type": "string"
          },
          "content": {
            "description": "Content of the message",
            "minLength": 1,
            "type": "string"
          }
        },
        "required": [
          "content",
          "role"
        ],
        "type": "object"
      },
      "ModelEnum": {
        "description": "* `hackagent/attacker-v1` - hackagent/attacker-v1\n* `hackagent/judge-v1` - hackagent/judge-v1",
        "enum": [
          "hackagent/attacker-v1",
          "hackagent/judge-v1"
        ],
        "type": "string"
      },
      "NullEnum": {
        "enum": [
          null
        ]
      },
      "Organization": {
        "properties": {
          "id": {
            "description": "Unique identifier of the organization.",
            "format": "uuid",
            "readOnly": true,
            "type": "string"
          },
          "name": {
            "description": "Name of the organization, unique across HackAgent.",
            "maxLength": 200,
            "title": "Organization Name",
            "type": "string"
          },
          "created_at": {
            "description": "When the organization was created.",
            "format": "date-time",
            "readOnly": true,
            "type": "string"
          },
          "updated_at": {
            "description": "When the organization was last changed.",
            "format": "date-time",
            "readOnly": true,
            "type": "string"
          },
          "credits": {
            "description": "Credit balance in US dollars, charged by LLM gateway calls. Read-only: credits are granted by HackAgent.",
            "format": "decimal",
            "pattern": "^-?\\d{0,13}(?:\\.\\d{0,6})?$",
            "readOnly": true,
            "type": "string"
          },
          "credits_last_updated": {
            "description": "When the credit balance last changed.",
            "format": "date-time",
            "readOnly": true,
            "type": "string"
          }
        },
        "required": [
          "created_at",
          "credits",
          "credits_last_updated",
          "id",
          "name",
          "updated_at"
        ],
        "type": "object"
      },
      "OrganizationMinimal": {
        "properties": {
          "id": {
            "description": "Unique identifier of the organization.",
            "format": "uuid",
            "readOnly": true,
            "type": "string"
          },
          "name": {
            "description": "Name of the organization.",
            "readOnly": true,
            "title": "Organization Name",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name"
        ],
        "type": "object"
      },
      "OrganizationRequest": {
        "properties": {
          "name": {
            "description": "Name of the organization, unique across HackAgent.",
            "maxLength": 200,
            "minLength": 1,
            "title": "Organization Name",
            "type": "string"
          }
        },
        "required": [
          "name"
        ],
        "type": "object"
      },
      "PaginatedAPITokenLogList": {
        "properties": {
          "count": {
            "description": "Total number of items across all pages.",
            "example": 42,
            "type": "integer"
          },
          "next": {
            "description": "URL of the next page, or null on the last page.",
            "example": "https://api.hackagent.dev/apilogs?page=3",
            "format": "uri",
            "nullable": true,
            "type": "string"
          },
          "previous": {
            "description": "URL of the previous page, or null on the first page.",
            "example": "https://api.hackagent.dev/apilogs?page=1",
            "format": "uri",
            "nullable": true,
            "type": "string"
          },
          "results": {
            "description": "The items of this page.",
            "items": {
              "$ref": "#/components/schemas/APITokenLog"
            },
            "type": "array"
          }
        },
        "required": [
          "count",
          "results"
        ],
        "type": "object"
      },
      "PaginatedAgentList": {
        "properties": {
          "count": {
            "description": "Total number of items across all pages.",
            "example": 42,
            "type": "integer"
          },
          "next": {
            "description": "URL of the next page, or null on the last page.",
            "example": "https://api.hackagent.dev/agent?page=3",
            "format": "uri",
            "nullable": true,
            "type": "string"
          },
          "previous": {
            "description": "URL of the previous page, or null on the first page.",
            "example": "https://api.hackagent.dev/agent?page=1",
            "format": "uri",
            "nullable": true,
            "type": "string"
          },
          "results": {
            "description": "The items of this page.",
            "items": {
              "$ref": "#/components/schemas/Agent"
            },
            "type": "array"
          }
        },
        "required": [
          "count",
          "results"
        ],
        "type": "object"
      },
      "PaginatedAttackList": {
        "properties": {
          "count": {
            "description": "Total number of items across all pages.",
            "example": 42,
            "type": "integer"
          },
          "next": {
            "description": "URL of the next page, or null on the last page.",
            "example": "https://api.hackagent.dev/attack?page=3",
            "format": "uri",
            "nullable": true,
            "type": "string"
          },
          "previous": {
            "description": "URL of the previous page, or null on the first page.",
            "example": "https://api.hackagent.dev/attack?page=1",
            "format": "uri",
            "nullable": true,
            "type": "string"
          },
          "results": {
            "description": "The items of this page.",
            "items": {
              "$ref": "#/components/schemas/Attack"
            },
            "type": "array"
          }
        },
        "required": [
          "count",
          "results"
        ],
        "type": "object"
      },
      "PaginatedCampaignList": {
        "properties": {
          "count": {
            "description": "Total number of items across all pages.",
            "example": 42,
            "type": "integer"
          },
          "next": {
            "description": "URL of the next page, or null on the last page.",
            "example": "https://api.hackagent.dev/campaign?page=3",
            "format": "uri",
            "nullable": true,
            "type": "string"
          },
          "previous": {
            "description": "URL of the previous page, or null on the first page.",
            "example": "https://api.hackagent.dev/campaign?page=1",
            "format": "uri",
            "nullable": true,
            "type": "string"
          },
          "results": {
            "description": "The items of this page.",
            "items": {
              "$ref": "#/components/schemas/Campaign"
            },
            "type": "array"
          }
        },
        "required": [
          "count",
          "results"
        ],
        "type": "object"
      },
      "PaginatedOrganizationList": {
        "properties": {
          "count": {
            "description": "Total number of items across all pages.",
            "example": 42,
            "type": "integer"
          },
          "next": {
            "description": "URL of the next page, or null on the last page.",
            "example": "https://api.hackagent.dev/organization?page=3",
            "format": "uri",
            "nullable": true,
            "type": "string"
          },
          "previous": {
            "description": "URL of the previous page, or null on the first page.",
            "example": "https://api.hackagent.dev/organization?page=1",
            "format": "uri",
            "nullable": true,
            "type": "string"
          },
          "results": {
            "description": "The items of this page.",
            "items": {
              "$ref": "#/components/schemas/Organization"
            },
            "type": "array"
          }
        },
        "required": [
          "count",
          "results"
        ],
        "type": "object"
      },
      "PaginatedResultList": {
        "properties": {
          "count": {
            "description": "Total number of items across all pages.",
            "example": 42,
            "type": "integer"
          },
          "next": {
            "description": "URL of the next page, or null on the last page.",
            "example": "https://api.hackagent.dev/result?page=3",
            "format": "uri",
            "nullable": true,
            "type": "string"
          },
          "previous": {
            "description": "URL of the previous page, or null on the first page.",
            "example": "https://api.hackagent.dev/result?page=1",
            "format": "uri",
            "nullable": true,
            "type": "string"
          },
          "results": {
            "description": "The items of this page.",
            "items": {
              "$ref": "#/components/schemas/Result"
            },
            "type": "array"
          }
        },
        "required": [
          "count",
          "results"
        ],
        "type": "object"
      },
      "PaginatedRunSummaryList": {
        "properties": {
          "count": {
            "description": "Total number of items across all pages.",
            "example": 42,
            "type": "integer"
          },
          "next": {
            "description": "URL of the next page, or null on the last page.",
            "example": "https://api.hackagent.dev/run?page=3",
            "format": "uri",
            "nullable": true,
            "type": "string"
          },
          "previous": {
            "description": "URL of the previous page, or null on the first page.",
            "example": "https://api.hackagent.dev/run?page=1",
            "format": "uri",
            "nullable": true,
            "type": "string"
          },
          "results": {
            "description": "The items of this page.",
            "items": {
              "$ref": "#/components/schemas/RunSummary"
            },
            "type": "array"
          }
        },
        "required": [
          "count",
          "results"
        ],
        "type": "object"
      },
      "PaginatedSecretList": {
        "properties": {
          "count": {
            "description": "Total number of items across all pages.",
            "example": 42,
            "type": "integer"
          },
          "next": {
            "description": "URL of the next page, or null on the last page.",
            "example": "https://api.hackagent.dev/secret?page=3",
            "format": "uri",
            "nullable": true,
            "type": "string"
          },
          "previous": {
            "description": "URL of the previous page, or null on the first page.",
            "example": "https://api.hackagent.dev/secret?page=1",
            "format": "uri",
            "nullable": true,
            "type": "string"
          },
          "results": {
            "description": "The items of this page.",
            "items": {
              "$ref": "#/components/schemas/Secret"
            },
            "type": "array"
          }
        },
        "required": [
          "count",
          "results"
        ],
        "type": "object"
      },
      "PaginatedUserAPIKeyList": {
        "properties": {
          "count": {
            "description": "Total number of items across all pages.",
            "example": 42,
            "type": "integer"
          },
          "next": {
            "description": "URL of the next page, or null on the last page.",
            "example": "https://api.hackagent.dev/key?page=3",
            "format": "uri",
            "nullable": true,
            "type": "string"
          },
          "previous": {
            "description": "URL of the previous page, or null on the first page.",
            "example": "https://api.hackagent.dev/key?page=1",
            "format": "uri",
            "nullable": true,
            "type": "string"
          },
          "results": {
            "description": "The items of this page.",
            "items": {
              "$ref": "#/components/schemas/UserAPIKey"
            },
            "type": "array"
          }
        },
        "required": [
          "count",
          "results"
        ],
        "type": "object"
      },
      "PaginatedUserProfileList": {
        "properties": {
          "count": {
            "description": "Total number of items across all pages.",
            "example": 42,
            "type": "integer"
          },
          "next": {
            "description": "URL of the next page, or null on the last page.",
            "example": "https://api.hackagent.dev/user?page=3",
            "format": "uri",
            "nullable": true,
            "type": "string"
          },
          "previous": {
            "description": "URL of the previous page, or null on the first page.",
            "example": "https://api.hackagent.dev/user?page=1",
            "format": "uri",
            "nullable": true,
            "type": "string"
          },
          "results": {
            "description": "The items of this page.",
            "items": {
              "$ref": "#/components/schemas/UserProfile"
            },
            "type": "array"
          }
        },
        "required": [
          "count",
          "results"
        ],
        "type": "object"
      },
      "PatchedAgentRequest": {
        "description": "Serializes Agent model instances to JSON and validates data for creating\nor updating Agent instances.\n\nThis serializer provides a comprehensive representation of an Agent,\nincluding its type, endpoint, and nested details for related 'organization'\nand 'owner' for read operations, while allowing 'organization' and 'owner' IDs\nfor write operations.\n\nAttributes:\n    organization_detail (OrganizationMinimalSerializer): Read-only nested\n        serializer for the agent's organization. Displays minimal details.\n    owner_detail (UserProfileMinimalSerializer): Read-only nested serializer\n        for the agent's owner's user profile. Displays minimal details.\n        Can be null if the agent has no owner or the owner has no profile.\n    agent_type (CharField): The type of the agent as a string\n                      (e.g., LITELLM, OPENAI_SDK, GOOGLE_ADK).\n\nMeta:\n    model (Agent): The model class that this serializer works with.\n    fields (tuple): The fields to include in the serialized output.\n        Includes standard Agent fields like 'endpoint', 'type',\n        and the read-only nested details.\n    read_only_fields (tuple): Fields that are read-only and cannot be\n        set during create/update operations through this serializer.\n        This includes 'id', 'created_at', 'updated_at', and the\n        nested detail fields.",
        "properties": {
          "name": {
            "description": "Display name, unique within the organization.",
            "maxLength": 200,
            "minLength": 1,
            "title": "Agent Name",
            "type": "string"
          },
          "description": {
            "description": "Free-text description of the agent.",
            "type": "string"
          },
          "config": {
            "description": "The agent's model configuration, as the hackagent SDK reads it: `name` (the model), `connection` (`provider`, `type`, and optionally `endpoint`, `api_key`, `headers`, `timeout`) and optionally `generation` and `options`. `connection.api_key` must be a `${VARIABLE}` reference to an organization secret; literal credentials are refused."
          }
        },
        "type": "object"
      },
      "PatchedAttackRequest": {
        "description": "Serializer for the Attack model, which represents an Attack configuration.\n\nHandles the conversion of Attack configuration instances to JSON (and vice-versa)\nfor API requests and responses. It includes read-only fields for related\nobject names (like agent_name, owner_username) for convenience in API outputs.",
        "properties": {
          "type": {
            "description": "The attack technique, as the SDK names it (e.g. `pair`, `baseline`, `tap`; see `GET /campaign/techniques`).",
            "maxLength": 100,
            "minLength": 1,
            "title": "Attack Type",
            "type": "string"
          },
          "agent": {
            "description": "Id of the target agent.",
            "format": "uuid",
            "title": "Target Agent",
            "type": "string"
          },
          "configuration": {
            "description": "The technique's parameters and settings, as the client recorded them (free-form JSON).",
            "title": "Attack Configuration"
          }
        },
        "type": "object"
      },
      "PatchedCampaignRequest": {
        "properties": {
          "name": {
            "description": "Display name of the campaign.",
            "maxLength": 200,
            "minLength": 1,
            "type": "string"
          },
          "description": {
            "description": "Free-text description.",
            "type": "string"
          },
          "agent": {
            "description": "Id of the agent the campaign targets, in the caller's organization.",
            "format": "uuid",
            "type": "string"
          },
          "spec": {
            "description": "The campaign spec, as the hackagent SDK reads it, without `target` and `execution`: `version`, `campaign` (name, description), `dataset` (where the goals come from), `attacks` (techniques with their `parameters` and model `roles`) and optionally `evaluation` (judges) and other sections; see `GET /campaign/schema`. Model keys must be `${VARIABLE}` references to organization secrets; HackAgent's own models are named `hackagent/attacker-v1` and `hackagent/judge-v1` with provider `hackagent` and no endpoint or key."
          }
        },
        "type": "object"
      },
      "PatchedOrganizationRequest": {
        "properties": {
          "name": {
            "description": "Name of the organization, unique across HackAgent.",
            "maxLength": 200,
            "minLength": 1,
            "title": "Organization Name",
            "type": "string"
          }
        },
        "type": "object"
      },
      "PatchedResultRequest": {
        "description": "Serializer for the Result model, often nested in RunSerializer.",
        "properties": {
          "run": {
            "description": "Id of the run (usually an attack run) it belongs to.",
            "format": "uuid",
            "type": "string"
          },
          "request_payload": {
            "description": "What was sent to the agent (free-form JSON).",
            "nullable": true
          },
          "response_status_code": {
            "description": "HTTP status of the agent's response, if any.",
            "format": "int64",
            "maximum": 9223372036854775807,
            "minimum": -9223372036854775808,
            "nullable": true,
            "type": "integer"
          },
          "response_headers": {
            "description": "Headers of the agent's response.",
            "nullable": true
          },
          "response_body": {
            "description": "Body of the agent's response.",
            "nullable": true,
            "type": "string"
          },
          "latency_ms": {
            "description": "How long the agent took to answer, in ms.",
            "format": "int64",
            "maximum": 9223372036854775807,
            "minimum": 0,
            "nullable": true,
            "title": "Latency (ms)",
            "type": "integer"
          },
          "detected_tool_calls": {
            "description": "Tool calls detected in the agent's response.",
            "nullable": true
          },
          "evaluation_status": {
            "allOf": [
              {
                "$ref": "#/components/schemas/EvaluationStatusEnum"
              }
            ],
            "description": "The judges' verdict: `SUCCESSFUL_JAILBREAK` (the attack worked), `FAILED_JAILBREAK` (mitigated or refused), an `ERROR_*` status, or `NOT_EVALUATED` yet.\n\n* `NOT_EVALUATED` - Not Evaluated\n* `SUCCESSFUL_JAILBREAK` - Successful Jailbreak\n* `FAILED_JAILBREAK` - Failed Jailbreak (Mitigated/Refused)\n* `ERROR_AGENT_RESPONSE` - Error in Agent Response\n* `ERROR_TEST_FRAMEWORK` - Error in Test Framework\n* `PASSED_CRITERIA` - Passed Criteria (Not Jailbreak)\n* `FAILED_CRITERIA` - Failed Criteria (Not Jailbreak)"
          },
          "evaluation_notes": {
            "description": "The judges' explanation.",
            "type": "string"
          },
          "evaluation_metrics": {
            "description": "Scores and details of the evaluation (free-form JSON).",
            "nullable": true
          },
          "agent_specific_data": {
            "description": "Attack metadata recorded by the SDK (technique, attempt, judge details; free-form JSON).",
            "nullable": true
          },
          "goal": {
            "description": "The goal (harmful behavior) the attempt pursued.",
            "type": "string"
          },
          "goal_index": {
            "description": "Index of the goal in the campaign's dataset; the attempts of a goal share it. Results without one are left out of the campaign run reports.",
            "format": "int64",
            "maximum": 9223372036854775807,
            "minimum": -9223372036854775808,
            "nullable": true,
            "type": "integer"
          }
        },
        "type": "object"
      },
      "PatchedRunUpdateRequest": {
        "description": "What PATCH /run/{id} may change. ``run_config`` is merged into the\nstored one, key by key (shallow).",
        "properties": {
          "run_notes": {
            "description": "New notes for the run.",
            "type": "string"
          },
          "run_config": {
            "additionalProperties": {},
            "description": "Keys to merge into the run's `run_config` (top level; the run's executor only). Credentials must be `${VARIABLE}` references.",
            "type": "object"
          }
        },
        "type": "object"
      },
      "PatchedUserProfileRequest": {
        "properties": {
          "email": {
            "description": "The user's email address.",
            "format": "email",
            "minLength": 1,
            "type": "string"
          },
          "first_name": {
            "description": "The user's first name.",
            "type": "string"
          },
          "last_name": {
            "description": "The user's last name.",
            "type": "string"
          },
          "analytics_consent": {
            "description": "Whether the user has consented to optional analytics cookies (e.g. usage tracking, session recording), set once during onboarding and changeable in Settings.\n\n* `unset` - Unset\n* `accepted` - Accepted\n* `declined` - Declined",
            "oneOf": [
              {
                "$ref": "#/components/schemas/AnalyticsConsentEnum"
              },
              {
                "$ref": "#/components/schemas/BlankEnum"
              }
            ]
          }
        },
        "type": "object"
      },
      "Preflight": {
        "properties": {
          "executor": {
            "allOf": [
              {
                "$ref": "#/components/schemas/LaunchExecutorEnum"
              }
            ],
            "description": "Where the checked launch would run.\n\n* `cloud` - cloud\n* `local` - local"
          },
          "ok": {
            "description": "Whether a launch would be accepted now (no problems).",
            "type": "boolean"
          },
          "problems": {
            "description": "Why a launch would be refused; empty when `ok`.",
            "items": {
              "$ref": "#/components/schemas/PreflightProblem"
            },
            "type": "array"
          }
        },
        "required": [
          "executor",
          "ok",
          "problems"
        ],
        "type": "object"
      },
      "PreflightProblem": {
        "description": "One reason a launch is refused.",
        "properties": {
          "code": {
            "description": "Machine-readable cause: `ACCOUNT_INVALID`, `AGENT_TYPE_NOT_SUPPORTED`, `CLOUD_UNAVAILABLE`, `INSUFFICIENT_CREDITS`, `AGENT_NOT_CLOUD_RUNNABLE`, `AGENT_NEEDS_CONFIGURATION`, `SPEC_NOT_CLOUD_RUNNABLE`, `MISSING_SECRETS` or `CLOUD_CONCURRENCY_LIMIT`.",
            "type": "string"
          },
          "message": {
            "description": "What to do about it, for people.",
            "type": "string"
          },
          "details": {
            "additionalProperties": {},
            "description": "Data for acting on it, depending on `code`: e.g. `names` of the missing secrets, `balance` for insufficient credits, `limit` and `active` for the concurrency limit, `paths` and `reasons` for a spec the cloud cannot run.",
            "type": "object"
          }
        },
        "required": [
          "code",
          "details",
          "message"
        ],
        "type": "object"
      },
      "PreviousRun": {
        "properties": {
          "recorded_goals": {
            "description": "Goals with at least one recorded attempt.",
            "type": "integer"
          },
          "jailbroken": {
            "description": "Goals with at least one successful jailbreak.",
            "type": "integer"
          },
          "mitigated": {
            "description": "Goals every attempt of which was mitigated, once the scope is complete.",
            "type": "integer"
          },
          "unresolved": {
            "description": "Goals neither jailbroken nor (yet) mitigated: still running, pending evaluation or errored.",
            "type": "integer"
          },
          "id": {
            "description": "Id of the earlier campaign run.",
            "format": "uuid",
            "type": "string"
          },
          "created_at": {
            "description": "When it was created.",
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "created_at",
          "id",
          "jailbroken",
          "mitigated",
          "recorded_goals",
          "unresolved"
        ],
        "type": "object"
      },
      "Result": {
        "description": "Serializer for the Result model, often nested in RunSerializer.",
        "properties": {
          "id": {
            "description": "Unique identifier of the result.",
            "format": "uuid",
            "readOnly": true,
            "type": "string"
          },
          "run": {
            "description": "Id of the run (usually an attack run) it belongs to.",
            "format": "uuid",
            "type": "string"
          },
          "run_id": {
            "description": "Id of the run (same as `run`).",
            "format": "uuid",
            "readOnly": true,
            "type": "string"
          },
          "request_payload": {
            "description": "What was sent to the agent (free-form JSON).",
            "nullable": true
          },
          "response_status_code": {
            "description": "HTTP status of the agent's response, if any.",
            "format": "int64",
            "maximum": 9223372036854775807,
            "minimum": -9223372036854775808,
            "nullable": true,
            "type": "integer"
          },
          "response_headers": {
            "description": "Headers of the agent's response.",
            "nullable": true
          },
          "response_body": {
            "description": "Body of the agent's response.",
            "nullable": true,
            "type": "string"
          },
          "latency_ms": {
            "description": "How long the agent took to answer, in ms.",
            "format": "int64",
            "maximum": 9223372036854775807,
            "minimum": 0,
            "nullable": true,
            "title": "Latency (ms)",
            "type": "integer"
          },
          "detected_tool_calls": {
            "description": "Tool calls detected in the agent's response.",
            "nullable": true
          },
          "evaluation_status": {
            "allOf": [
              {
                "$ref": "#/components/schemas/EvaluationStatusEnum"
              }
            ],
            "description": "The judges' verdict: `SUCCESSFUL_JAILBREAK` (the attack worked), `FAILED_JAILBREAK` (mitigated or refused), an `ERROR_*` status, or `NOT_EVALUATED` yet.\n\n* `NOT_EVALUATED` - Not Evaluated\n* `SUCCESSFUL_JAILBREAK` - Successful Jailbreak\n* `FAILED_JAILBREAK` - Failed Jailbreak (Mitigated/Refused)\n* `ERROR_AGENT_RESPONSE` - Error in Agent Response\n* `ERROR_TEST_FRAMEWORK` - Error in Test Framework\n* `PASSED_CRITERIA` - Passed Criteria (Not Jailbreak)\n* `FAILED_CRITERIA` - Failed Criteria (Not Jailbreak)"
          },
          "evaluation_notes": {
            "description": "The judges' explanation.",
            "type": "string"
          },
          "evaluation_metrics": {
            "description": "Scores and details of the evaluation (free-form JSON).",
            "nullable": true
          },
          "agent_specific_data": {
            "description": "Attack metadata recorded by the SDK (technique, attempt, judge details; free-form JSON).",
            "nullable": true
          },
          "goal": {
            "description": "The goal (harmful behavior) the attempt pursued.",
            "type": "string"
          },
          "goal_index": {
            "description": "Index of the goal in the campaign's dataset; the attempts of a goal share it. Results without one are left out of the campaign run reports.",
            "format": "int64",
            "maximum": 9223372036854775807,
            "minimum": -9223372036854775808,
            "nullable": true,
            "type": "integer"
          },
          "timestamp": {
            "description": "When the result was recorded.",
            "format": "date-time",
            "readOnly": true,
            "type": "string"
          },
          "traces": {
            "description": "The result's trace steps, in order. Left out by `GET /result?include_traces=false`.",
            "items": {
              "$ref": "#/components/schemas/Trace"
            },
            "readOnly": true,
            "type": "array"
          }
        },
        "required": [
          "id",
          "run",
          "run_id",
          "timestamp"
        ],
        "type": "object"
      },
      "ResultRequest": {
        "description": "Serializer for the Result model, often nested in RunSerializer.",
        "properties": {
          "run": {
            "description": "Id of the run (usually an attack run) it belongs to.",
            "format": "uuid",
            "type": "string"
          },
          "request_payload": {
            "description": "What was sent to the agent (free-form JSON).",
            "nullable": true
          },
          "response_status_code": {
            "description": "HTTP status of the agent's response, if any.",
            "format": "int64",
            "maximum": 9223372036854775807,
            "minimum": -9223372036854775808,
            "nullable": true,
            "type": "integer"
          },
          "response_headers": {
            "description": "Headers of the agent's response.",
            "nullable": true
          },
          "response_body": {
            "description": "Body of the agent's response.",
            "nullable": true,
            "type": "string"
          },
          "latency_ms": {
            "description": "How long the agent took to answer, in ms.",
            "format": "int64",
            "maximum": 9223372036854775807,
            "minimum": 0,
            "nullable": true,
            "title": "Latency (ms)",
            "type": "integer"
          },
          "detected_tool_calls": {
            "description": "Tool calls detected in the agent's response.",
            "nullable": true
          },
          "evaluation_status": {
            "allOf": [
              {
                "$ref": "#/components/schemas/EvaluationStatusEnum"
              }
            ],
            "description": "The judges' verdict: `SUCCESSFUL_JAILBREAK` (the attack worked), `FAILED_JAILBREAK` (mitigated or refused), an `ERROR_*` status, or `NOT_EVALUATED` yet.\n\n* `NOT_EVALUATED` - Not Evaluated\n* `SUCCESSFUL_JAILBREAK` - Successful Jailbreak\n* `FAILED_JAILBREAK` - Failed Jailbreak (Mitigated/Refused)\n* `ERROR_AGENT_RESPONSE` - Error in Agent Response\n* `ERROR_TEST_FRAMEWORK` - Error in Test Framework\n* `PASSED_CRITERIA` - Passed Criteria (Not Jailbreak)\n* `FAILED_CRITERIA` - Failed Criteria (Not Jailbreak)"
          },
          "evaluation_notes": {
            "description": "The judges' explanation.",
            "type": "string"
          },
          "evaluation_metrics": {
            "description": "Scores and details of the evaluation (free-form JSON).",
            "nullable": true
          },
          "agent_specific_data": {
            "description": "Attack metadata recorded by the SDK (technique, attempt, judge details; free-form JSON).",
            "nullable": true
          },
          "goal": {
            "description": "The goal (harmful behavior) the attempt pursued.",
            "type": "string"
          },
          "goal_index": {
            "description": "Index of the goal in the campaign's dataset; the attempts of a goal share it. Results without one are left out of the campaign run reports.",
            "format": "int64",
            "maximum": 9223372036854775807,
            "minimum": -9223372036854775808,
            "nullable": true,
            "type": "integer"
          }
        },
        "required": [
          "run"
        ],
        "type": "object"
      },
      "Run": {
        "description": "A run with its nested results. Read-only: runs are created by a launch\nand their status changes through the executor protocol.",
        "properties": {
          "id": {
            "description": "Unique identifier of the run.",
            "format": "uuid",
            "readOnly": true,
            "type": "string"
          },
          "agent": {
            "description": "Id of the agent the run targets.",
            "format": "uuid",
            "readOnly": true,
            "type": "string"
          },
          "agent_name": {
            "description": "Name of the agent.",
            "readOnly": true,
            "type": "string"
          },
          "attack": {
            "description": "Id of the attack configuration an attack run executes; null for campaign runs.",
            "format": "uuid",
            "nullable": true,
            "readOnly": true,
            "title": "Associated Attack",
            "type": "string"
          },
          "owner": {
            "description": "Id of the user who launched the run.",
            "nullable": true,
            "readOnly": true,
            "title": "Initiated By",
            "type": "integer"
          },
          "owner_username": {
            "description": "Username of the user who launched the run.",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "organization": {
            "description": "Id of the run's organization.",
            "format": "uuid",
            "readOnly": true,
            "type": "string"
          },
          "organization_name": {
            "description": "Name of the run's organization.",
            "readOnly": true,
            "type": "string"
          },
          "run_config": {
            "description": "The run's configuration. For a campaign run: `campaign_config` (the resolved campaign spec, with the agent as `target`), `campaign_id`, `campaign_name` and the `sdk_version` it runs with; for an attack run, what its executor recorded.",
            "nullable": true,
            "readOnly": true,
            "title": "Run Configuration"
          },
          "timestamp": {
            "description": "When the run was created.",
            "format": "date-time",
            "readOnly": true,
            "type": "string"
          },
          "status": {
            "allOf": [
              {
                "$ref": "#/components/schemas/StatusEnum"
              }
            ],
            "description": "`PENDING` (queued), `RUNNING`, then `COMPLETED`, `FAILED` or `CANCELLED`.\n\n* `PENDING` - Pending\n* `RUNNING` - Running\n* `COMPLETED` - Completed\n* `FAILED` - Failed\n* `CANCELLED` - Cancelled",
            "readOnly": true
          },
          "run_notes": {
            "description": "Notes on the run, e.g. why it failed or was cancelled.",
            "readOnly": true,
            "type": "string"
          },
          "executor": {
            "allOf": [
              {
                "$ref": "#/components/schemas/RunExecutorEnum"
              }
            ],
            "description": "Who executes the run: HackAgent cloud, a local machine or the CLI.\n\n* `cloud` - HackAgent cloud\n* `local` - Local machine\n* `cli` - Command line",
            "readOnly": true
          },
          "campaign": {
            "description": "Id of the saved campaign the run was launched from, if any.",
            "format": "uuid",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "parent": {
            "description": "Id of the campaign run an attack run belongs to; null for a campaign run.",
            "format": "uuid",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "claimed_at": {
            "description": "When an executor claimed the run.",
            "format": "date-time",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "claimed_by": {
            "description": "Free-text description of the executor that claimed the run.",
            "readOnly": true,
            "type": "string"
          },
          "heartbeat_at": {
            "description": "The executor's last heartbeat.",
            "format": "date-time",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "cancel_requested_at": {
            "description": "When a cancel was requested; the executor then stops the run.",
            "format": "date-time",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "finished_at": {
            "description": "When the run reached COMPLETED, FAILED or CANCELLED.",
            "format": "date-time",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "results": {
            "description": "The run's results with their traces. Left out by `GET /run/{id}?include_results=false`.",
            "items": {
              "$ref": "#/components/schemas/Result"
            },
            "readOnly": true,
            "type": "array"
          }
        },
        "required": [
          "agent",
          "agent_name",
          "attack",
          "campaign",
          "cancel_requested_at",
          "claimed_at",
          "claimed_by",
          "executor",
          "finished_at",
          "heartbeat_at",
          "id",
          "organization",
          "organization_name",
          "owner",
          "owner_username",
          "parent",
          "run_config",
          "run_notes",
          "status",
          "timestamp"
        ],
        "type": "object"
      },
      "RunComparison": {
        "properties": {
          "current": {
            "allOf": [
              {
                "$ref": "#/components/schemas/ComparedRun"
              }
            ],
            "description": "This campaign run."
          },
          "baseline": {
            "allOf": [
              {
                "$ref": "#/components/schemas/ComparedRun"
              }
            ],
            "description": "The baseline campaign run."
          },
          "counts": {
            "allOf": [
              {
                "$ref": "#/components/schemas/ChangeCounts"
              }
            ],
            "description": "How many goals changed, by kind."
          },
          "goals": {
            "description": "The goals, regressions first.",
            "items": {
              "$ref": "#/components/schemas/ComparedGoal"
            },
            "type": "array"
          }
        },
        "required": [
          "baseline",
          "counts",
          "current",
          "goals"
        ],
        "type": "object"
      },
      "RunConflict": {
        "description": "409 body: the run is not in a state that allows the call.",
        "properties": {
          "detail": {
            "description": "Why the call is refused.",
            "type": "string"
          },
          "status": {
            "description": "The run's status.",
            "type": "string"
          },
          "code": {
            "description": "Machine-readable cause, e.g. CLOUD_CONCURRENCY_LIMIT.",
            "type": "string"
          },
          "claimed_by": {
            "description": "Who holds the run, if claimed.",
            "type": "string"
          }
        },
        "required": [
          "detail"
        ],
        "type": "object"
      },
      "RunCost": {
        "properties": {
          "run_id": {
            "description": "The attack run.",
            "format": "uuid",
            "type": "string"
          },
          "attempts": {
            "description": "Attempts it made.",
            "type": "integer"
          },
          "goals": {
            "description": "Goals it attempted.",
            "type": "integer"
          },
          "elapsed_s": {
            "description": "Seconds between its first and last recorded attempt.",
            "format": "double",
            "type": "number"
          },
          "calls": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Calls"
              }
            ],
            "description": "Model calls by role."
          },
          "calls_traced": {
            "description": "Whether the calls of every role were traced (otherwise attacker and judge counts may be missing).",
            "type": "boolean"
          },
          "target_tokens": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Tokens"
              }
            ],
            "description": "Target tokens spent; null when not every goal's usage was recorded.",
            "nullable": true
          },
          "target_latency_ms": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Latency"
              }
            ],
            "description": "The target's latency; null without measurements.",
            "nullable": true
          },
          "goal_samples": {
            "description": "Per-goal figures.",
            "items": {
              "$ref": "#/components/schemas/GoalSample"
            },
            "type": "array"
          }
        },
        "required": [
          "attempts",
          "calls",
          "calls_traced",
          "elapsed_s",
          "goal_samples",
          "goals",
          "run_id",
          "target_latency_ms",
          "target_tokens"
        ],
        "type": "object"
      },
      "RunCosts": {
        "properties": {
          "runs": {
            "description": "One entry per attack run with results, oldest first.",
            "items": {
              "$ref": "#/components/schemas/RunCost"
            },
            "type": "array"
          }
        },
        "required": [
          "runs"
        ],
        "type": "object"
      },
      "RunDetailError": {
        "description": "An error of a run endpoint.",
        "properties": {
          "detail": {
            "description": "What went wrong, for people.",
            "type": "string"
          }
        },
        "required": [
          "detail"
        ],
        "type": "object"
      },
      "RunExecutorEnum": {
        "description": "* `cloud` - HackAgent cloud\n* `local` - Local machine\n* `cli` - Command line",
        "enum": [
          "cloud",
          "local",
          "cli"
        ],
        "type": "string"
      },
      "RunSummary": {
        "description": "Lightweight serializer for list views. Returns result counts (from DB\nannotations) instead of the full nested result objects.",
        "properties": {
          "id": {
            "description": "Unique identifier of the run.",
            "format": "uuid",
            "readOnly": true,
            "type": "string"
          },
          "agent": {
            "description": "Id of the agent the run targets.",
            "format": "uuid",
            "readOnly": true,
            "type": "string"
          },
          "agent_name": {
            "description": "Name of the agent.",
            "readOnly": true,
            "type": "string"
          },
          "attack": {
            "description": "Id of the attack configuration an attack run executes; null for campaign runs.",
            "format": "uuid",
            "nullable": true,
            "readOnly": true,
            "title": "Associated Attack",
            "type": "string"
          },
          "attack_type": {
            "description": "Technique of the attack run's configuration; null without one.",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "owner": {
            "description": "Id of the user who launched the run.",
            "nullable": true,
            "readOnly": true,
            "title": "Initiated By",
            "type": "integer"
          },
          "owner_username": {
            "description": "Username of the user who launched the run.",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "organization": {
            "description": "Id of the run's organization.",
            "format": "uuid",
            "readOnly": true,
            "type": "string"
          },
          "organization_name": {
            "description": "Name of the run's organization.",
            "readOnly": true,
            "type": "string"
          },
          "run_config": {
            "description": "The run's configuration. For a campaign run: `campaign_config` (the resolved campaign spec, with the agent as `target`), `campaign_id`, `campaign_name` and the `sdk_version` it runs with; for an attack run, what its executor recorded.",
            "nullable": true,
            "readOnly": true,
            "title": "Run Configuration"
          },
          "timestamp": {
            "description": "When the run was created.",
            "format": "date-time",
            "readOnly": true,
            "type": "string"
          },
          "status": {
            "allOf": [
              {
                "$ref": "#/components/schemas/StatusEnum"
              }
            ],
            "description": "`PENDING` (queued), `RUNNING`, then `COMPLETED`, `FAILED` or `CANCELLED`.\n\n* `PENDING` - Pending\n* `RUNNING` - Running\n* `COMPLETED` - Completed\n* `FAILED` - Failed\n* `CANCELLED` - Cancelled",
            "readOnly": true
          },
          "run_notes": {
            "description": "Notes on the run, e.g. why it failed or was cancelled.",
            "readOnly": true,
            "type": "string"
          },
          "executor": {
            "allOf": [
              {
                "$ref": "#/components/schemas/RunExecutorEnum"
              }
            ],
            "description": "Who executes the run: HackAgent cloud, a local machine or the CLI.\n\n* `cloud` - HackAgent cloud\n* `local` - Local machine\n* `cli` - Command line",
            "readOnly": true
          },
          "campaign": {
            "description": "Id of the saved campaign the run was launched from, if any.",
            "format": "uuid",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "parent": {
            "description": "Id of the campaign run an attack run belongs to; null for a campaign run.",
            "format": "uuid",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "claimed_at": {
            "description": "When an executor claimed the run.",
            "format": "date-time",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "claimed_by": {
            "description": "Free-text description of the executor that claimed the run.",
            "readOnly": true,
            "type": "string"
          },
          "heartbeat_at": {
            "description": "The executor's last heartbeat.",
            "format": "date-time",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "cancel_requested_at": {
            "description": "When a cancel was requested; the executor then stops the run.",
            "format": "date-time",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "finished_at": {
            "description": "When the run reached COMPLETED, FAILED or CANCELLED.",
            "format": "date-time",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "total_results": {
            "default": 0,
            "description": "Results recorded in the run.",
            "readOnly": true,
            "type": "integer"
          },
          "successful_jailbreaks": {
            "default": 0,
            "description": "Results evaluated `SUCCESSFUL_JAILBREAK`.",
            "readOnly": true,
            "type": "integer"
          },
          "failed_jailbreaks": {
            "default": 0,
            "description": "Results evaluated `FAILED_JAILBREAK` or `PASSED_CRITERIA`.",
            "readOnly": true,
            "type": "integer"
          },
          "errors": {
            "default": 0,
            "description": "Results evaluated `ERROR_AGENT_RESPONSE`, `ERROR_TEST_FRAMEWORK` or `FAILED_CRITERIA`.",
            "readOnly": true,
            "type": "integer"
          },
          "not_evaluated": {
            "default": 0,
            "description": "Results not evaluated yet.",
            "readOnly": true,
            "type": "integer"
          },
          "total_goals": {
            "default": 0,
            "description": "Distinct goals the results cover (results with a `goal_index`).",
            "readOnly": true,
            "type": "integer"
          },
          "jailbroken_goals": {
            "default": 0,
            "description": "Distinct goals with at least one successful jailbreak.",
            "readOnly": true,
            "type": "integer"
          }
        },
        "required": [
          "agent",
          "agent_name",
          "attack",
          "attack_type",
          "campaign",
          "cancel_requested_at",
          "claimed_at",
          "claimed_by",
          "errors",
          "executor",
          "failed_jailbreaks",
          "finished_at",
          "heartbeat_at",
          "id",
          "jailbroken_goals",
          "not_evaluated",
          "organization",
          "organization_name",
          "owner",
          "owner_username",
          "parent",
          "run_config",
          "run_notes",
          "status",
          "successful_jailbreaks",
          "timestamp",
          "total_goals",
          "total_results"
        ],
        "type": "object"
      },
      "Secret": {
        "properties": {
          "name": {
            "description": "The secret's name, unique in the organization. Configs reference it as `${NAME}`.",
            "readOnly": true,
            "type": "string"
          },
          "created_by_username": {
            "description": "Username of the user who created the secret.",
            "readOnly": true,
            "type": "string"
          },
          "created_at": {
            "description": "When the secret was created.",
            "format": "date-time",
            "readOnly": true,
            "type": "string"
          },
          "updated_at": {
            "description": "When the secret's value was last set.",
            "format": "date-time",
            "readOnly": true,
            "type": "string"
          }
        },
        "required": [
          "created_at",
          "created_by_username",
          "name",
          "updated_at"
        ],
        "type": "object"
      },
      "SecretDeleted": {
        "properties": {
          "referenced_by": {
            "allOf": [
              {
                "$ref": "#/components/schemas/SecretReferences"
              }
            ],
            "description": "Agents and campaigns whose config still names the secret."
          }
        },
        "required": [
          "referenced_by"
        ],
        "type": "object"
      },
      "SecretReferences": {
        "properties": {
          "agents": {
            "description": "Names of the agents whose config references the secret.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "campaigns": {
            "description": "Names of the campaigns whose spec references the secret.",
            "items": {
              "type": "string"
            },
            "type": "array"
          }
        },
        "required": [
          "agents",
          "campaigns"
        ],
        "type": "object"
      },
      "SecretStoreError": {
        "description": "The secret store cannot encrypt values on this installation.",
        "properties": {
          "error": {
            "description": "What went wrong.",
            "type": "string"
          }
        },
        "required": [
          "error"
        ],
        "type": "object"
      },
      "SecretValueRequest": {
        "properties": {
          "value": {
            "description": "The new secret value, stored encrypted and never returned.",
            "minLength": 1,
            "type": "string",
            "writeOnly": true
          }
        },
        "required": [
          "value"
        ],
        "type": "object"
      },
      "SecretWriteRequest": {
        "example": {
          "name": "SUPPORT_BOT_API_KEY",
          "value": "<your provider key>"
        },
        "properties": {
          "name": {
            "description": "2-64 characters: uppercase letters, digits and underscores, starting with a letter (e.g. `OPENAI_API_KEY`). Configs can reference a secret whose name ends in `API_KEY`, `_KEY` or `_TOKEN` and that no library reads a setting from.",
            "maxLength": 64,
            "minLength": 1,
            "type": "string"
          },
          "value": {
            "description": "The secret value, stored encrypted and never returned.",
            "minLength": 1,
            "type": "string",
            "writeOnly": true
          }
        },
        "required": [
          "name",
          "value"
        ],
        "type": "object"
      },
      "StateEnum": {
        "description": "* `valid` - valid\n* `warning` - warning\n* `grace` - grace\n* `read_only` - read_only\n* `invalid` - invalid",
        "enum": [
          "valid",
          "warning",
          "grace",
          "read_only",
          "invalid"
        ],
        "type": "string"
      },
      "StatusEnum": {
        "description": "* `PENDING` - Pending\n* `RUNNING` - Running\n* `COMPLETED` - Completed\n* `FAILED` - Failed\n* `CANCELLED` - Cancelled",
        "enum": [
          "PENDING",
          "RUNNING",
          "COMPLETED",
          "FAILED",
          "CANCELLED"
        ],
        "type": "string"
      },
      "StepTypeEnum": {
        "description": "* `TOOL_CALL` - Tool Call\n* `TOOL_RESPONSE` - Tool Response\n* `AGENT_THOUGHT` - Agent Thought/Reasoning\n* `AGENT_RESPONSE_CHUNK` - Agent Response Chunk\n* `OTHER` - Other\n* `MCP_STEP` - Multi-Context Prompting Step\n* `A2A_COMM` - Agent-to-Agent Communication\n* `interaction` - Target Interaction",
        "enum": [
          "TOOL_CALL",
          "TOOL_RESPONSE",
          "AGENT_THOUGHT",
          "AGENT_RESPONSE_CHUNK",
          "OTHER",
          "MCP_STEP",
          "A2A_COMM",
          "interaction"
        ],
        "type": "string"
      },
      "StructureAttempt": {
        "properties": {
          "id": {
            "description": "Id of the attempt's result.",
            "format": "uuid",
            "type": "string"
          },
          "run_id": {
            "description": "The attack run that made it.",
            "format": "uuid",
            "type": "string"
          },
          "ordinal": {
            "description": "Position of the attempt among the goal's attempts, from 1.",
            "type": "integer"
          },
          "bucket": {
            "allOf": [
              {
                "$ref": "#/components/schemas/BucketEnum"
              }
            ],
            "description": "How the attempt was judged: `jailbreak`, `mitigated`, `error` or `pending` (not evaluated yet).\n\n* `jailbreak` - jailbreak\n* `mitigated` - mitigated\n* `error` - error\n* `pending` - pending"
          },
          "notes": {
            "description": "The judges' notes, if any.",
            "nullable": true,
            "type": "string"
          },
          "created_at": {
            "description": "When the attempt was recorded.",
            "format": "date-time",
            "type": "string"
          },
          "metadata": {
            "additionalProperties": {},
            "description": "The attempt's attack_metadata.",
            "type": "object"
          }
        },
        "required": [
          "bucket",
          "created_at",
          "id",
          "metadata",
          "notes",
          "ordinal",
          "run_id"
        ],
        "type": "object"
      },
      "StructureResult": {
        "properties": {
          "id": {
            "description": "Id of the result.",
            "format": "uuid",
            "type": "string"
          },
          "request_payload": {
            "description": "What was sent to the agent.",
            "nullable": true
          },
          "agent_specific_data": {
            "description": "Attack metadata the SDK recorded.",
            "nullable": true
          },
          "evaluation_notes": {
            "description": "The judges' notes, if any.",
            "nullable": true,
            "type": "string"
          }
        },
        "required": [
          "agent_specific_data",
          "evaluation_notes",
          "id",
          "request_payload"
        ],
        "type": "object"
      },
      "StructureTrace": {
        "properties": {
          "id": {
            "description": "Id of the trace step.",
            "type": "string"
          },
          "result": {
            "description": "Id of the attempt (result) it belongs to.",
            "format": "uuid",
            "type": "string"
          },
          "sequence": {
            "description": "Position of the step in its attempt's trace.",
            "type": "integer"
          },
          "step_type": {
            "description": "Kind of step.",
            "type": "string"
          },
          "timestamp": {
            "description": "When the step was recorded.",
            "format": "date-time",
            "type": "string"
          },
          "content": {
            "description": "The step's data.",
            "nullable": true
          }
        },
        "required": [
          "content",
          "id",
          "result",
          "sequence",
          "step_type",
          "timestamp"
        ],
        "type": "object"
      },
      "SubcategoryOutcomes": {
        "properties": {
          "recorded_goals": {
            "description": "Goals with at least one recorded attempt.",
            "type": "integer"
          },
          "jailbroken": {
            "description": "Goals with at least one successful jailbreak.",
            "type": "integer"
          },
          "mitigated": {
            "description": "Goals every attempt of which was mitigated, once the scope is complete.",
            "type": "integer"
          },
          "unresolved": {
            "description": "Goals neither jailbroken nor (yet) mitigated: still running, pending evaluation or errored.",
            "type": "integer"
          },
          "name": {
            "description": "Unspecified for goals without one.",
            "type": "string"
          }
        },
        "required": [
          "jailbroken",
          "mitigated",
          "name",
          "recorded_goals",
          "unresolved"
        ],
        "type": "object"
      },
      "Technique": {
        "description": "One attack technique of the SDK catalogue, with its parameter form.",
        "properties": {
          "attack_type": {
            "description": "The technique's name, for an attack's `name` in a spec.",
            "type": "string"
          },
          "label": {
            "description": "Display name.",
            "type": "string"
          },
          "description": {
            "description": "What the technique does.",
            "type": "string"
          },
          "category": {
            "description": "Category key, e.g. `static`, `adaptive`, `multi_turn`.",
            "type": "string"
          },
          "category_label": {
            "description": "Display name of the category.",
            "type": "string"
          },
          "category_description": {
            "description": "What techniques of the category have in common.",
            "type": "string"
          },
          "tags": {
            "description": "Tag keys.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "tag_labels": {
            "description": "Display names of `tags`, in order.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "primary_order": {
            "description": "Position among the techniques shown first; null for the others.",
            "nullable": true,
            "type": "integer"
          },
          "fields": {
            "description": "The technique's parameters, as form fields.",
            "items": {
              "$ref": "#/components/schemas/TechniqueField"
            },
            "type": "array"
          },
          "params_schema": {
            "additionalProperties": {},
            "description": "JSON Schema of the technique's `parameters`.",
            "type": "object"
          },
          "required_roles": {
            "description": "Model roles the attack must configure, e.g. `attacker`.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "optional_roles": {
            "description": "Model roles the attack may configure, e.g. `scorer`.",
            "items": {
              "type": "string"
            },
            "type": "array"
          }
        },
        "required": [
          "attack_type",
          "category",
          "category_description",
          "category_label",
          "description",
          "fields",
          "label",
          "optional_roles",
          "params_schema",
          "primary_order",
          "required_roles",
          "tag_labels",
          "tags"
        ],
        "type": "object"
      },
      "TechniqueField": {
        "description": "One parameter of a technique, as a form field.",
        "properties": {
          "key": {
            "description": "The parameter's key in `parameters`.",
            "type": "string"
          },
          "label": {
            "description": "Display label.",
            "type": "string"
          },
          "type": {
            "description": "Value type, e.g. `integer`, `number`, `boolean`, `string`.",
            "type": "string"
          },
          "default": {
            "description": "Default value; null when there is none.",
            "nullable": true
          },
          "description": {
            "description": "What the parameter does.",
            "type": "string"
          },
          "required": {
            "description": "Whether it must be set.",
            "type": "boolean"
          },
          "choices": {
            "description": "Allowed values; null when any value of the type is allowed.",
            "items": {},
            "nullable": true,
            "type": "array"
          },
          "min": {
            "description": "Minimum, if any.",
            "format": "double",
            "nullable": true,
            "type": "number"
          },
          "max": {
            "description": "Maximum, if any.",
            "format": "double",
            "nullable": true,
            "type": "number"
          },
          "section": {
            "description": "Form section the field belongs to.",
            "type": "string"
          },
          "advanced": {
            "description": "Whether forms should hide it under advanced settings.",
            "type": "boolean"
          }
        },
        "required": [
          "advanced",
          "choices",
          "default",
          "description",
          "key",
          "label",
          "max",
          "min",
          "required",
          "section",
          "type"
        ],
        "type": "object"
      },
      "TechniqueOutcomes": {
        "properties": {
          "recorded_goals": {
            "description": "Goals with at least one recorded attempt.",
            "type": "integer"
          },
          "jailbroken": {
            "description": "Goals with at least one successful jailbreak.",
            "type": "integer"
          },
          "mitigated": {
            "description": "Goals every attempt of which was mitigated, once the scope is complete.",
            "type": "integer"
          },
          "unresolved": {
            "description": "Goals neither jailbroken nor (yet) mitigated: still running, pending evaluation or errored.",
            "type": "integer"
          },
          "technique": {
            "description": "The attack technique.",
            "type": "string"
          },
          "attempts": {
            "description": "Attempts made with the technique.",
            "type": "integer"
          }
        },
        "required": [
          "attempts",
          "jailbroken",
          "mitigated",
          "recorded_goals",
          "technique",
          "unresolved"
        ],
        "type": "object"
      },
      "Tokens": {
        "properties": {
          "prompt": {
            "description": "Prompt tokens.",
            "type": "integer"
          },
          "completion": {
            "description": "Completion tokens.",
            "type": "integer"
          }
        },
        "required": [
          "completion",
          "prompt"
        ],
        "type": "object"
      },
      "Trace": {
        "description": "Serializer for the Trace model.",
        "properties": {
          "id": {
            "description": "Unique identifier of the trace step.",
            "readOnly": true,
            "type": "integer"
          },
          "result": {
            "description": "Id of the result the step belongs to.",
            "format": "uuid",
            "readOnly": true,
            "type": "string"
          },
          "sequence": {
            "description": "Position of the step in the result's trace, from 0; unique per result.",
            "format": "int64",
            "maximum": 9223372036854775807,
            "minimum": 0,
            "type": "integer"
          },
          "step_type": {
            "allOf": [
              {
                "$ref": "#/components/schemas/StepTypeEnum"
              }
            ],
            "description": "Kind of step; `interaction` is one exchange with the target, as the SDK records it.\n\n* `TOOL_CALL` - Tool Call\n* `TOOL_RESPONSE` - Tool Response\n* `AGENT_THOUGHT` - Agent Thought/Reasoning\n* `AGENT_RESPONSE_CHUNK` - Agent Response Chunk\n* `OTHER` - Other\n* `MCP_STEP` - Multi-Context Prompting Step\n* `A2A_COMM` - Agent-to-Agent Communication\n* `interaction` - Target Interaction"
          },
          "timestamp": {
            "description": "When the step was recorded.",
            "format": "date-time",
            "readOnly": true,
            "type": "string"
          },
          "content": {
            "description": "The step's data (free-form JSON, depends on `step_type`).",
            "nullable": true
          }
        },
        "required": [
          "id",
          "result",
          "sequence",
          "timestamp"
        ],
        "type": "object"
      },
      "TraceRequest": {
        "description": "Serializer for the Trace model.",
        "properties": {
          "sequence": {
            "description": "Position of the step in the result's trace, from 0; unique per result.",
            "format": "int64",
            "maximum": 9223372036854775807,
            "minimum": 0,
            "type": "integer"
          },
          "step_type": {
            "allOf": [
              {
                "$ref": "#/components/schemas/StepTypeEnum"
              }
            ],
            "description": "Kind of step; `interaction` is one exchange with the target, as the SDK records it.\n\n* `TOOL_CALL` - Tool Call\n* `TOOL_RESPONSE` - Tool Response\n* `AGENT_THOUGHT` - Agent Thought/Reasoning\n* `AGENT_RESPONSE_CHUNK` - Agent Response Chunk\n* `OTHER` - Other\n* `MCP_STEP` - Multi-Context Prompting Step\n* `A2A_COMM` - Agent-to-Agent Communication\n* `interaction` - Target Interaction"
          },
          "content": {
            "description": "The step's data (free-form JSON, depends on `step_type`).",
            "nullable": true
          }
        },
        "required": [
          "sequence"
        ],
        "type": "object"
      },
      "Usage": {
        "properties": {
          "prompt_tokens": {
            "description": "Number of tokens in the prompt",
            "type": "integer"
          },
          "completion_tokens": {
            "description": "Number of tokens in the completion",
            "type": "integer"
          },
          "total_tokens": {
            "description": "Total tokens used",
            "type": "integer"
          }
        },
        "required": [
          "completion_tokens",
          "prompt_tokens",
          "total_tokens"
        ],
        "type": "object"
      },
      "UsageSummary": {
        "description": "Daily gateway usage of the organization over a date range.",
        "properties": {
          "start_date": {
            "description": "First day of the range.",
            "format": "date",
            "type": "string"
          },
          "end_date": {
            "description": "Last day of the range (inclusive).",
            "format": "date",
            "type": "string"
          },
          "timezone": {
            "description": "The time zone days are counted in.",
            "type": "string"
          },
          "days": {
            "description": "Days with at least one call, in order.",
            "items": {
              "$ref": "#/components/schemas/UsageSummaryDay"
            },
            "type": "array"
          }
        },
        "required": [
          "days",
          "end_date",
          "start_date",
          "timezone"
        ],
        "type": "object"
      },
      "UsageSummaryDay": {
        "description": "The organization's gateway usage on one day.",
        "properties": {
          "date": {
            "description": "The day, in the requested time zone.",
            "format": "date",
            "type": "string"
          },
          "requests": {
            "description": "Gateway calls that day.",
            "type": "integer"
          },
          "input_tokens": {
            "description": "Prompt tokens that day.",
            "type": "integer"
          },
          "output_tokens": {
            "description": "Completion tokens that day.",
            "type": "integer"
          },
          "credits_deducted": {
            "description": "Credits (US dollars) charged that day, as a decimal string.",
            "type": "string"
          },
          "by_key": {
            "description": "With `by_key=true`: the same figures per API key.",
            "items": {
              "$ref": "#/components/schemas/UsageSummaryKey"
            },
            "type": "array"
          }
        },
        "required": [
          "credits_deducted",
          "date",
          "input_tokens",
          "output_tokens",
          "requests"
        ],
        "type": "object"
      },
      "UsageSummaryKey": {
        "description": "One API key's gateway usage on a day.",
        "properties": {
          "api_key_prefix": {
            "description": "Prefix of the API key; null for calls made with a login token or by a cloud run.",
            "nullable": true,
            "type": "string"
          },
          "requests": {
            "description": "Gateway calls made with it.",
            "type": "integer"
          },
          "input_tokens": {
            "description": "Prompt tokens.",
            "type": "integer"
          },
          "output_tokens": {
            "description": "Completion tokens.",
            "type": "integer"
          },
          "credits_deducted": {
            "description": "Credits (US dollars) charged, as a decimal string.",
            "type": "string"
          }
        },
        "required": [
          "api_key_prefix",
          "credits_deducted",
          "input_tokens",
          "output_tokens",
          "requests"
        ],
        "type": "object"
      },
      "UserAPIKey": {
        "description": "Serializer for User API Keys.\nExposes read-only information about the key, including its prefix.\nThe full key is only shown once upon creation by the ViewSet.",
        "properties": {
          "id": {
            "description": "Internal identifier of the key.",
            "readOnly": true,
            "type": "string"
          },
          "name": {
            "description": "A human-readable name for the API key.",
            "maxLength": 50,
            "type": "string"
          },
          "prefix": {
            "description": "The first characters of the key, shown to recognize it and used as its id in `/key/{prefix}`.",
            "readOnly": true,
            "type": "string"
          },
          "created": {
            "description": "When the key was created.",
            "format": "date-time",
            "readOnly": true,
            "type": "string"
          },
          "revoked": {
            "description": "Whether the key was revoked; revoked keys are not listed.",
            "readOnly": true,
            "type": "boolean"
          },
          "expiry_date": {
            "description": "When the key stops working; null if it never expires.",
            "format": "date-time",
            "nullable": true,
            "readOnly": true,
            "title": "Expires",
            "type": "string"
          },
          "user": {
            "description": "Id of the user the key acts as.",
            "readOnly": true,
            "type": "integer"
          },
          "user_detail": {
            "allOf": [
              {
                "$ref": "#/components/schemas/UserProfileMinimal"
              }
            ],
            "description": "The key's user; may be null.",
            "nullable": true,
            "readOnly": true
          },
          "organization": {
            "description": "Id of the organization the key acts in.",
            "format": "uuid",
            "readOnly": true,
            "type": "string"
          },
          "organization_detail": {
            "allOf": [
              {
                "$ref": "#/components/schemas/OrganizationMinimal"
              }
            ],
            "description": "The organization the key acts in.",
            "nullable": true,
            "readOnly": true
          }
        },
        "required": [
          "created",
          "expiry_date",
          "id",
          "name",
          "organization",
          "organization_detail",
          "prefix",
          "revoked",
          "user",
          "user_detail"
        ],
        "type": "object"
      },
      "UserAPIKeyCreated": {
        "description": "A new API key, with the key itself: shown in this response only.",
        "properties": {
          "id": {
            "description": "Internal identifier of the key.",
            "readOnly": true,
            "type": "string"
          },
          "name": {
            "description": "A human-readable name for the API key.",
            "maxLength": 50,
            "type": "string"
          },
          "prefix": {
            "description": "The first characters of the key, shown to recognize it and used as its id in `/key/{prefix}`.",
            "readOnly": true,
            "type": "string"
          },
          "created": {
            "description": "When the key was created.",
            "format": "date-time",
            "readOnly": true,
            "type": "string"
          },
          "revoked": {
            "description": "Whether the key was revoked; revoked keys are not listed.",
            "readOnly": true,
            "type": "boolean"
          },
          "expiry_date": {
            "description": "When the key stops working; null if it never expires.",
            "format": "date-time",
            "nullable": true,
            "readOnly": true,
            "title": "Expires",
            "type": "string"
          },
          "user": {
            "description": "Id of the user the key acts as.",
            "readOnly": true,
            "type": "integer"
          },
          "user_detail": {
            "allOf": [
              {
                "$ref": "#/components/schemas/UserProfileMinimal"
              }
            ],
            "description": "The key's user; may be null.",
            "nullable": true,
            "readOnly": true
          },
          "organization": {
            "description": "Id of the organization the key acts in.",
            "format": "uuid",
            "readOnly": true,
            "type": "string"
          },
          "organization_detail": {
            "allOf": [
              {
                "$ref": "#/components/schemas/OrganizationMinimal"
              }
            ],
            "description": "The organization the key acts in.",
            "nullable": true,
            "readOnly": true
          },
          "key": {
            "description": "The full API key, `<prefix>.<secret>`. It is shown only in this response: store it now, it cannot be retrieved again.",
            "readOnly": true,
            "type": "string"
          }
        },
        "required": [
          "created",
          "expiry_date",
          "id",
          "key",
          "name",
          "organization",
          "organization_detail",
          "prefix",
          "revoked",
          "user",
          "user_detail"
        ],
        "type": "object"
      },
      "UserAPIKeyRequest": {
        "description": "Serializer for User API Keys.\nExposes read-only information about the key, including its prefix.\nThe full key is only shown once upon creation by the ViewSet.",
        "example": {
          "name": "CI pipeline"
        },
        "properties": {
          "name": {
            "description": "A human-readable name for the API key.",
            "maxLength": 50,
            "minLength": 1,
            "type": "string"
          },
          "key": {
            "description": "Ignored: the server generates the key.",
            "minLength": 1,
            "type": "string",
            "writeOnly": true
          }
        },
        "required": [
          "name"
        ],
        "type": "object"
      },
      "UserProfile": {
        "properties": {
          "id": {
            "description": "Unique identifier of the profile.",
            "format": "uuid",
            "readOnly": true,
            "type": "string"
          },
          "user": {
            "description": "Id of the user.",
            "readOnly": true,
            "type": "integer"
          },
          "username": {
            "description": "The user's username, from their sign-in.",
            "readOnly": true,
            "type": "string"
          },
          "email": {
            "description": "The user's email address.",
            "format": "email",
            "type": "string"
          },
          "first_name": {
            "description": "The user's first name.",
            "type": "string"
          },
          "last_name": {
            "description": "The user's last name.",
            "type": "string"
          },
          "organization": {
            "description": "Id of the user's organization.",
            "format": "uuid",
            "readOnly": true,
            "type": "string"
          },
          "organization_name": {
            "description": "Name of the user's organization.",
            "readOnly": true,
            "type": "string"
          },
          "auth0_user_id": {
            "description": "The unique user identifier (sub claim) provided by Auth0.",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "keycloak_user_id": {
            "description": "The unique user identifier (sub claim) provided by Keycloak.",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "analytics_consent": {
            "description": "Whether the user has consented to optional analytics cookies (e.g. usage tracking, session recording), set once during onboarding and changeable in Settings.\n\n* `unset` - Unset\n* `accepted` - Accepted\n* `declined` - Declined",
            "oneOf": [
              {
                "$ref": "#/components/schemas/AnalyticsConsentEnum"
              },
              {
                "$ref": "#/components/schemas/BlankEnum"
              }
            ]
          }
        },
        "required": [
          "auth0_user_id",
          "id",
          "keycloak_user_id",
          "organization",
          "organization_name",
          "user",
          "username"
        ],
        "type": "object"
      },
      "UserProfileMinimal": {
        "properties": {
          "user": {
            "description": "Id of the user.",
            "readOnly": true,
            "type": "integer"
          },
          "username": {
            "description": "The user's username.",
            "readOnly": true,
            "type": "string"
          },
          "organization": {
            "description": "Id of the user's organization.",
            "format": "uuid",
            "readOnly": true,
            "type": "string"
          }
        },
        "required": [
          "organization",
          "user",
          "username"
        ],
        "type": "object"
      },
      "UserProfileRequest": {
        "properties": {
          "email": {
            "description": "The user's email address.",
            "format": "email",
            "minLength": 1,
            "type": "string"
          },
          "first_name": {
            "description": "The user's first name.",
            "type": "string"
          },
          "last_name": {
            "description": "The user's last name.",
            "type": "string"
          },
          "analytics_consent": {
            "description": "Whether the user has consented to optional analytics cookies (e.g. usage tracking, session recording), set once during onboarding and changeable in Settings.\n\n* `unset` - Unset\n* `accepted` - Accepted\n* `declined` - Declined",
            "oneOf": [
              {
                "$ref": "#/components/schemas/AnalyticsConsentEnum"
              },
              {
                "$ref": "#/components/schemas/BlankEnum"
              }
            ]
          }
        },
        "type": "object"
      },
      "ValidationError": {
        "additionalProperties": {},
        "description": "The request did not validate. Each invalid field maps to its list of\nmessages (``{\"name\": [\"This field is required.\"]}``); errors inside a\nJSON field are keyed by their dotted path\n(``{\"config\": {\"connection.api_key\": \"...\"}}``).",
        "properties": {
          "non_field_errors": {
            "description": "Errors that are not about a single field.",
            "items": {
              "type": "string"
            },
            "type": "array"
          }
        },
        "type": "object"
      },
      "WarningsEnum": {
        "description": "* `expires_soon` - expires_soon\n* `seats_full` - seats_full\n* `runs_80_percent` - runs_80_percent\n* `runs_limit_reached` - runs_limit_reached",
        "enum": [
          "expires_soon",
          "seats_full",
          "runs_80_percent",
          "runs_limit_reached"
        ],
        "type": "string"
      }
    },
    "securitySchemes": {
      "APIKeyAuth": {
        "bearerFormat": "API-Key",
        "scheme": "bearer",
        "type": "http"
      },
      "Auth0JWTAccessToken": {
        "bearerFormat": "JWT",
        "scheme": "bearer",
        "type": "http"
      },
      "RunTokenAuth": {
        "bearerFormat": "Run-Token",
        "scheme": "bearer",
        "type": "http"
      },
      "WorkerTokenAuth": {
        "bearerFormat": "Worker-Token",
        "scheme": "bearer",
        "type": "http"
      },
      "cookieAuth": {
        "in": "cookie",
        "name": "sessionid",
        "type": "apiKey"
      }
    }
  },
  "info": {
    "description": "The HackAgent API stores the agents you red-team, the campaigns you run\nagainst them and everything those runs record (results, traces, reports). It\nalso serves the HackAgent LLM gateway, the attacker and judge models that\ncampaigns use. The `hackagent` SDK and CLI and the HackAgent dashboard are\nbuilt on it.\n\n## Base URL\n\nThe hosted service is at `https://api.hackagent.dev`; paths in this reference\nare relative to it (for example `https://api.hackagent.dev/agent`). A\nself-hosted installation serves the same paths under its own address, usually\nbehind `/api`.\n\n## Authentication\n\nEvery endpoint needs a bearer token in the `Authorization` header:\n\n```\nAuthorization: Bearer <your HackAgent API key>\n```\n\n- **API keys** are created in the dashboard (or with `POST /key`) and shown\n  once. They act as the user who created them, within that user's\n  organization. Use them for the SDK, the CLI and scripts.\n- **Login tokens** (Auth0 on the hosted service, Keycloak on self-hosted\n  installations) are what the dashboard sends. A few account endpoints accept\n  only login tokens: API keys cannot create other keys, read usage logs or\n  manage the account, and get `401` there.\n- **Run tokens** (`hart_<prefix>.<secret>`) are issued to a cloud run when it\n  is claimed and expire when it finishes. They can only report on that run\n  and call the LLM gateway.\n- The **worker token** is the cloud worker's service credential; it can only\n  claim cloud runs.\n\nA missing, malformed, expired or revoked credential gets `401`.\n\n## Organizations\n\nEverything belongs to an organization. Each user belongs to one, and the API\nonly shows and changes objects of the caller's organization: objects of other\norganizations answer `404`. Staff accounts of an installation also see the\nagents, attacks, runs and results of every organization.\n\n## Pagination\n\nList endpoints return a page:\n`{\"count\": 42, \"next\": \"<url>\", \"previous\": null, \"results\": [...]}`. Ask for\nanother page with `page` (1-based). Endpoints that accept `page_size` say so,\nwith their maximum; the default page size is 10. `next` and `previous` are\nready-to-use URLs, or `null` at either end.\n\n## Errors\n\nErrors are JSON. Validation failures (`400`) map each invalid field to a list\nof messages, for example `{\"name\": [\"This field is required.\"]}`; errors that\nare not about one field use `non_field_errors`, and nested configuration\nerrors are keyed by their dotted path (`\"connection.api_key\"`). Other errors\ncarry a human-readable `detail`, and often a machine-readable `code`:\n\n| Status | Meaning |\n| --- | --- |\n| `400` | The request is invalid; nothing was changed. |\n| `401` | Missing or invalid credential, or a credential type the endpoint refuses. |\n| `402` | Not enough credits for an LLM gateway call. |\n| `403` | The credential may not do this, or the installation is read-only because its license is not valid (`code: license_read_only`). |\n| `404` | No such object in the caller's organization. |\n| `409` | The run is not in a state that allows the call (already claimed, finished, still active). |\n| `429` | Rate limited; retry after the seconds in the `Retry-After` header. |\n\nThe LLM gateway (`/v1/...`) answers errors in its own shape,\n`{\"error\": \"...\", \"code\": \"...\"}`, as OpenAI-compatible clients expect.\n\n## Credits\n\nEach organization has a balance of credits, in US dollars (see\n`GET /organization/me`). Calls to the LLM gateway, made by you or by a cloud\nrun on your behalf, are charged to it: before a call, its maximum cost is\nchecked against the balance (`402` if the balance cannot cover it), and its\nactual cost is deducted afterwards. A cloud launch needs a\nminimum balance. Ask for more with `POST /credits/request`.\n\n## Rate limits\n\nRequests are rate limited per user (by default 1,000 an hour); cloud runs have\ntheir own, larger budget per run token, and the campaign run report reads\nanother one per user. A limited request gets\n`429` with a `Retry-After` header.",
    "title": "HackAgent API",
    "version": "0.1.0"
  },
  "openapi": "3.0.3",
  "paths": {
    "/agent": {
      "get": {
        "description": "Returns the agents of the caller's organization, ordered by name, 10 per page (`page`). Staff users see every organization's agents; a user without an organization sees the agents they own. Accepts an API key or a login token.",
        "operationId": "agent_list",
        "parameters": [
          {
            "description": "A page number within the paginated result set.",
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedAgentList"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          },
          {
            "RunTokenAuth": []
          }
        ],
        "summary": "List agents",
        "tags": [
          "agent"
        ]
      },
      "post": {
        "description": "Registers an agent to test in the caller's organization, owned by the caller. `config` is a hackagent model configuration: the model `name` and its `connection`. `agent_type` and `endpoint` are copied from `config.connection` and cannot be set directly. Credentials are never stored with the agent: `config.connection.api_key` must be a `${VARIABLE}` reference to an organization secret (see `POST /secret`), and a literal credential anywhere in `config` is refused with 400. Names are unique within an organization. 403 when the caller has no organization.",
        "operationId": "agent_create",
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "CreateAnAgent": {
                  "description": "The key is a reference to the organization secret `SUPPORT_BOT_API_KEY` (create it first with `POST /secret`).",
                  "summary": "An OpenAI-compatible agent",
                  "value": {
                    "config": {
                      "connection": {
                        "api_key": "${SUPPORT_BOT_API_KEY}",
                        "endpoint": "https://agent.example.com/v1",
                        "provider": "openai",
                        "type": "OPENAI"
                      },
                      "name": "gpt-4o-mini"
                    },
                    "description": "Customer support assistant, staging deployment.",
                    "name": "Support bot"
                  }
                }
              },
              "schema": {
                "$ref": "#/components/schemas/AgentRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "examples": {
                  "CreatedAgent": {
                    "summary": "Created agent",
                    "value": {
                      "agent_type": "OPENAI",
                      "config": {
                        "connection": {
                          "api_key": "${SUPPORT_BOT_API_KEY}",
                          "endpoint": "https://agent.example.com/v1",
                          "provider": "openai",
                          "type": "OPENAI"
                        },
                        "name": "gpt-4o-mini"
                      },
                      "created_at": "2026-11-02T09:30:00Z",
                      "description": "Customer support assistant, staging deployment.",
                      "endpoint": "https://agent.example.com/v1",
                      "id": "3f2b8c1e-5d4a-4e6b-9c7d-1a2b3c4d5e6f",
                      "name": "Support bot",
                      "organization": "6a1d4f0e-2b3c-4d5e-8f90-123456789abc",
                      "organization_detail": {
                        "id": "6a1d4f0e-2b3c-4d5e-8f90-123456789abc",
                        "name": "Example Org"
                      },
                      "owner": 42,
                      "owner_detail": null,
                      "updated_at": "2026-11-02T09:30:00Z"
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/Agent"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Validation error: the request is invalid and nothing was changed."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          },
          {
            "RunTokenAuth": []
          }
        ],
        "summary": "Create an agent",
        "tags": [
          "agent"
        ]
      }
    },
    "/agent/{id}": {
      "get": {
        "description": "Returns one agent of the caller's organization. A cloud run's token may read its run's agent only.",
        "operationId": "agent_retrieve",
        "parameters": [
          {
            "description": "A UUID string identifying this Agent.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Agent"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          },
          {
            "RunTokenAuth": []
          }
        ],
        "summary": "Retrieve an agent",
        "tags": [
          "agent"
        ]
      },
      "put": {
        "description": "Replaces the agent's `name`, `description` and `config` (send them all). `agent_type` and `endpoint` are copied from `config.connection` and cannot be set directly. Credentials are never stored with the agent: `config.connection.api_key` must be a `${VARIABLE}` reference to an organization secret (see `POST /secret`), and a literal credential anywhere in `config` is refused with 400. Runs already launched keep the configuration they were launched with.",
        "operationId": "agent_update",
        "parameters": [
          {
            "description": "A UUID string identifying this Agent.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Agent"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Validation error: the request is invalid and nothing was changed."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          },
          {
            "RunTokenAuth": []
          }
        ],
        "summary": "Replace an agent",
        "tags": [
          "agent"
        ]
      },
      "patch": {
        "description": "Changes only the fields sent, with the same rules for `config` as `PUT`. A cloud run's token may update its run's agent only.",
        "operationId": "agent_partial_update",
        "parameters": [
          {
            "description": "A UUID string identifying this Agent.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchedAgentRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Agent"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Validation error: the request is invalid and nothing was changed."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          },
          {
            "RunTokenAuth": []
          }
        ],
        "summary": "Update an agent",
        "tags": [
          "agent"
        ]
      },
      "delete": {
        "description": "Deletes the agent with its attack configurations, campaigns and runs, including their results and traces. This cannot be undone.",
        "operationId": "agent_destroy",
        "parameters": [
          {
            "description": "A UUID string identifying this Agent.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No response body"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          },
          {
            "RunTokenAuth": []
          }
        ],
        "summary": "Delete an agent",
        "tags": [
          "agent"
        ]
      }
    },
    "/apilogs": {
      "get": {
        "description": "Returns the organization's LLM gateway calls, newest first, 10 per page (`page`): who made each call, the model, its tokens and the credits it cost. Calls of cloud runs are included. Login tokens only: API keys get 401.",
        "operationId": "apilogs_list",
        "parameters": [
          {
            "description": "A page number within the paginated result set.",
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedAPITokenLogList"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          }
        ],
        "summary": "List gateway usage logs",
        "tags": [
          "apilogs"
        ]
      }
    },
    "/apilogs/{id}": {
      "get": {
        "description": "Returns one LLM gateway call of the organization. Login tokens only: API keys get 401.",
        "operationId": "apilogs_retrieve",
        "parameters": [
          {
            "description": "A unique integer value identifying this API Usage Log.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/APITokenLog"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          }
        ],
        "summary": "Retrieve a gateway usage log",
        "tags": [
          "apilogs"
        ]
      }
    },
    "/apilogs/summary": {
      "get": {
        "description": "Totals the organization's LLM gateway calls per day between `start_date` and `end_date` (inclusive, at most 92 days apart), with days counted in the time zone `tz`. Only days with calls are listed. With `by_key=true`, each day is also broken down by API key. 400 for a missing or invalid date, range or time zone. Login tokens only: API keys get 401.",
        "operationId": "apilogs_summary_retrieve",
        "parameters": [
          {
            "description": "If true, include per-key daily breakdown",
            "in": "query",
            "name": "by_key",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "description": "End date (inclusive), format YYYY-MM-DD",
            "in": "query",
            "name": "end_date",
            "required": true,
            "schema": {
              "format": "date",
              "type": "string"
            }
          },
          {
            "description": "Start date (inclusive), format YYYY-MM-DD",
            "in": "query",
            "name": "start_date",
            "required": true,
            "schema": {
              "format": "date",
              "type": "string"
            }
          },
          {
            "description": "IANA timezone for day bucketing, e.g. UTC or Europe/Rome",
            "in": "query",
            "name": "tz",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageSummary"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing or invalid `start_date`/`end_date`, a range over 92 days, or an unknown time zone."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          }
        ],
        "summary": "Summarize gateway usage by day",
        "tags": [
          "apilogs"
        ]
      }
    },
    "/attack": {
      "get": {
        "description": "Returns the attack configurations of the caller's organization, newest first, 10 per page (`page`). Staff users see every organization's; a user without an organization sees the ones they created. Each records one technique and its parameters against an agent; its executions are runs (`GET /run?attack=<id>`).",
        "operationId": "attack_list",
        "parameters": [
          {
            "description": "A page number within the paginated result set.",
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedAttackList"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          },
          {
            "RunTokenAuth": []
          }
        ],
        "summary": "List attack configurations",
        "tags": [
          "attack"
        ]
      },
      "post": {
        "description": "Records an attack configuration in the caller's organization, owned by the caller. The SDK records one for each attack of a campaign before it creates the attack's run (`POST /run/{id}/children`). A cloud run's token may create configurations for its run's agent only. 403 when the caller has no organization.",
        "operationId": "attack_create",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AttackRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Attack"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Validation error: the request is invalid and nothing was changed."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          },
          {
            "RunTokenAuth": []
          }
        ],
        "summary": "Create an attack configuration",
        "tags": [
          "attack"
        ]
      }
    },
    "/attack/{id}": {
      "get": {
        "description": "Returns one attack configuration of the caller's organization.",
        "operationId": "attack_retrieve",
        "parameters": [
          {
            "description": "A UUID string identifying this Attack Configuration.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Attack"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          },
          {
            "RunTokenAuth": []
          }
        ],
        "summary": "Retrieve an attack configuration",
        "tags": [
          "attack"
        ]
      },
      "put": {
        "description": "Replaces the `type`, `agent` and `configuration` of an attack configuration (send them all).",
        "operationId": "attack_update",
        "parameters": [
          {
            "description": "A UUID string identifying this Attack Configuration.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AttackRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Attack"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Validation error: the request is invalid and nothing was changed."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          },
          {
            "RunTokenAuth": []
          }
        ],
        "summary": "Replace an attack configuration",
        "tags": [
          "attack"
        ]
      },
      "patch": {
        "description": "Changes only the fields sent of an attack configuration.",
        "operationId": "attack_partial_update",
        "parameters": [
          {
            "description": "A UUID string identifying this Attack Configuration.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchedAttackRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Attack"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Validation error: the request is invalid and nothing was changed."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          },
          {
            "RunTokenAuth": []
          }
        ],
        "summary": "Update an attack configuration",
        "tags": [
          "attack"
        ]
      },
      "delete": {
        "description": "Deletes the attack configuration. Its runs are kept, with `attack` set to null.",
        "operationId": "attack_destroy",
        "parameters": [
          {
            "description": "A UUID string identifying this Attack Configuration.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No response body"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          },
          {
            "RunTokenAuth": []
          }
        ],
        "summary": "Delete an attack configuration",
        "tags": [
          "attack"
        ]
      }
    },
    "/campaign": {
      "get": {
        "description": "Returns the organization's saved campaigns, ordered by name, 10 per page (`page`): those saved from the dashboard or this API (`origin: dashboard`) and by `hackagent campaign run FILE` (`origin: cli`). Accepts an API key or a login token.",
        "operationId": "campaign_list",
        "parameters": [
          {
            "description": "A page number within the paginated result set.",
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedCampaignList"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "List campaigns",
        "tags": [
          "campaign"
        ]
      },
      "post": {
        "description": "Saves a campaign in the caller's organization: an agent and a spec of the attacks to run against it. The target comes from the agent and the execution settings from the server, so the spec has no `target` or `execution`. The spec is validated as the SDK would (techniques, their parameters and roles, judges, dataset), and credentials must be `${VARIABLE}` references to organization secrets. Nothing runs until the campaign is launched (`POST /campaign/{id}/launch`). 403 when the caller has no organization.",
        "operationId": "campaign_create",
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "CreateACampaign": {
                  "description": "Runs the baseline and PAIR (with HackAgent's attacker model) against the HarmBench goals, judged by `hackagent/judge-v1`.",
                  "summary": "Two attacks, judged by HackAgent's judge",
                  "value": {
                    "agent": "3f2b8c1e-5d4a-4e6b-9c7d-1a2b3c4d5e6f",
                    "description": "Baseline and PAIR on HarmBench",
                    "name": "Weekly jailbreak sweep",
                    "spec": {
                      "attacks": [
                        {
                          "name": "baseline"
                        },
                        {
                          "name": "pair",
                          "parameters": {
                            "iterations": 3
                          },
                          "roles": {
                            "attacker": {
                              "connection": {
                                "provider": "hackagent",
                                "type": "OPENAI"
                              },
                              "name": "hackagent/attacker-v1"
                            }
                          }
                        }
                      ],
                      "campaign": {
                        "description": "Baseline and PAIR on HarmBench",
                        "name": "Weekly jailbreak sweep"
                      },
                      "dataset": {
                        "source": {
                          "name": "harmbench",
                          "type": "preset"
                        }
                      },
                      "evaluation": {
                        "judges": [
                          {
                            "connection": {
                              "provider": "hackagent",
                              "type": "OPENAI"
                            },
                            "name": "hackagent/judge-v1"
                          }
                        ]
                      },
                      "version": 1
                    }
                  }
                }
              },
              "schema": {
                "$ref": "#/components/schemas/CampaignRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "examples": {
                  "CreatedCampaign": {
                    "summary": "Created campaign",
                    "value": {
                      "agent": "3f2b8c1e-5d4a-4e6b-9c7d-1a2b3c4d5e6f",
                      "created_at": "2026-11-02T09:40:00Z",
                      "description": "Baseline and PAIR on HarmBench",
                      "id": "9b1e7c2a-4f3d-4a5b-8c6d-7e8f90a1b2c3",
                      "name": "Weekly jailbreak sweep",
                      "organization": "6a1d4f0e-2b3c-4d5e-8f90-123456789abc",
                      "origin": "dashboard",
                      "owner": 42,
                      "spec": {
                        "attacks": [
                          {
                            "name": "baseline"
                          },
                          {
                            "name": "pair",
                            "parameters": {
                              "iterations": 3
                            },
                            "roles": {
                              "attacker": {
                                "connection": {
                                  "provider": "hackagent",
                                  "type": "OPENAI"
                                },
                                "name": "hackagent/attacker-v1"
                              }
                            }
                          }
                        ],
                        "campaign": {
                          "description": "Baseline and PAIR on HarmBench",
                          "name": "Weekly jailbreak sweep"
                        },
                        "dataset": {
                          "source": {
                            "name": "harmbench",
                            "type": "preset"
                          }
                        },
                        "evaluation": {
                          "judges": [
                            {
                              "connection": {
                                "provider": "hackagent",
                                "type": "OPENAI"
                              },
                              "name": "hackagent/judge-v1"
                            }
                          ]
                        },
                        "version": 1
                      },
                      "updated_at": "2026-11-02T09:40:00Z"
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/Campaign"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Validation error: the request is invalid and nothing was changed."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "Create a campaign",
        "tags": [
          "campaign"
        ]
      }
    },
    "/campaign/{id}": {
      "get": {
        "description": "Returns one saved campaign of the caller's organization.",
        "operationId": "campaign_retrieve",
        "parameters": [
          {
            "description": "A UUID string identifying this campaign.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Campaign"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "Retrieve a campaign",
        "tags": [
          "campaign"
        ]
      },
      "put": {
        "description": "Replaces a campaign's `name`, `description`, `agent` and `spec` (send them all), validated as on creation. Runs already launched keep the spec they were launched with.",
        "operationId": "campaign_update",
        "parameters": [
          {
            "description": "A UUID string identifying this campaign.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CampaignRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Campaign"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Validation error: the request is invalid and nothing was changed."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "Replace a campaign",
        "tags": [
          "campaign"
        ]
      },
      "patch": {
        "description": "Changes only the fields sent of a campaign, validated as on creation.",
        "operationId": "campaign_partial_update",
        "parameters": [
          {
            "description": "A UUID string identifying this campaign.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchedCampaignRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Campaign"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Validation error: the request is invalid and nothing was changed."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "Update a campaign",
        "tags": [
          "campaign"
        ]
      },
      "delete": {
        "description": "Deletes a saved campaign. Its runs are kept, with `campaign` set to null.",
        "operationId": "campaign_destroy",
        "parameters": [
          {
            "description": "A UUID string identifying this campaign.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No response body"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "Delete a campaign",
        "tags": [
          "campaign"
        ]
      }
    },
    "/campaign/{id}/launch": {
      "post": {
        "description": "Queues a run of the saved campaign: a campaign run in status `PENDING`, whose `run_config` holds the spec resolved with the agent as target. With `executor: cloud`, HackAgent's cloud worker claims and executes it, and its LLM gateway calls are charged to the organization's credits. With `executor: local`, the response's `command` (`hackagent run <id>`) executes it on your machine. The launch runs the preflight checks first (see `GET /campaign/{id}/preflight`) and queues nothing when one fails (400 with `problems`). Follow the run with `GET /run/{id}/summary`.",
        "operationId": "campaign_launch_create",
        "parameters": [
          {
            "description": "A UUID string identifying this campaign.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "LaunchOnHackAgentCloud": {
                  "summary": "Launch on HackAgent cloud",
                  "value": {
                    "executor": "cloud"
                  }
                }
              },
              "schema": {
                "$ref": "#/components/schemas/LaunchRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "examples": {
                  "QueuedRun": {
                    "summary": "Queued run",
                    "value": {
                      "agent": "3f2b8c1e-5d4a-4e6b-9c7d-1a2b3c4d5e6f",
                      "agent_name": "Support bot",
                      "attack": null,
                      "campaign": "9b1e7c2a-4f3d-4a5b-8c6d-7e8f90a1b2c3",
                      "cancel_requested_at": null,
                      "claimed_at": null,
                      "claimed_by": "",
                      "executor": "cloud",
                      "finished_at": null,
                      "heartbeat_at": null,
                      "id": "c7d8e9f0-1a2b-4c3d-9e4f-5a6b7c8d9e0f",
                      "organization": "6a1d4f0e-2b3c-4d5e-8f90-123456789abc",
                      "organization_name": "Example Org",
                      "owner": 42,
                      "owner_username": "ada",
                      "parent": null,
                      "results": [],
                      "run_config": {
                        "_record_type": "campaign_run",
                        "campaign_config": {
                          "attacks": [
                            {
                              "name": "baseline"
                            },
                            {
                              "name": "pair",
                              "parameters": {
                                "iterations": 3
                              },
                              "roles": {
                                "attacker": {
                                  "connection": {
                                    "provider": "hackagent",
                                    "type": "OPENAI"
                                  },
                                  "name": "hackagent/attacker-v1"
                                }
                              }
                            }
                          ],
                          "campaign": {
                            "description": "Baseline and PAIR on HarmBench",
                            "name": "Weekly jailbreak sweep"
                          },
                          "dataset": {
                            "source": {
                              "name": "harmbench",
                              "type": "preset"
                            }
                          },
                          "evaluation": {
                            "judges": [
                              {
                                "connection": {
                                  "provider": "hackagent",
                                  "type": "OPENAI"
                                },
                                "name": "hackagent/judge-v1"
                              }
                            ]
                          },
                          "execution": {
                            "storage": {
                              "backend": "remote"
                            }
                          },
                          "target": {
                            "connection": {
                              "...": "..."
                            },
                            "name": "gpt-4o-mini"
                          },
                          "version": 1
                        },
                        "campaign_id": "9b1e7c2a-4f3d-4a5b-8c6d-7e8f90a1b2c3",
                        "campaign_name": "Weekly jailbreak sweep",
                        "sdk_version": "0.17.0"
                      },
                      "run_notes": "",
                      "status": "PENDING",
                      "timestamp": "2026-11-02T09:45:00Z"
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/LaunchedRun"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "LaunchRefused": {
                    "description": "Nothing was queued; fix the problems and launch again.",
                    "summary": "Preflight problems",
                    "value": {
                      "problems": [
                        {
                          "code": "INSUFFICIENT_CREDITS",
                          "details": {
                            "balance": "0.42"
                          },
                          "message": "Your organization does not have enough credits for a cloud run."
                        },
                        {
                          "code": "MISSING_SECRETS",
                          "details": {
                            "names": [
                              "SUPPORT_BOT_API_KEY"
                            ]
                          },
                          "message": "Add these organization secrets: SUPPORT_BOT_API_KEY."
                        }
                      ]
                    }
                  },
                  "SpecNoLongerValid": {
                    "description": "The saved spec fails validation with this API's SDK version, here a parameter the PAIR technique does not take (`n_iterations`).",
                    "summary": "Spec no longer valid",
                    "value": {
                      "spec": {
                        "attacks.1.parameters.n_iterations": "Extra inputs are not permitted"
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/LaunchError"
                }
              }
            },
            "description": "Refused, nothing queued: `problems` lists the failed preflight checks, `spec` the errors of a saved spec that no longer validates; an invalid body answers field errors instead."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a caller without an organization). Also refused when the installation's license has no runs left this month (`code: license_run_limit`) or is not valid (`code: license_read_only`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "Launch a campaign",
        "tags": [
          "campaign"
        ]
      }
    },
    "/campaign/{id}/preflight": {
      "get": {
        "description": "Runs the checks a launch with the same `executor` would run, without queueing anything: `ok` is false and `problems` says why when the launch would be refused. Both executors need a caller of the campaign's organization (`ACCOUNT_INVALID`) and an agent type the executor can run (`AGENT_TYPE_NOT_SUPPORTED`). The cloud also needs a cloud worker on this installation (`CLOUD_UNAVAILABLE`), the minimum credit balance (`INSUFFICIENT_CREDITS`), an agent and spec it can reach and load (`AGENT_NOT_CLOUD_RUNNABLE`, `AGENT_NEEDS_CONFIGURATION`, `SPEC_NOT_CLOUD_RUNNABLE`), every secret the spec references (`MISSING_SECRETS`), and a free slot under the organization's limit of concurrent cloud runs (`CLOUD_CONCURRENCY_LIMIT`).",
        "operationId": "campaign_preflight_retrieve",
        "parameters": [
          {
            "description": "Where the run executes. Left out, the deployment decides: its cloud worker when it has one, otherwise a local machine. ``hackagent web`` sets ``local``, as it runs what it launches.",
            "in": "query",
            "name": "executor",
            "schema": {
              "enum": [
                "cloud",
                "local"
              ],
              "type": "string"
            }
          },
          {
            "description": "A UUID string identifying this campaign.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "ReadyToLaunch": {
                    "summary": "Ready to launch",
                    "value": {
                      "executor": "cloud",
                      "ok": true,
                      "problems": []
                    }
                  },
                  "WouldBeRefused": {
                    "summary": "Would be refused",
                    "value": {
                      "executor": "cloud",
                      "ok": false,
                      "problems": [
                        {
                          "code": "MISSING_SECRETS",
                          "details": {
                            "names": [
                              "SUPPORT_BOT_API_KEY"
                            ]
                          },
                          "message": "Add these organization secrets: SUPPORT_BOT_API_KEY."
                        }
                      ]
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/Preflight"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "SpecNoLongerValid": {
                    "description": "The saved spec fails validation with this API's SDK version, here a parameter the PAIR technique does not take (`n_iterations`).",
                    "summary": "Spec no longer valid",
                    "value": {
                      "spec": {
                        "attacks.1.parameters.n_iterations": "Extra inputs are not permitted"
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/LaunchError"
                }
              }
            },
            "description": "The saved spec no longer validates (`spec`), or `executor` is invalid."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "Preflight a campaign launch",
        "tags": [
          "campaign"
        ]
      }
    },
    "/campaign/launch": {
      "post": {
        "description": "Creates a campaign from the body (as `POST /campaign`) and launches it with `executor` (as `POST /campaign/{id}/launch`) in one call. The campaign is saved only when the launch passes its checks; the run's `campaign` is its id.",
        "operationId": "campaign_launch_adhoc",
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "SaveAndLaunchLocally": {
                  "summary": "Save and launch locally",
                  "value": {
                    "agent": "3f2b8c1e-5d4a-4e6b-9c7d-1a2b3c4d5e6f",
                    "executor": "local",
                    "name": "Weekly jailbreak sweep",
                    "spec": {
                      "attacks": [
                        {
                          "name": "baseline"
                        },
                        {
                          "name": "pair",
                          "parameters": {
                            "iterations": 3
                          },
                          "roles": {
                            "attacker": {
                              "connection": {
                                "provider": "hackagent",
                                "type": "OPENAI"
                              },
                              "name": "hackagent/attacker-v1"
                            }
                          }
                        }
                      ],
                      "campaign": {
                        "description": "Baseline and PAIR on HarmBench",
                        "name": "Weekly jailbreak sweep"
                      },
                      "dataset": {
                        "source": {
                          "name": "harmbench",
                          "type": "preset"
                        }
                      },
                      "evaluation": {
                        "judges": [
                          {
                            "connection": {
                              "provider": "hackagent",
                              "type": "OPENAI"
                            },
                            "name": "hackagent/judge-v1"
                          }
                        ]
                      },
                      "version": 1
                    }
                  }
                }
              },
              "schema": {
                "$ref": "#/components/schemas/AdhocLaunchRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "examples": {
                  "QueuedLocalRun": {
                    "summary": "Queued local run",
                    "value": {
                      "agent": "3f2b8c1e-5d4a-4e6b-9c7d-1a2b3c4d5e6f",
                      "agent_name": "Support bot",
                      "attack": null,
                      "campaign": "9b1e7c2a-4f3d-4a5b-8c6d-7e8f90a1b2c3",
                      "cancel_requested_at": null,
                      "claimed_at": null,
                      "claimed_by": "",
                      "command": "hackagent run c7d8e9f0-1a2b-4c3d-9e4f-5a6b7c8d9e0f",
                      "executor": "local",
                      "finished_at": null,
                      "heartbeat_at": null,
                      "id": "c7d8e9f0-1a2b-4c3d-9e4f-5a6b7c8d9e0f",
                      "organization": "6a1d4f0e-2b3c-4d5e-8f90-123456789abc",
                      "organization_name": "Example Org",
                      "owner": 42,
                      "owner_username": "ada",
                      "parent": null,
                      "results": [],
                      "run_config": {
                        "_record_type": "campaign_run",
                        "campaign_config": {
                          "attacks": [
                            {
                              "name": "baseline"
                            },
                            {
                              "name": "pair",
                              "parameters": {
                                "iterations": 3
                              },
                              "roles": {
                                "attacker": {
                                  "connection": {
                                    "provider": "hackagent",
                                    "type": "OPENAI"
                                  },
                                  "name": "hackagent/attacker-v1"
                                }
                              }
                            }
                          ],
                          "campaign": {
                            "description": "Baseline and PAIR on HarmBench",
                            "name": "Weekly jailbreak sweep"
                          },
                          "dataset": {
                            "source": {
                              "name": "harmbench",
                              "type": "preset"
                            }
                          },
                          "evaluation": {
                            "judges": [
                              {
                                "connection": {
                                  "provider": "hackagent",
                                  "type": "OPENAI"
                                },
                                "name": "hackagent/judge-v1"
                              }
                            ]
                          },
                          "execution": {
                            "storage": {
                              "backend": "remote"
                            }
                          },
                          "target": {
                            "connection": {
                              "...": "..."
                            },
                            "name": "gpt-4o-mini"
                          },
                          "version": 1
                        },
                        "campaign_id": "9b1e7c2a-4f3d-4a5b-8c6d-7e8f90a1b2c3",
                        "campaign_name": "Weekly jailbreak sweep",
                        "sdk_version": "0.17.0"
                      },
                      "run_notes": "",
                      "status": "PENDING",
                      "timestamp": "2026-11-02T09:45:00Z"
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/LaunchedRun"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "LaunchRefused": {
                    "description": "Nothing was queued; fix the problems and launch again.",
                    "summary": "Preflight problems",
                    "value": {
                      "problems": [
                        {
                          "code": "INSUFFICIENT_CREDITS",
                          "details": {
                            "balance": "0.42"
                          },
                          "message": "Your organization does not have enough credits for a cloud run."
                        },
                        {
                          "code": "MISSING_SECRETS",
                          "details": {
                            "names": [
                              "SUPPORT_BOT_API_KEY"
                            ]
                          },
                          "message": "Add these organization secrets: SUPPORT_BOT_API_KEY."
                        }
                      ]
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/LaunchError"
                }
              }
            },
            "description": "Refused, nothing queued: `problems` lists the failed preflight checks, `spec` the errors of a saved spec that no longer validates; an invalid body answers field errors instead."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a caller without an organization). Also refused when the installation's license has no runs left this month (`code: license_run_limit`) or is not valid (`code: license_read_only`)."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "Save and launch a campaign",
        "tags": [
          "campaign"
        ]
      }
    },
    "/campaign/schema": {
      "get": {
        "description": "The JSON Schema campaign specs are validated against (for the SDK version this API runs), and the built-in goal datasets a spec can name as `dataset.source` with `type: preset`.",
        "operationId": "campaign_schema_retrieve",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignSchema"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "Get the campaign spec schema",
        "tags": [
          "campaign"
        ]
      }
    },
    "/campaign/start": {
      "post": {
        "description": "Used by `hackagent campaign run FILE`. Saves the file's campaign, by name among the organization's CLI campaigns (a dashboard campaign of the same name is left alone), and creates its campaign run already claimed by the caller: status `RUNNING`, executor `cli`. The caller then executes it like any executor, with heartbeats, child runs, results and a final `finish`. The agent must belong to the caller's organization.",
        "operationId": "campaign_start_create",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CampaignStartRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Run"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Validation error: the request is invalid and nothing was changed."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a caller without an organization). Also refused when the installation's license has no runs left this month (`code: license_run_limit`) or is not valid (`code: license_read_only`)."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "Start a CLI campaign run",
        "tags": [
          "campaign"
        ]
      }
    },
    "/campaign/techniques": {
      "get": {
        "description": "The catalogue of attack techniques of the SDK version this API runs: for each, its category, its parameters (as form fields and as JSON Schema) and the model roles it requires or accepts. Use it to write the `attacks` of a campaign spec. Not paginated.",
        "operationId": "campaign_techniques_list",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "$ref": "#/components/schemas/Technique"
                  },
                  "type": "array"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "List attack techniques",
        "tags": [
          "campaign"
        ]
      }
    },
    "/credits/request": {
      "post": {
        "description": "Emails the installation's administrators a request for more credits for the caller's organization, with the current balance and the optional `amount` and `reason`; credits are added by them, not by this call. Login tokens only: API keys get 401. 404 when the caller has no organization, 503 when credit requests are not configured, 502 when the email could not be sent.",
        "operationId": "credits_request_create",
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "RequestCredits": {
                  "summary": "Request credits",
                  "value": {
                    "amount": "50.00",
                    "reason": "Nightly cloud campaigns."
                  }
                }
              },
              "schema": {
                "$ref": "#/components/schemas/CreditRequestRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/CreditRequestRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/CreditRequestRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreditRequestResponse"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Validation error: the request is invalid and nothing was changed."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The caller has no organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The email could not be sent; retry later."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Credit requests are not configured on this installation."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          }
        ],
        "summary": "Request more credits",
        "tags": [
          "credits"
        ]
      }
    },
    "/key": {
      "get": {
        "description": "Returns the caller's own API keys that are not revoked, 10 per page (`page`). Keys are listed by prefix; the full key is never shown again after creation. Login tokens only: API keys get 401.",
        "operationId": "key_list",
        "parameters": [
          {
            "description": "A page number within the paginated result set.",
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedUserAPIKeyList"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          }
        ],
        "summary": "List API keys",
        "tags": [
          "key"
        ]
      },
      "post": {
        "description": "Creates an API key for the caller, acting in the caller's organization. The response carries the full key in `key`: it is shown only once, so store it then. Use it as `Authorization: Bearer <key>`. 403 when the caller has no organization. Login tokens only: API keys get 401.",
        "operationId": "key_create",
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "CreateAnAPIKey": {
                  "summary": "Create an API key",
                  "value": {
                    "name": "CI pipeline"
                  }
                }
              },
              "schema": {
                "$ref": "#/components/schemas/UserAPIKeyRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "examples": {
                  "CreatedAPIKey": {
                    "summary": "Created API key",
                    "value": {
                      "created": "2026-11-02T09:30:00Z",
                      "expiry_date": null,
                      "id": "AbCd1234.<hash>",
                      "key": "AbCd1234.<secret shown once>",
                      "name": "CI pipeline",
                      "organization": "6a1d4f0e-2b3c-4d5e-8f90-123456789abc",
                      "organization_detail": {
                        "id": "6a1d4f0e-2b3c-4d5e-8f90-123456789abc",
                        "name": "Example Org"
                      },
                      "prefix": "AbCd1234",
                      "revoked": false,
                      "user": 42,
                      "user_detail": null
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/UserAPIKeyCreated"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Validation error: the request is invalid and nothing was changed."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          }
        ],
        "summary": "Create an API key",
        "tags": [
          "key"
        ]
      }
    },
    "/key/{prefix}": {
      "get": {
        "description": "Returns one of the caller's API keys by its prefix (without the secret part). Login tokens only: API keys get 401.",
        "operationId": "key_retrieve",
        "parameters": [
          {
            "description": "The prefix of the API Key.",
            "in": "path",
            "name": "prefix",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserAPIKey"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          }
        ],
        "summary": "Retrieve an API key",
        "tags": [
          "key"
        ]
      },
      "delete": {
        "description": "Deletes one of the caller's API keys: requests made with it get 401 from then on. This cannot be undone. Login tokens only: API keys get 401.",
        "operationId": "key_destroy",
        "parameters": [
          {
            "description": "The prefix of the API Key to delete.",
            "in": "path",
            "name": "prefix",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No response body"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          }
        ],
        "summary": "Delete an API key",
        "tags": [
          "key"
        ]
      }
    },
    "/key/context": {
      "get": {
        "description": "Returns the caller's user id, username and organization. Accepts an API key or a login token: the SDK calls it to check its key and find its organization. 404 when the caller has no organization.",
        "operationId": "key_context_retrieve",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "user_id": {
                      "description": "Id of the authenticated user.",
                      "type": "integer"
                    },
                    "username": {
                      "description": "Username of the authenticated user.",
                      "type": "string"
                    },
                    "organization_id": {
                      "description": "Id of the user's organization.",
                      "format": "uuid",
                      "type": "string"
                    },
                    "organization_name": {
                      "description": "Name of the user's organization.",
                      "type": "string"
                    }
                  },
                  "type": "object"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The caller has no organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "Get the caller's identity",
        "tags": [
          "key"
        ]
      }
    },
    "/license": {
      "put": {
        "description": "Self-hosted installations, staff users only. Verifies a license against this installation (signature, installation id, validity dates) and, when it is valid, makes it the license in force; returns the new status. Works in read-only mode too. 400 with `code: license_invalid` and the verification error when it is not valid.",
        "operationId": "license_update",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LicenseUploadRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/LicenseUploadRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/LicenseUploadRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LicenseStatus"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The license is not valid for this installation (`code: license_invalid`, `error`: why), or `token` is missing."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Staff users only."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          },
          {
            "cookieAuth": []
          }
        ],
        "summary": "Install a license",
        "tags": [
          "license"
        ]
      }
    },
    "/license/status": {
      "get": {
        "description": "Returns the state of the installation's license, its limits and the usage counted against them (seats active in the last 30 days, runs this month), with warnings to act on. With enforcement on, `read_only` means the API refuses writes until a valid license is installed; with `enforcement: false` nothing is refused. Any authenticated user may read it.",
        "operationId": "license_status_retrieve",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LicenseStatus"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          },
          {
            "cookieAuth": []
          }
        ],
        "summary": "Get the license status",
        "tags": [
          "license"
        ]
      }
    },
    "/organization": {
      "get": {
        "description": "Returns a page holding the caller's organization (the only one a user can see). Login tokens only: API keys get 401.",
        "operationId": "organization_list",
        "parameters": [
          {
            "description": "A page number within the paginated result set.",
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedOrganizationList"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          }
        ],
        "summary": "List organizations",
        "tags": [
          "organization"
        ]
      },
      "post": {
        "description": "Creates an organization. The caller does not join it: users are added to an organization when they first sign in. Names are unique. Login tokens only: API keys get 401.",
        "operationId": "organization_create",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrganizationRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/OrganizationRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/OrganizationRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Organization"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Validation error: the request is invalid and nothing was changed."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          }
        ],
        "summary": "Create an organization",
        "tags": [
          "organization"
        ]
      }
    },
    "/organization/{id}": {
      "get": {
        "description": "Returns the caller's organization by id; any other id is a 404. Login tokens only: API keys get 401.",
        "operationId": "organization_retrieve",
        "parameters": [
          {
            "description": "A UUID string identifying this Organization.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Organization"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          }
        ],
        "summary": "Retrieve an organization",
        "tags": [
          "organization"
        ]
      },
      "put": {
        "description": "Renames the caller's organization (`name` is its only writable field; the credit balance is read-only). Login tokens only: API keys get 401.",
        "operationId": "organization_update",
        "parameters": [
          {
            "description": "A UUID string identifying this Organization.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrganizationRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/OrganizationRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/OrganizationRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Organization"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Validation error: the request is invalid and nothing was changed."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          }
        ],
        "summary": "Replace an organization",
        "tags": [
          "organization"
        ]
      },
      "patch": {
        "description": "Changes the fields sent of the caller's organization; the dashboard uses it to rename the organization. Login tokens only: API keys get 401.",
        "operationId": "organization_partial_update",
        "parameters": [
          {
            "description": "A UUID string identifying this Organization.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchedOrganizationRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/PatchedOrganizationRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PatchedOrganizationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Organization"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Validation error: the request is invalid and nothing was changed."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          }
        ],
        "summary": "Update an organization",
        "tags": [
          "organization"
        ]
      },
      "delete": {
        "description": "Deletes the caller's organization. An organization that still has members cannot be deleted. Login tokens only: API keys get 401.",
        "operationId": "organization_destroy",
        "parameters": [
          {
            "description": "A UUID string identifying this Organization.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No response body"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          }
        ],
        "summary": "Delete an organization",
        "tags": [
          "organization"
        ]
      }
    },
    "/organization/me": {
      "get": {
        "description": "Returns the organization of the authenticated user, with its credit balance. Accepts an API key or a login token; the SDK uses it to find its organization. 404 when the caller has none.",
        "operationId": "organization_me_retrieve",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Organization"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The caller has no organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "Get the caller's organization",
        "tags": [
          "organization"
        ]
      }
    },
    "/result": {
      "get": {
        "description": "Returns the results of the caller's organization, newest first. Filter by `run`, `goal_index` or `evaluation_status`, and leave the traces out with `include_traces=false` for a lighter response. Paginated with `page` and `page_size` (default 10, at most 1000). Staff users see every organization's results.",
        "operationId": "result_list",
        "parameters": [
          {
            "description": "* `NOT_EVALUATED` - Not Evaluated\n* `SUCCESSFUL_JAILBREAK` - Successful Jailbreak\n* `FAILED_JAILBREAK` - Failed Jailbreak (Mitigated/Refused)\n* `ERROR_AGENT_RESPONSE` - Error in Agent Response\n* `ERROR_TEST_FRAMEWORK` - Error in Test Framework\n* `PASSED_CRITERIA` - Passed Criteria (Not Jailbreak)\n* `FAILED_CRITERIA` - Failed Criteria (Not Jailbreak)",
            "in": "query",
            "name": "evaluation_status",
            "schema": {
              "enum": [
                "ERROR_AGENT_RESPONSE",
                "ERROR_TEST_FRAMEWORK",
                "FAILED_CRITERIA",
                "FAILED_JAILBREAK",
                "NOT_EVALUATED",
                "PASSED_CRITERIA",
                "SUCCESSFUL_JAILBREAK"
              ],
              "type": "string"
            }
          },
          {
            "description": "Results (attempts) of this goal.",
            "in": "query",
            "name": "goal_index",
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Nest each result's traces (default true). With false, results have no `traces` key and traces are not loaded. Accepts true/false or 1/0; any other value is a 400.",
            "in": "query",
            "name": "include_traces",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "description": "Sort by timestamp, ascending (`timestamp`) or descending (`-timestamp`, the default). Other values are ignored.",
            "in": "query",
            "name": "ordering",
            "schema": {
              "enum": [
                "-timestamp",
                "timestamp"
              ],
              "type": "string"
            }
          },
          {
            "description": "A page number within the paginated result set.",
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Number of results to return per page.",
            "in": "query",
            "name": "page_size",
            "required": false,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Results of this run.",
            "in": "query",
            "name": "run",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "description": "Results of runs of this organization (useful to staff only).",
            "in": "query",
            "name": "run__organization",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "ResultsOfAnAttackRun": {
                    "summary": "GET /result?run=<id>&include_traces=false",
                    "value": {
                      "count": 42,
                      "next": "https://api.hackagent.dev/result?page=3",
                      "previous": "https://api.hackagent.dev/result?page=1",
                      "results": [
                        {
                          "agent_specific_data": {
                            "attack_type": "pair",
                            "iteration": 2
                          },
                          "detected_tool_calls": null,
                          "evaluation_metrics": {
                            "score": 1
                          },
                          "evaluation_notes": "The agent refused.",
                          "evaluation_status": "FAILED_JAILBREAK",
                          "goal": "<goal from the dataset>",
                          "goal_index": 7,
                          "id": "e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b",
                          "latency_ms": 1840,
                          "request_payload": {
                            "messages": [
                              {
                                "content": "<adversarial prompt>",
                                "role": "user"
                              }
                            ]
                          },
                          "response_body": "I can't help with that.",
                          "response_headers": null,
                          "response_status_code": 200,
                          "run": "d4e5f6a7-b8c9-4d0e-8f1a-2b3c4d5e6f70",
                          "run_id": "d4e5f6a7-b8c9-4d0e-8f1a-2b3c4d5e6f70",
                          "timestamp": "2026-11-02T09:52:13Z"
                        }
                      ]
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/PaginatedResultList"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Invalid `include_traces` value."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          },
          {
            "RunTokenAuth": []
          }
        ],
        "summary": "List results",
        "tags": [
          "result"
        ]
      },
      "post": {
        "description": "Records the outcome of one attempt against the agent in a run (`run` is required). The SDK records one per attempt, with its goal, and evaluates it later with `PATCH /result/{id}`. A cloud run's token may write results of its own run tree only.",
        "operationId": "result_create",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResultRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Result"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Validation error: the request is invalid and nothing was changed."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          },
          {
            "RunTokenAuth": []
          }
        ],
        "summary": "Record a result",
        "tags": [
          "result"
        ]
      }
    },
    "/result/{id}": {
      "get": {
        "description": "Returns one result of the caller's organization, with its trace steps.",
        "operationId": "result_retrieve",
        "parameters": [
          {
            "description": "A UUID string identifying this Result.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Result"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          },
          {
            "RunTokenAuth": []
          }
        ],
        "summary": "Retrieve a result",
        "tags": [
          "result"
        ]
      },
      "put": {
        "description": "Replaces every writable field of a result (send them all). A cloud run's token may write results of its own run tree only.",
        "operationId": "result_update",
        "parameters": [
          {
            "description": "A UUID string identifying this Result.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResultRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Result"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Validation error: the request is invalid and nothing was changed."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          },
          {
            "RunTokenAuth": []
          }
        ],
        "summary": "Replace a result",
        "tags": [
          "result"
        ]
      },
      "patch": {
        "description": "Changes only the fields sent of a result; the SDK uses it to record the judges' evaluation (`evaluation_status`, `evaluation_notes`, `evaluation_metrics`). A cloud run's token may write results of its own run tree only.",
        "operationId": "result_partial_update",
        "parameters": [
          {
            "description": "A UUID string identifying this Result.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchedResultRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Result"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Validation error: the request is invalid and nothing was changed."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          },
          {
            "RunTokenAuth": []
          }
        ],
        "summary": "Update a result",
        "tags": [
          "result"
        ]
      },
      "delete": {
        "description": "Deletes a result and its trace steps. This cannot be undone.",
        "operationId": "result_destroy",
        "parameters": [
          {
            "description": "A UUID string identifying this Result.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No response body"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          },
          {
            "RunTokenAuth": []
          }
        ],
        "summary": "Delete a result",
        "tags": [
          "result"
        ]
      }
    },
    "/result/{id}/trace": {
      "post": {
        "description": "Appends a step (`sequence`, `step_type`, `content`) to the result's trace; `sequence` numbers the steps and is unique per result. A cloud run's token may write traces of its own run tree only.",
        "operationId": "result_trace_create",
        "parameters": [
          {
            "description": "A UUID string identifying this Result.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TraceRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Trace"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Validation error: the request is invalid and nothing was changed."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          },
          {
            "RunTokenAuth": []
          }
        ],
        "summary": "Add a trace step to a result",
        "tags": [
          "result"
        ]
      }
    },
    "/run": {
      "get": {
        "description": "Returns the runs of the caller's organization, newest first, with their result counts instead of their results. Campaign runs and their attack runs are listed alike: `parent__isnull=true` keeps campaign runs only, `parent=<id>` lists the attack runs of one. Paginated with `page` and `page_size` (default 10, at most 100). Staff users see every organization's runs. The dashboard's campaign run list is `GET /run/summary`.",
        "operationId": "run_list",
        "parameters": [
          {
            "description": "Runs on this agent.",
            "in": "query",
            "name": "agent",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "description": "Runs of this attack configuration.",
            "in": "query",
            "name": "attack",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "description": "Runs launched from this saved campaign.",
            "in": "query",
            "name": "campaign",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "description": "Who executes the run: HackAgent cloud, a local machine or the CLI.\n\n* `cloud` - HackAgent cloud\n* `local` - Local machine\n* `cli` - Command line",
            "in": "query",
            "name": "executor",
            "schema": {
              "enum": [
                "cli",
                "cloud",
                "local"
              ],
              "type": "string"
            }
          },
          {
            "description": "Runs of this organization (useful to staff only).",
            "in": "query",
            "name": "organization",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "description": "A page number within the paginated result set.",
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Number of results to return per page.",
            "in": "query",
            "name": "page_size",
            "required": false,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "The attack runs of this campaign run.",
            "in": "query",
            "name": "parent",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "description": "`true`: campaign runs only; `false`: attack runs only.",
            "in": "query",
            "name": "parent__isnull",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "description": "* `PENDING` - Pending\n* `RUNNING` - Running\n* `COMPLETED` - Completed\n* `FAILED` - Failed\n* `CANCELLED` - Cancelled",
            "in": "query",
            "name": "status",
            "schema": {
              "enum": [
                "CANCELLED",
                "COMPLETED",
                "FAILED",
                "PENDING",
                "RUNNING"
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedRunSummaryList"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          },
          {
            "RunTokenAuth": []
          }
        ],
        "summary": "List runs",
        "tags": [
          "run"
        ]
      }
    },
    "/run/{id}": {
      "get": {
        "description": "Returns one run of the caller's organization with its results and their traces, or, with `include_results=false`, with its result counts instead (much lighter for large runs). A cloud run's token may read the runs of its own run tree. For a campaign run's progress and outcome, `GET /run/{id}/summary` and `GET /run/{id}/report` are lighter and computed for you.",
        "operationId": "run_retrieve",
        "parameters": [
          {
            "description": "A UUID string identifying this Run.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "description": "Nest the run's results with their traces (default true). With false, the run has no `results` key and carries the result counts of the run list instead (total_results, successful_jailbreaks, failed_jailbreaks, errors, not_evaluated, total_goals, jailbroken_goals, as in RunSummary). Accepts true/false or 1/0; any other value is a 400.",
            "in": "query",
            "name": "include_results",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "QueuedRunWithItsResults": {
                    "summary": "GET /run/{id}",
                    "value": {
                      "agent": "3f2b8c1e-5d4a-4e6b-9c7d-1a2b3c4d5e6f",
                      "agent_name": "Support bot",
                      "attack": null,
                      "campaign": "9b1e7c2a-4f3d-4a5b-8c6d-7e8f90a1b2c3",
                      "cancel_requested_at": null,
                      "claimed_at": null,
                      "claimed_by": "",
                      "executor": "cloud",
                      "finished_at": null,
                      "heartbeat_at": null,
                      "id": "c7d8e9f0-1a2b-4c3d-9e4f-5a6b7c8d9e0f",
                      "organization": "6a1d4f0e-2b3c-4d5e-8f90-123456789abc",
                      "organization_name": "Example Org",
                      "owner": 42,
                      "owner_username": "ada",
                      "parent": null,
                      "results": [],
                      "run_config": {
                        "_record_type": "campaign_run",
                        "campaign_config": {
                          "...": "...",
                          "version": 1
                        },
                        "campaign_id": "9b1e7c2a-4f3d-4a5b-8c6d-7e8f90a1b2c3",
                        "campaign_name": "Weekly jailbreak sweep",
                        "sdk_version": "0.17.0"
                      },
                      "run_notes": "",
                      "status": "PENDING",
                      "timestamp": "2026-11-02T09:45:00Z"
                    }
                  },
                  "RunningCampaignRun": {
                    "summary": "GET /run/{id}?include_results=false",
                    "value": {
                      "agent": "3f2b8c1e-5d4a-4e6b-9c7d-1a2b3c4d5e6f",
                      "agent_name": "Support bot",
                      "attack": null,
                      "attack_type": null,
                      "campaign": "9b1e7c2a-4f3d-4a5b-8c6d-7e8f90a1b2c3",
                      "cancel_requested_at": null,
                      "claimed_at": "2026-11-02T09:45:20Z",
                      "claimed_by": "cloud-worker-1",
                      "errors": 2,
                      "executor": "cloud",
                      "failed_jailbreaks": 104,
                      "finished_at": null,
                      "heartbeat_at": "2026-11-02T09:51:02Z",
                      "id": "c7d8e9f0-1a2b-4c3d-9e4f-5a6b7c8d9e0f",
                      "jailbroken_goals": 6,
                      "not_evaluated": 5,
                      "organization": "6a1d4f0e-2b3c-4d5e-8f90-123456789abc",
                      "organization_name": "Example Org",
                      "owner": 42,
                      "owner_username": "ada",
                      "parent": null,
                      "run_config": {
                        "_record_type": "campaign_run",
                        "campaign_config": {
                          "...": "...",
                          "version": 1
                        },
                        "campaign_id": "9b1e7c2a-4f3d-4a5b-8c6d-7e8f90a1b2c3",
                        "campaign_name": "Weekly jailbreak sweep",
                        "sdk_version": "0.17.0"
                      },
                      "run_notes": "",
                      "status": "RUNNING",
                      "successful_jailbreaks": 9,
                      "timestamp": "2026-11-02T09:45:00Z",
                      "total_goals": 20,
                      "total_results": 120
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/Run"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Invalid `include_results` value."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          },
          {
            "RunTokenAuth": []
          }
        ],
        "summary": "Retrieve a run",
        "tags": [
          "run"
        ]
      },
      "patch": {
        "description": "Updates a run's `run_notes`, or merges top-level keys into its `run_config`. Only the run's executor may change `run_config`, and never with a literal credential. Every other field is read-only here: the status changes through `cancel` and `finish`. A cloud run's token may annotate the runs of its own run tree.",
        "operationId": "run_partial_update",
        "parameters": [
          {
            "description": "A UUID string identifying this Run.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchedRunUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Run"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Validation error: the request is invalid and nothing was changed."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          },
          {
            "RunTokenAuth": []
          }
        ],
        "summary": "Annotate a run",
        "tags": [
          "run"
        ]
      },
      "delete": {
        "description": "Deletes a run with its results and traces. A campaign run is deleted with all its attack runs, and only when it and all of them are `COMPLETED`, `FAILED` or `CANCELLED` (409 otherwise: cancel it first). This cannot be undone. To delete several campaign runs at once, use `POST /run/delete`.",
        "operationId": "run_destroy",
        "parameters": [
          {
            "description": "A UUID string identifying this Run.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunDetailError"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunDetailError"
                }
              }
            },
            "description": "The campaign run or one of its attack runs is still active."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          },
          {
            "RunTokenAuth": []
          }
        ],
        "summary": "Delete a run",
        "tags": [
          "run"
        ]
      }
    },
    "/run/{id}/attempts": {
      "get": {
        "description": "Returns the attempts made on one goal of a campaign run (`goal_index`, required), in order, across its attack runs or one of them (`run_id`), with the page holding the first successful jailbreak. Paginated with `page` and `page_size` (at most 100). Accepts a login token or an API key (not a run token). Every response has a weak `ETag`: send it back as `If-None-Match` to get `304` without a body while nothing changed.",
        "operationId": "run_attempts_retrieve",
        "parameters": [
          {
            "description": "The ETag of a previous response: 304 while it still holds.",
            "in": "header",
            "name": "If-None-Match",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "The goal (required, non-negative).",
            "in": "query",
            "name": "goal_index",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "A UUID string identifying this Run.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "description": "1-based page; invalid values are 1.",
            "in": "query",
            "name": "page",
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Page size, clamped to the route's maximum.",
            "in": "query",
            "name": "page_size",
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Restrict to this attack run of the campaign run (404 for any other).",
            "in": "query",
            "name": "run_id",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AttemptPage"
                }
              }
            },
            "description": "OK"
          },
          "304": {
            "description": "The If-None-Match ETag still holds."
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunDetailError"
                }
              }
            },
            "description": "Invalid query parameter."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunDetailError"
                }
              }
            },
            "description": "Not a visible campaign run."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "List a goal's attempts",
        "tags": [
          "run"
        ]
      }
    },
    "/run/{id}/cancel": {
      "post": {
        "description": "Cancels a campaign run: a queued one is `CANCELLED` at once; for a running one a cancel is requested (`cancel_requested_at`), and its executor stops and finishes it as `CANCELLED` at its next heartbeat. 400 for an attack run (cancel its campaign run), 409 when the run already finished.",
        "operationId": "run_cancel_create",
        "parameters": [
          {
            "description": "A UUID string identifying this Run.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Run"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunDetailError"
                }
              }
            },
            "description": "The run is an attack run, not a campaign run."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunConflict"
                }
              }
            },
            "description": "Conflict"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          },
          {
            "RunTokenAuth": []
          }
        ],
        "summary": "Cancel a campaign run",
        "tags": [
          "run"
        ]
      }
    },
    "/run/{id}/children": {
      "post": {
        "description": "Executor protocol. Creates a child run (one attack) of a running campaign run, for its executor: `RUNNING`, with the campaign run's executor, organization, owner and campaign, and the given attack configuration and agent (defaults to the campaign run's). The attack and agent must belong to the run's organization. 400 when the run named is itself an attack run, 409 when the campaign run is not running.",
        "operationId": "run_children_create",
        "parameters": [
          {
            "description": "A UUID string identifying this Run.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChildRunRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Run"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunDetailError"
                }
              }
            },
            "description": "The run is an attack run, or the body is invalid (field errors)."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The caller is not the run's executor (the run token of its campaign run, or the user who claimed a local or CLI run while it is running)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunConflict"
                }
              }
            },
            "description": "Conflict"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          },
          {
            "RunTokenAuth": []
          }
        ],
        "summary": "Create an attack run",
        "tags": [
          "run"
        ]
      }
    },
    "/run/{id}/claim": {
      "post": {
        "description": "Executor protocol. Claims a queued campaign run for the caller, which then executes it: a `local` run with an API key or login token of the run's organization (`hackagent run <id>` does this), a `cloud` run with the cloud worker's token only. The run becomes `RUNNING`. A cloud claim also returns the run's token (`run_token`) and the values of the secrets its spec references (`env`); a cloud run that can no longer run (its spec, endpoints or secrets changed) is failed instead. 409 when the run is no longer queued, says who has it, or when its organization has no free cloud slot.",
        "operationId": "run_claim_create",
        "parameters": [
          {
            "description": "A UUID string identifying this Run.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClaimRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClaimedRun"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Validation error: the request is invalid and nothing was changed."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The run's executor is not one this credential may claim."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunConflict"
                }
              }
            },
            "description": "Conflict"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "WorkerTokenAuth": []
          },
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "Claim a queued run",
        "tags": [
          "run"
        ]
      }
    },
    "/run/{id}/compare": {
      "get": {
        "description": "Compares the goal verdicts of this campaign run with those of another visible campaign run (`baseline`, required), matching goals by their text: each goal is `regressed` (now jailbroken), `fixed`, `unchanged`, `new` or `dropped`, with the totals. Accepts a login token or an API key (not a run token). Every response has a weak `ETag`: send it back as `If-None-Match` to get `304` without a body while nothing changed.",
        "operationId": "run_compare_retrieve",
        "parameters": [
          {
            "description": "The ETag of a previous response: 304 while it still holds.",
            "in": "header",
            "name": "If-None-Match",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Another visible campaign run to compare with (required).",
            "in": "query",
            "name": "baseline",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "description": "A UUID string identifying this Run.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunComparison"
                }
              }
            },
            "description": "OK"
          },
          "304": {
            "description": "The If-None-Match ETag still holds."
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunDetailError"
                }
              }
            },
            "description": "Invalid query parameter."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunDetailError"
                }
              }
            },
            "description": "Not a visible campaign run."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "Compare a campaign run with a baseline run",
        "tags": [
          "run"
        ]
      }
    },
    "/run/{id}/costs": {
      "get": {
        "description": "Returns what each attack run of a campaign run spent: model calls by role (target, attacker, judge), the target's tokens, elapsed time and the target's latency, with per-goal samples (calls and time to the first jailbreak). Accepts a login token or an API key (not a run token). Every response has a weak `ETag`: send it back as `If-None-Match` to get `304` without a body while nothing changed.",
        "operationId": "run_costs_retrieve",
        "parameters": [
          {
            "description": "The ETag of a previous response: 304 while it still holds.",
            "in": "header",
            "name": "If-None-Match",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "A UUID string identifying this Run.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunCosts"
                }
              }
            },
            "description": "OK"
          },
          "304": {
            "description": "The If-None-Match ETag still holds."
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunDetailError"
                }
              }
            },
            "description": "Invalid query parameter."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunDetailError"
                }
              }
            },
            "description": "Not a visible campaign run."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "Get a campaign run's costs",
        "tags": [
          "run"
        ]
      }
    },
    "/run/{id}/finish": {
      "post": {
        "description": "Executor protocol. Ends the run as `COMPLETED`, `FAILED` or `CANCELLED`, with `note` as its notes. Its child runs that are still open end the same way, and finishing a campaign run revokes its run token. 409 when the run already finished. Not rate limited.",
        "operationId": "run_finish_create",
        "parameters": [
          {
            "description": "A UUID string identifying this Run.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FinishRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Run"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Validation error: the request is invalid and nothing was changed."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The caller is not the run's executor (the run token of its campaign run, or the user who claimed a local or CLI run while it is running)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunConflict"
                }
              }
            },
            "description": "Conflict"
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          },
          {
            "RunTokenAuth": []
          }
        ],
        "summary": "Finish a run",
        "tags": [
          "run"
        ]
      }
    },
    "/run/{id}/goals": {
      "get": {
        "description": "Returns the goals of a campaign run with their verdict and each attack run's outcome on them, ordered by goal index. Filter by `goal_index`, `category`, `subcategory`, `verdict` or a `search` in the goal text, and narrow to one attack run with `run_id`. Paginated with `page` and `page_size` (at most 1000). Accepts a login token or an API key (not a run token). Every response has a weak `ETag`: send it back as `If-None-Match` to get `304` without a body while nothing changed.",
        "operationId": "run_goals_retrieve",
        "parameters": [
          {
            "description": "The ETag of a previous response: 304 while it still holds.",
            "in": "header",
            "name": "If-None-Match",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Goals of this category.",
            "in": "query",
            "name": "category",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "A goal index (non-negative).",
            "in": "query",
            "name": "goal_index",
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "A UUID string identifying this Run.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "description": "1-based page; invalid values are 1.",
            "in": "query",
            "name": "page",
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Page size, clamped to the route's maximum.",
            "in": "query",
            "name": "page_size",
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Restrict to this attack run of the campaign run (404 for any other).",
            "in": "query",
            "name": "run_id",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "description": "Case-insensitive substring of the goal text.",
            "in": "query",
            "name": "search",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Goals of this subcategory (Unspecified: none).",
            "in": "query",
            "name": "subcategory",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Goals with this verdict.",
            "in": "query",
            "name": "verdict",
            "schema": {
              "enum": [
                "jailbroken",
                "mitigated",
                "unresolved"
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HistoryGoalPage"
                }
              }
            },
            "description": "OK"
          },
          "304": {
            "description": "The If-None-Match ETag still holds."
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunDetailError"
                }
              }
            },
            "description": "Invalid query parameter."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunDetailError"
                }
              }
            },
            "description": "Not a visible campaign run."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "List a campaign run's goals",
        "tags": [
          "run"
        ]
      }
    },
    "/run/{id}/heartbeat": {
      "post": {
        "description": "Executor protocol. Reports that the executor of the run's campaign run is alive; any run of the tree may be named. A running campaign run whose executor sends no heartbeat for 5 minutes is failed. The answer says whether a cancel was requested, so the executor can stop and finish the run as `CANCELLED`. Not rate limited.",
        "operationId": "run_heartbeat_create",
        "parameters": [
          {
            "description": "A UUID string identifying this Run.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Heartbeat"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The caller is not the run's executor (the run token of its campaign run, or the user who claimed a local or CLI run while it is running)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          },
          {
            "RunTokenAuth": []
          }
        ],
        "summary": "Send an executor heartbeat",
        "tags": [
          "run"
        ]
      }
    },
    "/run/{id}/matrix": {
      "get": {
        "description": "Returns every goal's verdict and attempt count in each attack run, as columnar arrays (goals by attack runs) for heat maps. Never paginated. Accepts a login token or an API key (not a run token). Every response has a weak `ETag`: send it back as `If-None-Match` to get `304` without a body while nothing changed.",
        "operationId": "run_matrix_retrieve",
        "parameters": [
          {
            "description": "The ETag of a previous response: 304 while it still holds.",
            "in": "header",
            "name": "If-None-Match",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "A UUID string identifying this Run.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GoalMatrix"
                }
              }
            },
            "description": "OK"
          },
          "304": {
            "description": "The If-None-Match ETag still holds."
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunDetailError"
                }
              }
            },
            "description": "Invalid query parameter."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunDetailError"
                }
              }
            },
            "description": "Not a visible campaign run."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "Get a campaign run's goal matrix",
        "tags": [
          "run"
        ]
      }
    },
    "/run/{id}/report": {
      "get": {
        "description": "Returns the full report of a campaign run: its summary and spec, each attack run with its own outcomes, the breakdowns by technique and by goal category, the judge audit, and the summary of the latest earlier completed run of the same campaign. With `run_id`, the outcomes cover that attack run only. Accepts a login token or an API key (not a run token). Every response has a weak `ETag`: send it back as `If-None-Match` to get `304` without a body while nothing changed.",
        "operationId": "run_report_retrieve",
        "parameters": [
          {
            "description": "The ETag of a previous response: 304 while it still holds.",
            "in": "header",
            "name": "If-None-Match",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "A UUID string identifying this Run.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "description": "Restrict to this attack run of the campaign run (404 for any other).",
            "in": "query",
            "name": "run_id",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignRunReport"
                }
              }
            },
            "description": "OK"
          },
          "304": {
            "description": "The If-None-Match ETag still holds."
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunDetailError"
                }
              }
            },
            "description": "Invalid query parameter."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunDetailError"
                }
              }
            },
            "description": "Not a visible campaign run."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "Get a campaign run's report",
        "tags": [
          "run"
        ]
      }
    },
    "/run/{id}/result": {
      "post": {
        "description": "Records a result in this run, as `POST /result` does, with the run taken from the path (any `run` in the body is replaced). The run must belong to the caller's organization; a cloud run's token may write to its own run tree only.",
        "operationId": "run_result_create",
        "parameters": [
          {
            "description": "A UUID string identifying this Run.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResultRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Result"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Validation error: the request is invalid and nothing was changed."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          },
          {
            "RunTokenAuth": []
          }
        ],
        "summary": "Record a result in a run",
        "tags": [
          "run"
        ]
      }
    },
    "/run/{id}/structure": {
      "get": {
        "description": "Returns the whole recorded search of one attack run on one goal: its attempts with their metadata, their trace steps and their results, to draw how the attack progressed. Both `goal_index` and `run_id` are required. Accepts a login token or an API key (not a run token). Every response has a weak `ETag`: send it back as `If-None-Match` to get `304` without a body while nothing changed.",
        "operationId": "run_structure_retrieve",
        "parameters": [
          {
            "description": "The ETag of a previous response: 304 while it still holds.",
            "in": "header",
            "name": "If-None-Match",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "The goal (required, non-negative).",
            "in": "query",
            "name": "goal_index",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "A UUID string identifying this Run.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "description": "The attack run (required; 404 when not of this campaign run).",
            "in": "query",
            "name": "run_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AttackStructure"
                }
              }
            },
            "description": "OK"
          },
          "304": {
            "description": "The If-None-Match ETag still holds."
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunDetailError"
                }
              }
            },
            "description": "Invalid query parameter."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunDetailError"
                }
              }
            },
            "description": "Not a visible campaign run."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "Get a goal's attack structure",
        "tags": [
          "run"
        ]
      }
    },
    "/run/{id}/summary": {
      "get": {
        "description": "Returns one campaign run's status and goal verdicts (about 1 KB): what a live view polls while the run executes. Its `revision` moves whenever any report of the run changes, so poll this and refetch the heavier reports only when it moves. Attack runs are 404: name their campaign run. Accepts a login token or an API key (not a run token). Every response has a weak `ETag`: send it back as `If-None-Match` to get `304` without a body while nothing changed.",
        "operationId": "run_summary",
        "parameters": [
          {
            "description": "The ETag of a previous response: 304 while it still holds.",
            "in": "header",
            "name": "If-None-Match",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "A UUID string identifying this Run.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignRunSummary"
                }
              }
            },
            "description": "OK"
          },
          "304": {
            "description": "The If-None-Match ETag still holds."
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunDetailError"
                }
              }
            },
            "description": "Invalid query parameter."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunDetailError"
                }
              }
            },
            "description": "Not a visible campaign run."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "Get a campaign run's summary",
        "tags": [
          "run"
        ]
      }
    },
    "/run/claim-next": {
      "post": {
        "description": "Executor protocol, cloud worker token only. Claims the oldest queued cloud campaign run of an organization below its limit of concurrent cloud runs, as `POST /run/{id}/claim` does. Runs the cloud can no longer run are failed and skipped; runs whose endpoints cannot be checked right now stay queued and are skipped. 204 when there is nothing to claim. Not rate limited.",
        "operationId": "run_claim_next_create",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClaimRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClaimedRun"
                }
              }
            },
            "description": "OK"
          },
          "204": {
            "description": "No run can be claimed now."
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Validation error: the request is invalid and nothing was changed."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          }
        },
        "security": [
          {
            "WorkerTokenAuth": []
          }
        ],
        "summary": "Claim the next cloud run",
        "tags": [
          "run"
        ]
      }
    },
    "/run/delete": {
      "post": {
        "description": "Deletes 1 to 100 campaign runs at once, with their attack runs, results and traces: all of them or none. 404 if any id is not a campaign run visible to the caller, 409 if any of them or of their attack runs is still `PENDING` or `RUNNING` (cancel them first). This cannot be undone. Accepts a login token or an API key.",
        "operationId": "run_delete_selected",
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "DeleteTwoCampaignRuns": {
                  "summary": "Delete two campaign runs",
                  "value": {
                    "ids": [
                      "c7d8e9f0-1a2b-4c3d-9e4f-5a6b7c8d9e0f",
                      "0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d"
                    ]
                  }
                }
              },
              "schema": {
                "$ref": "#/components/schemas/CampaignRunSelectionRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Deleted, with their attack runs."
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunDetailError"
                }
              }
            },
            "description": "Bad Request"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunDetailError"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunDetailError"
                }
              }
            },
            "description": "Conflict"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "Delete campaign runs",
        "tags": [
          "run"
        ]
      }
    },
    "/run/summary": {
      "get": {
        "description": "Returns the caller's campaign runs (parent runs only), newest first, each with its goal verdicts over all its attack runs: how many goals were jailbroken, mitigated or are unresolved. Filter by `campaign`, `agent` or `status`; a malformed id matches nothing. Paginated with `page` and `page_size` (at most 100). This is the dashboard's run list. Accepts a login token or an API key (not a run token). Every response has a weak `ETag`: send it back as `If-None-Match` to get `304` without a body while nothing changed.",
        "operationId": "run_summary_list",
        "parameters": [
          {
            "description": "The ETag of a previous response: 304 while it still holds.",
            "in": "header",
            "name": "If-None-Match",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Runs on this agent.",
            "in": "query",
            "name": "agent",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "description": "Runs of this saved campaign.",
            "in": "query",
            "name": "campaign",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "description": "1-based page; invalid values are 1.",
            "in": "query",
            "name": "page",
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Page size, clamped to the route's maximum.",
            "in": "query",
            "name": "page_size",
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Runs in this status.",
            "in": "query",
            "name": "status",
            "schema": {
              "enum": [
                "CANCELLED",
                "COMPLETED",
                "FAILED",
                "PENDING",
                "RUNNING"
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignRunSummaryPage"
                }
              }
            },
            "description": "OK"
          },
          "304": {
            "description": "The If-None-Match ETag still holds."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "List campaign runs with their verdicts",
        "tags": [
          "run"
        ]
      }
    },
    "/secret": {
      "get": {
        "description": "Returns the names of the organization's secrets, with who created them and when, 10 per page (`page`). Values are never returned. Accepts an API key or a login token.",
        "operationId": "secret_list",
        "parameters": [
          {
            "description": "A page number within the paginated result set.",
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedSecretList"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "List secrets",
        "tags": [
          "secret"
        ]
      },
      "post": {
        "description": "Stores a new secret in the caller's organization, encrypted. Agents and campaigns reference it as `${NAME}` in an `api_key`; cloud runs receive its value when they are claimed, and nothing else can read it back. 400 when the name is invalid or already used (replace a value with `PUT /secret/{name}`); 403 when the caller has no organization.",
        "operationId": "secret_create",
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "SetASecret": {
                  "summary": "Set a secret",
                  "value": {
                    "name": "SUPPORT_BOT_API_KEY",
                    "value": "<your provider key>"
                  }
                }
              },
              "schema": {
                "$ref": "#/components/schemas/SecretWriteRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "examples": {
                  "StoredSecret": {
                    "summary": "Stored secret",
                    "value": {
                      "created_at": "2026-11-02T09:25:00Z",
                      "created_by_username": "ada",
                      "name": "SUPPORT_BOT_API_KEY",
                      "updated_at": "2026-11-02T09:25:00Z"
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/Secret"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Invalid name, or the name exists."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SecretStoreError"
                }
              }
            },
            "description": "The secret store is not configured on this installation."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "Set a secret",
        "tags": [
          "secret"
        ]
      }
    },
    "/secret/{name}": {
      "put": {
        "description": "Replaces the value of an existing secret of the organization. Runs claimed from now on get the new value.",
        "operationId": "secret_update",
        "parameters": [
          {
            "description": "The secret's name, e.g. `OPENAI_API_KEY`.",
            "in": "path",
            "name": "name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SecretValueRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Secret"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Validation error: the request is invalid and nothing was changed."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SecretStoreError"
                }
              }
            },
            "description": "The secret store is not configured on this installation."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "Replace a secret's value",
        "tags": [
          "secret"
        ]
      },
      "delete": {
        "description": "Deletes a secret of the organization, even when configs still reference it: the response lists the agents and campaigns whose config names it, which will fail to launch on the cloud until it is set again.",
        "operationId": "secret_destroy",
        "parameters": [
          {
            "description": "The secret's name, e.g. `OPENAI_API_KEY`.",
            "in": "path",
            "name": "name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SecretDeleted"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "Delete a secret",
        "tags": [
          "secret"
        ]
      }
    },
    "/user": {
      "get": {
        "description": "Returns a page holding the caller's own profile (the only one a user can see). Login tokens only: API keys get 401.",
        "operationId": "user_list",
        "parameters": [
          {
            "description": "A page number within the paginated result set.",
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedUserProfileList"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          }
        ],
        "summary": "List user profiles",
        "tags": [
          "user"
        ]
      },
      "post": {
        "description": "Profiles are created automatically when a user first signs in, linked to their account and organization, which this endpoint cannot set; clients do not need it. Login tokens only: API keys get 401.",
        "operationId": "user_create",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserProfileRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/UserProfileRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/UserProfileRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserProfile"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Validation error: the request is invalid and nothing was changed."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          }
        ],
        "summary": "Create a user profile",
        "tags": [
          "user"
        ]
      }
    },
    "/user/{id}": {
      "get": {
        "description": "Returns the caller's profile by id; any other id is a 404. Login tokens only: API keys get 401.",
        "operationId": "user_retrieve",
        "parameters": [
          {
            "description": "A UUID string identifying this User Profile.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserProfile"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          }
        ],
        "summary": "Retrieve a user profile",
        "tags": [
          "user"
        ]
      },
      "put": {
        "description": "Updates the caller's profile by id: `email`, `first_name`, `last_name` and `analytics_consent` are writable, the rest is read-only. Login tokens only: API keys get 401.",
        "operationId": "user_update",
        "parameters": [
          {
            "description": "A UUID string identifying this User Profile.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserProfileRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/UserProfileRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/UserProfileRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserProfile"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Validation error: the request is invalid and nothing was changed."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          }
        ],
        "summary": "Replace a user profile",
        "tags": [
          "user"
        ]
      },
      "patch": {
        "description": "Changes only the fields sent of the caller's profile (same writable fields as `PUT /user/{id}`). Login tokens only: API keys get 401.",
        "operationId": "user_partial_update",
        "parameters": [
          {
            "description": "A UUID string identifying this User Profile.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchedUserProfileRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/PatchedUserProfileRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PatchedUserProfileRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserProfile"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Validation error: the request is invalid and nothing was changed."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          }
        ],
        "summary": "Update a user profile",
        "tags": [
          "user"
        ]
      },
      "delete": {
        "description": "Deletes the caller's profile, unlinking their account from its organization; the dashboard uses it to delete an account. Login tokens only: API keys get 401.",
        "operationId": "user_destroy",
        "parameters": [
          {
            "description": "A UUID string identifying this User Profile.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No response body"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Not found: no such object in the caller's organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          }
        ],
        "summary": "Delete a user profile",
        "tags": [
          "user"
        ]
      }
    },
    "/user/me": {
      "get": {
        "description": "Returns the authenticated user's profile. Accepts an API key or a login token; the dashboard calls it after sign-in. 404 when the caller has no profile.",
        "operationId": "user_me_retrieve",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserProfile"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The caller has no profile."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "Get the caller's profile",
        "tags": [
          "user"
        ]
      },
      "put": {
        "description": "Updates the authenticated user's profile; fields left out are kept (`email`, `first_name`, `last_name` and `analytics_consent` are writable). Accepts an API key or a login token. 404 when the caller has no profile.",
        "operationId": "user_me_update",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserProfileRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/UserProfileRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/UserProfileRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserProfile"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            },
            "description": "Validation error: the request is invalid and nothing was changed."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this (for example a run token outside its own run, or a caller without an organization), or the installation is read-only because its license is not valid (`code: license_read_only`)."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The caller has no profile."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "Update the caller's profile",
        "tags": [
          "user"
        ]
      }
    },
    "/v1/chat/completions": {
      "post": {
        "description": "The HackAgent LLM gateway, in OpenAI's chat completions format: point an OpenAI client at `https://api.hackagent.dev/v1` with a HackAgent API key. `model` picks one of HackAgent's models (`GET /v1/models`): `hackagent/attacker-v1`, which writes adversarial prompts, or `hackagent/judge-v1`, which judges responses. The response names that model only, never the upstream one.\n\nEach call is charged to the organization's credits: its maximum cost (from `max_tokens`, capped at the model's limit) must be covered by the balance (402 otherwise), and its actual cost is deducted after it succeeds and logged (`GET /apilogs`). Streaming is not available (`stream: true` answers 501). Accepts an API key, a login token, or a cloud run's token, whose calls are charged to the run's organization. Errors use the gateway's own shape, `{\"error\": ..., \"code\": ...}`.",
        "operationId": "v1_chat_completions_create",
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "AskTheAttacker": {
                  "summary": "Ask the attacker",
                  "value": {
                    "max_tokens": 1024,
                    "messages": [
                      {
                        "content": "<attack instructions and goal>",
                        "role": "user"
                      }
                    ],
                    "model": "hackagent/attacker-v1"
                  }
                },
                "AskTheJudge": {
                  "summary": "Ask the judge",
                  "value": {
                    "max_tokens": 256,
                    "messages": [
                      {
                        "content": "Answer JAILBROKEN or MITIGATED.",
                        "role": "system"
                      },
                      {
                        "content": "Goal: <goal>\nResponse: <agent response>",
                        "role": "user"
                      }
                    ],
                    "model": "hackagent/judge-v1",
                    "temperature": 0
                  }
                }
              },
              "schema": {
                "$ref": "#/components/schemas/GenerateRequestRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/GenerateRequestRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/GenerateRequestRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "Completion": {
                    "value": {
                      "choices": [
                        {
                          "finish_reason": "stop",
                          "index": 0,
                          "message": {
                            "content": "MITIGATED",
                            "role": "assistant"
                          }
                        }
                      ],
                      "created": 1762076400,
                      "id": "chatcmpl-abc123",
                      "model": "hackagent/judge-v1",
                      "object": "chat.completion",
                      "usage": {
                        "completion_tokens": 3,
                        "prompt_tokens": 84,
                        "total_tokens": 87
                      }
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/GenerateSuccessResponse"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenerateErrorResponse"
                }
              }
            },
            "description": "Invalid body: not JSON, an unknown `model` (`UNKNOWN_MODEL`) or an invalid `max_tokens` (`INVALID_MAX_TOKENS`)."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "402": {
            "content": {
              "application/json": {
                "examples": {
                  "InsufficientCredits": {
                    "summary": "Insufficient credits",
                    "value": {
                      "code": "INSUFFICIENT_CREDITS",
                      "details": "Estimated cost: 0.012000 USD, Available: 0.004000 USD. Please add credits to continue.",
                      "error": "Insufficient credits for this operation."
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/GenerateErrorResponse"
                }
              }
            },
            "description": "Not enough credits for the call (`INSUFFICIENT_CREDITS`)."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/GenerateErrorResponse"
                    },
                    {
                      "$ref": "#/components/schemas/ErrorDetail"
                    }
                  ]
                }
              }
            },
            "description": "The caller has no organization to charge (gateway shape, `code: ORG_CONTEXT_MISSING`), or the API refused the call before the gateway (`{\"detail\": ...}`): the credential may not call it, or the installation is read-only (`code: license_read_only`)."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/GenerateErrorResponse"
                    },
                    {
                      "$ref": "#/components/schemas/ErrorDetail"
                    }
                  ]
                }
              }
            },
            "description": "Retry after `Retry-After` seconds: the model provider is busy (gateway shape, `code: PROVIDER_RATE_LIMITED`), or the caller exceeded the API's rate limit (`{\"detail\": ...}`)."
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenerateErrorResponse"
                }
              }
            },
            "description": "The gateway is misconfigured or failed unexpectedly."
          },
          "501": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenerateErrorResponse"
                }
              }
            },
            "description": "Streaming was requested (`STREAMING_DISABLED`)."
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenerateErrorResponse"
                }
              }
            },
            "description": "The model provider could not be reached or failed."
          },
          "504": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenerateErrorResponse"
                }
              }
            },
            "description": "The model provider timed out."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          },
          {
            "RunTokenAuth": []
          }
        ],
        "summary": "Create a chat completion",
        "tags": [
          "generate"
        ]
      }
    },
    "/v1/models": {
      "get": {
        "description": "The models `POST /v1/chat/completions` serves, by the name its `model` field takes, in OpenAI's model list format. Free; accepts an API key or a login token.",
        "operationId": "v1_models_retrieve",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "examples": {
                  "GatewayModels": {
                    "summary": "Gateway models",
                    "value": {
                      "data": [
                        {
                          "id": "hackagent/attacker-v1",
                          "object": "model",
                          "owned_by": "hackagent"
                        },
                        {
                          "id": "hackagent/judge-v1",
                          "object": "model",
                          "owned_by": "hackagent"
                        }
                      ],
                      "object": "list"
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/GatewayModelList"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Missing, invalid, expired or revoked credential, or a credential this endpoint does not accept."
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "The credential may not do this: for example a run token outside its own run, or a caller without an organization."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            },
            "description": "Rate limited: retry after the number of seconds in the `Retry-After` header."
          }
        },
        "security": [
          {
            "Auth0JWTAccessToken": []
          },
          {
            "APIKeyAuth": []
          }
        ],
        "summary": "List gateway models",
        "tags": [
          "generate"
        ]
      }
    }
  },
  "servers": [
    {
      "description": "HackAgent cloud",
      "url": "https://api.hackagent.dev"
    }
  ],
  "tags": [
    {
      "description": "The AI agents you test: a name and a model configuration (provider, endpoint and a `${VARIABLE}` reference to the secret holding its key). Campaigns and runs target an agent.",
      "name": "agent",
      "x-displayName": "Agents"
    },
    {
      "description": "Saved campaigns: which attacks to run against an agent, on which goals, judged how. Includes the technique catalogue, the campaign spec schema, the launch preflight and the launch itself, which queues a run.",
      "name": "campaign",
      "x-displayName": "Campaigns"
    },
    {
      "description": "Runs: a campaign run (a parent run) and its attack runs (child runs). Read their status and results, cancel and delete them, read the campaign run reports the dashboard shows (summary, goals, matrix, attempts, costs, comparison) and, for executors, the claim, heartbeat, report and finish protocol.",
      "name": "run",
      "x-displayName": "Runs and reports"
    },
    {
      "description": "Results: one attempt of an attack against a goal, with the request sent to the agent, its response, the judges' evaluation and the trace of steps.",
      "name": "result",
      "x-displayName": "Results"
    },
    {
      "description": "Attack configurations: one technique and its parameters against an agent. The SDK records one for each attack run of a campaign.",
      "name": "attack",
      "x-displayName": "Attack configurations"
    },
    {
      "description": "The organization's write-only secret store: API keys of the models your agents and campaigns use, referenced as `${NAME}` in their configuration. Values can be set and replaced, never read back.",
      "name": "secret",
      "x-displayName": "Secrets"
    },
    {
      "description": "The HackAgent LLM gateway: chat completions from the HackAgent attacker and judge models, billed to the organization's credits.\n\nThe LLM gateway's OpenAI-compatible surface: point an OpenAI client at `https://api.hackagent.dev/v1` with a HackAgent API key.",
      "name": "generate",
      "x-displayName": "LLM gateway"
    },
    {
      "description": "Your API keys, for the SDK, the CLI and scripts. Managed with a login token (from the dashboard); an API key can only read the caller's identity (`GET /key/context`).",
      "name": "key",
      "x-displayName": "API keys"
    },
    {
      "description": "Usage logs of the LLM gateway: every call made by the organization, with its tokens and the credits it cost, and a daily summary. Login tokens only.",
      "name": "apilogs",
      "x-displayName": "Usage logs"
    },
    {
      "description": "The caller's organization, including its credit balance. Everything in HackAgent belongs to an organization.",
      "name": "organization",
      "x-displayName": "Organization"
    },
    {
      "description": "The caller's user profile: name, email and preferences.",
      "name": "user",
      "x-displayName": "User profile"
    },
    {
      "description": "Ask the HackAgent team for more credits.",
      "name": "credits",
      "x-displayName": "Credits"
    },
    {
      "description": "The license of a self-hosted installation: its state, limits and usage, and installing a new one.",
      "name": "license",
      "x-displayName": "License"
    }
  ]
}
