From dbeebc4b368824c137f489e60b319795450cba6f Mon Sep 17 00:00:00 2001 From: Lev Neiman Date: Thu, 19 Mar 2026 18:06:51 -0700 Subject: [PATCH 1/5] fix: create controls atomically with optional data --- models/src/agent_control_models/server.py | 4 + sdks/python/src/agent_control/controls.py | 19 +- .../src/generated/funcs/controls-create.ts | 6 +- .../models/create-control-request.ts | 11 + sdks/typescript/src/generated/sdk/controls.ts | 6 +- .../endpoints/controls.py | 42 +- server/tests/test_controls.py | 49 + ui/src/core/api/generated/api-types.ts | 9480 ++++++++--------- .../query-hooks/use-add-control-to-agent.ts | 25 +- .../hooks/query-hooks/use-create-control.ts | 19 +- 10 files changed, 4843 insertions(+), 4818 deletions(-) diff --git a/models/src/agent_control_models/server.py b/models/src/agent_control_models/server.py index cdc48cdc..8c7ced01 100644 --- a/models/src/agent_control_models/server.py +++ b/models/src/agent_control_models/server.py @@ -119,6 +119,10 @@ class CreateControlRequest(BaseModel): ..., description="Unique control name (letters, numbers, hyphens, underscores)", ) + data: ControlDefinition | None = Field( + default=None, + description="Optional control definition to validate and store during creation", + ) class InitAgentRequest(BaseModel): diff --git a/sdks/python/src/agent_control/controls.py b/sdks/python/src/agent_control/controls.py index 1305fca4..1994fe68 100644 --- a/sdks/python/src/agent_control/controls.py +++ b/sdks/python/src/agent_control/controls.py @@ -170,22 +170,21 @@ async def create_control( ) print(f"Created and configured control: {result['control_id']}") """ - # Step 1: Create the control with name + payload: dict[str, Any] = {"name": name} + if data is not None: + if isinstance(data, ControlDefinition): + payload["data"] = data.model_dump(mode="json", exclude_none=True) + else: + payload["data"] = cast(dict[str, Any], data) + response = await client.http_client.put( "/api/v1/controls", - json={"name": name} + json=payload, ) response.raise_for_status() result = cast(dict[str, Any], response.json()) - # Step 2: If data provided, configure the control - if data is not None: - control_id = result["control_id"] - await set_control_data(client, control_id, data) - result["configured"] = True - else: - result["configured"] = False - + result["configured"] = data is not None return result diff --git a/sdks/typescript/src/generated/funcs/controls-create.ts b/sdks/typescript/src/generated/funcs/controls-create.ts index 05cf703a..380f1c17 100644 --- a/sdks/typescript/src/generated/funcs/controls-create.ts +++ b/sdks/typescript/src/generated/funcs/controls-create.ts @@ -30,13 +30,13 @@ import { Result } from "../types/fp.js"; * Create a new control * * @remarks - * Create a new control with a unique name and empty data. + * Create a new control with a unique name. * * Controls define protection logic and can be added to policies. - * Use the PUT /{control_id}/data endpoint to set control configuration. + * Optionally provide control data to validate and persist it atomically. * * Args: - * request: Control creation request with unique name + * request: Control creation request with unique name and optional data * db: Database session (injected) * * Returns: diff --git a/sdks/typescript/src/generated/models/create-control-request.ts b/sdks/typescript/src/generated/models/create-control-request.ts index 925b2aee..0cb5e0bc 100644 --- a/sdks/typescript/src/generated/models/create-control-request.ts +++ b/sdks/typescript/src/generated/models/create-control-request.ts @@ -3,8 +3,17 @@ */ import * as z from "zod/v4-mini"; +import { + ControlDefinitionInput, + ControlDefinitionInput$Outbound, + ControlDefinitionInput$outboundSchema, +} from "./control-definition-input.js"; export type CreateControlRequest = { + /** + * Optional control definition to validate and store during creation + */ + data?: ControlDefinitionInput | null | undefined; /** * Unique control name (letters, numbers, hyphens, underscores) */ @@ -13,6 +22,7 @@ export type CreateControlRequest = { /** @internal */ export type CreateControlRequest$Outbound = { + data?: ControlDefinitionInput$Outbound | null | undefined; name: string; }; @@ -21,6 +31,7 @@ export const CreateControlRequest$outboundSchema: z.ZodMiniType< CreateControlRequest$Outbound, CreateControlRequest > = z.object({ + data: z.optional(z.nullable(ControlDefinitionInput$outboundSchema)), name: z.string(), }); diff --git a/sdks/typescript/src/generated/sdk/controls.ts b/sdks/typescript/src/generated/sdk/controls.ts index c32be744..7d94a8d2 100644 --- a/sdks/typescript/src/generated/sdk/controls.ts +++ b/sdks/typescript/src/generated/sdk/controls.ts @@ -56,13 +56,13 @@ export class Controls extends ClientSDK { * Create a new control * * @remarks - * Create a new control with a unique name and empty data. + * Create a new control with a unique name. * * Controls define protection logic and can be added to policies. - * Use the PUT /{control_id}/data endpoint to set control configuration. + * Optionally provide control data to validate and persist it atomically. * * Args: - * request: Control creation request with unique name + * request: Control creation request with unique name and optional data * db: Database session (injected) * * Returns: diff --git a/server/src/agent_control_server/endpoints/controls.py b/server/src/agent_control_server/endpoints/controls.py index a8ab1354..1f32b0c2 100644 --- a/server/src/agent_control_server/endpoints/controls.py +++ b/server/src/agent_control_server/endpoints/controls.py @@ -81,6 +81,21 @@ def _iter_condition_leaves( yield from _iter_condition_leaves(node.not_, path=f"{path}.not") +def _serialize_control_definition(control_def: ControlDefinition) -> dict[str, object]: + """Serialize control data for storage while omitting null scope fields.""" + data_json = control_def.model_dump( + mode="json", + by_alias=True, + exclude_none=True, + exclude_unset=True, + ) + if "scope" in data_json and isinstance(data_json["scope"], dict): + data_json["scope"] = { + k: v for k, v in data_json["scope"].items() if v is not None + } + return data_json + + async def _validate_control_definition( control_def: ControlDefinition, db: AsyncSession ) -> None: @@ -252,13 +267,13 @@ async def create_control( request: CreateControlRequest, db: AsyncSession = Depends(get_async_db) ) -> CreateControlResponse: """ - Create a new control with a unique name and empty data. + Create a new control with a unique name. Controls define protection logic and can be added to policies. - Use the PUT /{control_id}/data endpoint to set control configuration. + Optionally provide control data to validate and persist it atomically. Args: - request: Control creation request with unique name + request: Control creation request with unique name and optional data db: Database session (injected) Returns: @@ -279,7 +294,12 @@ async def create_control( hint="Choose a different name or update the existing control.", ) - control = Control(name=request.name, data={}) + control_data: dict[str, object] = {} + if request.data is not None: + await _validate_control_definition(request.data, db) + control_data = _serialize_control_definition(request.data) + + control = Control(name=request.name, data=control_data) db.add(control) try: await db.commit() @@ -451,19 +471,7 @@ async def set_control_data( # Validate evaluator config using shared logic await _validate_control_definition(request.data, db) - data_json = request.data.model_dump( - mode="json", - by_alias=True, - exclude_none=True, - exclude_unset=True, - ) - # Ensure scope does not store null/None for step_names or other optional fields, - # so round-trip (save then load) preserves step selection in the UI. - if "scope" in data_json and isinstance(data_json["scope"], dict): - data_json["scope"] = { - k: v for k, v in data_json["scope"].items() if v is not None - } - control.data = data_json + control.data = _serialize_control_definition(request.data) try: await db.commit() except Exception: diff --git a/server/tests/test_controls.py b/server/tests/test_controls.py index 51520e7a..e774ccbf 100644 --- a/server/tests/test_controls.py +++ b/server/tests/test_controls.py @@ -23,6 +23,55 @@ def test_create_control_returns_id(client: TestClient) -> None: assert isinstance(resp.json()["control_id"], int) +def test_create_control_with_data_stores_configured_payload(client: TestClient) -> None: + # Given: a valid control payload included during create + name = f"control-{uuid.uuid4()}" + + # When: creating the control with data in one request + resp = client.put("/api/v1/controls", json={"name": name, "data": VALID_CONTROL_DATA}) + + # Then: the control is created successfully + assert resp.status_code == 200, resp.text + control_id = resp.json()["control_id"] + + # When: reading back its data + data_resp = client.get(f"/api/v1/controls/{control_id}/data") + + # Then: the configured payload was stored immediately + assert data_resp.status_code == 200 + data = data_resp.json()["data"] + assert data["description"] == VALID_CONTROL_DATA["description"] + assert data["execution"] == VALID_CONTROL_DATA["execution"] + assert data["condition"]["evaluator"] == VALID_CONTROL_DATA["condition"]["evaluator"] + + +def test_create_control_invalid_data_returns_422_without_persisting(client: TestClient) -> None: + # Given: a create request whose control data fails evaluator validation + name = f"control-{uuid.uuid4()}" + invalid_data = deepcopy(VALID_CONTROL_DATA) + invalid_data["condition"]["evaluator"] = { + "name": "list", + "config": { + "values": ["a", "b"], + "logic": "invalid_logic", + "match_on": "match", + }, + } + + # When: creating the control with invalid data + resp = client.put("/api/v1/controls", json={"name": name, "data": invalid_data}) + + # Then: the request is rejected + assert resp.status_code == 422 + + # And: no shell control was persisted + list_resp = client.get("/api/v1/controls", params={"name": name}) + assert list_resp.status_code == 200 + body = list_resp.json() + assert body["pagination"]["total"] == 0 + assert body["controls"] == [] + + def test_get_control_data_initially_unconfigured(client: TestClient) -> None: # Given: a newly created control (no data set yet) control_id = create_control(client) diff --git a/ui/src/core/api/generated/api-types.ts b/ui/src/core/api/generated/api-types.ts index 55b9538c..652a2644 100644 --- a/ui/src/core/api/generated/api-types.ts +++ b/ui/src/core/api/generated/api-types.ts @@ -4,4763 +4,4743 @@ */ export interface paths { - '/api/config': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; + "/api/config": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * UI configuration + * @description Return configuration flags that drive UI behavior. + * + * If authentication is enabled, this also reports whether the current + * request has an active session (via header or cookie), allowing the UI + * to skip the login prompt on refresh when a valid cookie is present. + */ + get: operations["get_config_api_config_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/login": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Login with API key + * @description Validate an API key and issue a signed JWT session cookie. + * + * The raw API key is transmitted only in this single request and is never + * stored in the cookie. Subsequent requests authenticate via the JWT. + */ + post: operations["login_api_login_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/logout": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Logout (clear session cookie) + * @description Clear the session cookie. + */ + post: operations["logout_api_logout_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/v1/agents": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List all agents + * @description List all registered agents with cursor-based pagination. + * + * Returns a summary of each agent including identifier, policy associations, + * and counts of registered steps and evaluators. + * + * Args: + * cursor: Optional cursor for pagination (last agent name from previous page) + * limit: Pagination limit (default 20, max 100) + * name: Optional name filter (case-insensitive partial match) + * db: Database session (injected) + * + * Returns: + * ListAgentsResponse with agent summaries and pagination info + */ + get: operations["list_agents_api_v1_agents_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/v1/agents/initAgent": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Initialize or update an agent + * @description Register a new agent or update an existing agent's steps and metadata. + * + * This endpoint is idempotent: + * - If the agent name doesn't exist, creates a new agent + * - If the agent name exists, updates registration data in place + * + * conflict_mode controls registration conflict handling: + * - strict (default): preserve compatibility checks and conflict errors + * - overwrite: latest init payload replaces steps/evaluators and returns change summary + * + * Args: + * request: Agent metadata and step schemas + * db: Database session (injected) + * + * Returns: + * InitAgentResponse with created flag and active controls (policy-derived + direct) + */ + post: operations["init_agent_api_v1_agents_initAgent_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/v1/agents/{agent_name}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get agent details + * @description Retrieve agent metadata and all registered steps. + * + * Returns the latest version of each step (deduplicated by type+name). + * + * Args: + * agent_name: Agent identifier + * db: Database session (injected) + * + * Returns: + * GetAgentResponse with agent metadata and step list + * + * Raises: + * HTTPException 404: Agent not found + * HTTPException 422: Agent data is corrupted + */ + get: operations["get_agent_api_v1_agents__agent_name__get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + /** + * Modify agent (remove steps/evaluators) + * @description Remove steps and/or evaluators from an agent. + * + * This is the complement to initAgent which only adds items. + * Removals are idempotent - attempting to remove non-existent items is not an error. + * + * Args: + * agent_name: Agent identifier + * request: Lists of step/evaluator identifiers to remove + * db: Database session (injected) + * + * Returns: + * PatchAgentResponse with lists of actually removed items + * + * Raises: + * HTTPException 404: Agent not found + * HTTPException 500: Database error during update + */ + patch: operations["patch_agent_api_v1_agents__agent_name__patch"]; + trace?: never; + }; + "/api/v1/agents/{agent_name}/controls": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List agent's active controls + * @description List all protection controls active for an agent. + * + * Controls include the union of policy-derived and directly associated controls. + * + * Args: + * agent_name: Agent identifier + * db: Database session (injected) + * + * Returns: + * AgentControlsResponse with list of active controls + * + * Raises: + * HTTPException 404: Agent not found + */ + get: operations["list_agent_controls_api_v1_agents__agent_name__controls_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/v1/agents/{agent_name}/controls/{control_id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Associate control directly with agent + * @description Associate a control directly with an agent (idempotent). + */ + post: operations["add_agent_control_api_v1_agents__agent_name__controls__control_id__post"]; + /** + * Remove direct control association from agent + * @description Remove a direct control association from an agent (idempotent). + */ + delete: operations["remove_agent_control_api_v1_agents__agent_name__controls__control_id__delete"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/v1/agents/{agent_name}/evaluators": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List agent's registered evaluator schemas + * @description List all evaluator schemas registered with an agent. + * + * Evaluator schemas are registered via initAgent and used for: + * - Config validation when creating Controls + * - UI to display available config options + * + * Args: + * agent_name: Agent identifier + * cursor: Optional cursor for pagination (name of last evaluator from previous page) + * limit: Pagination limit (default 20, max 100) + * db: Database session (injected) + * + * Returns: + * ListEvaluatorsResponse with evaluator schemas and pagination + * + * Raises: + * HTTPException 404: Agent not found + */ + get: operations["list_agent_evaluators_api_v1_agents__agent_name__evaluators_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/v1/agents/{agent_name}/evaluators/{evaluator_name}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get specific evaluator schema + * @description Get a specific evaluator schema registered with an agent. + * + * Args: + * agent_name: Agent identifier + * evaluator_name: Name of the evaluator + * db: Database session (injected) + * + * Returns: + * EvaluatorSchemaItem with schema details + * + * Raises: + * HTTPException 404: Agent or evaluator not found + */ + get: operations["get_agent_evaluator_api_v1_agents__agent_name__evaluators__evaluator_name__get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/v1/agents/{agent_name}/policies": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List policies associated with agent + * @description List policy IDs associated with an agent. + */ + get: operations["get_agent_policies_api_v1_agents__agent_name__policies_get"]; + put?: never; + post?: never; + /** + * Remove all policy associations from agent + * @description Remove all policy associations from an agent. + */ + delete: operations["remove_all_agent_policies_api_v1_agents__agent_name__policies_delete"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/v1/agents/{agent_name}/policies/{policy_id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Associate policy with agent + * @description Associate a policy with an agent (idempotent). + */ + post: operations["add_agent_policy_api_v1_agents__agent_name__policies__policy_id__post"]; + /** + * Remove policy association from agent + * @description Remove a policy association from an agent. + * + * Idempotent for existing resources: removing a non-associated link is a no-op. + * Missing agent/policy resources still return 404. + */ + delete: operations["remove_agent_policy_api_v1_agents__agent_name__policies__policy_id__delete"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/v1/agents/{agent_name}/policy": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get agent's assigned policy (compatibility) + * @description Compatibility endpoint that returns the first associated policy. + */ + get: operations["get_agent_policy_api_v1_agents__agent_name__policy_get"]; + put?: never; + post?: never; + /** + * Remove agent's policy assignment (compatibility) + * @description Compatibility endpoint that removes all policy associations. + */ + delete: operations["delete_agent_policy_api_v1_agents__agent_name__policy_delete"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/v1/agents/{agent_name}/policy/{policy_id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Assign policy to agent (compatibility) + * @description Compatibility endpoint that replaces all policy associations with one policy. + */ + post: operations["set_agent_policy_api_v1_agents__agent_name__policy__policy_id__post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/v1/controls": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List all controls + * @description List all controls with optional filtering and cursor-based pagination. + * + * Controls are returned ordered by ID descending (newest first). + * + * Args: + * cursor: ID of the last control from the previous page (for pagination) + * limit: Maximum number of controls to return (default 20, max 100) + * name: Optional filter by name (partial, case-insensitive match) + * enabled: Optional filter by enabled status + * step_type: Optional filter by step type (built-ins: 'tool', 'llm') + * stage: Optional filter by stage ('pre' or 'post') + * execution: Optional filter by execution ('server' or 'sdk') + * tag: Optional filter by tag + * db: Database session (injected) + * + * Returns: + * ListControlsResponse with control summaries and pagination info + * + * Example: + * GET /controls?limit=10&enabled=true&step_type=tool + */ + get: operations["list_controls_api_v1_controls_get"]; + /** + * Create a new control + * @description Create a new control with a unique name. + * + * Controls define protection logic and can be added to policies. + * Optionally provide control data to validate and persist it atomically. + * + * Args: + * request: Control creation request with unique name and optional data + * db: Database session (injected) + * + * Returns: + * CreateControlResponse with the new control's ID + * + * Raises: + * HTTPException 409: Control with this name already exists + * HTTPException 500: Database error during creation + */ + put: operations["create_control_api_v1_controls_put"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/v1/controls/validate": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Validate control configuration + * @description Validate control configuration data without saving it. + * + * Args: + * request: Control configuration data to validate + * db: Database session (injected) + * + * Returns: + * ValidateControlDataResponse with success=True if valid + */ + post: operations["validate_control_data_api_v1_controls_validate_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/v1/controls/{control_id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get control details + * @description Retrieve a control by ID including its name and configuration data. + * + * Args: + * control_id: ID of the control + * db: Database session (injected) + * + * Returns: + * GetControlResponse with control id, name, and data + * + * Raises: + * HTTPException 404: Control not found + */ + get: operations["get_control_api_v1_controls__control_id__get"]; + put?: never; + post?: never; + /** + * Delete a control + * @description Delete a control by ID. + * + * By default, deletion fails if the control is associated with any policy or agent. + * Use force=true to automatically dissociate and delete. + * + * Args: + * control_id: ID of the control to delete + * force: If true, remove associations before deleting + * db: Database session (injected) + * + * Returns: + * DeleteControlResponse with success flag and dissociation details + * + * Raises: + * HTTPException 404: Control not found + * HTTPException 409: Control is in use (and force=false) + * HTTPException 500: Database error during deletion + */ + delete: operations["delete_control_api_v1_controls__control_id__delete"]; + options?: never; + head?: never; + /** + * Update control metadata + * @description Update control metadata (name and/or enabled status). + * + * This endpoint allows partial updates: + * - To rename: provide 'name' field + * - To enable/disable: provide 'enabled' field (updates the control's data) + * + * Args: + * control_id: ID of the control to update + * request: Fields to update (name, enabled) + * db: Database session (injected) + * + * Returns: + * PatchControlResponse with current control state + * + * Raises: + * HTTPException 404: Control not found + * HTTPException 409: New name conflicts with existing control + * HTTPException 422: Cannot update enabled status (control has no data configured) + * HTTPException 500: Database error during update + */ + patch: operations["patch_control_api_v1_controls__control_id__patch"]; + trace?: never; + }; + "/api/v1/controls/{control_id}/data": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get control configuration data + * @description Retrieve the configuration data for a control. + * + * Control data is a JSONB field that must follow the ControlDefinition schema. + * + * Args: + * control_id: ID of the control + * db: Database session (injected) + * + * Returns: + * GetControlDataResponse with validated ControlDefinition + * + * Raises: + * HTTPException 404: Control not found + * HTTPException 422: Control data is corrupted + */ + get: operations["get_control_data_api_v1_controls__control_id__data_get"]; + /** + * Update control configuration data + * @description Update the configuration data for a control. + * + * This replaces the entire data payload. The data is validated against + * the ControlDefinition schema. + * + * Args: + * control_id: ID of the control + * request: New control data (replaces existing) + * db: Database session (injected) + * + * Returns: + * SetControlDataResponse with success flag + * + * Raises: + * HTTPException 404: Control not found + * HTTPException 500: Database error during update + */ + put: operations["set_control_data_api_v1_controls__control_id__data_put"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/v1/evaluation": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Analyze content safety + * @description Analyze content for safety and control violations. + * + * Runs all controls assigned to the agent via policy through the + * evaluation engine. Controls are evaluated in parallel with + * cancel-on-deny for efficiency. + * + * Custom evaluators must be deployed as Evaluator classes + * with the engine. Their schemas are registered via initAgent. + * + * Optionally accepts X-Trace-Id and X-Span-Id headers for + * OpenTelemetry-compatible distributed tracing. + */ + post: operations["evaluate_api_v1_evaluation_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/v1/evaluator-configs": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** List evaluator configs */ + get: operations["list_evaluator_configs_api_v1_evaluator_configs_get"]; + put?: never; + /** Create evaluator config */ + post: operations["create_evaluator_config_api_v1_evaluator_configs_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/v1/evaluator-configs/{config_id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Get evaluator config */ + get: operations["get_evaluator_config_api_v1_evaluator_configs__config_id__get"]; + /** Update evaluator config */ + put: operations["update_evaluator_config_api_v1_evaluator_configs__config_id__put"]; + post?: never; + /** Delete evaluator config */ + delete: operations["delete_evaluator_config_api_v1_evaluator_configs__config_id__delete"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/v1/evaluators": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List available evaluators + * @description List all available evaluators. + * + * Returns metadata and JSON Schema for each built-in evaluator. + * + * Built-in evaluators: + * - **regex**: Regular expression pattern matching + * - **list**: List-based value matching with flexible logic + * - **json**: JSON validation with schema, types, constraints + * - **sql**: SQL query validation + * + * Custom evaluators are registered per-agent via initAgent. + * Use GET /agents/{agent_name}/evaluators to list agent-specific schemas. + */ + get: operations["get_evaluators_api_v1_evaluators_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/v1/observability/events": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Ingest Events + * @description Ingest batched control execution events. + * + * Events are stored directly to the database with ~5-20ms latency. + * + * Args: + * request: Batch of events to ingest + * ingestor: Event ingestor (injected) + * + * Returns: + * BatchEventsResponse with counts of received/processed/dropped + */ + post: operations["ingest_events_api_v1_observability_events_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/v1/observability/events/query": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Query Events + * @description Query raw control execution events. + * + * Supports filtering by: + * - trace_id: Get all events for a request + * - span_id: Get all events for a function call + * - control_execution_id: Get a specific event + * - agent_name: Filter by agent + * - control_ids: Filter by controls + * - actions: Filter by actions (allow, deny, warn, log) + * - matched: Filter by matched status + * - check_stages: Filter by check stage (pre, post) + * - applies_to: Filter by call type (llm_call, tool_call) + * - start_time/end_time: Filter by time range + * + * Results are paginated with limit/offset. + * + * Args: + * request: Query parameters + * store: Event store (injected) + * + * Returns: + * EventQueryResponse with matching events and pagination info + */ + post: operations["query_events_api_v1_observability_events_query_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/v1/observability/stats": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get Stats + * @description Get agent-level aggregated statistics. + * + * Returns totals across all controls plus per-control breakdown. + * Use /stats/controls/{control_id} for single control stats. + * + * Args: + * agent_name: Agent to get stats for + * time_range: Time range (1m, 5m, 15m, 1h, 24h, 7d, 30d, 180d, 365d) + * include_timeseries: Include time-series data points for trend visualization + * store: Event store (injected) + * + * Returns: + * StatsResponse with agent-level totals and per-control breakdown + */ + get: operations["get_stats_api_v1_observability_stats_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/v1/observability/stats/controls/{control_id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get Control Stats + * @description Get statistics for a single control. + * + * Returns stats for the specified control with optional time-series. + * + * Args: + * control_id: Control ID to get stats for + * agent_name: Agent to get stats for + * time_range: Time range (1m, 5m, 15m, 1h, 24h, 7d, 30d, 180d, 365d) + * include_timeseries: Include time-series data points for trend visualization + * store: Event store (injected) + * + * Returns: + * ControlStatsResponse with control stats and optional timeseries + */ + get: operations["get_control_stats_api_v1_observability_stats_controls__control_id__get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/v1/observability/status": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get Status + * @description Get observability system status. + * + * Returns basic health information. + */ + get: operations["get_status_api_v1_observability_status_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/v1/policies": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + /** + * Create a new policy + * @description Create a new empty policy with a unique name. + * + * Policies contain controls and can be assigned to agents. + * A newly created policy has no controls until they are explicitly added. + * + * Args: + * request: Policy creation request with unique name + * db: Database session (injected) + * + * Returns: + * CreatePolicyResponse with the new policy's ID + * + * Raises: + * HTTPException 409: Policy with this name already exists + * HTTPException 500: Database error during creation + */ + put: operations["create_policy_api_v1_policies_put"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/v1/policies/{policy_id}/controls": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List policy's controls + * @description List all controls associated with a policy. + * + * Args: + * policy_id: ID of the policy + * db: Database session (injected) + * + * Returns: + * GetPolicyControlsResponse with list of control IDs + * + * Raises: + * HTTPException 404: Policy not found + */ + get: operations["list_policy_controls_api_v1_policies__policy_id__controls_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/v1/policies/{policy_id}/controls/{control_id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Add control to policy + * @description Associate a control with a policy. + * + * This operation is idempotent - adding the same control multiple times has no effect. + * Agents with this policy will immediately see the added control. + * + * Args: + * policy_id: ID of the policy + * control_id: ID of the control to add + * db: Database session (injected) + * + * Returns: + * AssocResponse with success flag + * + * Raises: + * HTTPException 404: Policy or control not found + * HTTPException 500: Database error + */ + post: operations["add_control_to_policy_api_v1_policies__policy_id__controls__control_id__post"]; + /** + * Remove control from policy + * @description Remove a control from a policy. + * + * This operation is idempotent - removing a non-associated control has no effect. + * Agents with this policy will immediately lose the removed control. + * + * Args: + * policy_id: ID of the policy + * control_id: ID of the control to remove + * db: Database session (injected) + * + * Returns: + * AssocResponse with success flag + * + * Raises: + * HTTPException 404: Policy or control not found + * HTTPException 500: Database error + */ + delete: operations["remove_control_from_policy_api_v1_policies__policy_id__controls__control_id__delete"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/health": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Health check + * @description Check if the server is running and responsive. + * + * This endpoint does not check database connectivity. + * + * Returns: + * HealthResponse with status and version + */ + get: operations["health_check_health_get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; }; - /** - * UI configuration - * @description Return configuration flags that drive UI behavior. - * - * If authentication is enabled, this also reports whether the current - * request has an active session (via header or cookie), allowing the UI - * to skip the login prompt on refresh when a valid cookie is present. - */ - get: operations['get_config_api_config_get']; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - '/api/login': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * Login with API key - * @description Validate an API key and issue a signed JWT session cookie. - * - * The raw API key is transmitted only in this single request and is never - * stored in the cookie. Subsequent requests authenticate via the JWT. - */ - post: operations['login_api_login_post']; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - '/api/logout': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * Logout (clear session cookie) - * @description Clear the session cookie. - */ - post: operations['logout_api_logout_post']; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - '/api/v1/agents': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * List all agents - * @description List all registered agents with cursor-based pagination. - * - * Returns a summary of each agent including identifier, policy associations, - * and counts of registered steps and evaluators. - * - * Args: - * cursor: Optional cursor for pagination (last agent name from previous page) - * limit: Pagination limit (default 20, max 100) - * name: Optional name filter (case-insensitive partial match) - * db: Database session (injected) - * - * Returns: - * ListAgentsResponse with agent summaries and pagination info - */ - get: operations['list_agents_api_v1_agents_get']; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - '/api/v1/agents/initAgent': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * Initialize or update an agent - * @description Register a new agent or update an existing agent's steps and metadata. - * - * This endpoint is idempotent: - * - If the agent name doesn't exist, creates a new agent - * - If the agent name exists, updates registration data in place - * - * conflict_mode controls registration conflict handling: - * - strict (default): preserve compatibility checks and conflict errors - * - overwrite: latest init payload replaces steps/evaluators and returns change summary - * - * Args: - * request: Agent metadata and step schemas - * db: Database session (injected) - * - * Returns: - * InitAgentResponse with created flag and active controls (policy-derived + direct) - */ - post: operations['init_agent_api_v1_agents_initAgent_post']; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - '/api/v1/agents/{agent_name}': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get agent details - * @description Retrieve agent metadata and all registered steps. - * - * Returns the latest version of each step (deduplicated by type+name). - * - * Args: - * agent_name: Agent identifier - * db: Database session (injected) - * - * Returns: - * GetAgentResponse with agent metadata and step list - * - * Raises: - * HTTPException 404: Agent not found - * HTTPException 422: Agent data is corrupted - */ - get: operations['get_agent_api_v1_agents__agent_name__get']; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - /** - * Modify agent (remove steps/evaluators) - * @description Remove steps and/or evaluators from an agent. - * - * This is the complement to initAgent which only adds items. - * Removals are idempotent - attempting to remove non-existent items is not an error. - * - * Args: - * agent_name: Agent identifier - * request: Lists of step/evaluator identifiers to remove - * db: Database session (injected) - * - * Returns: - * PatchAgentResponse with lists of actually removed items - * - * Raises: - * HTTPException 404: Agent not found - * HTTPException 500: Database error during update - */ - patch: operations['patch_agent_api_v1_agents__agent_name__patch']; - trace?: never; - }; - '/api/v1/agents/{agent_name}/controls': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * List agent's active controls - * @description List all protection controls active for an agent. - * - * Controls include the union of policy-derived and directly associated controls. - * - * Args: - * agent_name: Agent identifier - * db: Database session (injected) - * - * Returns: - * AgentControlsResponse with list of active controls - * - * Raises: - * HTTPException 404: Agent not found - */ - get: operations['list_agent_controls_api_v1_agents__agent_name__controls_get']; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - '/api/v1/agents/{agent_name}/controls/{control_id}': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * Associate control directly with agent - * @description Associate a control directly with an agent (idempotent). - */ - post: operations['add_agent_control_api_v1_agents__agent_name__controls__control_id__post']; - /** - * Remove direct control association from agent - * @description Remove a direct control association from an agent (idempotent). - */ - delete: operations['remove_agent_control_api_v1_agents__agent_name__controls__control_id__delete']; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - '/api/v1/agents/{agent_name}/evaluators': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * List agent's registered evaluator schemas - * @description List all evaluator schemas registered with an agent. - * - * Evaluator schemas are registered via initAgent and used for: - * - Config validation when creating Controls - * - UI to display available config options - * - * Args: - * agent_name: Agent identifier - * cursor: Optional cursor for pagination (name of last evaluator from previous page) - * limit: Pagination limit (default 20, max 100) - * db: Database session (injected) - * - * Returns: - * ListEvaluatorsResponse with evaluator schemas and pagination - * - * Raises: - * HTTPException 404: Agent not found - */ - get: operations['list_agent_evaluators_api_v1_agents__agent_name__evaluators_get']; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - '/api/v1/agents/{agent_name}/evaluators/{evaluator_name}': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get specific evaluator schema - * @description Get a specific evaluator schema registered with an agent. - * - * Args: - * agent_name: Agent identifier - * evaluator_name: Name of the evaluator - * db: Database session (injected) - * - * Returns: - * EvaluatorSchemaItem with schema details - * - * Raises: - * HTTPException 404: Agent or evaluator not found - */ - get: operations['get_agent_evaluator_api_v1_agents__agent_name__evaluators__evaluator_name__get']; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - '/api/v1/agents/{agent_name}/policies': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * List policies associated with agent - * @description List policy IDs associated with an agent. - */ - get: operations['get_agent_policies_api_v1_agents__agent_name__policies_get']; - put?: never; - post?: never; - /** - * Remove all policy associations from agent - * @description Remove all policy associations from an agent. - */ - delete: operations['remove_all_agent_policies_api_v1_agents__agent_name__policies_delete']; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - '/api/v1/agents/{agent_name}/policies/{policy_id}': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * Associate policy with agent - * @description Associate a policy with an agent (idempotent). - */ - post: operations['add_agent_policy_api_v1_agents__agent_name__policies__policy_id__post']; - /** - * Remove policy association from agent - * @description Remove a policy association from an agent. - * - * Idempotent for existing resources: removing a non-associated link is a no-op. - * Missing agent/policy resources still return 404. - */ - delete: operations['remove_agent_policy_api_v1_agents__agent_name__policies__policy_id__delete']; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - '/api/v1/agents/{agent_name}/policy': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get agent's assigned policy (compatibility) - * @description Compatibility endpoint that returns the first associated policy. - */ - get: operations['get_agent_policy_api_v1_agents__agent_name__policy_get']; - put?: never; - post?: never; - /** - * Remove agent's policy assignment (compatibility) - * @description Compatibility endpoint that removes all policy associations. - */ - delete: operations['delete_agent_policy_api_v1_agents__agent_name__policy_delete']; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - '/api/v1/agents/{agent_name}/policy/{policy_id}': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * Assign policy to agent (compatibility) - * @description Compatibility endpoint that replaces all policy associations with one policy. - */ - post: operations['set_agent_policy_api_v1_agents__agent_name__policy__policy_id__post']; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - '/api/v1/controls': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * List all controls - * @description List all controls with optional filtering and cursor-based pagination. - * - * Controls are returned ordered by ID descending (newest first). - * - * Args: - * cursor: ID of the last control from the previous page (for pagination) - * limit: Maximum number of controls to return (default 20, max 100) - * name: Optional filter by name (partial, case-insensitive match) - * enabled: Optional filter by enabled status - * step_type: Optional filter by step type (built-ins: 'tool', 'llm') - * stage: Optional filter by stage ('pre' or 'post') - * execution: Optional filter by execution ('server' or 'sdk') - * tag: Optional filter by tag - * db: Database session (injected) - * - * Returns: - * ListControlsResponse with control summaries and pagination info - * - * Example: - * GET /controls?limit=10&enabled=true&step_type=tool - */ - get: operations['list_controls_api_v1_controls_get']; - /** - * Create a new control - * @description Create a new control with a unique name and empty data. - * - * Controls define protection logic and can be added to policies. - * Use the PUT /{control_id}/data endpoint to set control configuration. - * - * Args: - * request: Control creation request with unique name - * db: Database session (injected) - * - * Returns: - * CreateControlResponse with the new control's ID - * - * Raises: - * HTTPException 409: Control with this name already exists - * HTTPException 500: Database error during creation - */ - put: operations['create_control_api_v1_controls_put']; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - '/api/v1/controls/validate': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * Validate control configuration - * @description Validate control configuration data without saving it. - * - * Args: - * request: Control configuration data to validate - * db: Database session (injected) - * - * Returns: - * ValidateControlDataResponse with success=True if valid - */ - post: operations['validate_control_data_api_v1_controls_validate_post']; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - '/api/v1/controls/{control_id}': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get control details - * @description Retrieve a control by ID including its name and configuration data. - * - * Args: - * control_id: ID of the control - * db: Database session (injected) - * - * Returns: - * GetControlResponse with control id, name, and data - * - * Raises: - * HTTPException 404: Control not found - */ - get: operations['get_control_api_v1_controls__control_id__get']; - put?: never; - post?: never; - /** - * Delete a control - * @description Delete a control by ID. - * - * By default, deletion fails if the control is associated with any policy or agent. - * Use force=true to automatically dissociate and delete. - * - * Args: - * control_id: ID of the control to delete - * force: If true, remove associations before deleting - * db: Database session (injected) - * - * Returns: - * DeleteControlResponse with success flag and dissociation details - * - * Raises: - * HTTPException 404: Control not found - * HTTPException 409: Control is in use (and force=false) - * HTTPException 500: Database error during deletion - */ - delete: operations['delete_control_api_v1_controls__control_id__delete']; - options?: never; - head?: never; - /** - * Update control metadata - * @description Update control metadata (name and/or enabled status). - * - * This endpoint allows partial updates: - * - To rename: provide 'name' field - * - To enable/disable: provide 'enabled' field (updates the control's data) - * - * Args: - * control_id: ID of the control to update - * request: Fields to update (name, enabled) - * db: Database session (injected) - * - * Returns: - * PatchControlResponse with current control state - * - * Raises: - * HTTPException 404: Control not found - * HTTPException 409: New name conflicts with existing control - * HTTPException 422: Cannot update enabled status (control has no data configured) - * HTTPException 500: Database error during update - */ - patch: operations['patch_control_api_v1_controls__control_id__patch']; - trace?: never; - }; - '/api/v1/controls/{control_id}/data': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get control configuration data - * @description Retrieve the configuration data for a control. - * - * Control data is a JSONB field that must follow the ControlDefinition schema. - * - * Args: - * control_id: ID of the control - * db: Database session (injected) - * - * Returns: - * GetControlDataResponse with validated ControlDefinition - * - * Raises: - * HTTPException 404: Control not found - * HTTPException 422: Control data is corrupted - */ - get: operations['get_control_data_api_v1_controls__control_id__data_get']; - /** - * Update control configuration data - * @description Update the configuration data for a control. - * - * This replaces the entire data payload. The data is validated against - * the ControlDefinition schema. - * - * Args: - * control_id: ID of the control - * request: New control data (replaces existing) - * db: Database session (injected) - * - * Returns: - * SetControlDataResponse with success flag - * - * Raises: - * HTTPException 404: Control not found - * HTTPException 500: Database error during update - */ - put: operations['set_control_data_api_v1_controls__control_id__data_put']; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - '/api/v1/evaluation': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * Analyze content safety - * @description Analyze content for safety and control violations. - * - * Runs all controls assigned to the agent via policy through the - * evaluation engine. Controls are evaluated in parallel with - * cancel-on-deny for efficiency. - * - * Custom evaluators must be deployed as Evaluator classes - * with the engine. Their schemas are registered via initAgent. - * - * Optionally accepts X-Trace-Id and X-Span-Id headers for - * OpenTelemetry-compatible distributed tracing. - */ - post: operations['evaluate_api_v1_evaluation_post']; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - '/api/v1/evaluator-configs': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** List evaluator configs */ - get: operations['list_evaluator_configs_api_v1_evaluator_configs_get']; - put?: never; - /** Create evaluator config */ - post: operations['create_evaluator_config_api_v1_evaluator_configs_post']; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - '/api/v1/evaluator-configs/{config_id}': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get evaluator config */ - get: operations['get_evaluator_config_api_v1_evaluator_configs__config_id__get']; - /** Update evaluator config */ - put: operations['update_evaluator_config_api_v1_evaluator_configs__config_id__put']; - post?: never; - /** Delete evaluator config */ - delete: operations['delete_evaluator_config_api_v1_evaluator_configs__config_id__delete']; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - '/api/v1/evaluators': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * List available evaluators - * @description List all available evaluators. - * - * Returns metadata and JSON Schema for each built-in evaluator. - * - * Built-in evaluators: - * - **regex**: Regular expression pattern matching - * - **list**: List-based value matching with flexible logic - * - **json**: JSON validation with schema, types, constraints - * - **sql**: SQL query validation - * - * Custom evaluators are registered per-agent via initAgent. - * Use GET /agents/{agent_name}/evaluators to list agent-specific schemas. - */ - get: operations['get_evaluators_api_v1_evaluators_get']; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - '/api/v1/observability/events': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * Ingest Events - * @description Ingest batched control execution events. - * - * Events are stored directly to the database with ~5-20ms latency. - * - * Args: - * request: Batch of events to ingest - * ingestor: Event ingestor (injected) - * - * Returns: - * BatchEventsResponse with counts of received/processed/dropped - */ - post: operations['ingest_events_api_v1_observability_events_post']; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - '/api/v1/observability/events/query': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * Query Events - * @description Query raw control execution events. - * - * Supports filtering by: - * - trace_id: Get all events for a request - * - span_id: Get all events for a function call - * - control_execution_id: Get a specific event - * - agent_name: Filter by agent - * - control_ids: Filter by controls - * - actions: Filter by actions (allow, deny, warn, log) - * - matched: Filter by matched status - * - check_stages: Filter by check stage (pre, post) - * - applies_to: Filter by call type (llm_call, tool_call) - * - start_time/end_time: Filter by time range - * - * Results are paginated with limit/offset. - * - * Args: - * request: Query parameters - * store: Event store (injected) - * - * Returns: - * EventQueryResponse with matching events and pagination info - */ - post: operations['query_events_api_v1_observability_events_query_post']; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - '/api/v1/observability/stats': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get Stats - * @description Get agent-level aggregated statistics. - * - * Returns totals across all controls plus per-control breakdown. - * Use /stats/controls/{control_id} for single control stats. - * - * Args: - * agent_name: Agent to get stats for - * time_range: Time range (1m, 5m, 15m, 1h, 24h, 7d, 30d, 180d, 365d) - * include_timeseries: Include time-series data points for trend visualization - * store: Event store (injected) - * - * Returns: - * StatsResponse with agent-level totals and per-control breakdown - */ - get: operations['get_stats_api_v1_observability_stats_get']; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - '/api/v1/observability/stats/controls/{control_id}': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get Control Stats - * @description Get statistics for a single control. - * - * Returns stats for the specified control with optional time-series. - * - * Args: - * control_id: Control ID to get stats for - * agent_name: Agent to get stats for - * time_range: Time range (1m, 5m, 15m, 1h, 24h, 7d, 30d, 180d, 365d) - * include_timeseries: Include time-series data points for trend visualization - * store: Event store (injected) - * - * Returns: - * ControlStatsResponse with control stats and optional timeseries - */ - get: operations['get_control_stats_api_v1_observability_stats_controls__control_id__get']; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - '/api/v1/observability/status': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get Status - * @description Get observability system status. - * - * Returns basic health information. - */ - get: operations['get_status_api_v1_observability_status_get']; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - '/api/v1/policies': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - /** - * Create a new policy - * @description Create a new empty policy with a unique name. - * - * Policies contain controls and can be assigned to agents. - * A newly created policy has no controls until they are explicitly added. - * - * Args: - * request: Policy creation request with unique name - * db: Database session (injected) - * - * Returns: - * CreatePolicyResponse with the new policy's ID - * - * Raises: - * HTTPException 409: Policy with this name already exists - * HTTPException 500: Database error during creation - */ - put: operations['create_policy_api_v1_policies_put']; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - '/api/v1/policies/{policy_id}/controls': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * List policy's controls - * @description List all controls associated with a policy. - * - * Args: - * policy_id: ID of the policy - * db: Database session (injected) - * - * Returns: - * GetPolicyControlsResponse with list of control IDs - * - * Raises: - * HTTPException 404: Policy not found - */ - get: operations['list_policy_controls_api_v1_policies__policy_id__controls_get']; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - '/api/v1/policies/{policy_id}/controls/{control_id}': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * Add control to policy - * @description Associate a control with a policy. - * - * This operation is idempotent - adding the same control multiple times has no effect. - * Agents with this policy will immediately see the added control. - * - * Args: - * policy_id: ID of the policy - * control_id: ID of the control to add - * db: Database session (injected) - * - * Returns: - * AssocResponse with success flag - * - * Raises: - * HTTPException 404: Policy or control not found - * HTTPException 500: Database error - */ - post: operations['add_control_to_policy_api_v1_policies__policy_id__controls__control_id__post']; - /** - * Remove control from policy - * @description Remove a control from a policy. - * - * This operation is idempotent - removing a non-associated control has no effect. - * Agents with this policy will immediately lose the removed control. - * - * Args: - * policy_id: ID of the policy - * control_id: ID of the control to remove - * db: Database session (injected) - * - * Returns: - * AssocResponse with success flag - * - * Raises: - * HTTPException 404: Policy or control not found - * HTTPException 500: Database error - */ - delete: operations['remove_control_from_policy_api_v1_policies__policy_id__controls__control_id__delete']; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - '/health': { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Health check - * @description Check if the server is running and responsive. - * - * This endpoint does not check database connectivity. - * - * Returns: - * HealthResponse with status and version - */ - get: operations['health_check_health_get']; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; } export type webhooks = Record; export interface components { - schemas: { - /** - * Agent - * @description Agent metadata for registration and tracking. - * - * An agent represents an AI system that can be protected and monitored. - * Each agent has a unique immutable name and can have multiple steps registered with it. - * @example { - * "agent_description": "Handles customer inquiries and support tickets", - * "agent_metadata": { - * "environment": "production", - * "team": "support" - * }, - * "agent_name": "customer-service-bot", - * "agent_version": "1.0.0" - * } - */ - Agent: { - /** - * Agent Created At - * @description ISO 8601 timestamp when agent was created - */ - agent_created_at?: string | null; - /** - * Agent Description - * @description Optional description of the agent's purpose - */ - agent_description?: string | null; - /** - * Agent Metadata - * @description Free-form metadata dictionary for custom properties - */ - agent_metadata?: { - [key: string]: unknown; - } | null; - /** - * Agent Name - * @description Unique immutable identifier for the agent - */ - agent_name: string; - /** - * Agent Updated At - * @description ISO 8601 timestamp when agent was last updated - */ - agent_updated_at?: string | null; - /** - * Agent Version - * @description Semantic version string (e.g. '1.0.0') - */ - agent_version?: string | null; - }; - /** AgentControlsResponse */ - AgentControlsResponse: { - /** - * Controls - * @description List of active controls associated with the agent - */ - controls: components['schemas']['Control'][]; - }; - /** - * AgentRef - * @description Reference to an agent (for listing which agents use a control). - */ - AgentRef: { - /** - * Agent Name - * @description Agent name - */ - agent_name: string; - }; - /** - * AgentSummary - * @description Summary of an agent for list responses. - */ - AgentSummary: { - /** - * Active Controls Count - * @description Number of active controls for this agent - * @default 0 - */ - active_controls_count: number; - /** - * Agent Name - * @description Unique identifier of the agent - */ - agent_name: string; - /** - * Created At - * @description ISO 8601 timestamp when agent was created - */ - created_at?: string | null; - /** - * Evaluator Count - * @description Number of evaluators registered with the agent - * @default 0 - */ - evaluator_count: number; - /** - * Policy Ids - * @description IDs of policies associated with the agent - */ - policy_ids?: number[]; - /** - * Step Count - * @description Number of steps registered with the agent - * @default 0 - */ - step_count: number; - }; - /** AssocResponse */ - AssocResponse: { - /** - * Success - * @description Whether the association change succeeded - */ - success: boolean; - }; - /** - * AuthMode - * @description Authentication mode advertised to the UI. - * @enum {string} - */ - AuthMode: 'none' | 'api-key'; - /** - * BatchEventsRequest - * @description Request model for batch event ingestion. - * - * SDKs batch events and send them to the server periodically. - * This reduces HTTP overhead significantly (100x reduction). - * - * Attributes: - * events: List of control execution events to ingest - * @example { - * "events": [ - * { - * "action": "deny", - * "agent_name": "my-agent", - * "applies_to": "llm_call", - * "check_stage": "pre", - * "confidence": 0.95, - * "control_id": 123, - * "control_name": "sql-injection-check", - * "matched": true, - * "span_id": "00f067aa0ba902b7", - * "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736" - * } - * ] - * } - */ - BatchEventsRequest: { - /** - * Events - * @description List of events to ingest - */ - events: components['schemas']['ControlExecutionEvent'][]; - }; - /** - * BatchEventsResponse - * @description Response model for batch event ingestion. - * - * Attributes: - * received: Number of events received - * enqueued: Number of events successfully enqueued - * dropped: Number of events dropped (queue full) - * status: Overall status ('queued', 'partial', 'failed') - */ - BatchEventsResponse: { - /** - * Dropped - * @description Number of events dropped - */ - dropped: number; - /** - * Enqueued - * @description Number of events enqueued - */ - enqueued: number; - /** - * Received - * @description Number of events received - */ - received: number; - /** - * Status - * @description Overall ingestion status - * @enum {string} - */ - status: 'queued' | 'partial' | 'failed'; - }; - /** - * ConditionNode - * @description Recursive boolean condition tree for control evaluation. - * @example { - * "evaluator": { - * "config": { - * "pattern": "\\d{3}-\\d{2}-\\d{4}" - * }, - * "name": "regex" - * }, - * "selector": { - * "path": "output" - * } - * } - * @example { - * "and": [ - * { - * "evaluator": { - * "config": { - * "values": [ - * "high", - * "critical" - * ] - * }, - * "name": "list" - * }, - * "selector": { - * "path": "context.risk_level" - * } - * }, - * { - * "not": { - * "evaluator": { - * "config": { - * "values": [ - * "admin", - * "security" - * ] - * }, - * "name": "list" - * }, - * "selector": { - * "path": "context.user_role" - * } - * } - * } - * ] - * } - */ - 'ConditionNode-Input': { - /** - * And - * @description Logical AND over child conditions. - */ - and?: components['schemas']['ConditionNode-Input'][] | null; - /** @description Leaf evaluator. Must be provided together with selector. */ - evaluator?: components['schemas']['EvaluatorSpec'] | null; - /** @description Logical NOT over a single child condition. */ - not?: components['schemas']['ConditionNode-Input'] | null; - /** - * Or - * @description Logical OR over child conditions. - */ - or?: components['schemas']['ConditionNode-Input'][] | null; - /** @description Leaf selector. Must be provided together with evaluator. */ - selector?: components['schemas']['ControlSelector'] | null; - }; - /** - * ConditionNode - * @description Recursive boolean condition tree for control evaluation. - * @example { - * "evaluator": { - * "config": { - * "pattern": "\\d{3}-\\d{2}-\\d{4}" - * }, - * "name": "regex" - * }, - * "selector": { - * "path": "output" - * } - * } - * @example { - * "and": [ - * { - * "evaluator": { - * "config": { - * "values": [ - * "high", - * "critical" - * ] - * }, - * "name": "list" - * }, - * "selector": { - * "path": "context.risk_level" - * } - * }, - * { - * "not": { - * "evaluator": { - * "config": { - * "values": [ - * "admin", - * "security" - * ] - * }, - * "name": "list" - * }, - * "selector": { - * "path": "context.user_role" - * } - * } - * } - * ] - * } - */ - 'ConditionNode-Output': { - /** - * And - * @description Logical AND over child conditions. - */ - and?: components['schemas']['ConditionNode-Output'][] | null; - /** @description Leaf evaluator. Must be provided together with selector. */ - evaluator?: components['schemas']['EvaluatorSpec'] | null; - /** @description Logical NOT over a single child condition. */ - not?: components['schemas']['ConditionNode-Output'] | null; - /** - * Or - * @description Logical OR over child conditions. - */ - or?: components['schemas']['ConditionNode-Output'][] | null; - /** @description Leaf selector. Must be provided together with evaluator. */ - selector?: components['schemas']['ControlSelector'] | null; - }; - /** - * ConfigResponse - * @description Configuration surface exposed to the UI. - */ - ConfigResponse: { - auth_mode: components['schemas']['AuthMode']; - /** - * Has Active Session - * @default false - */ - has_active_session: boolean; - /** Requires Api Key */ - requires_api_key: boolean; - }; - /** - * ConflictMode - * @description Conflict handling mode for initAgent registration updates. - * - * STRICT preserves compatibility checks and raises conflicts on incompatible changes. - * OVERWRITE applies latest-init-wins replacement for steps and evaluators. - * @enum {string} - */ - ConflictMode: 'strict' | 'overwrite'; - /** - * Control - * @description A control with identity and configuration. - * - * Note: Only fully-configured controls (with valid ControlDefinition) - * are returned from API endpoints. Unconfigured controls are filtered out. - */ - Control: { - control: components['schemas']['ControlDefinition-Output']; - /** Id */ - id: number; - /** Name */ - name: string; - }; - /** - * ControlAction - * @description What to do when control matches. - */ - ControlAction: { - /** - * Decision - * @description Action to take when control is triggered - * @enum {string} - */ - decision: 'allow' | 'deny' | 'steer' | 'warn' | 'log'; - /** @description Steering context object for steer actions. Strongly recommended when decision='steer' to provide correction suggestions. If not provided, the evaluator result message will be used as fallback. */ - steering_context?: components['schemas']['SteeringContext'] | null; - }; - /** - * ControlDefinition - * @description A control definition to evaluate agent interactions. - * - * This model contains only the logic and configuration. - * Identity fields (id, name) are managed by the database. - * @example { - * "action": { - * "decision": "deny" - * }, - * "condition": { - * "evaluator": { - * "config": { - * "pattern": "\\b\\d{3}-\\d{2}-\\d{4}\\b" - * }, - * "name": "regex" - * }, - * "selector": { - * "path": "output" - * } - * }, - * "description": "Block outputs containing US Social Security Numbers", - * "enabled": true, - * "execution": "server", - * "scope": { - * "stages": [ - * "post" - * ], - * "step_types": [ - * "llm" - * ] - * }, - * "tags": [ - * "pii", - * "compliance" - * ] - * } - */ - 'ControlDefinition-Input': { - /** @description What action to take when control matches */ - action: components['schemas']['ControlAction']; - /** @description Recursive boolean condition tree. Leaf nodes contain selector + evaluator; composite nodes contain and/or/not. */ - condition: components['schemas']['ConditionNode-Input']; - /** - * Description - * @description Detailed description of the control - */ - description?: string | null; - /** - * Enabled - * @description Whether this control is active - * @default true - */ - enabled: boolean; - /** - * Execution - * @description Where this control executes - * @enum {string} - */ - execution: 'server' | 'sdk'; - /** @description Which steps and stages this control applies to */ - scope?: components['schemas']['ControlScope']; - /** - * Tags - * @description Tags for categorization - */ - tags?: string[]; - }; - /** - * ControlDefinition - * @description A control definition to evaluate agent interactions. - * - * This model contains only the logic and configuration. - * Identity fields (id, name) are managed by the database. - * @example { - * "action": { - * "decision": "deny" - * }, - * "condition": { - * "evaluator": { - * "config": { - * "pattern": "\\b\\d{3}-\\d{2}-\\d{4}\\b" - * }, - * "name": "regex" - * }, - * "selector": { - * "path": "output" - * } - * }, - * "description": "Block outputs containing US Social Security Numbers", - * "enabled": true, - * "execution": "server", - * "scope": { - * "stages": [ - * "post" - * ], - * "step_types": [ - * "llm" - * ] - * }, - * "tags": [ - * "pii", - * "compliance" - * ] - * } - */ - 'ControlDefinition-Output': { - /** @description What action to take when control matches */ - action: components['schemas']['ControlAction']; - /** @description Recursive boolean condition tree. Leaf nodes contain selector + evaluator; composite nodes contain and/or/not. */ - condition: components['schemas']['ConditionNode-Output']; - /** - * Description - * @description Detailed description of the control - */ - description?: string | null; - /** - * Enabled - * @description Whether this control is active - * @default true - */ - enabled: boolean; - /** - * Execution - * @description Where this control executes - * @enum {string} - */ - execution: 'server' | 'sdk'; - /** @description Which steps and stages this control applies to */ - scope?: components['schemas']['ControlScope']; - /** - * Tags - * @description Tags for categorization - */ - tags?: string[]; - }; - /** - * ControlExecutionEvent - * @description Represents a single control execution event. - * - * This is the core observability data model, capturing: - * - Identity: control_execution_id, trace_id, span_id (OpenTelemetry-compatible) - * - Context: agent, control, check stage, applies to - * - Result: action taken, whether matched, confidence score - * - Timing: when it happened, how long it took - * - Optional details: evaluator name, selector path, errors, metadata - * - * Attributes: - * control_execution_id: Unique ID for this specific control execution - * trace_id: OpenTelemetry-compatible trace ID (128-bit hex, 32 chars) - * span_id: OpenTelemetry-compatible span ID (64-bit hex, 16 chars) - * agent_name: Identifier of the agent that executed the control - * control_id: Database ID of the control - * control_name: Name of the control (denormalized for queries) - * check_stage: "pre" (before execution) or "post" (after execution) - * applies_to: "llm_call" or "tool_call" - * action: The action taken (allow, deny, warn, log) - * matched: Whether the control evaluator matched - * confidence: Confidence score from the evaluator (0.0-1.0) - * timestamp: When the control was executed (UTC) - * execution_duration_ms: How long the control evaluation took - * evaluator_name: Name of the evaluator used - * selector_path: The selector path used to extract data - * error_message: Error message if evaluation failed - * metadata: Additional metadata for extensibility - * @example { - * "action": "deny", - * "agent_name": "my-agent", - * "applies_to": "llm_call", - * "check_stage": "pre", - * "confidence": 0.95, - * "control_execution_id": "550e8400-e29b-41d4-a716-446655440000", - * "control_id": 123, - * "control_name": "sql-injection-check", - * "evaluator_name": "regex", - * "execution_duration_ms": 15.3, - * "matched": true, - * "selector_path": "input", - * "span_id": "00f067aa0ba902b7", - * "timestamp": "2025-01-09T10:30:00Z", - * "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736" - * } - */ - ControlExecutionEvent: { - /** - * Action - * @description Action taken by the control - * @enum {string} - */ - action: 'allow' | 'deny' | 'steer' | 'warn' | 'log'; - /** - * Agent Name - * @description Identifier of the agent - */ - agent_name: string; - /** - * Applies To - * @description Type of call: 'llm_call' or 'tool_call' - * @enum {string} - */ - applies_to: 'llm_call' | 'tool_call'; - /** - * Check Stage - * @description Check stage: 'pre' or 'post' - * @enum {string} - */ - check_stage: 'pre' | 'post'; - /** - * Confidence - * @description Confidence score (0.0 to 1.0) - */ - confidence: number; - /** - * Control Execution Id - * @description Unique ID for this control execution - */ - control_execution_id?: string; - /** - * Control Id - * @description Database ID of the control - */ - control_id: number; - /** - * Control Name - * @description Name of the control (denormalized) - */ - control_name: string; - /** - * Error Message - * @description Error message if evaluation failed - */ - error_message?: string | null; - /** - * Evaluator Name - * @description Name of the evaluator used - */ - evaluator_name?: string | null; - /** - * Execution Duration Ms - * @description Execution duration in milliseconds - */ - execution_duration_ms?: number | null; - /** - * Matched - * @description Whether the evaluator matched (True) or not (False) - */ - matched: boolean; - /** - * Metadata - * @description Additional metadata - */ - metadata?: { - [key: string]: unknown; - }; - /** - * Selector Path - * @description Selector path used to extract data - */ - selector_path?: string | null; - /** - * Span Id - * @description Span ID for distributed tracing (SDK generates OTEL-compatible 16-char hex) - */ - span_id: string; - /** - * Timestamp - * Format: date-time - * @description When the control was executed (UTC) - */ - timestamp?: string; - /** - * Trace Id - * @description Trace ID for distributed tracing (SDK generates OTEL-compatible 32-char hex) - */ - trace_id: string; - }; - /** - * ControlMatch - * @description Represents a control evaluation result (match, non-match, or error). - */ - ControlMatch: { - /** - * Action - * @description Action configured for this control - * @enum {string} - */ - action: 'allow' | 'deny' | 'steer' | 'warn' | 'log'; - /** - * Control Execution Id - * @description Unique ID for this control execution (generated by engine) - */ - control_execution_id?: string; - /** - * Control Id - * @description Database ID of the control - */ - control_id: number; - /** - * Control Name - * @description Name of the control - */ - control_name: string; - /** @description Evaluator result (confidence, message, metadata) */ - result: components['schemas']['EvaluatorResult']; - /** @description Steering context for steer actions if configured */ - steering_context?: components['schemas']['SteeringContext'] | null; - }; - /** - * ControlScope - * @description Defines when a control applies to a Step. - * @example { - * "stages": [ - * "pre" - * ], - * "step_types": [ - * "tool" - * ] - * } - * @example { - * "step_names": [ - * "search_db", - * "fetch_user" - * ] - * } - * @example { - * "step_name_regex": "^db_.*" - * } - * @example { - * "stages": [ - * "post" - * ], - * "step_types": [ - * "llm" - * ] - * } - */ - ControlScope: { - /** - * Stages - * @description Evaluation stages this control applies to - */ - stages?: ('pre' | 'post')[] | null; - /** - * Step Name Regex - * @description RE2 pattern matched with search() against step name - */ - step_name_regex?: string | null; - /** - * Step Names - * @description Exact step names this control applies to - */ - step_names?: string[] | null; - /** - * Step Types - * @description Step types this control applies to (omit to apply to all types). Built-in types are 'tool' and 'llm'. - */ - step_types?: string[] | null; - }; - /** - * ControlSelector - * @description Selects data from a Step payload. - * - * - path: which slice of the Step to feed into the evaluator. Optional, defaults to "*" - * meaning the entire Step object. - * @example { - * "path": "output" - * } - * @example { - * "path": "context.user_id" - * } - * @example { - * "path": "input" - * } - * @example { - * "path": "*" - * } - * @example { - * "path": "name" - * } - * @example { - * "path": "output" - * } - */ - ControlSelector: { - /** - * Path - * @description Path to data using dot notation. Examples: 'input', 'output', 'context.user_id', 'name', 'type', '*' - * @default * - */ - path: string | null; - }; - /** - * ControlStats - * @description Aggregated statistics for a single control. - * - * Attributes: - * control_id: Database ID of the control - * control_name: Name of the control - * execution_count: Total number of executions - * match_count: Number of times the control matched - * non_match_count: Number of times the control did not match - * allow_count: Number of allow actions - * deny_count: Number of deny actions - * steer_count: Number of steer actions - * warn_count: Number of warn actions - * log_count: Number of log actions - * error_count: Number of errors during evaluation - * avg_confidence: Average confidence score - * avg_duration_ms: Average execution duration in milliseconds - */ - ControlStats: { - /** - * Allow Count - * @description Allow actions - */ - allow_count: number; - /** - * Avg Confidence - * @description Average confidence - */ - avg_confidence: number; - /** - * Avg Duration Ms - * @description Average duration (ms) - */ - avg_duration_ms?: number | null; - /** - * Control Id - * @description Control ID - */ - control_id: number; - /** - * Control Name - * @description Control name - */ - control_name: string; - /** - * Deny Count - * @description Deny actions - */ - deny_count: number; - /** - * Error Count - * @description Evaluation errors - */ - error_count: number; - /** - * Execution Count - * @description Total executions - */ - execution_count: number; - /** - * Log Count - * @description Log actions - */ - log_count: number; - /** - * Match Count - * @description Total matches - */ - match_count: number; - /** - * Non Match Count - * @description Total non-matches - */ - non_match_count: number; - /** - * Steer Count - * @description Steer actions - */ - steer_count: number; - /** - * Warn Count - * @description Warn actions - */ - warn_count: number; - }; - /** - * ControlStatsResponse - * @description Response model for control-level statistics. - * - * Contains stats for a single control (with optional timeseries). - * - * Attributes: - * agent_name: Agent identifier - * time_range: Time range used - * control_id: Control ID - * control_name: Control name - * stats: Control statistics (includes timeseries when requested) - */ - ControlStatsResponse: { - /** - * Agent Name - * @description Agent identifier - */ - agent_name: string; - /** - * Control Id - * @description Control ID - */ - control_id: number; - /** - * Control Name - * @description Control name - */ - control_name: string; - /** @description Control statistics */ - stats: components['schemas']['StatsTotals']; - /** - * Time Range - * @description Time range used - */ - time_range: string; - }; - /** - * ControlSummary - * @description Summary of a control for list responses. - */ - ControlSummary: { - /** - * Description - * @description Control description - */ - description?: string | null; - /** - * Enabled - * @description Whether control is enabled - * @default true - */ - enabled: boolean; - /** - * Execution - * @description 'server' or 'sdk' - */ - execution?: string | null; - /** - * Id - * @description Control ID - */ - id: number; - /** - * Name - * @description Control name - */ - name: string; - /** - * Stages - * @description Evaluation stages in scope - */ - stages?: string[] | null; - /** - * Step Types - * @description Step types in scope - */ - step_types?: string[] | null; - /** - * Tags - * @description Control tags - */ - tags?: string[]; - /** @description Agent using this control */ - used_by_agent?: components['schemas']['AgentRef'] | null; - /** - * Used By Agents Count - * @description Number of unique agents using this control - * @default 0 - */ - used_by_agents_count: number; - }; - /** CreateControlRequest */ - CreateControlRequest: { - /** - * Name - * @description Unique control name (letters, numbers, hyphens, underscores) - */ - name: string; - }; - /** CreateControlResponse */ - CreateControlResponse: { - /** - * Control Id - * @description Identifier of the created control - */ - control_id: number; - }; - /** - * CreateEvaluatorConfigRequest - * @description Request to create an evaluator config template. - */ - CreateEvaluatorConfigRequest: { - /** - * Config - * @description Evaluator-specific configuration - */ - config: { - [key: string]: unknown; - }; - /** - * Description - * @description Optional description - */ - description?: string | null; - /** - * Evaluator - * @description Evaluator name (built-in or custom) - */ - evaluator: string; - /** - * Name - * @description Unique evaluator config name (letters, numbers, hyphens, underscores) - */ - name: string; - }; - /** CreatePolicyRequest */ - CreatePolicyRequest: { - /** - * Name - * @description Unique policy name (letters, numbers, hyphens, underscores) - */ - name: string; - }; - /** CreatePolicyResponse */ - CreatePolicyResponse: { - /** - * Policy Id - * @description Identifier of the created policy - */ - policy_id: number; - }; - /** - * DeleteControlResponse - * @description Response for deleting a control. - */ - DeleteControlResponse: { - /** - * Dissociated From - * @description Deprecated: policy IDs the control was removed from before deletion - */ - dissociated_from?: number[]; - /** - * Dissociated From Agents - * @description Agent names the control was removed from before deletion - */ - dissociated_from_agents?: string[]; - /** - * Dissociated From Policies - * @description Policy IDs the control was removed from before deletion - */ - dissociated_from_policies?: number[]; - /** - * Success - * @description Whether the control was deleted - */ - success: boolean; - }; - /** - * DeleteEvaluatorConfigResponse - * @description Response for deleting an evaluator config. - */ - DeleteEvaluatorConfigResponse: { - /** - * Success - * @description Whether the evaluator config was deleted - */ - success: boolean; - }; - /** - * DeletePolicyResponse - * @description Compatibility response for singular policy deletion endpoint. - */ - DeletePolicyResponse: { - /** - * Success - * @description Whether the request succeeded - */ - success: boolean; - }; - /** - * EvaluationRequest - * @description Request model for evaluation analysis. - * - * Used to analyze agent interactions for safety violations, - * policy compliance, and control rules. - * - * Attributes: - * agent_name: Unique identifier of the agent making the request - * step: Step payload for evaluation - * stage: 'pre' (before execution) or 'post' (after execution) - * @example { - * "agent_name": "customer-service-bot", - * "stage": "pre", - * "step": { - * "context": { - * "session_id": "abc123", - * "user_id": "user123" - * }, - * "input": "What is the customer's credit card number?", - * "name": "support-answer", - * "type": "llm" - * } - * } - * @example { - * "agent_name": "customer-service-bot", - * "stage": "post", - * "step": { - * "context": { - * "session_id": "abc123", - * "user_id": "user123" - * }, - * "input": "What is the customer's credit card number?", - * "name": "support-answer", - * "output": "I cannot share sensitive payment information.", - * "type": "llm" - * } - * } - * @example { - * "agent_name": "customer-service-bot", - * "stage": "pre", - * "step": { - * "context": { - * "user_id": "user123" - * }, - * "input": { - * "query": "SELECT * FROM users" - * }, - * "name": "search_database", - * "type": "tool" - * } - * } - * @example { - * "agent_name": "customer-service-bot", - * "stage": "post", - * "step": { - * "context": { - * "user_id": "user123" - * }, - * "input": { - * "query": "SELECT * FROM users" - * }, - * "name": "search_database", - * "output": { - * "results": [] - * }, - * "type": "tool" - * } - * } - */ - EvaluationRequest: { - /** - * Agent Name - * @description Identifier of the agent making the evaluation request - */ - agent_name: string; - /** - * Stage - * @description Evaluation stage: 'pre' or 'post' - * @enum {string} - */ - stage: 'pre' | 'post'; - /** @description Agent step payload to evaluate */ - step: components['schemas']['Step']; - }; - /** - * EvaluationResponse - * @description Response model from evaluation analysis (server-side). - * - * This is what the server returns. The SDK may transform this - * into an EvaluationResult for client convenience. - * - * Attributes: - * is_safe: Whether the content is considered safe - * confidence: Confidence score between 0.0 and 1.0 - * reason: Optional explanation for the decision - * matches: List of controls that matched/triggered (if any) - * errors: List of controls that failed during evaluation (if any) - * non_matches: List of controls that were evaluated but did not match (if any) - */ - EvaluationResponse: { - /** - * Confidence - * @description Confidence score (0.0 to 1.0) - */ - confidence: number; - /** - * Errors - * @description List of controls that failed during evaluation (if any) - */ - errors?: components['schemas']['ControlMatch'][] | null; - /** - * Is Safe - * @description Whether content is safe - */ - is_safe: boolean; - /** - * Matches - * @description List of controls that matched/triggered (if any) - */ - matches?: components['schemas']['ControlMatch'][] | null; - /** - * Non Matches - * @description List of controls that were evaluated but did not match (if any) - */ - non_matches?: components['schemas']['ControlMatch'][] | null; - /** - * Reason - * @description Explanation for the decision - */ - reason?: string | null; - }; - /** - * EvaluatorConfigItem - * @description Evaluator config template stored in the server. - */ - EvaluatorConfigItem: { - /** - * Config - * @description Evaluator-specific configuration - */ - config: { - [key: string]: unknown; - }; - /** - * Created At - * @description ISO 8601 created timestamp - */ - created_at?: string | null; - /** - * Description - * @description Optional description - */ - description?: string | null; - /** - * Evaluator - * @description Evaluator name (built-in or custom) - */ - evaluator: string; - /** - * Id - * @description Evaluator config ID - */ - id: number; - /** - * Name - * @description Unique evaluator config name (letters, numbers, hyphens, underscores) - */ - name: string; - /** - * Updated At - * @description ISO 8601 updated timestamp - */ - updated_at?: string | null; - }; - /** - * EvaluatorInfo - * @description Information about a registered evaluator. - */ - EvaluatorInfo: { - /** - * Config Schema - * @description JSON Schema for config - */ - config_schema: { - [key: string]: unknown; - }; - /** - * Description - * @description Evaluator description - */ - description: string; - /** - * Name - * @description Evaluator name - */ - name: string; - /** - * Requires Api Key - * @description Whether evaluator requires API key - */ - requires_api_key: boolean; - /** - * Timeout Ms - * @description Default timeout in milliseconds - */ - timeout_ms: number; - /** - * Version - * @description Evaluator version - */ - version: string; - }; - /** - * EvaluatorResult - * @description Result from a control evaluator. - * - * The `error` field indicates evaluator failures, NOT validation failures: - * - Set `error` for: evaluator crashes, timeouts, missing dependencies, external service errors - * - Do NOT set `error` for: invalid input, syntax errors, schema violations, constraint failures - * - * When `error` is set, `matched` must be False (fail-open on evaluator errors). - * When `error` is None, `matched` reflects the actual validation result. - * - * This distinction allows: - * - Clients to distinguish "data violated rules" from "evaluator is broken" - * - Observability systems to monitor evaluator health separately from validation outcomes - */ - EvaluatorResult: { - /** - * Confidence - * @description Confidence in the evaluation - */ - confidence: number; - /** - * Error - * @description Error message if evaluation failed internally. When set, matched=False is due to error, not actual evaluation. - */ - error?: string | null; - /** - * Matched - * @description Whether the pattern matched - */ - matched: boolean; - /** - * Message - * @description Explanation of the result - */ - message?: string | null; - /** - * Metadata - * @description Additional result metadata - */ - metadata?: { - [key: string]: unknown; - } | null; - }; - /** - * EvaluatorSchema - * @description Schema for a custom evaluator registered with an agent. - * - * Custom evaluators are Evaluator classes deployed with the engine. - * This schema is registered via initAgent for validation and UI purposes. - */ - EvaluatorSchema: { - /** - * Config Schema - * @description JSON Schema for evaluator config validation - */ - config_schema?: { - [key: string]: unknown; - }; - /** - * Description - * @description Optional description - */ - description?: string | null; - /** - * Name - * @description Unique evaluator name - */ - name: string; - }; - /** - * EvaluatorSchemaItem - * @description Evaluator schema summary for list response. - */ - EvaluatorSchemaItem: { - /** Config Schema */ - config_schema: { - [key: string]: unknown; - }; - /** Description */ - description: string | null; - /** Name */ - name: string; - }; - /** - * EvaluatorSpec - * @description Evaluator specification. See GET /evaluators for available evaluators and schemas. - * - * Evaluator reference formats: - * - Built-in: "regex", "list", "json", "sql" - * - External: "galileo.luna2" (requires agent-control-evaluators[galileo]) - * - Agent-scoped: "my-agent:my-evaluator" (validated in endpoint, not here) - */ - EvaluatorSpec: { - /** - * Config - * @description Evaluator-specific configuration - * @example { - * "pattern": "\\d{3}-\\d{2}-\\d{4}" - * } - * @example { - * "logic": "any", - * "values": [ - * "admin" - * ] - * } - */ - config: { - [key: string]: unknown; - }; - /** - * Name - * @description Evaluator name or agent-scoped reference (agent:evaluator) - * @example regex - * @example list - * @example my-agent:pii-detector - */ - name: string; - }; - /** - * EventQueryRequest - * @description Request model for querying raw events. - * - * Supports filtering by various criteria and pagination. - * - * Attributes: - * trace_id: Filter by trace ID (get all events for a request) - * span_id: Filter by span ID (get all events for a function call) - * control_execution_id: Filter by specific event ID - * agent_name: Filter by agent identifier - * control_ids: Filter by control IDs - * actions: Filter by actions (allow, deny, steer, warn, log) - * matched: Filter by matched status - * check_stages: Filter by check stages (pre, post) - * applies_to: Filter by call type (llm_call, tool_call) - * start_time: Filter events after this time - * end_time: Filter events before this time - * limit: Maximum number of events to return - * offset: Offset for pagination - * @example { - * "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736" - * } - * @example { - * "actions": [ - * "deny", - * "warn" - * ], - * "agent_name": "my-agent", - * "limit": 50, - * "start_time": "2025-01-09T00:00:00Z" - * } - */ - EventQueryRequest: { - /** - * Actions - * @description Filter by actions - */ - actions?: ('allow' | 'deny' | 'steer' | 'warn' | 'log')[] | null; - /** - * Agent Name - * @description Filter by agent identifier - */ - agent_name?: string | null; - /** - * Applies To - * @description Filter by call types - */ - applies_to?: ('llm_call' | 'tool_call')[] | null; - /** - * Check Stages - * @description Filter by check stages - */ - check_stages?: ('pre' | 'post')[] | null; - /** - * Control Execution Id - * @description Filter by specific event ID - */ - control_execution_id?: string | null; - /** - * Control Ids - * @description Filter by control IDs - */ - control_ids?: number[] | null; - /** - * End Time - * @description Filter events before this time - */ - end_time?: string | null; - /** - * Limit - * @description Maximum events - * @default 100 - */ - limit: number; - /** - * Matched - * @description Filter by matched status - */ - matched?: boolean | null; - /** - * Offset - * @description Pagination offset - * @default 0 - */ - offset: number; - /** - * Span Id - * @description Filter by span ID (all events for a function) - */ - span_id?: string | null; - /** - * Start Time - * @description Filter events after this time - */ - start_time?: string | null; - /** - * Trace Id - * @description Filter by trace ID (all events for a request) - */ - trace_id?: string | null; - }; - /** - * EventQueryResponse - * @description Response model for event queries. - * - * Attributes: - * events: List of matching events - * total: Total number of matching events (for pagination) - * limit: Limit used in query - * offset: Offset used in query - */ - EventQueryResponse: { - /** - * Events - * @description Matching events - */ - events: components['schemas']['ControlExecutionEvent'][]; - /** - * Limit - * @description Limit used in query - */ - limit: number; - /** - * Offset - * @description Offset used in query - */ - offset: number; - /** - * Total - * @description Total matching events - */ - total: number; - }; - /** GetAgentPoliciesResponse */ - GetAgentPoliciesResponse: { - /** - * Policy Ids - * @description IDs of policies associated with the agent - */ - policy_ids?: number[]; - }; - /** - * GetAgentResponse - * @description Response containing agent details and registered steps. - */ - GetAgentResponse: { - /** @description Agent metadata */ - agent: components['schemas']['Agent']; - /** - * Evaluators - * @description Custom evaluators registered with this agent - */ - evaluators?: components['schemas']['EvaluatorSchema'][]; - /** - * Steps - * @description Steps registered with this agent - */ - steps: components['schemas']['StepSchema'][]; - }; - /** GetControlDataResponse */ - GetControlDataResponse: { - /** @description Control data payload */ - data: components['schemas']['ControlDefinition-Output']; - }; - /** - * GetControlResponse - * @description Response containing control details. - */ - GetControlResponse: { - /** @description Control configuration data (None if not yet configured) */ - data?: components['schemas']['ControlDefinition-Output'] | null; - /** - * Id - * @description Control ID - */ - id: number; - /** - * Name - * @description Control name - */ - name: string; - }; - /** - * GetPolicyControlsResponse - * @description Response containing control IDs associated with a policy. - */ - GetPolicyControlsResponse: { - /** - * Control Ids - * @description List of control IDs associated with the policy - */ - control_ids: number[]; - }; - /** - * GetPolicyResponse - * @description Compatibility response for singular policy retrieval endpoint. - */ - GetPolicyResponse: { - /** - * Policy Id - * @description Associated policy ID - */ - policy_id: number; - }; - /** HTTPValidationError */ - HTTPValidationError: { - /** Detail */ - detail?: components['schemas']['ValidationError'][]; - }; - /** - * HealthResponse - * @description Health check response model. - * - * Attributes: - * status: Current health status (e.g., "healthy", "degraded", "unhealthy") - * version: Application version - */ - HealthResponse: { - /** Status */ - status: string; - /** Version */ - version: string; - }; - /** - * InitAgentEvaluatorRemoval - * @description Details for an evaluator removed during overwrite mode. - */ - InitAgentEvaluatorRemoval: { - /** - * Control Ids - * @description IDs of active controls referencing this evaluator - */ - control_ids?: number[]; - /** - * Control Names - * @description Names of active controls referencing this evaluator - */ - control_names?: string[]; - /** - * Name - * @description Evaluator name removed by overwrite - */ - name: string; - /** - * Referenced By Active Controls - * @description Whether this evaluator is still referenced by active controls - * @default false - */ - referenced_by_active_controls: boolean; - }; - /** - * InitAgentOverwriteChanges - * @description Detailed change summary for initAgent overwrite mode. - */ - InitAgentOverwriteChanges: { - /** - * Evaluator Removals - * @description Per-evaluator removal details, including active control references - */ - evaluator_removals?: components['schemas']['InitAgentEvaluatorRemoval'][]; - /** - * Evaluators Added - * @description Evaluator names added by overwrite - */ - evaluators_added?: string[]; - /** - * Evaluators Removed - * @description Evaluator names removed by overwrite - */ - evaluators_removed?: string[]; - /** - * Evaluators Updated - * @description Existing evaluator names updated by overwrite - */ - evaluators_updated?: string[]; - /** - * Metadata Changed - * @description Whether agent metadata changed - * @default false - */ - metadata_changed: boolean; - /** - * Steps Added - * @description Steps added by overwrite - */ - steps_added?: components['schemas']['StepKey'][]; - /** - * Steps Removed - * @description Steps removed by overwrite - */ - steps_removed?: components['schemas']['StepKey'][]; - /** - * Steps Updated - * @description Existing steps updated by overwrite - */ - steps_updated?: components['schemas']['StepKey'][]; - }; - /** - * InitAgentRequest - * @description Request to initialize or update an agent registration. - * @example { - * "agent": { - * "agent_description": "Handles customer inquiries", - * "agent_name": "customer-service-bot", - * "agent_version": "1.0.0" - * }, - * "evaluators": [ - * { - * "config_schema": { - * "properties": { - * "sensitivity": { - * "type": "string" - * } - * }, - * "type": "object" - * }, - * "description": "Detects PII in text", - * "name": "pii-detector" - * } - * ], - * "steps": [ - * { - * "input_schema": { - * "query": { - * "type": "string" - * } - * }, - * "name": "search_kb", - * "output_schema": { - * "results": { - * "type": "array" - * } - * }, - * "type": "tool" - * } - * ] - * } - */ - InitAgentRequest: { - /** @description Agent metadata including ID, name, and version */ - agent: components['schemas']['Agent']; - /** - * @description Conflict handling mode for init registration updates. 'strict' preserves existing compatibility checks. 'overwrite' applies latest-init-wins replacement for steps and evaluators. - * @default strict - */ - conflict_mode: components['schemas']['ConflictMode']; - /** - * Evaluators - * @description Custom evaluator schemas for config validation - */ - evaluators?: components['schemas']['EvaluatorSchema'][]; - /** - * Force Replace - * @description If true, replace corrupted agent data instead of failing. Use only when agent data is corrupted and cannot be parsed. - * @default false - */ - force_replace: boolean; - /** - * Steps - * @description List of steps available to the agent - */ - steps?: components['schemas']['StepSchema'][]; - }; - /** - * InitAgentResponse - * @description Response from agent initialization. - */ - InitAgentResponse: { - /** - * Controls - * @description Active protection controls for the agent - */ - controls?: components['schemas']['Control'][]; - /** - * Created - * @description True if agent was newly created, False if updated - */ - created: boolean; - /** - * Overwrite Applied - * @description True if overwrite mode changed registration data on an existing agent - * @default false - */ - overwrite_applied: boolean; - /** @description Detailed list of changes applied in overwrite mode */ - overwrite_changes?: components['schemas']['InitAgentOverwriteChanges']; - }; - JSONObject: { - [key: string]: components['schemas']['JSONValue']; - }; - /** @description Any JSON value */ - JSONValue: unknown; - /** - * ListAgentsResponse - * @description Response for listing agents. - */ - ListAgentsResponse: { - /** - * Agents - * @description List of agent summaries - */ - agents: components['schemas']['AgentSummary'][]; - /** @description Pagination metadata */ - pagination: components['schemas']['PaginationInfo']; - }; - /** - * ListControlsResponse - * @description Response for listing controls. - */ - ListControlsResponse: { - /** - * Controls - * @description List of control summaries - */ - controls: components['schemas']['ControlSummary'][]; - /** @description Pagination metadata */ - pagination: components['schemas']['PaginationInfo']; - }; - /** - * ListEvaluatorConfigsResponse - * @description Response for listing evaluator configs. - */ - ListEvaluatorConfigsResponse: { - /** - * Evaluator Configs - * @description List of evaluator configs - */ - evaluator_configs: components['schemas']['EvaluatorConfigItem'][]; - /** @description Pagination metadata */ - pagination: components['schemas']['PaginationInfo']; - }; - /** - * ListEvaluatorsResponse - * @description Response for listing agent's evaluator schemas. - */ - ListEvaluatorsResponse: { - /** Evaluators */ - evaluators: components['schemas']['EvaluatorSchemaItem'][]; - pagination: components['schemas']['PaginationInfo']; - }; - /** - * LoginRequest - * @description Request body for the /login endpoint. - */ - LoginRequest: { - /** Api Key */ - api_key: string; - }; - /** - * LoginResponse - * @description Response body for the /login endpoint. - */ - LoginResponse: { - /** Authenticated */ - authenticated: boolean; - /** Is Admin */ - is_admin: boolean; - }; - /** - * PaginationInfo - * @description Pagination metadata for cursor-based pagination. - */ - PaginationInfo: { - /** - * Has More - * @description Whether there are more pages available - */ - has_more: boolean; - /** - * Limit - * @description Number of items per page - */ - limit: number; - /** - * Next Cursor - * @description Cursor for fetching the next page (null if no more pages) - */ - next_cursor?: string | null; - /** - * Total - * @description Total number of items - */ - total: number; - }; - /** - * PatchAgentRequest - * @description Request to modify an agent (remove steps/evaluators). - */ - PatchAgentRequest: { - /** - * Remove Evaluators - * @description Evaluator names to remove from the agent - */ - remove_evaluators?: string[]; - /** - * Remove Steps - * @description Step identifiers to remove from the agent - */ - remove_steps?: components['schemas']['StepKey'][]; - }; - /** - * PatchAgentResponse - * @description Response from agent modification. - */ - PatchAgentResponse: { - /** - * Evaluators Removed - * @description Evaluator names that were removed - */ - evaluators_removed?: string[]; - /** - * Steps Removed - * @description Step identifiers that were removed - */ - steps_removed?: components['schemas']['StepKey'][]; - }; - /** - * PatchControlRequest - * @description Request to update control metadata (name, enabled status). - */ - PatchControlRequest: { - /** - * Enabled - * @description Enable or disable the control - */ - enabled?: boolean | null; - /** - * Name - * @description New name for the control - */ - name?: string | null; - }; - /** - * PatchControlResponse - * @description Response from control metadata update. - */ - PatchControlResponse: { - /** - * Enabled - * @description Current enabled status (if control has data configured) - */ - enabled?: boolean | null; - /** - * Name - * @description Current control name (may have changed) - */ - name: string; - /** - * Success - * @description Whether the update succeeded - */ - success: boolean; - }; - /** - * RemoveAgentControlResponse - * @description Response for removing a direct agent-control association. - */ - RemoveAgentControlResponse: { - /** - * Control Still Active - * @description True if the control remains active via policy association(s) - */ - control_still_active: boolean; - /** - * Removed Direct Association - * @description True if a direct agent-control link was removed - */ - removed_direct_association: boolean; - /** - * Success - * @description Whether the request succeeded - */ - success: boolean; - }; - /** - * SetControlDataRequest - * @description Request to update control configuration data. - */ - SetControlDataRequest: { - /** @description Control configuration data (replaces existing) */ - data: components['schemas']['ControlDefinition-Input']; - }; - /** SetControlDataResponse */ - SetControlDataResponse: { - /** - * Success - * @description Whether the control data was updated - */ - success: boolean; - }; - /** - * SetPolicyResponse - * @description Compatibility response for singular policy assignment endpoint. - */ - SetPolicyResponse: { - /** - * Old Policy Id - * @description Previously associated policy ID, if any - */ - old_policy_id?: number | null; - /** - * Success - * @description Whether the request succeeded - */ - success: boolean; - }; - /** - * StatsResponse - * @description Response model for agent-level aggregated statistics. - * - * Contains agent-level totals (with optional timeseries) and per-control breakdown. - * - * Attributes: - * agent_name: Agent identifier - * time_range: Time range used - * totals: Agent-level aggregate statistics (includes timeseries) - * controls: Per-control breakdown for discovery and detail - */ - StatsResponse: { - /** - * Agent Name - * @description Agent identifier - */ - agent_name: string; - /** - * Controls - * @description Per-control breakdown - */ - controls: components['schemas']['ControlStats'][]; - /** - * Time Range - * @description Time range used - */ - time_range: string; - /** @description Agent-level aggregate statistics */ - totals: components['schemas']['StatsTotals']; - }; - /** - * StatsTotals - * @description Agent-level aggregate statistics. - * - * Invariant: execution_count = match_count + non_match_count + error_count - * - * Matches have actions (allow, deny, steer, warn, log) tracked in action_counts. - * sum(action_counts.values()) == match_count - * - * Attributes: - * execution_count: Total executions across all controls - * match_count: Total matches across all controls (evaluator matched) - * non_match_count: Total non-matches across all controls (evaluator didn't match) - * error_count: Total errors across all controls (evaluation failed) - * action_counts: Breakdown of actions for matched executions - * timeseries: Time-series data points (only when include_timeseries=true) - */ - StatsTotals: { - /** - * Action Counts - * @description Action breakdown for matches: {allow, deny, steer, warn, log} - */ - action_counts?: { - [key: string]: number; - }; - /** - * Error Count - * @description Total errors - * @default 0 - */ - error_count: number; - /** - * Execution Count - * @description Total executions - */ - execution_count: number; - /** - * Match Count - * @description Total matches - * @default 0 - */ - match_count: number; - /** - * Non Match Count - * @description Total non-matches - * @default 0 - */ - non_match_count: number; - /** - * Timeseries - * @description Time-series data points (only when include_timeseries=true) - */ - timeseries?: components['schemas']['TimeseriesBucket'][] | null; - }; - /** - * SteeringContext - * @description Steering context for steer actions. - * - * This model provides an extensible structure for steering guidance. - * Future fields could include severity, categories, suggested_actions, etc. - * @example { - * "message": "This large transfer requires user verification. Request 2FA code from user, verify it, then retry the transaction with verified_2fa=True." - * } - * @example { - * "message": "Transfer exceeds daily limit. Steps: 1) Ask user for business justification, 2) Request manager approval with amount and justification, 3) If approved, retry with manager_approved=True and justification filled in." - * } - */ - SteeringContext: { - /** - * Message - * @description Guidance message explaining what needs to be corrected and how - */ - message: string; - }; - /** - * Step - * @description Runtime payload for an agent step invocation. - */ - Step: { - /** @description Optional context (conversation history, metadata, etc.) */ - context?: components['schemas']['JSONObject'] | null; - /** @description Input content for this step */ - input: components['schemas']['JSONValue']; - /** - * Name - * @description Step name (tool name or model/chain id) - */ - name: string; - /** @description Output content for this step (None for pre-checks) */ - output?: components['schemas']['JSONValue'] | null; - /** - * Type - * @description Step type (e.g., 'tool', 'llm') - */ - type: string; - }; - /** - * StepKey - * @description Identifies a registered step schema by type and name. - */ - StepKey: { - /** - * Name - * @description Registered step name - */ - name: string; - /** - * Type - * @description Step type - */ - type: string; - }; - /** - * StepSchema - * @description Schema for a registered agent step. - * @example { - * "description": "Search the internal knowledge base", - * "input_schema": { - * "query": { - * "description": "Search query", - * "type": "string" - * } - * }, - * "name": "search_knowledge_base", - * "output_schema": { - * "results": { - * "items": { - * "type": "object" - * }, - * "type": "array" - * } - * }, - * "type": "tool" - * } - * @example { - * "description": "Customer support response generation", - * "input_schema": { - * "messages": { - * "items": { - * "type": "object" - * }, - * "type": "array" - * } - * }, - * "name": "support-answer", - * "output_schema": { - * "text": { - * "type": "string" - * } - * }, - * "type": "llm" - * } - */ - StepSchema: { - /** - * Description - * @description Optional description of the step - */ - description?: string | null; - /** - * Input Schema - * @description JSON schema describing step input - */ - input_schema?: { - [key: string]: unknown; - } | null; - /** - * Metadata - * @description Additional metadata for the step - */ - metadata?: { - [key: string]: unknown; - } | null; - /** - * Name - * @description Unique name for the step - */ - name: string; - /** - * Output Schema - * @description JSON schema describing step output - */ - output_schema?: { - [key: string]: unknown; - } | null; - /** - * Type - * @description Step type for this schema (e.g., 'tool', 'llm') - */ - type: string; - }; - /** - * TimeseriesBucket - * @description Single data point in a time-series. - * - * Represents aggregated metrics for a single time bucket. - * - * Attributes: - * timestamp: Start time of the bucket (UTC, always timezone-aware) - * execution_count: Total executions in this bucket - * match_count: Number of matches in this bucket - * non_match_count: Number of non-matches in this bucket - * error_count: Number of errors in this bucket - * action_counts: Breakdown of actions for matched executions - * avg_confidence: Average confidence score (None if no executions) - * avg_duration_ms: Average execution duration in milliseconds (None if no data) - */ - TimeseriesBucket: { - /** - * Action Counts - * @description Action breakdown: {allow, deny, steer, warn, log} - */ - action_counts?: { - [key: string]: number; - }; - /** - * Avg Confidence - * @description Average confidence score - */ - avg_confidence?: number | null; - /** - * Avg Duration Ms - * @description Average duration (ms) - */ - avg_duration_ms?: number | null; - /** - * Error Count - * @description Errors in bucket - */ - error_count: number; - /** - * Execution Count - * @description Total executions in bucket - */ - execution_count: number; - /** - * Match Count - * @description Matches in bucket - */ - match_count: number; - /** - * Non Match Count - * @description Non-matches in bucket - */ - non_match_count: number; - /** - * Timestamp - * Format: date-time - * @description Start time of the bucket (UTC) - */ - timestamp: string; - }; - /** - * UpdateEvaluatorConfigRequest - * @description Request to replace an evaluator config template. - */ - UpdateEvaluatorConfigRequest: { - /** - * Config - * @description Evaluator-specific configuration - */ - config: { - [key: string]: unknown; - }; - /** - * Description - * @description Optional description - */ - description?: string | null; - /** - * Evaluator - * @description Evaluator name (built-in or custom) - */ - evaluator: string; - /** - * Name - * @description Unique evaluator config name (letters, numbers, hyphens, underscores) - */ - name: string; - }; - /** - * ValidateControlDataRequest - * @description Request to validate control configuration data without saving. - */ - ValidateControlDataRequest: { - /** @description Control configuration data to validate */ - data: components['schemas']['ControlDefinition-Input']; - }; - /** ValidateControlDataResponse */ - ValidateControlDataResponse: { - /** - * Success - * @description Whether the control data is valid - */ - success: boolean; - }; - /** ValidationError */ - ValidationError: { - /** Context */ - ctx?: Record; - /** Input */ - input?: unknown; - /** Location */ - loc: (string | number)[]; - /** Message */ - msg: string; - /** Error Type */ - type: string; - }; - }; - responses: never; - parameters: never; - requestBodies: never; - headers: never; - pathItems: never; + schemas: { + /** + * Agent + * @description Agent metadata for registration and tracking. + * + * An agent represents an AI system that can be protected and monitored. + * Each agent has a unique immutable name and can have multiple steps registered with it. + * @example { + * "agent_description": "Handles customer inquiries and support tickets", + * "agent_metadata": { + * "environment": "production", + * "team": "support" + * }, + * "agent_name": "customer-service-bot", + * "agent_version": "1.0.0" + * } + */ + Agent: { + /** + * Agent Created At + * @description ISO 8601 timestamp when agent was created + */ + agent_created_at?: string | null; + /** + * Agent Description + * @description Optional description of the agent's purpose + */ + agent_description?: string | null; + /** + * Agent Metadata + * @description Free-form metadata dictionary for custom properties + */ + agent_metadata?: { + [key: string]: unknown; + } | null; + /** + * Agent Name + * @description Unique immutable identifier for the agent + */ + agent_name: string; + /** + * Agent Updated At + * @description ISO 8601 timestamp when agent was last updated + */ + agent_updated_at?: string | null; + /** + * Agent Version + * @description Semantic version string (e.g. '1.0.0') + */ + agent_version?: string | null; + }; + /** AgentControlsResponse */ + AgentControlsResponse: { + /** + * Controls + * @description List of active controls associated with the agent + */ + controls: components["schemas"]["Control"][]; + }; + /** + * AgentRef + * @description Reference to an agent (for listing which agents use a control). + */ + AgentRef: { + /** + * Agent Name + * @description Agent name + */ + agent_name: string; + }; + /** + * AgentSummary + * @description Summary of an agent for list responses. + */ + AgentSummary: { + /** + * Active Controls Count + * @description Number of active controls for this agent + * @default 0 + */ + active_controls_count: number; + /** + * Agent Name + * @description Unique identifier of the agent + */ + agent_name: string; + /** + * Created At + * @description ISO 8601 timestamp when agent was created + */ + created_at?: string | null; + /** + * Evaluator Count + * @description Number of evaluators registered with the agent + * @default 0 + */ + evaluator_count: number; + /** + * Policy Ids + * @description IDs of policies associated with the agent + */ + policy_ids?: number[]; + /** + * Step Count + * @description Number of steps registered with the agent + * @default 0 + */ + step_count: number; + }; + /** AssocResponse */ + AssocResponse: { + /** + * Success + * @description Whether the association change succeeded + */ + success: boolean; + }; + /** + * AuthMode + * @description Authentication mode advertised to the UI. + * @enum {string} + */ + AuthMode: "none" | "api-key"; + /** + * BatchEventsRequest + * @description Request model for batch event ingestion. + * + * SDKs batch events and send them to the server periodically. + * This reduces HTTP overhead significantly (100x reduction). + * + * Attributes: + * events: List of control execution events to ingest + * @example { + * "events": [ + * { + * "action": "deny", + * "agent_name": "my-agent", + * "applies_to": "llm_call", + * "check_stage": "pre", + * "confidence": 0.95, + * "control_id": 123, + * "control_name": "sql-injection-check", + * "matched": true, + * "span_id": "00f067aa0ba902b7", + * "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736" + * } + * ] + * } + */ + BatchEventsRequest: { + /** + * Events + * @description List of events to ingest + */ + events: components["schemas"]["ControlExecutionEvent"][]; + }; + /** + * BatchEventsResponse + * @description Response model for batch event ingestion. + * + * Attributes: + * received: Number of events received + * enqueued: Number of events successfully enqueued + * dropped: Number of events dropped (queue full) + * status: Overall status ('queued', 'partial', 'failed') + */ + BatchEventsResponse: { + /** + * Dropped + * @description Number of events dropped + */ + dropped: number; + /** + * Enqueued + * @description Number of events enqueued + */ + enqueued: number; + /** + * Received + * @description Number of events received + */ + received: number; + /** + * Status + * @description Overall ingestion status + * @enum {string} + */ + status: "queued" | "partial" | "failed"; + }; + /** + * ConditionNode + * @description Recursive boolean condition tree for control evaluation. + * @example { + * "evaluator": { + * "config": { + * "pattern": "\\d{3}-\\d{2}-\\d{4}" + * }, + * "name": "regex" + * }, + * "selector": { + * "path": "output" + * } + * } + * @example { + * "and": [ + * { + * "evaluator": { + * "config": { + * "values": [ + * "high", + * "critical" + * ] + * }, + * "name": "list" + * }, + * "selector": { + * "path": "context.risk_level" + * } + * }, + * { + * "not": { + * "evaluator": { + * "config": { + * "values": [ + * "admin", + * "security" + * ] + * }, + * "name": "list" + * }, + * "selector": { + * "path": "context.user_role" + * } + * } + * } + * ] + * } + */ + "ConditionNode-Input": { + /** + * And + * @description Logical AND over child conditions. + */ + and?: components["schemas"]["ConditionNode-Input"][] | null; + /** @description Leaf evaluator. Must be provided together with selector. */ + evaluator?: components["schemas"]["EvaluatorSpec"] | null; + /** @description Logical NOT over a single child condition. */ + not?: components["schemas"]["ConditionNode-Input"] | null; + /** + * Or + * @description Logical OR over child conditions. + */ + or?: components["schemas"]["ConditionNode-Input"][] | null; + /** @description Leaf selector. Must be provided together with evaluator. */ + selector?: components["schemas"]["ControlSelector"] | null; + }; + /** + * ConditionNode + * @description Recursive boolean condition tree for control evaluation. + * @example { + * "evaluator": { + * "config": { + * "pattern": "\\d{3}-\\d{2}-\\d{4}" + * }, + * "name": "regex" + * }, + * "selector": { + * "path": "output" + * } + * } + * @example { + * "and": [ + * { + * "evaluator": { + * "config": { + * "values": [ + * "high", + * "critical" + * ] + * }, + * "name": "list" + * }, + * "selector": { + * "path": "context.risk_level" + * } + * }, + * { + * "not": { + * "evaluator": { + * "config": { + * "values": [ + * "admin", + * "security" + * ] + * }, + * "name": "list" + * }, + * "selector": { + * "path": "context.user_role" + * } + * } + * } + * ] + * } + */ + "ConditionNode-Output": { + /** + * And + * @description Logical AND over child conditions. + */ + and?: components["schemas"]["ConditionNode-Output"][] | null; + /** @description Leaf evaluator. Must be provided together with selector. */ + evaluator?: components["schemas"]["EvaluatorSpec"] | null; + /** @description Logical NOT over a single child condition. */ + not?: components["schemas"]["ConditionNode-Output"] | null; + /** + * Or + * @description Logical OR over child conditions. + */ + or?: components["schemas"]["ConditionNode-Output"][] | null; + /** @description Leaf selector. Must be provided together with evaluator. */ + selector?: components["schemas"]["ControlSelector"] | null; + }; + /** + * ConfigResponse + * @description Configuration surface exposed to the UI. + */ + ConfigResponse: { + auth_mode: components["schemas"]["AuthMode"]; + /** + * Has Active Session + * @default false + */ + has_active_session: boolean; + /** Requires Api Key */ + requires_api_key: boolean; + }; + /** + * ConflictMode + * @description Conflict handling mode for initAgent registration updates. + * + * STRICT preserves compatibility checks and raises conflicts on incompatible changes. + * OVERWRITE applies latest-init-wins replacement for steps and evaluators. + * @enum {string} + */ + ConflictMode: "strict" | "overwrite"; + /** + * Control + * @description A control with identity and configuration. + * + * Note: Only fully-configured controls (with valid ControlDefinition) + * are returned from API endpoints. Unconfigured controls are filtered out. + */ + Control: { + control: components["schemas"]["ControlDefinition-Output"]; + /** Id */ + id: number; + /** Name */ + name: string; + }; + /** + * ControlAction + * @description What to do when control matches. + */ + ControlAction: { + /** + * Decision + * @description Action to take when control is triggered + * @enum {string} + */ + decision: "allow" | "deny" | "steer" | "warn" | "log"; + /** @description Steering context object for steer actions. Strongly recommended when decision='steer' to provide correction suggestions. If not provided, the evaluator result message will be used as fallback. */ + steering_context?: components["schemas"]["SteeringContext"] | null; + }; + /** + * ControlDefinition + * @description A control definition to evaluate agent interactions. + * + * This model contains only the logic and configuration. + * Identity fields (id, name) are managed by the database. + * @example { + * "action": { + * "decision": "deny" + * }, + * "condition": { + * "evaluator": { + * "config": { + * "pattern": "\\b\\d{3}-\\d{2}-\\d{4}\\b" + * }, + * "name": "regex" + * }, + * "selector": { + * "path": "output" + * } + * }, + * "description": "Block outputs containing US Social Security Numbers", + * "enabled": true, + * "execution": "server", + * "scope": { + * "stages": [ + * "post" + * ], + * "step_types": [ + * "llm" + * ] + * }, + * "tags": [ + * "pii", + * "compliance" + * ] + * } + */ + "ControlDefinition-Input": { + /** @description What action to take when control matches */ + action: components["schemas"]["ControlAction"]; + /** @description Recursive boolean condition tree. Leaf nodes contain selector + evaluator; composite nodes contain and/or/not. */ + condition: components["schemas"]["ConditionNode-Input"]; + /** + * Description + * @description Detailed description of the control + */ + description?: string | null; + /** + * Enabled + * @description Whether this control is active + * @default true + */ + enabled: boolean; + /** + * Execution + * @description Where this control executes + * @enum {string} + */ + execution: "server" | "sdk"; + /** @description Which steps and stages this control applies to */ + scope?: components["schemas"]["ControlScope"]; + /** + * Tags + * @description Tags for categorization + */ + tags?: string[]; + }; + /** + * ControlDefinition + * @description A control definition to evaluate agent interactions. + * + * This model contains only the logic and configuration. + * Identity fields (id, name) are managed by the database. + * @example { + * "action": { + * "decision": "deny" + * }, + * "condition": { + * "evaluator": { + * "config": { + * "pattern": "\\b\\d{3}-\\d{2}-\\d{4}\\b" + * }, + * "name": "regex" + * }, + * "selector": { + * "path": "output" + * } + * }, + * "description": "Block outputs containing US Social Security Numbers", + * "enabled": true, + * "execution": "server", + * "scope": { + * "stages": [ + * "post" + * ], + * "step_types": [ + * "llm" + * ] + * }, + * "tags": [ + * "pii", + * "compliance" + * ] + * } + */ + "ControlDefinition-Output": { + /** @description What action to take when control matches */ + action: components["schemas"]["ControlAction"]; + /** @description Recursive boolean condition tree. Leaf nodes contain selector + evaluator; composite nodes contain and/or/not. */ + condition: components["schemas"]["ConditionNode-Output"]; + /** + * Description + * @description Detailed description of the control + */ + description?: string | null; + /** + * Enabled + * @description Whether this control is active + * @default true + */ + enabled: boolean; + /** + * Execution + * @description Where this control executes + * @enum {string} + */ + execution: "server" | "sdk"; + /** @description Which steps and stages this control applies to */ + scope?: components["schemas"]["ControlScope"]; + /** + * Tags + * @description Tags for categorization + */ + tags?: string[]; + }; + /** + * ControlExecutionEvent + * @description Represents a single control execution event. + * + * This is the core observability data model, capturing: + * - Identity: control_execution_id, trace_id, span_id (OpenTelemetry-compatible) + * - Context: agent, control, check stage, applies to + * - Result: action taken, whether matched, confidence score + * - Timing: when it happened, how long it took + * - Optional details: evaluator name, selector path, errors, metadata + * + * Attributes: + * control_execution_id: Unique ID for this specific control execution + * trace_id: OpenTelemetry-compatible trace ID (128-bit hex, 32 chars) + * span_id: OpenTelemetry-compatible span ID (64-bit hex, 16 chars) + * agent_name: Identifier of the agent that executed the control + * control_id: Database ID of the control + * control_name: Name of the control (denormalized for queries) + * check_stage: "pre" (before execution) or "post" (after execution) + * applies_to: "llm_call" or "tool_call" + * action: The action taken (allow, deny, warn, log) + * matched: Whether the control evaluator matched + * confidence: Confidence score from the evaluator (0.0-1.0) + * timestamp: When the control was executed (UTC) + * execution_duration_ms: How long the control evaluation took + * evaluator_name: Name of the evaluator used + * selector_path: The selector path used to extract data + * error_message: Error message if evaluation failed + * metadata: Additional metadata for extensibility + * @example { + * "action": "deny", + * "agent_name": "my-agent", + * "applies_to": "llm_call", + * "check_stage": "pre", + * "confidence": 0.95, + * "control_execution_id": "550e8400-e29b-41d4-a716-446655440000", + * "control_id": 123, + * "control_name": "sql-injection-check", + * "evaluator_name": "regex", + * "execution_duration_ms": 15.3, + * "matched": true, + * "selector_path": "input", + * "span_id": "00f067aa0ba902b7", + * "timestamp": "2025-01-09T10:30:00Z", + * "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736" + * } + */ + ControlExecutionEvent: { + /** + * Action + * @description Action taken by the control + * @enum {string} + */ + action: "allow" | "deny" | "steer" | "warn" | "log"; + /** + * Agent Name + * @description Identifier of the agent + */ + agent_name: string; + /** + * Applies To + * @description Type of call: 'llm_call' or 'tool_call' + * @enum {string} + */ + applies_to: "llm_call" | "tool_call"; + /** + * Check Stage + * @description Check stage: 'pre' or 'post' + * @enum {string} + */ + check_stage: "pre" | "post"; + /** + * Confidence + * @description Confidence score (0.0 to 1.0) + */ + confidence: number; + /** + * Control Execution Id + * @description Unique ID for this control execution + */ + control_execution_id?: string; + /** + * Control Id + * @description Database ID of the control + */ + control_id: number; + /** + * Control Name + * @description Name of the control (denormalized) + */ + control_name: string; + /** + * Error Message + * @description Error message if evaluation failed + */ + error_message?: string | null; + /** + * Evaluator Name + * @description Name of the evaluator used + */ + evaluator_name?: string | null; + /** + * Execution Duration Ms + * @description Execution duration in milliseconds + */ + execution_duration_ms?: number | null; + /** + * Matched + * @description Whether the evaluator matched (True) or not (False) + */ + matched: boolean; + /** + * Metadata + * @description Additional metadata + */ + metadata?: { + [key: string]: unknown; + }; + /** + * Selector Path + * @description Selector path used to extract data + */ + selector_path?: string | null; + /** + * Span Id + * @description Span ID for distributed tracing (SDK generates OTEL-compatible 16-char hex) + */ + span_id: string; + /** + * Timestamp + * Format: date-time + * @description When the control was executed (UTC) + */ + timestamp?: string; + /** + * Trace Id + * @description Trace ID for distributed tracing (SDK generates OTEL-compatible 32-char hex) + */ + trace_id: string; + }; + /** + * ControlMatch + * @description Represents a control evaluation result (match, non-match, or error). + */ + ControlMatch: { + /** + * Action + * @description Action configured for this control + * @enum {string} + */ + action: "allow" | "deny" | "steer" | "warn" | "log"; + /** + * Control Execution Id + * @description Unique ID for this control execution (generated by engine) + */ + control_execution_id?: string; + /** + * Control Id + * @description Database ID of the control + */ + control_id: number; + /** + * Control Name + * @description Name of the control + */ + control_name: string; + /** @description Evaluator result (confidence, message, metadata) */ + result: components["schemas"]["EvaluatorResult"]; + /** @description Steering context for steer actions if configured */ + steering_context?: components["schemas"]["SteeringContext"] | null; + }; + /** + * ControlScope + * @description Defines when a control applies to a Step. + * @example { + * "stages": [ + * "pre" + * ], + * "step_types": [ + * "tool" + * ] + * } + * @example { + * "step_names": [ + * "search_db", + * "fetch_user" + * ] + * } + * @example { + * "step_name_regex": "^db_.*" + * } + * @example { + * "stages": [ + * "post" + * ], + * "step_types": [ + * "llm" + * ] + * } + */ + ControlScope: { + /** + * Stages + * @description Evaluation stages this control applies to + */ + stages?: ("pre" | "post")[] | null; + /** + * Step Name Regex + * @description RE2 pattern matched with search() against step name + */ + step_name_regex?: string | null; + /** + * Step Names + * @description Exact step names this control applies to + */ + step_names?: string[] | null; + /** + * Step Types + * @description Step types this control applies to (omit to apply to all types). Built-in types are 'tool' and 'llm'. + */ + step_types?: string[] | null; + }; + /** + * ControlSelector + * @description Selects data from a Step payload. + * + * - path: which slice of the Step to feed into the evaluator. Optional, defaults to "*" + * meaning the entire Step object. + * @example { + * "path": "output" + * } + * @example { + * "path": "context.user_id" + * } + * @example { + * "path": "input" + * } + * @example { + * "path": "*" + * } + * @example { + * "path": "name" + * } + * @example { + * "path": "output" + * } + */ + ControlSelector: { + /** + * Path + * @description Path to data using dot notation. Examples: 'input', 'output', 'context.user_id', 'name', 'type', '*' + * @default * + */ + path: string | null; + }; + /** + * ControlStats + * @description Aggregated statistics for a single control. + * + * Attributes: + * control_id: Database ID of the control + * control_name: Name of the control + * execution_count: Total number of executions + * match_count: Number of times the control matched + * non_match_count: Number of times the control did not match + * allow_count: Number of allow actions + * deny_count: Number of deny actions + * steer_count: Number of steer actions + * warn_count: Number of warn actions + * log_count: Number of log actions + * error_count: Number of errors during evaluation + * avg_confidence: Average confidence score + * avg_duration_ms: Average execution duration in milliseconds + */ + ControlStats: { + /** + * Allow Count + * @description Allow actions + */ + allow_count: number; + /** + * Avg Confidence + * @description Average confidence + */ + avg_confidence: number; + /** + * Avg Duration Ms + * @description Average duration (ms) + */ + avg_duration_ms?: number | null; + /** + * Control Id + * @description Control ID + */ + control_id: number; + /** + * Control Name + * @description Control name + */ + control_name: string; + /** + * Deny Count + * @description Deny actions + */ + deny_count: number; + /** + * Error Count + * @description Evaluation errors + */ + error_count: number; + /** + * Execution Count + * @description Total executions + */ + execution_count: number; + /** + * Log Count + * @description Log actions + */ + log_count: number; + /** + * Match Count + * @description Total matches + */ + match_count: number; + /** + * Non Match Count + * @description Total non-matches + */ + non_match_count: number; + /** + * Steer Count + * @description Steer actions + */ + steer_count: number; + /** + * Warn Count + * @description Warn actions + */ + warn_count: number; + }; + /** + * ControlStatsResponse + * @description Response model for control-level statistics. + * + * Contains stats for a single control (with optional timeseries). + * + * Attributes: + * agent_name: Agent identifier + * time_range: Time range used + * control_id: Control ID + * control_name: Control name + * stats: Control statistics (includes timeseries when requested) + */ + ControlStatsResponse: { + /** + * Agent Name + * @description Agent identifier + */ + agent_name: string; + /** + * Control Id + * @description Control ID + */ + control_id: number; + /** + * Control Name + * @description Control name + */ + control_name: string; + /** @description Control statistics */ + stats: components["schemas"]["StatsTotals"]; + /** + * Time Range + * @description Time range used + */ + time_range: string; + }; + /** + * ControlSummary + * @description Summary of a control for list responses. + */ + ControlSummary: { + /** + * Description + * @description Control description + */ + description?: string | null; + /** + * Enabled + * @description Whether control is enabled + * @default true + */ + enabled: boolean; + /** + * Execution + * @description 'server' or 'sdk' + */ + execution?: string | null; + /** + * Id + * @description Control ID + */ + id: number; + /** + * Name + * @description Control name + */ + name: string; + /** + * Stages + * @description Evaluation stages in scope + */ + stages?: string[] | null; + /** + * Step Types + * @description Step types in scope + */ + step_types?: string[] | null; + /** + * Tags + * @description Control tags + */ + tags?: string[]; + /** @description Agent using this control */ + used_by_agent?: components["schemas"]["AgentRef"] | null; + /** + * Used By Agents Count + * @description Number of unique agents using this control + * @default 0 + */ + used_by_agents_count: number; + }; + /** CreateControlRequest */ + CreateControlRequest: { + /** @description Optional control definition to validate and store during creation */ + data?: components["schemas"]["ControlDefinition-Input"] | null; + /** + * Name + * @description Unique control name (letters, numbers, hyphens, underscores) + */ + name: string; + }; + /** CreateControlResponse */ + CreateControlResponse: { + /** + * Control Id + * @description Identifier of the created control + */ + control_id: number; + }; + /** + * CreateEvaluatorConfigRequest + * @description Request to create an evaluator config template. + */ + CreateEvaluatorConfigRequest: { + /** + * Config + * @description Evaluator-specific configuration + */ + config: { + [key: string]: unknown; + }; + /** + * Description + * @description Optional description + */ + description?: string | null; + /** + * Evaluator + * @description Evaluator name (built-in or custom) + */ + evaluator: string; + /** + * Name + * @description Unique evaluator config name (letters, numbers, hyphens, underscores) + */ + name: string; + }; + /** CreatePolicyRequest */ + CreatePolicyRequest: { + /** + * Name + * @description Unique policy name (letters, numbers, hyphens, underscores) + */ + name: string; + }; + /** CreatePolicyResponse */ + CreatePolicyResponse: { + /** + * Policy Id + * @description Identifier of the created policy + */ + policy_id: number; + }; + /** + * DeleteControlResponse + * @description Response for deleting a control. + */ + DeleteControlResponse: { + /** + * Dissociated From + * @description Deprecated: policy IDs the control was removed from before deletion + */ + dissociated_from?: number[]; + /** + * Dissociated From Agents + * @description Agent names the control was removed from before deletion + */ + dissociated_from_agents?: string[]; + /** + * Dissociated From Policies + * @description Policy IDs the control was removed from before deletion + */ + dissociated_from_policies?: number[]; + /** + * Success + * @description Whether the control was deleted + */ + success: boolean; + }; + /** + * DeleteEvaluatorConfigResponse + * @description Response for deleting an evaluator config. + */ + DeleteEvaluatorConfigResponse: { + /** + * Success + * @description Whether the evaluator config was deleted + */ + success: boolean; + }; + /** + * DeletePolicyResponse + * @description Compatibility response for singular policy deletion endpoint. + */ + DeletePolicyResponse: { + /** + * Success + * @description Whether the request succeeded + */ + success: boolean; + }; + /** + * EvaluationRequest + * @description Request model for evaluation analysis. + * + * Used to analyze agent interactions for safety violations, + * policy compliance, and control rules. + * + * Attributes: + * agent_name: Unique identifier of the agent making the request + * step: Step payload for evaluation + * stage: 'pre' (before execution) or 'post' (after execution) + * @example { + * "agent_name": "customer-service-bot", + * "stage": "pre", + * "step": { + * "context": { + * "session_id": "abc123", + * "user_id": "user123" + * }, + * "input": "What is the customer's credit card number?", + * "name": "support-answer", + * "type": "llm" + * } + * } + * @example { + * "agent_name": "customer-service-bot", + * "stage": "post", + * "step": { + * "context": { + * "session_id": "abc123", + * "user_id": "user123" + * }, + * "input": "What is the customer's credit card number?", + * "name": "support-answer", + * "output": "I cannot share sensitive payment information.", + * "type": "llm" + * } + * } + * @example { + * "agent_name": "customer-service-bot", + * "stage": "pre", + * "step": { + * "context": { + * "user_id": "user123" + * }, + * "input": { + * "query": "SELECT * FROM users" + * }, + * "name": "search_database", + * "type": "tool" + * } + * } + * @example { + * "agent_name": "customer-service-bot", + * "stage": "post", + * "step": { + * "context": { + * "user_id": "user123" + * }, + * "input": { + * "query": "SELECT * FROM users" + * }, + * "name": "search_database", + * "output": { + * "results": [] + * }, + * "type": "tool" + * } + * } + */ + EvaluationRequest: { + /** + * Agent Name + * @description Identifier of the agent making the evaluation request + */ + agent_name: string; + /** + * Stage + * @description Evaluation stage: 'pre' or 'post' + * @enum {string} + */ + stage: "pre" | "post"; + /** @description Agent step payload to evaluate */ + step: components["schemas"]["Step"]; + }; + /** + * EvaluationResponse + * @description Response model from evaluation analysis (server-side). + * + * This is what the server returns. The SDK may transform this + * into an EvaluationResult for client convenience. + * + * Attributes: + * is_safe: Whether the content is considered safe + * confidence: Confidence score between 0.0 and 1.0 + * reason: Optional explanation for the decision + * matches: List of controls that matched/triggered (if any) + * errors: List of controls that failed during evaluation (if any) + * non_matches: List of controls that were evaluated but did not match (if any) + */ + EvaluationResponse: { + /** + * Confidence + * @description Confidence score (0.0 to 1.0) + */ + confidence: number; + /** + * Errors + * @description List of controls that failed during evaluation (if any) + */ + errors?: components["schemas"]["ControlMatch"][] | null; + /** + * Is Safe + * @description Whether content is safe + */ + is_safe: boolean; + /** + * Matches + * @description List of controls that matched/triggered (if any) + */ + matches?: components["schemas"]["ControlMatch"][] | null; + /** + * Non Matches + * @description List of controls that were evaluated but did not match (if any) + */ + non_matches?: components["schemas"]["ControlMatch"][] | null; + /** + * Reason + * @description Explanation for the decision + */ + reason?: string | null; + }; + /** + * EvaluatorConfigItem + * @description Evaluator config template stored in the server. + */ + EvaluatorConfigItem: { + /** + * Config + * @description Evaluator-specific configuration + */ + config: { + [key: string]: unknown; + }; + /** + * Created At + * @description ISO 8601 created timestamp + */ + created_at?: string | null; + /** + * Description + * @description Optional description + */ + description?: string | null; + /** + * Evaluator + * @description Evaluator name (built-in or custom) + */ + evaluator: string; + /** + * Id + * @description Evaluator config ID + */ + id: number; + /** + * Name + * @description Unique evaluator config name (letters, numbers, hyphens, underscores) + */ + name: string; + /** + * Updated At + * @description ISO 8601 updated timestamp + */ + updated_at?: string | null; + }; + /** + * EvaluatorInfo + * @description Information about a registered evaluator. + */ + EvaluatorInfo: { + /** + * Config Schema + * @description JSON Schema for config + */ + config_schema: { + [key: string]: unknown; + }; + /** + * Description + * @description Evaluator description + */ + description: string; + /** + * Name + * @description Evaluator name + */ + name: string; + /** + * Requires Api Key + * @description Whether evaluator requires API key + */ + requires_api_key: boolean; + /** + * Timeout Ms + * @description Default timeout in milliseconds + */ + timeout_ms: number; + /** + * Version + * @description Evaluator version + */ + version: string; + }; + /** + * EvaluatorResult + * @description Result from a control evaluator. + * + * The `error` field indicates evaluator failures, NOT validation failures: + * - Set `error` for: evaluator crashes, timeouts, missing dependencies, external service errors + * - Do NOT set `error` for: invalid input, syntax errors, schema violations, constraint failures + * + * When `error` is set, `matched` must be False (fail-open on evaluator errors). + * When `error` is None, `matched` reflects the actual validation result. + * + * This distinction allows: + * - Clients to distinguish "data violated rules" from "evaluator is broken" + * - Observability systems to monitor evaluator health separately from validation outcomes + */ + EvaluatorResult: { + /** + * Confidence + * @description Confidence in the evaluation + */ + confidence: number; + /** + * Error + * @description Error message if evaluation failed internally. When set, matched=False is due to error, not actual evaluation. + */ + error?: string | null; + /** + * Matched + * @description Whether the pattern matched + */ + matched: boolean; + /** + * Message + * @description Explanation of the result + */ + message?: string | null; + /** + * Metadata + * @description Additional result metadata + */ + metadata?: { + [key: string]: unknown; + } | null; + }; + /** + * EvaluatorSchema + * @description Schema for a custom evaluator registered with an agent. + * + * Custom evaluators are Evaluator classes deployed with the engine. + * This schema is registered via initAgent for validation and UI purposes. + */ + EvaluatorSchema: { + /** + * Config Schema + * @description JSON Schema for evaluator config validation + */ + config_schema?: { + [key: string]: unknown; + }; + /** + * Description + * @description Optional description + */ + description?: string | null; + /** + * Name + * @description Unique evaluator name + */ + name: string; + }; + /** + * EvaluatorSchemaItem + * @description Evaluator schema summary for list response. + */ + EvaluatorSchemaItem: { + /** Config Schema */ + config_schema: { + [key: string]: unknown; + }; + /** Description */ + description: string | null; + /** Name */ + name: string; + }; + /** + * EvaluatorSpec + * @description Evaluator specification. See GET /evaluators for available evaluators and schemas. + * + * Evaluator reference formats: + * - Built-in: "regex", "list", "json", "sql" + * - External: "galileo.luna2" (requires agent-control-evaluators[galileo]) + * - Agent-scoped: "my-agent:my-evaluator" (validated in endpoint, not here) + */ + EvaluatorSpec: { + /** + * Config + * @description Evaluator-specific configuration + * @example { + * "pattern": "\\d{3}-\\d{2}-\\d{4}" + * } + * @example { + * "logic": "any", + * "values": [ + * "admin" + * ] + * } + */ + config: { + [key: string]: unknown; + }; + /** + * Name + * @description Evaluator name or agent-scoped reference (agent:evaluator) + * @example regex + * @example list + * @example my-agent:pii-detector + */ + name: string; + }; + /** + * EventQueryRequest + * @description Request model for querying raw events. + * + * Supports filtering by various criteria and pagination. + * + * Attributes: + * trace_id: Filter by trace ID (get all events for a request) + * span_id: Filter by span ID (get all events for a function call) + * control_execution_id: Filter by specific event ID + * agent_name: Filter by agent identifier + * control_ids: Filter by control IDs + * actions: Filter by actions (allow, deny, steer, warn, log) + * matched: Filter by matched status + * check_stages: Filter by check stages (pre, post) + * applies_to: Filter by call type (llm_call, tool_call) + * start_time: Filter events after this time + * end_time: Filter events before this time + * limit: Maximum number of events to return + * offset: Offset for pagination + * @example { + * "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736" + * } + * @example { + * "actions": [ + * "deny", + * "warn" + * ], + * "agent_name": "my-agent", + * "limit": 50, + * "start_time": "2025-01-09T00:00:00Z" + * } + */ + EventQueryRequest: { + /** + * Actions + * @description Filter by actions + */ + actions?: ("allow" | "deny" | "steer" | "warn" | "log")[] | null; + /** + * Agent Name + * @description Filter by agent identifier + */ + agent_name?: string | null; + /** + * Applies To + * @description Filter by call types + */ + applies_to?: ("llm_call" | "tool_call")[] | null; + /** + * Check Stages + * @description Filter by check stages + */ + check_stages?: ("pre" | "post")[] | null; + /** + * Control Execution Id + * @description Filter by specific event ID + */ + control_execution_id?: string | null; + /** + * Control Ids + * @description Filter by control IDs + */ + control_ids?: number[] | null; + /** + * End Time + * @description Filter events before this time + */ + end_time?: string | null; + /** + * Limit + * @description Maximum events + * @default 100 + */ + limit: number; + /** + * Matched + * @description Filter by matched status + */ + matched?: boolean | null; + /** + * Offset + * @description Pagination offset + * @default 0 + */ + offset: number; + /** + * Span Id + * @description Filter by span ID (all events for a function) + */ + span_id?: string | null; + /** + * Start Time + * @description Filter events after this time + */ + start_time?: string | null; + /** + * Trace Id + * @description Filter by trace ID (all events for a request) + */ + trace_id?: string | null; + }; + /** + * EventQueryResponse + * @description Response model for event queries. + * + * Attributes: + * events: List of matching events + * total: Total number of matching events (for pagination) + * limit: Limit used in query + * offset: Offset used in query + */ + EventQueryResponse: { + /** + * Events + * @description Matching events + */ + events: components["schemas"]["ControlExecutionEvent"][]; + /** + * Limit + * @description Limit used in query + */ + limit: number; + /** + * Offset + * @description Offset used in query + */ + offset: number; + /** + * Total + * @description Total matching events + */ + total: number; + }; + /** GetAgentPoliciesResponse */ + GetAgentPoliciesResponse: { + /** + * Policy Ids + * @description IDs of policies associated with the agent + */ + policy_ids?: number[]; + }; + /** + * GetAgentResponse + * @description Response containing agent details and registered steps. + */ + GetAgentResponse: { + /** @description Agent metadata */ + agent: components["schemas"]["Agent"]; + /** + * Evaluators + * @description Custom evaluators registered with this agent + */ + evaluators?: components["schemas"]["EvaluatorSchema"][]; + /** + * Steps + * @description Steps registered with this agent + */ + steps: components["schemas"]["StepSchema"][]; + }; + /** GetControlDataResponse */ + GetControlDataResponse: { + /** @description Control data payload */ + data: components["schemas"]["ControlDefinition-Output"]; + }; + /** + * GetControlResponse + * @description Response containing control details. + */ + GetControlResponse: { + /** @description Control configuration data (None if not yet configured) */ + data?: components["schemas"]["ControlDefinition-Output"] | null; + /** + * Id + * @description Control ID + */ + id: number; + /** + * Name + * @description Control name + */ + name: string; + }; + /** + * GetPolicyControlsResponse + * @description Response containing control IDs associated with a policy. + */ + GetPolicyControlsResponse: { + /** + * Control Ids + * @description List of control IDs associated with the policy + */ + control_ids: number[]; + }; + /** + * GetPolicyResponse + * @description Compatibility response for singular policy retrieval endpoint. + */ + GetPolicyResponse: { + /** + * Policy Id + * @description Associated policy ID + */ + policy_id: number; + }; + /** HTTPValidationError */ + HTTPValidationError: { + /** Detail */ + detail?: components["schemas"]["ValidationError"][]; + }; + /** + * HealthResponse + * @description Health check response model. + * + * Attributes: + * status: Current health status (e.g., "healthy", "degraded", "unhealthy") + * version: Application version + */ + HealthResponse: { + /** Status */ + status: string; + /** Version */ + version: string; + }; + /** + * InitAgentEvaluatorRemoval + * @description Details for an evaluator removed during overwrite mode. + */ + InitAgentEvaluatorRemoval: { + /** + * Control Ids + * @description IDs of active controls referencing this evaluator + */ + control_ids?: number[]; + /** + * Control Names + * @description Names of active controls referencing this evaluator + */ + control_names?: string[]; + /** + * Name + * @description Evaluator name removed by overwrite + */ + name: string; + /** + * Referenced By Active Controls + * @description Whether this evaluator is still referenced by active controls + * @default false + */ + referenced_by_active_controls: boolean; + }; + /** + * InitAgentOverwriteChanges + * @description Detailed change summary for initAgent overwrite mode. + */ + InitAgentOverwriteChanges: { + /** + * Evaluator Removals + * @description Per-evaluator removal details, including active control references + */ + evaluator_removals?: components["schemas"]["InitAgentEvaluatorRemoval"][]; + /** + * Evaluators Added + * @description Evaluator names added by overwrite + */ + evaluators_added?: string[]; + /** + * Evaluators Removed + * @description Evaluator names removed by overwrite + */ + evaluators_removed?: string[]; + /** + * Evaluators Updated + * @description Existing evaluator names updated by overwrite + */ + evaluators_updated?: string[]; + /** + * Metadata Changed + * @description Whether agent metadata changed + * @default false + */ + metadata_changed: boolean; + /** + * Steps Added + * @description Steps added by overwrite + */ + steps_added?: components["schemas"]["StepKey"][]; + /** + * Steps Removed + * @description Steps removed by overwrite + */ + steps_removed?: components["schemas"]["StepKey"][]; + /** + * Steps Updated + * @description Existing steps updated by overwrite + */ + steps_updated?: components["schemas"]["StepKey"][]; + }; + /** + * InitAgentRequest + * @description Request to initialize or update an agent registration. + * @example { + * "agent": { + * "agent_description": "Handles customer inquiries", + * "agent_name": "customer-service-bot", + * "agent_version": "1.0.0" + * }, + * "evaluators": [ + * { + * "config_schema": { + * "properties": { + * "sensitivity": { + * "type": "string" + * } + * }, + * "type": "object" + * }, + * "description": "Detects PII in text", + * "name": "pii-detector" + * } + * ], + * "steps": [ + * { + * "input_schema": { + * "query": { + * "type": "string" + * } + * }, + * "name": "search_kb", + * "output_schema": { + * "results": { + * "type": "array" + * } + * }, + * "type": "tool" + * } + * ] + * } + */ + InitAgentRequest: { + /** @description Agent metadata including ID, name, and version */ + agent: components["schemas"]["Agent"]; + /** + * @description Conflict handling mode for init registration updates. 'strict' preserves existing compatibility checks. 'overwrite' applies latest-init-wins replacement for steps and evaluators. + * @default strict + */ + conflict_mode: components["schemas"]["ConflictMode"]; + /** + * Evaluators + * @description Custom evaluator schemas for config validation + */ + evaluators?: components["schemas"]["EvaluatorSchema"][]; + /** + * Force Replace + * @description If true, replace corrupted agent data instead of failing. Use only when agent data is corrupted and cannot be parsed. + * @default false + */ + force_replace: boolean; + /** + * Steps + * @description List of steps available to the agent + */ + steps?: components["schemas"]["StepSchema"][]; + }; + /** + * InitAgentResponse + * @description Response from agent initialization. + */ + InitAgentResponse: { + /** + * Controls + * @description Active protection controls for the agent + */ + controls?: components["schemas"]["Control"][]; + /** + * Created + * @description True if agent was newly created, False if updated + */ + created: boolean; + /** + * Overwrite Applied + * @description True if overwrite mode changed registration data on an existing agent + * @default false + */ + overwrite_applied: boolean; + /** @description Detailed list of changes applied in overwrite mode */ + overwrite_changes?: components["schemas"]["InitAgentOverwriteChanges"]; + }; + JSONObject: { + [key: string]: components["schemas"]["JSONValue"]; + }; + /** @description Any JSON value */ + JSONValue: unknown; + /** + * ListAgentsResponse + * @description Response for listing agents. + */ + ListAgentsResponse: { + /** + * Agents + * @description List of agent summaries + */ + agents: components["schemas"]["AgentSummary"][]; + /** @description Pagination metadata */ + pagination: components["schemas"]["PaginationInfo"]; + }; + /** + * ListControlsResponse + * @description Response for listing controls. + */ + ListControlsResponse: { + /** + * Controls + * @description List of control summaries + */ + controls: components["schemas"]["ControlSummary"][]; + /** @description Pagination metadata */ + pagination: components["schemas"]["PaginationInfo"]; + }; + /** + * ListEvaluatorConfigsResponse + * @description Response for listing evaluator configs. + */ + ListEvaluatorConfigsResponse: { + /** + * Evaluator Configs + * @description List of evaluator configs + */ + evaluator_configs: components["schemas"]["EvaluatorConfigItem"][]; + /** @description Pagination metadata */ + pagination: components["schemas"]["PaginationInfo"]; + }; + /** + * ListEvaluatorsResponse + * @description Response for listing agent's evaluator schemas. + */ + ListEvaluatorsResponse: { + /** Evaluators */ + evaluators: components["schemas"]["EvaluatorSchemaItem"][]; + pagination: components["schemas"]["PaginationInfo"]; + }; + /** + * LoginRequest + * @description Request body for the /login endpoint. + */ + LoginRequest: { + /** Api Key */ + api_key: string; + }; + /** + * LoginResponse + * @description Response body for the /login endpoint. + */ + LoginResponse: { + /** Authenticated */ + authenticated: boolean; + /** Is Admin */ + is_admin: boolean; + }; + /** + * PaginationInfo + * @description Pagination metadata for cursor-based pagination. + */ + PaginationInfo: { + /** + * Has More + * @description Whether there are more pages available + */ + has_more: boolean; + /** + * Limit + * @description Number of items per page + */ + limit: number; + /** + * Next Cursor + * @description Cursor for fetching the next page (null if no more pages) + */ + next_cursor?: string | null; + /** + * Total + * @description Total number of items + */ + total: number; + }; + /** + * PatchAgentRequest + * @description Request to modify an agent (remove steps/evaluators). + */ + PatchAgentRequest: { + /** + * Remove Evaluators + * @description Evaluator names to remove from the agent + */ + remove_evaluators?: string[]; + /** + * Remove Steps + * @description Step identifiers to remove from the agent + */ + remove_steps?: components["schemas"]["StepKey"][]; + }; + /** + * PatchAgentResponse + * @description Response from agent modification. + */ + PatchAgentResponse: { + /** + * Evaluators Removed + * @description Evaluator names that were removed + */ + evaluators_removed?: string[]; + /** + * Steps Removed + * @description Step identifiers that were removed + */ + steps_removed?: components["schemas"]["StepKey"][]; + }; + /** + * PatchControlRequest + * @description Request to update control metadata (name, enabled status). + */ + PatchControlRequest: { + /** + * Enabled + * @description Enable or disable the control + */ + enabled?: boolean | null; + /** + * Name + * @description New control name (letters, numbers, hyphens, underscores) + */ + name?: string | null; + }; + /** + * PatchControlResponse + * @description Response from control metadata update. + */ + PatchControlResponse: { + /** + * Enabled + * @description Current enabled status (if control has data configured) + */ + enabled?: boolean | null; + /** + * Name + * @description Current control name (may have changed) + */ + name: string; + /** + * Success + * @description Whether the update succeeded + */ + success: boolean; + }; + /** + * RemoveAgentControlResponse + * @description Response for removing a direct agent-control association. + */ + RemoveAgentControlResponse: { + /** + * Control Still Active + * @description True if the control remains active via policy association(s) + */ + control_still_active: boolean; + /** + * Removed Direct Association + * @description True if a direct agent-control link was removed + */ + removed_direct_association: boolean; + /** + * Success + * @description Whether the request succeeded + */ + success: boolean; + }; + /** + * SetControlDataRequest + * @description Request to update control configuration data. + */ + SetControlDataRequest: { + /** @description Control configuration data (replaces existing) */ + data: components["schemas"]["ControlDefinition-Input"]; + }; + /** SetControlDataResponse */ + SetControlDataResponse: { + /** + * Success + * @description Whether the control data was updated + */ + success: boolean; + }; + /** + * SetPolicyResponse + * @description Compatibility response for singular policy assignment endpoint. + */ + SetPolicyResponse: { + /** + * Old Policy Id + * @description Previously associated policy ID, if any + */ + old_policy_id?: number | null; + /** + * Success + * @description Whether the request succeeded + */ + success: boolean; + }; + /** + * StatsResponse + * @description Response model for agent-level aggregated statistics. + * + * Contains agent-level totals (with optional timeseries) and per-control breakdown. + * + * Attributes: + * agent_name: Agent identifier + * time_range: Time range used + * totals: Agent-level aggregate statistics (includes timeseries) + * controls: Per-control breakdown for discovery and detail + */ + StatsResponse: { + /** + * Agent Name + * @description Agent identifier + */ + agent_name: string; + /** + * Controls + * @description Per-control breakdown + */ + controls: components["schemas"]["ControlStats"][]; + /** + * Time Range + * @description Time range used + */ + time_range: string; + /** @description Agent-level aggregate statistics */ + totals: components["schemas"]["StatsTotals"]; + }; + /** + * StatsTotals + * @description Agent-level aggregate statistics. + * + * Invariant: execution_count = match_count + non_match_count + error_count + * + * Matches have actions (allow, deny, steer, warn, log) tracked in action_counts. + * sum(action_counts.values()) == match_count + * + * Attributes: + * execution_count: Total executions across all controls + * match_count: Total matches across all controls (evaluator matched) + * non_match_count: Total non-matches across all controls (evaluator didn't match) + * error_count: Total errors across all controls (evaluation failed) + * action_counts: Breakdown of actions for matched executions + * timeseries: Time-series data points (only when include_timeseries=true) + */ + StatsTotals: { + /** + * Action Counts + * @description Action breakdown for matches: {allow, deny, steer, warn, log} + */ + action_counts?: { + [key: string]: number; + }; + /** + * Error Count + * @description Total errors + * @default 0 + */ + error_count: number; + /** + * Execution Count + * @description Total executions + */ + execution_count: number; + /** + * Match Count + * @description Total matches + * @default 0 + */ + match_count: number; + /** + * Non Match Count + * @description Total non-matches + * @default 0 + */ + non_match_count: number; + /** + * Timeseries + * @description Time-series data points (only when include_timeseries=true) + */ + timeseries?: components["schemas"]["TimeseriesBucket"][] | null; + }; + /** + * SteeringContext + * @description Steering context for steer actions. + * + * This model provides an extensible structure for steering guidance. + * Future fields could include severity, categories, suggested_actions, etc. + * @example { + * "message": "This large transfer requires user verification. Request 2FA code from user, verify it, then retry the transaction with verified_2fa=True." + * } + * @example { + * "message": "Transfer exceeds daily limit. Steps: 1) Ask user for business justification, 2) Request manager approval with amount and justification, 3) If approved, retry with manager_approved=True and justification filled in." + * } + */ + SteeringContext: { + /** + * Message + * @description Guidance message explaining what needs to be corrected and how + */ + message: string; + }; + /** + * Step + * @description Runtime payload for an agent step invocation. + */ + Step: { + /** @description Optional context (conversation history, metadata, etc.) */ + context?: components["schemas"]["JSONObject"] | null; + /** @description Input content for this step */ + input: components["schemas"]["JSONValue"]; + /** + * Name + * @description Step name (tool name or model/chain id) + */ + name: string; + /** @description Output content for this step (None for pre-checks) */ + output?: components["schemas"]["JSONValue"] | null; + /** + * Type + * @description Step type (e.g., 'tool', 'llm') + */ + type: string; + }; + /** + * StepKey + * @description Identifies a registered step schema by type and name. + */ + StepKey: { + /** + * Name + * @description Registered step name + */ + name: string; + /** + * Type + * @description Step type + */ + type: string; + }; + /** + * StepSchema + * @description Schema for a registered agent step. + * @example { + * "description": "Search the internal knowledge base", + * "input_schema": { + * "query": { + * "description": "Search query", + * "type": "string" + * } + * }, + * "name": "search_knowledge_base", + * "output_schema": { + * "results": { + * "items": { + * "type": "object" + * }, + * "type": "array" + * } + * }, + * "type": "tool" + * } + * @example { + * "description": "Customer support response generation", + * "input_schema": { + * "messages": { + * "items": { + * "type": "object" + * }, + * "type": "array" + * } + * }, + * "name": "support-answer", + * "output_schema": { + * "text": { + * "type": "string" + * } + * }, + * "type": "llm" + * } + */ + StepSchema: { + /** + * Description + * @description Optional description of the step + */ + description?: string | null; + /** + * Input Schema + * @description JSON schema describing step input + */ + input_schema?: { + [key: string]: unknown; + } | null; + /** + * Metadata + * @description Additional metadata for the step + */ + metadata?: { + [key: string]: unknown; + } | null; + /** + * Name + * @description Unique name for the step + */ + name: string; + /** + * Output Schema + * @description JSON schema describing step output + */ + output_schema?: { + [key: string]: unknown; + } | null; + /** + * Type + * @description Step type for this schema (e.g., 'tool', 'llm') + */ + type: string; + }; + /** + * TimeseriesBucket + * @description Single data point in a time-series. + * + * Represents aggregated metrics for a single time bucket. + * + * Attributes: + * timestamp: Start time of the bucket (UTC, always timezone-aware) + * execution_count: Total executions in this bucket + * match_count: Number of matches in this bucket + * non_match_count: Number of non-matches in this bucket + * error_count: Number of errors in this bucket + * action_counts: Breakdown of actions for matched executions + * avg_confidence: Average confidence score (None if no executions) + * avg_duration_ms: Average execution duration in milliseconds (None if no data) + */ + TimeseriesBucket: { + /** + * Action Counts + * @description Action breakdown: {allow, deny, steer, warn, log} + */ + action_counts?: { + [key: string]: number; + }; + /** + * Avg Confidence + * @description Average confidence score + */ + avg_confidence?: number | null; + /** + * Avg Duration Ms + * @description Average duration (ms) + */ + avg_duration_ms?: number | null; + /** + * Error Count + * @description Errors in bucket + */ + error_count: number; + /** + * Execution Count + * @description Total executions in bucket + */ + execution_count: number; + /** + * Match Count + * @description Matches in bucket + */ + match_count: number; + /** + * Non Match Count + * @description Non-matches in bucket + */ + non_match_count: number; + /** + * Timestamp + * Format: date-time + * @description Start time of the bucket (UTC) + */ + timestamp: string; + }; + /** + * UpdateEvaluatorConfigRequest + * @description Request to replace an evaluator config template. + */ + UpdateEvaluatorConfigRequest: { + /** + * Config + * @description Evaluator-specific configuration + */ + config: { + [key: string]: unknown; + }; + /** + * Description + * @description Optional description + */ + description?: string | null; + /** + * Evaluator + * @description Evaluator name (built-in or custom) + */ + evaluator: string; + /** + * Name + * @description Unique evaluator config name (letters, numbers, hyphens, underscores) + */ + name: string; + }; + /** + * ValidateControlDataRequest + * @description Request to validate control configuration data without saving. + */ + ValidateControlDataRequest: { + /** @description Control configuration data to validate */ + data: components["schemas"]["ControlDefinition-Input"]; + }; + /** ValidateControlDataResponse */ + ValidateControlDataResponse: { + /** + * Success + * @description Whether the control data is valid + */ + success: boolean; + }; + /** ValidationError */ + ValidationError: { + /** Location */ + loc: (string | number)[]; + /** Message */ + msg: string; + /** Error Type */ + type: string; + }; + }; + responses: never; + parameters: never; + requestBodies: never; + headers: never; + pathItems: never; } export type $defs = Record; export interface operations { - get_config_api_config_get: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Configuration flags for UI behavior */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['ConfigResponse']; - }; - }; - }; - }; - login_api_login_post: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - 'application/json': components['schemas']['LoginRequest']; - }; - }; - responses: { - /** @description Authentication result; sets HttpOnly session cookie on success */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['LoginResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - logout_api_logout_post: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Successful Response */ - 204: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - }; - }; - list_agents_api_v1_agents_get: { - parameters: { - query?: { - cursor?: string | null; - limit?: number; - name?: string | null; - }; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Paginated list of agent summaries */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['ListAgentsResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - init_agent_api_v1_agents_initAgent_post: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - 'application/json': components['schemas']['InitAgentRequest']; - }; - }; - responses: { - /** @description Agent registration status with active controls */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['InitAgentResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - get_agent_api_v1_agents__agent_name__get: { - parameters: { - query?: never; - header?: never; - path: { - agent_name: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Agent metadata and registered steps */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['GetAgentResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - patch_agent_api_v1_agents__agent_name__patch: { - parameters: { - query?: never; - header?: never; - path: { - agent_name: string; - }; - cookie?: never; - }; - requestBody: { - content: { - 'application/json': components['schemas']['PatchAgentRequest']; - }; - }; - responses: { - /** @description Lists of removed items */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['PatchAgentResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - list_agent_controls_api_v1_agents__agent_name__controls_get: { - parameters: { - query?: never; - header?: never; - path: { - agent_name: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description List of controls from agent policy and direct associations */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['AgentControlsResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - add_agent_control_api_v1_agents__agent_name__controls__control_id__post: { - parameters: { - query?: never; - header?: never; - path: { - agent_name: string; - control_id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Success confirmation */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['AssocResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - remove_agent_control_api_v1_agents__agent_name__controls__control_id__delete: { - parameters: { - query?: never; - header?: never; - path: { - agent_name: string; - control_id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Success confirmation */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['RemoveAgentControlResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - list_agent_evaluators_api_v1_agents__agent_name__evaluators_get: { - parameters: { - query?: { - cursor?: string | null; - limit?: number; - }; - header?: never; - path: { - agent_name: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Evaluator schemas registered with this agent */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['ListEvaluatorsResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - get_agent_evaluator_api_v1_agents__agent_name__evaluators__evaluator_name__get: { - parameters: { - query?: never; - header?: never; - path: { - agent_name: string; - evaluator_name: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Evaluator schema details */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['EvaluatorSchemaItem']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - get_agent_policies_api_v1_agents__agent_name__policies_get: { - parameters: { - query?: never; - header?: never; - path: { - agent_name: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description List of policy IDs */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['GetAgentPoliciesResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - remove_all_agent_policies_api_v1_agents__agent_name__policies_delete: { - parameters: { - query?: never; - header?: never; - path: { - agent_name: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Success confirmation */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['AssocResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - add_agent_policy_api_v1_agents__agent_name__policies__policy_id__post: { - parameters: { - query?: never; - header?: never; - path: { - agent_name: string; - policy_id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Success confirmation */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['AssocResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - remove_agent_policy_api_v1_agents__agent_name__policies__policy_id__delete: { - parameters: { - query?: never; - header?: never; - path: { - agent_name: string; - policy_id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Success confirmation */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['AssocResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - get_agent_policy_api_v1_agents__agent_name__policy_get: { - parameters: { - query?: never; - header?: never; - path: { - agent_name: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Policy ID */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['GetPolicyResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - delete_agent_policy_api_v1_agents__agent_name__policy_delete: { - parameters: { - query?: never; - header?: never; - path: { - agent_name: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Success confirmation */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['DeletePolicyResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - set_agent_policy_api_v1_agents__agent_name__policy__policy_id__post: { - parameters: { - query?: never; - header?: never; - path: { - agent_name: string; - policy_id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Success status with previous policy ID */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['SetPolicyResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - list_controls_api_v1_controls_get: { - parameters: { - query?: { - /** @description Control ID to start after */ - cursor?: number | null; - limit?: number; - /** @description Filter by name (partial, case-insensitive) */ - name?: string | null; - /** @description Filter by enabled status */ - enabled?: boolean | null; - /** @description Filter by step type (built-ins: 'tool', 'llm') */ - step_type?: string | null; - /** @description Filter by stage ('pre' or 'post') */ - stage?: string | null; - /** @description Filter by execution ('server' or 'sdk') */ - execution?: string | null; - /** @description Filter by tag */ - tag?: string | null; - }; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Paginated list of controls */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['ListControlsResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - create_control_api_v1_controls_put: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - 'application/json': components['schemas']['CreateControlRequest']; - }; - }; - responses: { - /** @description Created control ID */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['CreateControlResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - validate_control_data_api_v1_controls_validate_post: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - 'application/json': components['schemas']['ValidateControlDataRequest']; - }; - }; - responses: { - /** @description Validation result */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['ValidateControlDataResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - get_control_api_v1_controls__control_id__get: { - parameters: { - query?: never; - header?: never; - path: { - control_id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Control metadata and configuration */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['GetControlResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - delete_control_api_v1_controls__control_id__delete: { - parameters: { - query?: { - /** @description If true, dissociate from all policy/agent links before deleting. If false, fail if control is associated with any policy or agent. */ - force?: boolean; - }; - header?: never; - path: { - control_id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Deletion confirmation with dissociation info */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['DeleteControlResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - patch_control_api_v1_controls__control_id__patch: { - parameters: { - query?: never; - header?: never; - path: { - control_id: number; - }; - cookie?: never; - }; - requestBody: { - content: { - 'application/json': components['schemas']['PatchControlRequest']; - }; - }; - responses: { - /** @description Updated control information */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['PatchControlResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - get_control_data_api_v1_controls__control_id__data_get: { - parameters: { - query?: never; - header?: never; - path: { - control_id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Control data payload */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['GetControlDataResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - set_control_data_api_v1_controls__control_id__data_put: { - parameters: { - query?: never; - header?: never; - path: { - control_id: number; - }; - cookie?: never; - }; - requestBody: { - content: { - 'application/json': components['schemas']['SetControlDataRequest']; - }; - }; - responses: { - /** @description Success confirmation */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['SetControlDataResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - evaluate_api_v1_evaluation_post: { - parameters: { - query?: never; - header?: { - 'X-Trace-Id'?: string | null; - 'X-Span-Id'?: string | null; - }; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - 'application/json': components['schemas']['EvaluationRequest']; - }; - }; - responses: { - /** @description Safety analysis result */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['EvaluationResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - list_evaluator_configs_api_v1_evaluator_configs_get: { - parameters: { - query?: { - /** @description Evaluator config ID to start after */ - cursor?: number | null; - limit?: number; - /** @description Filter by name (partial, case-insensitive) */ - name?: string | null; - /** @description Filter by evaluator name */ - evaluator?: string | null; - }; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Paginated list of evaluator configs */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['ListEvaluatorConfigsResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - create_evaluator_config_api_v1_evaluator_configs_post: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - 'application/json': components['schemas']['CreateEvaluatorConfigRequest']; - }; - }; - responses: { - /** @description Created evaluator config */ - 201: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['EvaluatorConfigItem']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - get_evaluator_config_api_v1_evaluator_configs__config_id__get: { - parameters: { - query?: never; - header?: never; - path: { - config_id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Evaluator config details */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['EvaluatorConfigItem']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - update_evaluator_config_api_v1_evaluator_configs__config_id__put: { - parameters: { - query?: never; - header?: never; - path: { - config_id: number; - }; - cookie?: never; - }; - requestBody: { - content: { - 'application/json': components['schemas']['UpdateEvaluatorConfigRequest']; - }; - }; - responses: { - /** @description Updated evaluator config */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['EvaluatorConfigItem']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - delete_evaluator_config_api_v1_evaluator_configs__config_id__delete: { - parameters: { - query?: never; - header?: never; - path: { - config_id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Deletion confirmation */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['DeleteEvaluatorConfigResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - get_evaluators_api_v1_evaluators_get: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Dictionary of evaluator name to evaluator info */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': { - [key: string]: components['schemas']['EvaluatorInfo']; - }; - }; - }; - }; - }; - ingest_events_api_v1_observability_events_post: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - 'application/json': components['schemas']['BatchEventsRequest']; - }; - }; - responses: { - /** @description Successful Response */ - 202: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['BatchEventsResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - query_events_api_v1_observability_events_query_post: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - 'application/json': components['schemas']['EventQueryRequest']; - }; - }; - responses: { - /** @description Successful Response */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['EventQueryResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - get_stats_api_v1_observability_stats_get: { - parameters: { - query: { - agent_name: string; - time_range?: - | '1m' - | '5m' - | '15m' - | '1h' - | '24h' - | '7d' - | '30d' - | '180d' - | '365d'; - include_timeseries?: boolean; - }; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Successful Response */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['StatsResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - get_control_stats_api_v1_observability_stats_controls__control_id__get: { - parameters: { - query: { - agent_name: string; - time_range?: - | '1m' - | '5m' - | '15m' - | '1h' - | '24h' - | '7d' - | '30d' - | '180d' - | '365d'; - include_timeseries?: boolean; - }; - header?: never; - path: { - control_id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Successful Response */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['ControlStatsResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - get_status_api_v1_observability_status_get: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Successful Response */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': { - [key: string]: unknown; - }; - }; - }; - }; - }; - create_policy_api_v1_policies_put: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - 'application/json': components['schemas']['CreatePolicyRequest']; - }; - }; - responses: { - /** @description Created policy ID */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['CreatePolicyResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - list_policy_controls_api_v1_policies__policy_id__controls_get: { - parameters: { - query?: never; - header?: never; - path: { - policy_id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description List of control IDs */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['GetPolicyControlsResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - add_control_to_policy_api_v1_policies__policy_id__controls__control_id__post: { - parameters: { - query?: never; - header?: never; - path: { - policy_id: number; - control_id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Success confirmation */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['AssocResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - remove_control_from_policy_api_v1_policies__policy_id__controls__control_id__delete: { - parameters: { - query?: never; - header?: never; - path: { - policy_id: number; - control_id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Success confirmation */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['AssocResponse']; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HTTPValidationError']; - }; - }; - }; - }; - health_check_health_get: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Server health status */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - 'application/json': components['schemas']['HealthResponse']; + get_config_api_config_get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Configuration flags for UI behavior */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ConfigResponse"]; + }; + }; + }; + }; + login_api_login_post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["LoginRequest"]; + }; + }; + responses: { + /** @description Authentication result; sets HttpOnly session cookie on success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["LoginResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + logout_api_logout_post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + list_agents_api_v1_agents_get: { + parameters: { + query?: { + cursor?: string | null; + limit?: number; + name?: string | null; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Paginated list of agent summaries */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ListAgentsResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + init_agent_api_v1_agents_initAgent_post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["InitAgentRequest"]; + }; + }; + responses: { + /** @description Agent registration status with active controls */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["InitAgentResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_agent_api_v1_agents__agent_name__get: { + parameters: { + query?: never; + header?: never; + path: { + agent_name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Agent metadata and registered steps */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["GetAgentResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + patch_agent_api_v1_agents__agent_name__patch: { + parameters: { + query?: never; + header?: never; + path: { + agent_name: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["PatchAgentRequest"]; + }; + }; + responses: { + /** @description Lists of removed items */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PatchAgentResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + list_agent_controls_api_v1_agents__agent_name__controls_get: { + parameters: { + query?: never; + header?: never; + path: { + agent_name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description List of controls from agent policy and direct associations */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["AgentControlsResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + add_agent_control_api_v1_agents__agent_name__controls__control_id__post: { + parameters: { + query?: never; + header?: never; + path: { + agent_name: string; + control_id: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success confirmation */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["AssocResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + remove_agent_control_api_v1_agents__agent_name__controls__control_id__delete: { + parameters: { + query?: never; + header?: never; + path: { + agent_name: string; + control_id: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success confirmation */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["RemoveAgentControlResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + list_agent_evaluators_api_v1_agents__agent_name__evaluators_get: { + parameters: { + query?: { + cursor?: string | null; + limit?: number; + }; + header?: never; + path: { + agent_name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Evaluator schemas registered with this agent */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ListEvaluatorsResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_agent_evaluator_api_v1_agents__agent_name__evaluators__evaluator_name__get: { + parameters: { + query?: never; + header?: never; + path: { + agent_name: string; + evaluator_name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Evaluator schema details */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["EvaluatorSchemaItem"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_agent_policies_api_v1_agents__agent_name__policies_get: { + parameters: { + query?: never; + header?: never; + path: { + agent_name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description List of policy IDs */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["GetAgentPoliciesResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + remove_all_agent_policies_api_v1_agents__agent_name__policies_delete: { + parameters: { + query?: never; + header?: never; + path: { + agent_name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success confirmation */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["AssocResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + add_agent_policy_api_v1_agents__agent_name__policies__policy_id__post: { + parameters: { + query?: never; + header?: never; + path: { + agent_name: string; + policy_id: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success confirmation */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["AssocResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + remove_agent_policy_api_v1_agents__agent_name__policies__policy_id__delete: { + parameters: { + query?: never; + header?: never; + path: { + agent_name: string; + policy_id: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success confirmation */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["AssocResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_agent_policy_api_v1_agents__agent_name__policy_get: { + parameters: { + query?: never; + header?: never; + path: { + agent_name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Policy ID */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["GetPolicyResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + delete_agent_policy_api_v1_agents__agent_name__policy_delete: { + parameters: { + query?: never; + header?: never; + path: { + agent_name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success confirmation */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DeletePolicyResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + set_agent_policy_api_v1_agents__agent_name__policy__policy_id__post: { + parameters: { + query?: never; + header?: never; + path: { + agent_name: string; + policy_id: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success status with previous policy ID */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["SetPolicyResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + list_controls_api_v1_controls_get: { + parameters: { + query?: { + /** @description Control ID to start after */ + cursor?: number | null; + limit?: number; + /** @description Filter by name (partial, case-insensitive) */ + name?: string | null; + /** @description Filter by enabled status */ + enabled?: boolean | null; + /** @description Filter by step type (built-ins: 'tool', 'llm') */ + step_type?: string | null; + /** @description Filter by stage ('pre' or 'post') */ + stage?: string | null; + /** @description Filter by execution ('server' or 'sdk') */ + execution?: string | null; + /** @description Filter by tag */ + tag?: string | null; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Paginated list of controls */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ListControlsResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + create_control_api_v1_controls_put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreateControlRequest"]; + }; + }; + responses: { + /** @description Created control ID */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CreateControlResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + validate_control_data_api_v1_controls_validate_post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ValidateControlDataRequest"]; + }; + }; + responses: { + /** @description Validation result */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ValidateControlDataResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_control_api_v1_controls__control_id__get: { + parameters: { + query?: never; + header?: never; + path: { + control_id: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Control metadata and configuration */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["GetControlResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + delete_control_api_v1_controls__control_id__delete: { + parameters: { + query?: { + /** @description If true, dissociate from all policy/agent links before deleting. If false, fail if control is associated with any policy or agent. */ + force?: boolean; + }; + header?: never; + path: { + control_id: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Deletion confirmation with dissociation info */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DeleteControlResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + patch_control_api_v1_controls__control_id__patch: { + parameters: { + query?: never; + header?: never; + path: { + control_id: number; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["PatchControlRequest"]; + }; + }; + responses: { + /** @description Updated control information */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PatchControlResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_control_data_api_v1_controls__control_id__data_get: { + parameters: { + query?: never; + header?: never; + path: { + control_id: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Control data payload */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["GetControlDataResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + set_control_data_api_v1_controls__control_id__data_put: { + parameters: { + query?: never; + header?: never; + path: { + control_id: number; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["SetControlDataRequest"]; + }; + }; + responses: { + /** @description Success confirmation */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["SetControlDataResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + evaluate_api_v1_evaluation_post: { + parameters: { + query?: never; + header?: { + "X-Trace-Id"?: string | null; + "X-Span-Id"?: string | null; + }; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["EvaluationRequest"]; + }; + }; + responses: { + /** @description Safety analysis result */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["EvaluationResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + list_evaluator_configs_api_v1_evaluator_configs_get: { + parameters: { + query?: { + /** @description Evaluator config ID to start after */ + cursor?: number | null; + limit?: number; + /** @description Filter by name (partial, case-insensitive) */ + name?: string | null; + /** @description Filter by evaluator name */ + evaluator?: string | null; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Paginated list of evaluator configs */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ListEvaluatorConfigsResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + create_evaluator_config_api_v1_evaluator_configs_post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreateEvaluatorConfigRequest"]; + }; + }; + responses: { + /** @description Created evaluator config */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["EvaluatorConfigItem"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_evaluator_config_api_v1_evaluator_configs__config_id__get: { + parameters: { + query?: never; + header?: never; + path: { + config_id: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Evaluator config details */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["EvaluatorConfigItem"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + update_evaluator_config_api_v1_evaluator_configs__config_id__put: { + parameters: { + query?: never; + header?: never; + path: { + config_id: number; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdateEvaluatorConfigRequest"]; + }; + }; + responses: { + /** @description Updated evaluator config */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["EvaluatorConfigItem"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + delete_evaluator_config_api_v1_evaluator_configs__config_id__delete: { + parameters: { + query?: never; + header?: never; + path: { + config_id: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Deletion confirmation */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DeleteEvaluatorConfigResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_evaluators_api_v1_evaluators_get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Dictionary of evaluator name to evaluator info */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + [key: string]: components["schemas"]["EvaluatorInfo"]; + }; + }; + }; + }; + }; + ingest_events_api_v1_observability_events_post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["BatchEventsRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 202: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["BatchEventsResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + query_events_api_v1_observability_events_query_post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["EventQueryRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["EventQueryResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_stats_api_v1_observability_stats_get: { + parameters: { + query: { + agent_name: string; + time_range?: "1m" | "5m" | "15m" | "1h" | "24h" | "7d" | "30d" | "180d" | "365d"; + include_timeseries?: boolean; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["StatsResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_control_stats_api_v1_observability_stats_controls__control_id__get: { + parameters: { + query: { + agent_name: string; + time_range?: "1m" | "5m" | "15m" | "1h" | "24h" | "7d" | "30d" | "180d" | "365d"; + include_timeseries?: boolean; + }; + header?: never; + path: { + control_id: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ControlStatsResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + get_status_api_v1_observability_status_get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + [key: string]: unknown; + }; + }; + }; + }; + }; + create_policy_api_v1_policies_put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreatePolicyRequest"]; + }; + }; + responses: { + /** @description Created policy ID */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CreatePolicyResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + list_policy_controls_api_v1_policies__policy_id__controls_get: { + parameters: { + query?: never; + header?: never; + path: { + policy_id: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description List of control IDs */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["GetPolicyControlsResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + add_control_to_policy_api_v1_policies__policy_id__controls__control_id__post: { + parameters: { + query?: never; + header?: never; + path: { + policy_id: number; + control_id: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success confirmation */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["AssocResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + remove_control_from_policy_api_v1_policies__policy_id__controls__control_id__delete: { + parameters: { + query?: never; + header?: never; + path: { + policy_id: number; + control_id: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success confirmation */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["AssocResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + health_check_health_get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Server health status */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HealthResponse"]; + }; + }; }; - }; }; - }; } diff --git a/ui/src/core/hooks/query-hooks/use-add-control-to-agent.ts b/ui/src/core/hooks/query-hooks/use-add-control-to-agent.ts index 40c9ce2c..932699aa 100644 --- a/ui/src/core/hooks/query-hooks/use-add-control-to-agent.ts +++ b/ui/src/core/hooks/query-hooks/use-add-control-to-agent.ts @@ -13,9 +13,8 @@ type AddControlToAgentParams = { /** * Mutation hook to add a control to an agent * Flow: - * 1. Create the control - * 2. Set control data (definition) - * 3. Associate the control directly with the agent + * 1. Create the control with its definition + * 2. Associate the control directly with the agent */ export function useAddControlToAgent() { const queryClient = useQueryClient(); @@ -29,12 +28,12 @@ export function useAddControlToAgent() { let createdControlId: number | null = null; try { - // Step 1: Create the control + // Step 1: Create and validate the control atomically. const { data: createControlResult, error: createControlError, response: createControlResponse, - } = await api.controls.create({ name: controlName }); + } = await api.controls.create({ name: controlName, data: definition }); if (createControlError || !createControlResult) { throw parseApiError( @@ -46,21 +45,7 @@ export function useAddControlToAgent() { createdControlId = createControlResult.control_id; - // Step 2: Set control data (definition) - const { error: setDataError, response: setDataResponse } = - await api.controls.setData(createdControlId, { - data: definition, - }); - - if (setDataError) { - throw parseApiError( - setDataError, - 'Failed to set control data', - setDataResponse?.status - ); - } - - // Step 3: Associate control directly with the agent. + // Step 2: Associate control directly with the agent. const { error: associateError, response: associateResponse } = await api.agents.addControl(agentId, createdControlId); diff --git a/ui/src/core/hooks/query-hooks/use-create-control.ts b/ui/src/core/hooks/query-hooks/use-create-control.ts index 3a89d46f..521795ba 100644 --- a/ui/src/core/hooks/query-hooks/use-create-control.ts +++ b/ui/src/core/hooks/query-hooks/use-create-control.ts @@ -9,31 +9,20 @@ type CreateControlParams = { }; /** - * Mutation hook to create a new control with its definition - * 1. Creates the control with a name - * 2. Sets the control data (definition) + * Mutation hook to create a new control with its definition in one request. */ export function useCreateControl() { const queryClient = useQueryClient(); return useMutation({ mutationFn: async ({ name, definition }: CreateControlParams) => { - // Step 1: Create control with name + // Create and validate the control atomically on the server. const { data: createResult, error: createError } = - await api.controls.create({ name }); + await api.controls.create({ name, data: definition }); if (createError) throw createError; if (!createResult) throw new Error('Failed to create control'); - - const controlId = createResult.control_id; - - // Step 2: Set control data (definition) - const { data: setDataResult, error: setDataError } = - await api.controls.setData(controlId, { data: definition }); - - if (setDataError) throw setDataError; - - return { controlId, ...setDataResult }; + return { controlId: createResult.control_id, success: true }; }, onSuccess: () => { // Invalidate relevant queries to refetch data From 5f03ba36d28b3dea8880b533ac49d5d0b713aaa8 Mon Sep 17 00:00:00 2001 From: Lev Neiman Date: Thu, 19 Mar 2026 18:20:39 -0700 Subject: [PATCH 2/5] fix: require control data on create --- examples/agent_control_demo/setup_controls.py | 11 +--- examples/deepeval/setup_controls.py | 19 +++---- models/src/agent_control_models/server.py | 6 +-- sdks/python/ARCHITECTURE.md | 22 +++++++- sdks/python/src/agent_control/__init__.py | 14 ++--- .../src/agent_control/control_decorators.py | 3 +- sdks/python/src/agent_control/controls.py | 27 ++++------ .../src/generated/funcs/controls-create.ts | 4 +- .../models/create-control-request.ts | 13 +++-- sdks/typescript/src/generated/sdk/controls.ts | 4 +- .../endpoints/controls.py | 10 ++-- server/src/agent_control_server/main.py | 2 +- server/tests/test_agents_additional.py | 32 ++++++++---- server/tests/test_auth.py | 14 ++++- server/tests/test_control_compatibility.py | 32 ++++++------ server/tests/test_controls.py | 51 +++++++++++++------ server/tests/test_controls_additional.py | 31 +++++++++-- server/tests/test_controls_validation.py | 2 +- server/tests/test_error_handling.py | 22 ++++++-- server/tests/test_evaluation_e2e.py | 12 +++-- .../tests/test_evaluation_error_handling.py | 24 ++++----- server/tests/test_init_agent.py | 7 +-- server/tests/test_init_agent_conflict_mode.py | 14 ++--- server/tests/test_new_features.py | 20 +++----- server/tests/test_policies.py | 4 +- server/tests/test_policy_integration.py | 11 +--- server/tests/utils.py | 14 ++--- ui/src/core/api/generated/api-types.ts | 8 +-- 28 files changed, 242 insertions(+), 191 deletions(-) diff --git a/examples/agent_control_demo/setup_controls.py b/examples/agent_control_demo/setup_controls.py index 09811fcb..3c3a97c1 100644 --- a/examples/agent_control_demo/setup_controls.py +++ b/examples/agent_control_demo/setup_controls.py @@ -77,10 +77,10 @@ async def create_control( ) -> int: """Create a control with the given definition.""" try: - # Step 1: Create the control (just the name) + # Create and validate the control atomically. response = await client.http_client.put( "/api/v1/controls", - json={"name": name} + json={"name": name, "data": control_definition}, ) if response.status_code == 409: @@ -93,13 +93,6 @@ async def create_control( response.raise_for_status() control_id = response.json().get("control_id") - # Step 2: Set the control data - response = await client.http_client.put( - f"/api/v1/controls/{control_id}/data", - json={"data": control_definition} - ) - response.raise_for_status() - print(f"✓ Created control '{name}' with ID: {control_id}") return control_id diff --git a/examples/deepeval/setup_controls.py b/examples/deepeval/setup_controls.py index 86caad58..a7913326 100755 --- a/examples/deepeval/setup_controls.py +++ b/examples/deepeval/setup_controls.py @@ -193,12 +193,13 @@ async def setup_demo(quiet: bool = False): description = control_spec["description"] try: - # Create control + # Create and validate the control atomically. resp = await client.put( "/api/v1/controls", - json={"name": control_name}, + json={"name": control_name, "data": definition}, ) - if resp.status_code == 409: + control_exists = resp.status_code == 409 + if control_exists: # Control exists, get its ID resp = await client.get("/api/v1/controls", params={"name": control_name}) resp.raise_for_status() @@ -213,12 +214,12 @@ async def setup_demo(quiet: bool = False): control_id = resp.json()["control_id"] controls_created += 1 - # Set control definition - resp = await client.put( - f"/api/v1/controls/{control_id}/data", - json={"data": definition}, - ) - resp.raise_for_status() + if control_exists: + resp = await client.put( + f"/api/v1/controls/{control_id}/data", + json={"data": definition}, + ) + resp.raise_for_status() # Associate control directly with the agent resp = await client.post(f"/api/v1/agents/{agent_name}/controls/{control_id}") diff --git a/models/src/agent_control_models/server.py b/models/src/agent_control_models/server.py index 8c7ced01..bf388707 100644 --- a/models/src/agent_control_models/server.py +++ b/models/src/agent_control_models/server.py @@ -119,9 +119,9 @@ class CreateControlRequest(BaseModel): ..., description="Unique control name (letters, numbers, hyphens, underscores)", ) - data: ControlDefinition | None = Field( - default=None, - description="Optional control definition to validate and store during creation", + data: ControlDefinition = Field( + ..., + description="Control definition to validate and store during creation", ) diff --git a/sdks/python/ARCHITECTURE.md b/sdks/python/ARCHITECTURE.md index 6c1d8db3..ff67180b 100644 --- a/sdks/python/ARCHITECTURE.md +++ b/sdks/python/ARCHITECTURE.md @@ -113,7 +113,7 @@ async with agent_control.AgentControlClient() as client: - `GET /api/v1/controls/{control_id}/rules` - List control rules **Functions**: -- `async def create_control(client, name)` - Create a new control +- `async def create_control(client, name, data)` - Create a new configured control - `async def add_rule_to_control(client, control_id, rule_id)` - Associate rule - `async def remove_rule_from_control(client, control_id, rule_id)` - Dissociate rule - `async def list_control_rules(client, control_id)` - List all rules in control @@ -124,7 +124,25 @@ import agent_control async with agent_control.AgentControlClient() as client: # Create control - result = await agent_control.controls.create_control(client, "pii-protection") + result = await agent_control.controls.create_control( + client, + "pii-protection", + { + "description": "PII protection", + "enabled": True, + "execution": "server", + "scope": {"step_types": ["llm"], "stages": ["post"]}, + "condition": { + "selector": {"path": "output"}, + "evaluator": { + "name": "regex", + "config": {"pattern": "\\\\d{3}-\\\\d{2}-\\\\d{4}", "flags": []}, + }, + }, + "action": {"decision": "deny"}, + "tags": ["security"], + }, + ) control_id = result["control_id"] # Add rule to control diff --git a/sdks/python/src/agent_control/__init__.py b/sdks/python/src/agent_control/__init__.py index b3e41d90..33658fb4 100644 --- a/sdks/python/src/agent_control/__init__.py +++ b/sdks/python/src/agent_control/__init__.py @@ -935,26 +935,23 @@ async def main(): async def create_control( name: str, - data: dict[str, Any] | ControlDefinition | None = None, + data: dict[str, Any] | ControlDefinition, server_url: str | None = None, api_key: str | None = None, ) -> dict[str, Any]: """ - Create a new control, optionally with configuration. - - If `data` is provided, the control is created and configured in one call. - Otherwise, use `agent_control.controls.set_control_data()` to configure it later. + Create a new control with configuration. Args: name: Unique name for the control - data: Optional control definition with a condition tree, action, scope, etc. + data: Control definition with a condition tree, action, scope, etc. server_url: Optional server URL (defaults to AGENT_CONTROL_URL env var) api_key: Optional API key for authentication (defaults to AGENT_CONTROL_API_KEY env var) Returns: Dictionary containing: - control_id: ID of the created control - - configured: True if data was set, False if only name was created + - configured: Always True because create requires data Raises: httpx.HTTPError: If request fails @@ -984,9 +981,6 @@ async def main(): ) print(f"Created control {result['control_id']}") - # Or create without config (configure later) - result = await agent_control.create_control(name="my-control") - asyncio.run(main()) """ _final_server_url = server_url or os.getenv('AGENT_CONTROL_URL') or 'http://localhost:8000' diff --git a/sdks/python/src/agent_control/control_decorators.py b/sdks/python/src/agent_control/control_decorators.py index 1da113b1..d1edb06e 100644 --- a/sdks/python/src/agent_control/control_decorators.py +++ b/sdks/python/src/agent_control/control_decorators.py @@ -793,8 +793,7 @@ async def handle_user_input(user_message: str) -> str: Server Setup (separate from agent code): 1. Create controls via API: - PUT /api/v1/controls {"name": "block-toxic-inputs"} - PUT /api/v1/controls/{id}/data {"data": {...}} + PUT /api/v1/controls {"name": "block-toxic-inputs", "data": {...}} 2. Create policy and add controls: PUT /api/v1/policies {"name": "safety-policy"} diff --git a/sdks/python/src/agent_control/controls.py b/sdks/python/src/agent_control/controls.py index 1994fe68..767f2c86 100644 --- a/sdks/python/src/agent_control/controls.py +++ b/sdks/python/src/agent_control/controls.py @@ -118,13 +118,10 @@ async def get_control( async def create_control( client: AgentControlClient, name: str, - data: dict[str, Any] | ControlDefinition | None = None, + data: dict[str, Any] | ControlDefinition, ) -> dict[str, Any]: """ - Create a new control with a unique name, optionally with configuration. - - If `data` is provided, the control is created and configured in one call. - Otherwise, use `set_control_data()` to configure it later. + Create a new control with a unique name and configuration. Control names are canonicalized by the API (leading/trailing whitespace is trimmed); callers may pass trimmed names for consistency. @@ -132,12 +129,12 @@ async def create_control( Args: client: AgentControlClient instance name: Unique name for the control - data: Optional control definition (condition tree, action, scope, etc.) + data: Control definition (condition tree, action, scope, etc.) Returns: Dictionary containing: - control_id: ID of the created control - - configured: True if data was set, False if only name was created + - configured: Always True because create requires data Raises: httpx.HTTPError: If request fails @@ -147,11 +144,6 @@ async def create_control( Example: async with AgentControlClient() as client: - # Create without configuration (configure later) - result = await create_control(client, "pii-protection") - control_id = result["control_id"] - - # Or create with configuration in one call result = await create_control( client, name="ssn-blocker", @@ -171,11 +163,10 @@ async def create_control( print(f"Created and configured control: {result['control_id']}") """ payload: dict[str, Any] = {"name": name} - if data is not None: - if isinstance(data, ControlDefinition): - payload["data"] = data.model_dump(mode="json", exclude_none=True) - else: - payload["data"] = cast(dict[str, Any], data) + if isinstance(data, ControlDefinition): + payload["data"] = data.model_dump(mode="json", exclude_none=True) + else: + payload["data"] = cast(dict[str, Any], data) response = await client.http_client.put( "/api/v1/controls", @@ -184,7 +175,7 @@ async def create_control( response.raise_for_status() result = cast(dict[str, Any], response.json()) - result["configured"] = data is not None + result["configured"] = True return result diff --git a/sdks/typescript/src/generated/funcs/controls-create.ts b/sdks/typescript/src/generated/funcs/controls-create.ts index 380f1c17..188be0c4 100644 --- a/sdks/typescript/src/generated/funcs/controls-create.ts +++ b/sdks/typescript/src/generated/funcs/controls-create.ts @@ -33,10 +33,10 @@ import { Result } from "../types/fp.js"; * Create a new control with a unique name. * * Controls define protection logic and can be added to policies. - * Optionally provide control data to validate and persist it atomically. + * Control data is required and is validated before anything is inserted. * * Args: - * request: Control creation request with unique name and optional data + * request: Control creation request with unique name and data * db: Database session (injected) * * Returns: diff --git a/sdks/typescript/src/generated/models/create-control-request.ts b/sdks/typescript/src/generated/models/create-control-request.ts index 0cb5e0bc..83a198ba 100644 --- a/sdks/typescript/src/generated/models/create-control-request.ts +++ b/sdks/typescript/src/generated/models/create-control-request.ts @@ -11,9 +11,14 @@ import { export type CreateControlRequest = { /** - * Optional control definition to validate and store during creation + * A control definition to evaluate agent interactions. + * + * @remarks + * + * This model contains only the logic and configuration. + * Identity fields (id, name) are managed by the database. */ - data?: ControlDefinitionInput | null | undefined; + data: ControlDefinitionInput; /** * Unique control name (letters, numbers, hyphens, underscores) */ @@ -22,7 +27,7 @@ export type CreateControlRequest = { /** @internal */ export type CreateControlRequest$Outbound = { - data?: ControlDefinitionInput$Outbound | null | undefined; + data: ControlDefinitionInput$Outbound; name: string; }; @@ -31,7 +36,7 @@ export const CreateControlRequest$outboundSchema: z.ZodMiniType< CreateControlRequest$Outbound, CreateControlRequest > = z.object({ - data: z.optional(z.nullable(ControlDefinitionInput$outboundSchema)), + data: ControlDefinitionInput$outboundSchema, name: z.string(), }); diff --git a/sdks/typescript/src/generated/sdk/controls.ts b/sdks/typescript/src/generated/sdk/controls.ts index 7d94a8d2..67583335 100644 --- a/sdks/typescript/src/generated/sdk/controls.ts +++ b/sdks/typescript/src/generated/sdk/controls.ts @@ -59,10 +59,10 @@ export class Controls extends ClientSDK { * Create a new control with a unique name. * * Controls define protection logic and can be added to policies. - * Optionally provide control data to validate and persist it atomically. + * Control data is required and is validated before anything is inserted. * * Args: - * request: Control creation request with unique name and optional data + * request: Control creation request with unique name and data * db: Database session (injected) * * Returns: diff --git a/server/src/agent_control_server/endpoints/controls.py b/server/src/agent_control_server/endpoints/controls.py index 1f32b0c2..4f83df96 100644 --- a/server/src/agent_control_server/endpoints/controls.py +++ b/server/src/agent_control_server/endpoints/controls.py @@ -270,10 +270,10 @@ async def create_control( Create a new control with a unique name. Controls define protection logic and can be added to policies. - Optionally provide control data to validate and persist it atomically. + Control data is required and is validated before anything is inserted. Args: - request: Control creation request with unique name and optional data + request: Control creation request with unique name and data db: Database session (injected) Returns: @@ -294,10 +294,8 @@ async def create_control( hint="Choose a different name or update the existing control.", ) - control_data: dict[str, object] = {} - if request.data is not None: - await _validate_control_definition(request.data, db) - control_data = _serialize_control_definition(request.data) + await _validate_control_definition(request.data, db) + control_data = _serialize_control_definition(request.data) control = Control(name=request.name, data=control_data) db.add(control) diff --git a/server/src/agent_control_server/main.py b/server/src/agent_control_server/main.py index 50429fa5..6fbeee2b 100644 --- a/server/src/agent_control_server/main.py +++ b/server/src/agent_control_server/main.py @@ -140,7 +140,7 @@ async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]: ## Quick Start 1. Register your agent with `/api/v1/agents/initAgent` -2. Create controls with `/api/v1/controls` and configure them +2. Create configured controls with `/api/v1/controls` 3. Create a policy and add controls to it 4. Assign the policy to your agent 5. Query agent's active controls with `/api/v1/agents/{agent_name}/controls` diff --git a/server/tests/test_agents_additional.py b/server/tests/test_agents_additional.py index 8c69f79f..1044a89f 100644 --- a/server/tests/test_agents_additional.py +++ b/server/tests/test_agents_additional.py @@ -6,6 +6,9 @@ from fastapi.testclient import TestClient from sqlalchemy import text +from sqlalchemy.orm import Session + +from agent_control_server.models import Control from .utils import VALID_CONTROL_PAYLOAD, canonicalize_control_payload from .conftest import engine @@ -36,15 +39,24 @@ def _init_agent( def _create_control_with_data(client: TestClient, data: dict) -> int: - resp = client.put("/api/v1/controls", json={"name": f"control-{uuid.uuid4()}"}) - assert resp.status_code == 200 - control_id = resp.json()["control_id"] - set_resp = client.put( - f"/api/v1/controls/{control_id}/data", - json={"data": canonicalize_control_payload(data)}, + resp = client.put( + "/api/v1/controls", + json={ + "name": f"control-{uuid.uuid4()}", + "data": canonicalize_control_payload(data), + }, ) - assert set_resp.status_code == 200, set_resp.text - return control_id + assert resp.status_code == 200, resp.text + return resp.json()["control_id"] + + +def _insert_unconfigured_control() -> int: + control = Control(name=f"control-{uuid.uuid4()}", data={}) + with Session(engine) as session: + session.add(control) + session.commit() + session.refresh(control) + return int(control.id) def _create_policy(client: TestClient) -> int: @@ -661,9 +673,7 @@ def test_set_agent_policy_skips_controls_without_data(client: TestClient) -> Non # Given: an agent and a policy with a control that has no data configured agent_name, _ = _init_agent(client) policy_id = _create_policy(client) - control_resp = client.put("/api/v1/controls", json={"name": f"control-{uuid.uuid4()}"}) - assert control_resp.status_code == 200 - control_id = control_resp.json()["control_id"] + control_id = _insert_unconfigured_control() assoc = client.post(f"/api/v1/policies/{policy_id}/controls/{control_id}") assert assoc.status_code == 200 diff --git a/server/tests/test_auth.py b/server/tests/test_auth.py index d31522a8..7f6d8d6f 100644 --- a/server/tests/test_auth.py +++ b/server/tests/test_auth.py @@ -8,6 +8,9 @@ from agent_control_server import __version__ as server_version from agent_control_server.config import auth_settings +from .utils import VALID_CONTROL_PAYLOAD + + class TestHealthEndpoint: """Health endpoint should always be accessible without authentication.""" @@ -163,7 +166,11 @@ class TestAdminWriteEndpointAuthorization: @pytest.mark.parametrize( ("method", "path", "json_body"), [ - ("PUT", "/api/v1/controls", {"name": "control-authz-blocked"}), + ( + "PUT", + "/api/v1/controls", + {"name": "control-authz-blocked", "data": _VALID_CONTROL_DATA}, + ), ("PUT", "/api/v1/controls/1/data", {"data": _VALID_CONTROL_DATA}), ("PATCH", "/api/v1/controls/1", {"enabled": False}), ("DELETE", "/api/v1/controls/1", None), @@ -248,7 +255,10 @@ def test_non_admin_key_can_init_agent_and_fetch_controls( def test_admin_key_allowed_on_representative_mutations(self, admin_client: TestClient) -> None: control_name = f"control-authz-{uuid.uuid4().hex[:8]}" - control_response = admin_client.put("/api/v1/controls", json={"name": control_name}) + control_response = admin_client.put( + "/api/v1/controls", + json={"name": control_name, "data": VALID_CONTROL_PAYLOAD}, + ) assert control_response.status_code == 200 control_id = control_response.json()["control_id"] diff --git a/server/tests/test_control_compatibility.py b/server/tests/test_control_compatibility.py index 6485f1c3..f6e39fd5 100644 --- a/server/tests/test_control_compatibility.py +++ b/server/tests/test_control_compatibility.py @@ -52,16 +52,13 @@ def test_set_agent_policy_accepts_legacy_stored_control_payload(client: TestClie agent_name = _init_agent(client) policy_id = _create_policy(client) - control_resp = client.put("/api/v1/controls", json={"name": f"control-{uuid.uuid4()}"}) + control_resp = client.put( + "/api/v1/controls", + json={"name": f"control-{uuid.uuid4()}", "data": VALID_CONTROL_PAYLOAD}, + ) assert control_resp.status_code == 200 control_id = control_resp.json()["control_id"] - set_resp = client.put( - f"/api/v1/controls/{control_id}/data", - json={"data": VALID_CONTROL_PAYLOAD}, - ) - assert set_resp.status_code == 200 - assoc = client.post(f"/api/v1/policies/{policy_id}/controls/{control_id}") assert assoc.status_code == 200 @@ -83,7 +80,10 @@ def test_get_control_data_returns_canonical_shape_for_legacy_stored_payload( client: TestClient, ) -> None: # Given: a control whose stored row has been reverted to the legacy flat shape - control_resp = client.put("/api/v1/controls", json={"name": f"control-{uuid.uuid4()}"}) + control_resp = client.put( + "/api/v1/controls", + json={"name": f"control-{uuid.uuid4()}", "data": VALID_CONTROL_PAYLOAD}, + ) assert control_resp.status_code == 200 control_id = control_resp.json()["control_id"] @@ -112,16 +112,13 @@ def test_list_agent_controls_returns_canonical_shape_for_legacy_stored_payload( agent_name = _init_agent(client) policy_id = _create_policy(client) - control_resp = client.put("/api/v1/controls", json={"name": f"control-{uuid.uuid4()}"}) + control_resp = client.put( + "/api/v1/controls", + json={"name": f"control-{uuid.uuid4()}", "data": VALID_CONTROL_PAYLOAD}, + ) assert control_resp.status_code == 200 control_id = control_resp.json()["control_id"] - set_resp = client.put( - f"/api/v1/controls/{control_id}/data", - json={"data": VALID_CONTROL_PAYLOAD}, - ) - assert set_resp.status_code == 200 - assoc = client.post(f"/api/v1/policies/{policy_id}/controls/{control_id}") assert assoc.status_code == 200 assign = client.post(f"/api/v1/agents/{agent_name}/policy/{policy_id}") @@ -151,7 +148,10 @@ def test_get_control_data_rejects_partial_legacy_stored_payload( client: TestClient, ) -> None: # Given: a stored control row with only one half of the legacy flat shape - control_resp = client.put("/api/v1/controls", json={"name": f"control-{uuid.uuid4()}"}) + control_resp = client.put( + "/api/v1/controls", + json={"name": f"control-{uuid.uuid4()}", "data": VALID_CONTROL_PAYLOAD}, + ) assert control_resp.status_code == 200 control_id = control_resp.json()["control_id"] diff --git a/server/tests/test_controls.py b/server/tests/test_controls.py index e774ccbf..bc20f5da 100644 --- a/server/tests/test_controls.py +++ b/server/tests/test_controls.py @@ -3,21 +3,39 @@ from typing import Any from fastapi.testclient import TestClient +from sqlalchemy.orm import Session +from agent_control_server.models import Control -def create_control(client: TestClient) -> int: +from .conftest import engine + + +def create_control(client: TestClient, data: dict[str, Any] | None = None) -> int: name = f"control-{uuid.uuid4()}" - resp = client.put("/api/v1/controls", json={"name": name}) + payload = data if data is not None else VALID_CONTROL_DATA + resp = client.put("/api/v1/controls", json={"name": name, "data": payload}) assert resp.status_code == 200 cid = resp.json()["control_id"] assert isinstance(cid, int) return cid +def create_unconfigured_control(name: str | None = None) -> int: + control = Control(name=name or f"control-{uuid.uuid4()}", data={}) + with Session(engine) as session: + session.add(control) + session.commit() + session.refresh(control) + return int(control.id) + + def test_create_control_returns_id(client: TestClient) -> None: # Given: no prior controls # When: creating a control via API - resp = client.put("/api/v1/controls", json={"name": f"control-{uuid.uuid4()}"}) + resp = client.put( + "/api/v1/controls", + json={"name": f"control-{uuid.uuid4()}", "data": VALID_CONTROL_DATA}, + ) # Then: a control_id is returned (integer) assert resp.status_code == 200 assert isinstance(resp.json()["control_id"], int) @@ -72,9 +90,14 @@ def test_create_control_invalid_data_returns_422_without_persisting(client: Test assert body["controls"] == [] +def test_create_control_without_data_returns_422(client: TestClient) -> None: + resp = client.put("/api/v1/controls", json={"name": f"control-{uuid.uuid4()}"}) + assert resp.status_code == 422 + + def test_get_control_data_initially_unconfigured(client: TestClient) -> None: - # Given: a newly created control (no data set yet) - control_id = create_control(client) + # Given: a legacy control row with no data set + control_id = create_unconfigured_control() # When: fetching its data resp = client.get(f"/api/v1/controls/{control_id}/data") # Then: 422 because empty data is not a valid ControlDefinition (RFC 7807 format) @@ -100,8 +123,8 @@ def test_get_control_data_initially_unconfigured(client: TestClient) -> None: } def test_set_control_data_replaces_existing(client: TestClient) -> None: - # Given: a control with empty data - control_id = create_control(client) + # Given: a legacy control with empty data + control_id = create_unconfigured_control() # When: setting data payload = VALID_CONTROL_DATA resp_put = client.put(f"/api/v1/controls/{control_id}/data", json={"data": payload}) @@ -224,10 +247,10 @@ def test_set_control_data_requires_body_with_data_key(client: TestClient) -> Non def test_create_control_duplicate_name_409(client: TestClient) -> None: # Given: a specific control name name = f"dup-control-{uuid.uuid4()}" - r1 = client.put("/api/v1/controls", json={"name": name}) + r1 = client.put("/api/v1/controls", json={"name": name, "data": VALID_CONTROL_DATA}) assert r1.status_code == 200 # When: creating again with the same name - r2 = client.put("/api/v1/controls", json={"name": name}) + r2 = client.put("/api/v1/controls", json={"name": name, "data": VALID_CONTROL_DATA}) # Then: conflict assert r2.status_code == 409 @@ -238,17 +261,15 @@ def test_create_control_duplicate_name_409(client: TestClient) -> None: def test_get_control_returns_metadata(client: TestClient) -> None: - """Test GET /controls/{id} returns control id, name, and data.""" - # Given: a control with a specific name + """Test GET /controls/{id} returns id, name, and None data for legacy rows.""" + # Given: a legacy control with a specific name and no configured data name = f"test-control-{uuid.uuid4()}" - resp = client.put("/api/v1/controls", json={"name": name}) - assert resp.status_code == 200 - control_id = resp.json()["control_id"] + control_id = create_unconfigured_control(name) # When: fetching the control get_resp = client.get(f"/api/v1/controls/{control_id}") - # Then: returns id, name, and data (None for unconfigured) + # Then: returns id, name, and data (None for legacy unconfigured rows) assert get_resp.status_code == 200 body = get_resp.json() assert body["id"] == control_id diff --git a/server/tests/test_controls_additional.py b/server/tests/test_controls_additional.py index a5be9777..bafbab67 100644 --- a/server/tests/test_controls_additional.py +++ b/server/tests/test_controls_additional.py @@ -26,13 +26,28 @@ from .utils import VALID_CONTROL_PAYLOAD -def _create_control(client: TestClient, name: str | None = None) -> tuple[int, str]: +def _create_control( + client: TestClient, + name: str | None = None, + data: dict | None = None, +) -> tuple[int, str]: control_name = name or f"control-{uuid.uuid4()}" - resp = client.put("/api/v1/controls", json={"name": control_name}) + payload = deepcopy(data) if data is not None else deepcopy(VALID_CONTROL_PAYLOAD) + resp = client.put("/api/v1/controls", json={"name": control_name, "data": payload}) assert resp.status_code == 200 return resp.json()["control_id"], control_name +def _insert_unconfigured_control(name: str | None = None) -> tuple[int, str]: + control_name = name or f"control-{uuid.uuid4()}" + control = Control(name=control_name, data={}) + with Session(engine) as session: + session.add(control) + session.commit() + session.refresh(control) + return int(control.id), control_name + + def _set_control_data(client: TestClient, control_id: int, data: dict) -> None: resp = client.put(f"/api/v1/controls/{control_id}/data", json={"data": data}) assert resp.status_code == 200, resp.text @@ -60,7 +75,10 @@ async def mock_db_integrity_error() -> AsyncGenerator[AsyncSession, None]: app.dependency_overrides[get_async_db] = mock_db_integrity_error try: - resp = client.put("/api/v1/controls", json={"name": "duplicate-control"}) + resp = client.put( + "/api/v1/controls", + json={"name": "duplicate-control", "data": VALID_CONTROL_PAYLOAD}, + ) finally: app.dependency_overrides.clear() @@ -199,7 +217,7 @@ def test_list_controls_filters_and_pagination(client: TestClient) -> None: def test_patch_control_enabled_requires_data(client: TestClient) -> None: # Given: a control without configured data - control_id, _ = _create_control(client) + control_id, _ = _insert_unconfigured_control() # When: toggling enabled without data resp = client.patch(f"/api/v1/controls/{control_id}", json={"enabled": False}) @@ -242,7 +260,10 @@ def test_patch_control_rename_with_spaces_rejected(client: TestClient) -> None: def test_create_control_trimmed_name_stored(client: TestClient) -> None: """Control names are canonicalized at the API boundary: leading/trailing whitespace is trimmed.""" - resp = client.put("/api/v1/controls", json={"name": " trimmed-control "}) + resp = client.put( + "/api/v1/controls", + json={"name": " trimmed-control ", "data": VALID_CONTROL_PAYLOAD}, + ) assert resp.status_code == 200 control_id = resp.json()["control_id"] get_resp = client.get(f"/api/v1/controls/{control_id}") diff --git a/server/tests/test_controls_validation.py b/server/tests/test_controls_validation.py index 25a295f8..2761bdd3 100644 --- a/server/tests/test_controls_validation.py +++ b/server/tests/test_controls_validation.py @@ -10,7 +10,7 @@ def create_control(client: TestClient) -> int: name = f"control-{uuid.uuid4()}" - resp = client.put("/api/v1/controls", json={"name": name}) + resp = client.put("/api/v1/controls", json={"name": name, "data": VALID_CONTROL_PAYLOAD}) assert resp.status_code == 200 return resp.json()["control_id"] diff --git a/server/tests/test_error_handling.py b/server/tests/test_error_handling.py index f9689851..12e5b519 100644 --- a/server/tests/test_error_handling.py +++ b/server/tests/test_error_handling.py @@ -11,6 +11,8 @@ from agent_control_server.db import get_async_db +from .utils import VALID_CONTROL_PAYLOAD + async def mock_db_with_commit_failure() -> AsyncGenerator[AsyncSession, None]: """Mock database session that fails on commit.""" @@ -287,7 +289,10 @@ def test_create_control_rollback_on_failure( # When: commit fails during control creation app.dependency_overrides[get_async_db] = mock_db_with_commit_failure try: - resp = client.put("/api/v1/controls", json={"name": control_name}) + resp = client.put( + "/api/v1/controls", + json={"name": control_name, "data": VALID_CONTROL_PAYLOAD}, + ) # Then: rollback is called and 500 error is returned assert resp.status_code == 500 @@ -302,7 +307,10 @@ def test_delete_control_rollback_on_failure( """Test that delete_control rolls back when commit fails.""" # Given: an existing control control_name = f"test-control-{uuid.uuid4()}" - create_resp = client.put("/api/v1/controls", json={"name": control_name}) + create_resp = client.put( + "/api/v1/controls", + json={"name": control_name, "data": VALID_CONTROL_PAYLOAD}, + ) assert create_resp.status_code == 200 control_id = create_resp.json()["control_id"] @@ -441,7 +449,10 @@ def test_set_control_data_rollback_on_failure( """Test that set_control_data rolls back transaction when commit fails.""" # Given: an existing control control_name = f"test-control-{uuid.uuid4()}" - r1 = client.put("/api/v1/controls", json={"name": control_name}) + r1 = client.put( + "/api/v1/controls", + json={"name": control_name, "data": VALID_CONTROL_PAYLOAD}, + ) assert r1.status_code == 200 control_id = r1.json()["control_id"] @@ -497,7 +508,10 @@ def test_patch_control_rollback_on_failure( """Test that patch_control rolls back when commit fails.""" # Given: an existing control control_name = f"test-control-{uuid.uuid4()}" - create_resp = client.put("/api/v1/controls", json={"name": control_name}) + create_resp = client.put( + "/api/v1/controls", + json={"name": control_name, "data": VALID_CONTROL_PAYLOAD}, + ) assert create_resp.status_code == 200 control_id = create_resp.json()["control_id"] diff --git a/server/tests/test_evaluation_e2e.py b/server/tests/test_evaluation_e2e.py index 7ebb03b9..3ba5cde6 100644 --- a/server/tests/test_evaluation_e2e.py +++ b/server/tests/test_evaluation_e2e.py @@ -236,12 +236,14 @@ def test_evaluation_deny_precedence(client: TestClient): "evaluator": {"name": "regex", "config": {"pattern": "keyword"}}, "action": {"decision": "deny"} } - resp = client.put("/api/v1/controls", json={"name": f"deny-control-{uuid.uuid4()}"}) - deny_control_id = resp.json()["control_id"] - client.put( - f"/api/v1/controls/{deny_control_id}/data", - json={"data": canonicalize_control_payload(control_deny)}, + resp = client.put( + "/api/v1/controls", + json={ + "name": f"deny-control-{uuid.uuid4()}", + "data": canonicalize_control_payload(control_deny), + }, ) + deny_control_id = resp.json()["control_id"] # Add Control to Agent's Policy client.post(f"/api/v1/policies/{policy_id}/controls/{deny_control_id}") diff --git a/server/tests/test_evaluation_error_handling.py b/server/tests/test_evaluation_error_handling.py index 5a3db01b..82549652 100644 --- a/server/tests/test_evaluation_error_handling.py +++ b/server/tests/test_evaluation_error_handling.py @@ -47,13 +47,11 @@ def test_evaluation_with_agent_scoped_evaluator_missing(client: TestClient): "action": {"decision": "deny"} } - # When: creating the control shell - control_resp = client.put("/api/v1/controls", json={"name": f"control-{uuid.uuid4().hex[:8]}"}) - assert control_resp.status_code == 200 - control_id = control_resp.json()["control_id"] - - # When: setting control data with a missing agent-scoped evaluator - set_resp = client.put(f"/api/v1/controls/{control_id}/data", json={"data": control_data}) + # When: creating the control with a missing agent-scoped evaluator + set_resp = client.put( + "/api/v1/controls", + json={"name": f"control-{uuid.uuid4().hex[:8]}", "data": control_data}, + ) # Then: a validation or not-found error is returned # This will fail because the agent doesn't exist yet @@ -67,12 +65,7 @@ def test_evaluation_control_with_invalid_config_caught_early(client: TestClient) When: Setting control data Then: Returns 422 with validation error """ - # Given: a control shell to configure - control_resp = client.put("/api/v1/controls", json={"name": f"control-{uuid.uuid4().hex[:8]}"}) - assert control_resp.status_code == 200 - control_id = control_resp.json()["control_id"] - - # When: setting control data with invalid regex config (missing required 'pattern') + # When: creating a control with invalid regex config (missing required 'pattern') control_data = { "description": "Test control", "enabled": True, @@ -86,7 +79,10 @@ def test_evaluation_control_with_invalid_config_caught_early(client: TestClient) "action": {"decision": "deny"} } - set_resp = client.put(f"/api/v1/controls/{control_id}/data", json={"data": control_data}) + set_resp = client.put( + "/api/v1/controls", + json={"name": f"control-{uuid.uuid4().hex[:8]}", "data": control_data}, + ) # Then: a validation error is returned assert set_resp.status_code == 422 diff --git a/server/tests/test_init_agent.py b/server/tests/test_init_agent.py index 7140e736..2dfe9eaa 100644 --- a/server/tests/test_init_agent.py +++ b/server/tests/test_init_agent.py @@ -437,13 +437,10 @@ def test_list_agent_controls_with_policy(client: TestClient) -> None: policy_id = pol.json()["policy_id"] ctl_name = f"control-{uuid.uuid4()}" - ctl = client.put("/api/v1/controls", json={"name": ctl_name}) - control_id = ctl.json()["control_id"] - - # Set control data from .utils import VALID_CONTROL_PAYLOAD data_payload = VALID_CONTROL_PAYLOAD - client.put(f"/api/v1/controls/{control_id}/data", json={"data": data_payload}) + ctl = client.put("/api/v1/controls", json={"name": ctl_name, "data": data_payload}) + control_id = ctl.json()["control_id"] # Associate control -> policy; assign policy to agent client.post(f"/api/v1/policies/{policy_id}/controls/{control_id}") diff --git a/server/tests/test_init_agent_conflict_mode.py b/server/tests/test_init_agent_conflict_mode.py index 9c29d0d1..8a9e2ce1 100644 --- a/server/tests/test_init_agent_conflict_mode.py +++ b/server/tests/test_init_agent_conflict_mode.py @@ -41,21 +41,17 @@ def _create_policy_with_agent_evaluator_control( agent_name: str, evaluator_name: str, ) -> tuple[int, int, str]: - control_name = f"control-{uuid.uuid4().hex[:8]}" - create_control_resp = client.put("/api/v1/controls", json={"name": control_name}) - assert create_control_resp.status_code == 200 - control_id = create_control_resp.json()["control_id"] - control_data = deepcopy(VALID_CONTROL_PAYLOAD) + control_name = f"control-{uuid.uuid4().hex[:8]}" control_data["condition"]["evaluator"] = { "name": f"{agent_name}:{evaluator_name}", "config": {}, } - set_data_resp = client.put( - f"/api/v1/controls/{control_id}/data", - json={"data": control_data}, + create_control_resp = client.put( + "/api/v1/controls", json={"name": control_name, "data": control_data} ) - assert set_data_resp.status_code == 200 + assert create_control_resp.status_code == 200 + control_id = create_control_resp.json()["control_id"] policy_name = f"policy-{uuid.uuid4().hex[:8]}" create_policy_resp = client.put("/api/v1/policies", json={"name": policy_name}) diff --git a/server/tests/test_new_features.py b/server/tests/test_new_features.py index f79682a2..435273a7 100644 --- a/server/tests/test_new_features.py +++ b/server/tests/test_new_features.py @@ -264,17 +264,13 @@ def _create_policy_with_control( policy_id = pol_resp.json()["policy_id"] # Create control - ctl_resp = client.put("/api/v1/controls", json={"name": control_name}) + ctl_resp = client.put( + "/api/v1/controls", + json={"name": control_name, "data": canonicalize_control_payload(control_data)}, + ) assert ctl_resp.status_code == 200 control_id = ctl_resp.json()["control_id"] - # Set control data - data_resp = client.put( - f"/api/v1/controls/{control_id}/data", - json={"data": canonicalize_control_payload(control_data)}, - ) - assert data_resp.status_code == 200 - # Add control to policy client.post(f"/api/v1/policies/{policy_id}/controls/{control_id}") @@ -342,20 +338,18 @@ def test_policy_assignment_with_registered_agent_evaluator(client: TestClient) - def test_control_creation_with_unregistered_evaluator_fails(client: TestClient) -> None: - """Given an agent without evaluator, when setting control to use that evaluator, then fails.""" + """Given an agent without evaluator, when creating a control that uses it, then fails.""" # Given: agent_name = f"agent-{uuid.uuid4().hex[:12]}" agent_name = agent_name payload = make_agent_payload(agent_name=agent_name, name=agent_name) client.post("/api/v1/agents/initAgent", json=payload) - ctl_resp = client.put("/api/v1/controls", json={"name": f"control-{uuid.uuid4().hex[:8]}"}) - control_id = ctl_resp.json()["control_id"] - # When: data_resp = client.put( - f"/api/v1/controls/{control_id}/data", + "/api/v1/controls", json={ + "name": f"control-{uuid.uuid4().hex[:8]}", "data": { "execution": "server", "scope": {"step_types": ["llm"], "stages": ["pre"]}, diff --git a/server/tests/test_policies.py b/server/tests/test_policies.py index f40e20dc..e961a989 100644 --- a/server/tests/test_policies.py +++ b/server/tests/test_policies.py @@ -9,6 +9,8 @@ from agent_control_server.db import get_async_db from agent_control_server.models import Control, Policy +from .utils import VALID_CONTROL_PAYLOAD + def _create_policy(client: TestClient) -> int: name = f"pol-{uuid.uuid4()}" @@ -19,7 +21,7 @@ def _create_policy(client: TestClient) -> int: def _create_control(client: TestClient) -> int: name = f"ctrl-{uuid.uuid4()}" - r = client.put("/api/v1/controls", json={"name": name}) + r = client.put("/api/v1/controls", json={"name": name, "data": VALID_CONTROL_PAYLOAD}) assert r.status_code == 200 return r.json()["control_id"] diff --git a/server/tests/test_policy_integration.py b/server/tests/test_policy_integration.py index bd3ba15d..a50a3510 100644 --- a/server/tests/test_policy_integration.py +++ b/server/tests/test_policy_integration.py @@ -38,18 +38,11 @@ def _create_policy(client: TestClient, name: str | None = None) -> int: def _create_control(client: TestClient, name: str | None = None, data: dict | None = None) -> int: """Helper: Create a control and return control_id.""" control_name = name or f"control-{uuid.uuid4()}" - resp = client.put("/api/v1/controls", json={"name": control_name}) - assert resp.status_code == 200 - control_id = resp.json()["control_id"] - - # Always set valid data, using name/data in description for traceability payload = VALID_CONTROL_PAYLOAD.copy() payload["description"] = f"Name: {control_name}, Data: {data}" - - resp = client.put(f"/api/v1/controls/{control_id}/data", json={"data": payload}) + resp = client.put("/api/v1/controls", json={"name": control_name, "data": payload}) assert resp.status_code == 200 - - return control_id + return resp.json()["control_id"] def test_agent_gets_controls_from_policy(client: TestClient) -> None: diff --git a/server/tests/utils.py b/server/tests/utils.py index 64c455c5..92cf6c4d 100644 --- a/server/tests/utils.py +++ b/server/tests/utils.py @@ -49,25 +49,21 @@ def create_and_assign_policy( # 1. Create Control control_name = f"control-{uuid.uuid4()}" - resp = client.put("/api/v1/controls", json={"name": control_name}) + resp = client.put("/api/v1/controls", json={"name": control_name, "data": control_config}) assert resp.status_code == 200 control_id = resp.json()["control_id"] - # 2. Configure Control - resp = client.put(f"/api/v1/controls/{control_id}/data", json={"data": control_config}) - assert resp.status_code == 200 - - # 3. Create Policy + # 2. Create Policy policy_name = f"policy-{uuid.uuid4()}" resp = client.put("/api/v1/policies", json={"name": policy_name}) assert resp.status_code == 200 policy_id = resp.json()["policy_id"] - # 4. Add Control to Policy (direct relationship) + # 3. Add Control to Policy (direct relationship) resp = client.post(f"/api/v1/policies/{policy_id}/controls/{control_id}") assert resp.status_code == 200 - # 5. Register Agent + # 4. Register Agent normalized_agent_name = agent_name.lower() if len(normalized_agent_name) < 10: normalized_agent_name = f"{normalized_agent_name}-agent".replace("--", "-") @@ -79,7 +75,7 @@ def create_and_assign_policy( }) assert resp.status_code == 200 - # 6. Assign Policy to Agent + # 5. Assign Policy to Agent resp = client.post(f"/api/v1/agents/{normalized_agent_name}/policy/{policy_id}") assert resp.status_code == 200 diff --git a/ui/src/core/api/generated/api-types.ts b/ui/src/core/api/generated/api-types.ts index 652a2644..1d56d259 100644 --- a/ui/src/core/api/generated/api-types.ts +++ b/ui/src/core/api/generated/api-types.ts @@ -444,10 +444,10 @@ export interface paths { * @description Create a new control with a unique name. * * Controls define protection logic and can be added to policies. - * Optionally provide control data to validate and persist it atomically. + * Control data is required and is validated before anything is inserted. * * Args: - * request: Control creation request with unique name and optional data + * request: Control creation request with unique name and data * db: Database session (injected) * * Returns: @@ -1961,8 +1961,8 @@ export interface components { }; /** CreateControlRequest */ CreateControlRequest: { - /** @description Optional control definition to validate and store during creation */ - data?: components["schemas"]["ControlDefinition-Input"] | null; + /** @description Control definition to validate and store during creation */ + data: components["schemas"]["ControlDefinition-Input"]; /** * Name * @description Unique control name (letters, numbers, hyphens, underscores) From 627244c3987bd89ade2cdc9c02c9344f423647f4 Mon Sep 17 00:00:00 2001 From: Lev Neiman Date: Thu, 19 Mar 2026 21:32:40 -0700 Subject: [PATCH 3/5] test: update sdk control fixture for required data --- sdks/python/tests/conftest.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/sdks/python/tests/conftest.py b/sdks/python/tests/conftest.py index eabd7ec9..2110594c 100644 --- a/sdks/python/tests/conftest.py +++ b/sdks/python/tests/conftest.py @@ -186,7 +186,22 @@ async def test_control( """ result = await agent_control.controls.create_control( client, - f"test-control-{unique_name}" + f"test-control-{unique_name}", + { + "description": "SDK integration test control", + "enabled": True, + "execution": "server", + "scope": {"step_types": ["llm"], "stages": ["pre"]}, + "condition": { + "selector": {"path": "input"}, + "evaluator": { + "name": "regex", + "config": {"pattern": "test", "flags": []}, + }, + }, + "action": {"decision": "deny"}, + "tags": ["sdk-test"], + }, ) yield result From f10cbb6f23dead53908b7e7f7b5d977a8a864446 Mon Sep 17 00:00:00 2001 From: Lev Neiman Date: Thu, 19 Mar 2026 21:40:42 -0700 Subject: [PATCH 4/5] test: fix sdk and ui ci checks --- sdks/typescript/tests/client-api.test.ts | 39 + ui/src/core/api/generated/api-types.ts | 9478 +++++++++++----------- 2 files changed, 4787 insertions(+), 4730 deletions(-) diff --git a/sdks/typescript/tests/client-api.test.ts b/sdks/typescript/tests/client-api.test.ts index c6c11864..fe5a98db 100644 --- a/sdks/typescript/tests/client-api.test.ts +++ b/sdks/typescript/tests/client-api.test.ts @@ -77,6 +77,25 @@ describe("AgentControlClient API wiring", () => { await client.controls.create({ name: "deny-pii", + data: { + action: { + decision: "deny", + }, + condition: { + evaluator: { + name: "regex", + config: { pattern: "pii" }, + }, + selector: { + path: "input", + }, + }, + execution: "server", + scope: { + stages: ["pre"], + stepTypes: ["llm"], + }, + }, }); expect(fetchMock).toHaveBeenCalledTimes(1); @@ -87,6 +106,26 @@ describe("AgentControlClient API wiring", () => { expect(request.headers.get("content-type")).toContain("application/json"); await expect(request.clone().json()).resolves.toEqual({ name: "deny-pii", + data: { + action: { + decision: "deny", + }, + condition: { + evaluator: { + name: "regex", + config: { pattern: "pii" }, + }, + selector: { + path: "input", + }, + }, + enabled: true, + execution: "server", + scope: { + stages: ["pre"], + step_types: ["llm"], + }, + }, }); }); diff --git a/ui/src/core/api/generated/api-types.ts b/ui/src/core/api/generated/api-types.ts index 1d56d259..01625731 100644 --- a/ui/src/core/api/generated/api-types.ts +++ b/ui/src/core/api/generated/api-types.ts @@ -4,4743 +4,4761 @@ */ export interface paths { - "/api/config": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * UI configuration - * @description Return configuration flags that drive UI behavior. - * - * If authentication is enabled, this also reports whether the current - * request has an active session (via header or cookie), allowing the UI - * to skip the login prompt on refresh when a valid cookie is present. - */ - get: operations["get_config_api_config_get"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/login": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * Login with API key - * @description Validate an API key and issue a signed JWT session cookie. - * - * The raw API key is transmitted only in this single request and is never - * stored in the cookie. Subsequent requests authenticate via the JWT. - */ - post: operations["login_api_login_post"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/logout": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * Logout (clear session cookie) - * @description Clear the session cookie. - */ - post: operations["logout_api_logout_post"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/v1/agents": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * List all agents - * @description List all registered agents with cursor-based pagination. - * - * Returns a summary of each agent including identifier, policy associations, - * and counts of registered steps and evaluators. - * - * Args: - * cursor: Optional cursor for pagination (last agent name from previous page) - * limit: Pagination limit (default 20, max 100) - * name: Optional name filter (case-insensitive partial match) - * db: Database session (injected) - * - * Returns: - * ListAgentsResponse with agent summaries and pagination info - */ - get: operations["list_agents_api_v1_agents_get"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/v1/agents/initAgent": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * Initialize or update an agent - * @description Register a new agent or update an existing agent's steps and metadata. - * - * This endpoint is idempotent: - * - If the agent name doesn't exist, creates a new agent - * - If the agent name exists, updates registration data in place - * - * conflict_mode controls registration conflict handling: - * - strict (default): preserve compatibility checks and conflict errors - * - overwrite: latest init payload replaces steps/evaluators and returns change summary - * - * Args: - * request: Agent metadata and step schemas - * db: Database session (injected) - * - * Returns: - * InitAgentResponse with created flag and active controls (policy-derived + direct) - */ - post: operations["init_agent_api_v1_agents_initAgent_post"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/v1/agents/{agent_name}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get agent details - * @description Retrieve agent metadata and all registered steps. - * - * Returns the latest version of each step (deduplicated by type+name). - * - * Args: - * agent_name: Agent identifier - * db: Database session (injected) - * - * Returns: - * GetAgentResponse with agent metadata and step list - * - * Raises: - * HTTPException 404: Agent not found - * HTTPException 422: Agent data is corrupted - */ - get: operations["get_agent_api_v1_agents__agent_name__get"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - /** - * Modify agent (remove steps/evaluators) - * @description Remove steps and/or evaluators from an agent. - * - * This is the complement to initAgent which only adds items. - * Removals are idempotent - attempting to remove non-existent items is not an error. - * - * Args: - * agent_name: Agent identifier - * request: Lists of step/evaluator identifiers to remove - * db: Database session (injected) - * - * Returns: - * PatchAgentResponse with lists of actually removed items - * - * Raises: - * HTTPException 404: Agent not found - * HTTPException 500: Database error during update - */ - patch: operations["patch_agent_api_v1_agents__agent_name__patch"]; - trace?: never; - }; - "/api/v1/agents/{agent_name}/controls": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * List agent's active controls - * @description List all protection controls active for an agent. - * - * Controls include the union of policy-derived and directly associated controls. - * - * Args: - * agent_name: Agent identifier - * db: Database session (injected) - * - * Returns: - * AgentControlsResponse with list of active controls - * - * Raises: - * HTTPException 404: Agent not found - */ - get: operations["list_agent_controls_api_v1_agents__agent_name__controls_get"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/v1/agents/{agent_name}/controls/{control_id}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * Associate control directly with agent - * @description Associate a control directly with an agent (idempotent). - */ - post: operations["add_agent_control_api_v1_agents__agent_name__controls__control_id__post"]; - /** - * Remove direct control association from agent - * @description Remove a direct control association from an agent (idempotent). - */ - delete: operations["remove_agent_control_api_v1_agents__agent_name__controls__control_id__delete"]; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/v1/agents/{agent_name}/evaluators": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * List agent's registered evaluator schemas - * @description List all evaluator schemas registered with an agent. - * - * Evaluator schemas are registered via initAgent and used for: - * - Config validation when creating Controls - * - UI to display available config options - * - * Args: - * agent_name: Agent identifier - * cursor: Optional cursor for pagination (name of last evaluator from previous page) - * limit: Pagination limit (default 20, max 100) - * db: Database session (injected) - * - * Returns: - * ListEvaluatorsResponse with evaluator schemas and pagination - * - * Raises: - * HTTPException 404: Agent not found - */ - get: operations["list_agent_evaluators_api_v1_agents__agent_name__evaluators_get"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/v1/agents/{agent_name}/evaluators/{evaluator_name}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get specific evaluator schema - * @description Get a specific evaluator schema registered with an agent. - * - * Args: - * agent_name: Agent identifier - * evaluator_name: Name of the evaluator - * db: Database session (injected) - * - * Returns: - * EvaluatorSchemaItem with schema details - * - * Raises: - * HTTPException 404: Agent or evaluator not found - */ - get: operations["get_agent_evaluator_api_v1_agents__agent_name__evaluators__evaluator_name__get"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/v1/agents/{agent_name}/policies": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * List policies associated with agent - * @description List policy IDs associated with an agent. - */ - get: operations["get_agent_policies_api_v1_agents__agent_name__policies_get"]; - put?: never; - post?: never; - /** - * Remove all policy associations from agent - * @description Remove all policy associations from an agent. - */ - delete: operations["remove_all_agent_policies_api_v1_agents__agent_name__policies_delete"]; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/v1/agents/{agent_name}/policies/{policy_id}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * Associate policy with agent - * @description Associate a policy with an agent (idempotent). - */ - post: operations["add_agent_policy_api_v1_agents__agent_name__policies__policy_id__post"]; - /** - * Remove policy association from agent - * @description Remove a policy association from an agent. - * - * Idempotent for existing resources: removing a non-associated link is a no-op. - * Missing agent/policy resources still return 404. - */ - delete: operations["remove_agent_policy_api_v1_agents__agent_name__policies__policy_id__delete"]; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/v1/agents/{agent_name}/policy": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get agent's assigned policy (compatibility) - * @description Compatibility endpoint that returns the first associated policy. - */ - get: operations["get_agent_policy_api_v1_agents__agent_name__policy_get"]; - put?: never; - post?: never; - /** - * Remove agent's policy assignment (compatibility) - * @description Compatibility endpoint that removes all policy associations. - */ - delete: operations["delete_agent_policy_api_v1_agents__agent_name__policy_delete"]; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/v1/agents/{agent_name}/policy/{policy_id}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * Assign policy to agent (compatibility) - * @description Compatibility endpoint that replaces all policy associations with one policy. - */ - post: operations["set_agent_policy_api_v1_agents__agent_name__policy__policy_id__post"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/v1/controls": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * List all controls - * @description List all controls with optional filtering and cursor-based pagination. - * - * Controls are returned ordered by ID descending (newest first). - * - * Args: - * cursor: ID of the last control from the previous page (for pagination) - * limit: Maximum number of controls to return (default 20, max 100) - * name: Optional filter by name (partial, case-insensitive match) - * enabled: Optional filter by enabled status - * step_type: Optional filter by step type (built-ins: 'tool', 'llm') - * stage: Optional filter by stage ('pre' or 'post') - * execution: Optional filter by execution ('server' or 'sdk') - * tag: Optional filter by tag - * db: Database session (injected) - * - * Returns: - * ListControlsResponse with control summaries and pagination info - * - * Example: - * GET /controls?limit=10&enabled=true&step_type=tool - */ - get: operations["list_controls_api_v1_controls_get"]; - /** - * Create a new control - * @description Create a new control with a unique name. - * - * Controls define protection logic and can be added to policies. - * Control data is required and is validated before anything is inserted. - * - * Args: - * request: Control creation request with unique name and data - * db: Database session (injected) - * - * Returns: - * CreateControlResponse with the new control's ID - * - * Raises: - * HTTPException 409: Control with this name already exists - * HTTPException 500: Database error during creation - */ - put: operations["create_control_api_v1_controls_put"]; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/v1/controls/validate": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * Validate control configuration - * @description Validate control configuration data without saving it. - * - * Args: - * request: Control configuration data to validate - * db: Database session (injected) - * - * Returns: - * ValidateControlDataResponse with success=True if valid - */ - post: operations["validate_control_data_api_v1_controls_validate_post"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/v1/controls/{control_id}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get control details - * @description Retrieve a control by ID including its name and configuration data. - * - * Args: - * control_id: ID of the control - * db: Database session (injected) - * - * Returns: - * GetControlResponse with control id, name, and data - * - * Raises: - * HTTPException 404: Control not found - */ - get: operations["get_control_api_v1_controls__control_id__get"]; - put?: never; - post?: never; - /** - * Delete a control - * @description Delete a control by ID. - * - * By default, deletion fails if the control is associated with any policy or agent. - * Use force=true to automatically dissociate and delete. - * - * Args: - * control_id: ID of the control to delete - * force: If true, remove associations before deleting - * db: Database session (injected) - * - * Returns: - * DeleteControlResponse with success flag and dissociation details - * - * Raises: - * HTTPException 404: Control not found - * HTTPException 409: Control is in use (and force=false) - * HTTPException 500: Database error during deletion - */ - delete: operations["delete_control_api_v1_controls__control_id__delete"]; - options?: never; - head?: never; - /** - * Update control metadata - * @description Update control metadata (name and/or enabled status). - * - * This endpoint allows partial updates: - * - To rename: provide 'name' field - * - To enable/disable: provide 'enabled' field (updates the control's data) - * - * Args: - * control_id: ID of the control to update - * request: Fields to update (name, enabled) - * db: Database session (injected) - * - * Returns: - * PatchControlResponse with current control state - * - * Raises: - * HTTPException 404: Control not found - * HTTPException 409: New name conflicts with existing control - * HTTPException 422: Cannot update enabled status (control has no data configured) - * HTTPException 500: Database error during update - */ - patch: operations["patch_control_api_v1_controls__control_id__patch"]; - trace?: never; - }; - "/api/v1/controls/{control_id}/data": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get control configuration data - * @description Retrieve the configuration data for a control. - * - * Control data is a JSONB field that must follow the ControlDefinition schema. - * - * Args: - * control_id: ID of the control - * db: Database session (injected) - * - * Returns: - * GetControlDataResponse with validated ControlDefinition - * - * Raises: - * HTTPException 404: Control not found - * HTTPException 422: Control data is corrupted - */ - get: operations["get_control_data_api_v1_controls__control_id__data_get"]; - /** - * Update control configuration data - * @description Update the configuration data for a control. - * - * This replaces the entire data payload. The data is validated against - * the ControlDefinition schema. - * - * Args: - * control_id: ID of the control - * request: New control data (replaces existing) - * db: Database session (injected) - * - * Returns: - * SetControlDataResponse with success flag - * - * Raises: - * HTTPException 404: Control not found - * HTTPException 500: Database error during update - */ - put: operations["set_control_data_api_v1_controls__control_id__data_put"]; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/v1/evaluation": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * Analyze content safety - * @description Analyze content for safety and control violations. - * - * Runs all controls assigned to the agent via policy through the - * evaluation engine. Controls are evaluated in parallel with - * cancel-on-deny for efficiency. - * - * Custom evaluators must be deployed as Evaluator classes - * with the engine. Their schemas are registered via initAgent. - * - * Optionally accepts X-Trace-Id and X-Span-Id headers for - * OpenTelemetry-compatible distributed tracing. - */ - post: operations["evaluate_api_v1_evaluation_post"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/v1/evaluator-configs": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** List evaluator configs */ - get: operations["list_evaluator_configs_api_v1_evaluator_configs_get"]; - put?: never; - /** Create evaluator config */ - post: operations["create_evaluator_config_api_v1_evaluator_configs_post"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/v1/evaluator-configs/{config_id}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get evaluator config */ - get: operations["get_evaluator_config_api_v1_evaluator_configs__config_id__get"]; - /** Update evaluator config */ - put: operations["update_evaluator_config_api_v1_evaluator_configs__config_id__put"]; - post?: never; - /** Delete evaluator config */ - delete: operations["delete_evaluator_config_api_v1_evaluator_configs__config_id__delete"]; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/v1/evaluators": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * List available evaluators - * @description List all available evaluators. - * - * Returns metadata and JSON Schema for each built-in evaluator. - * - * Built-in evaluators: - * - **regex**: Regular expression pattern matching - * - **list**: List-based value matching with flexible logic - * - **json**: JSON validation with schema, types, constraints - * - **sql**: SQL query validation - * - * Custom evaluators are registered per-agent via initAgent. - * Use GET /agents/{agent_name}/evaluators to list agent-specific schemas. - */ - get: operations["get_evaluators_api_v1_evaluators_get"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/v1/observability/events": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * Ingest Events - * @description Ingest batched control execution events. - * - * Events are stored directly to the database with ~5-20ms latency. - * - * Args: - * request: Batch of events to ingest - * ingestor: Event ingestor (injected) - * - * Returns: - * BatchEventsResponse with counts of received/processed/dropped - */ - post: operations["ingest_events_api_v1_observability_events_post"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/v1/observability/events/query": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * Query Events - * @description Query raw control execution events. - * - * Supports filtering by: - * - trace_id: Get all events for a request - * - span_id: Get all events for a function call - * - control_execution_id: Get a specific event - * - agent_name: Filter by agent - * - control_ids: Filter by controls - * - actions: Filter by actions (allow, deny, warn, log) - * - matched: Filter by matched status - * - check_stages: Filter by check stage (pre, post) - * - applies_to: Filter by call type (llm_call, tool_call) - * - start_time/end_time: Filter by time range - * - * Results are paginated with limit/offset. - * - * Args: - * request: Query parameters - * store: Event store (injected) - * - * Returns: - * EventQueryResponse with matching events and pagination info - */ - post: operations["query_events_api_v1_observability_events_query_post"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/v1/observability/stats": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get Stats - * @description Get agent-level aggregated statistics. - * - * Returns totals across all controls plus per-control breakdown. - * Use /stats/controls/{control_id} for single control stats. - * - * Args: - * agent_name: Agent to get stats for - * time_range: Time range (1m, 5m, 15m, 1h, 24h, 7d, 30d, 180d, 365d) - * include_timeseries: Include time-series data points for trend visualization - * store: Event store (injected) - * - * Returns: - * StatsResponse with agent-level totals and per-control breakdown - */ - get: operations["get_stats_api_v1_observability_stats_get"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/v1/observability/stats/controls/{control_id}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get Control Stats - * @description Get statistics for a single control. - * - * Returns stats for the specified control with optional time-series. - * - * Args: - * control_id: Control ID to get stats for - * agent_name: Agent to get stats for - * time_range: Time range (1m, 5m, 15m, 1h, 24h, 7d, 30d, 180d, 365d) - * include_timeseries: Include time-series data points for trend visualization - * store: Event store (injected) - * - * Returns: - * ControlStatsResponse with control stats and optional timeseries - */ - get: operations["get_control_stats_api_v1_observability_stats_controls__control_id__get"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/v1/observability/status": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get Status - * @description Get observability system status. - * - * Returns basic health information. - */ - get: operations["get_status_api_v1_observability_status_get"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/v1/policies": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - /** - * Create a new policy - * @description Create a new empty policy with a unique name. - * - * Policies contain controls and can be assigned to agents. - * A newly created policy has no controls until they are explicitly added. - * - * Args: - * request: Policy creation request with unique name - * db: Database session (injected) - * - * Returns: - * CreatePolicyResponse with the new policy's ID - * - * Raises: - * HTTPException 409: Policy with this name already exists - * HTTPException 500: Database error during creation - */ - put: operations["create_policy_api_v1_policies_put"]; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/v1/policies/{policy_id}/controls": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * List policy's controls - * @description List all controls associated with a policy. - * - * Args: - * policy_id: ID of the policy - * db: Database session (injected) - * - * Returns: - * GetPolicyControlsResponse with list of control IDs - * - * Raises: - * HTTPException 404: Policy not found - */ - get: operations["list_policy_controls_api_v1_policies__policy_id__controls_get"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/v1/policies/{policy_id}/controls/{control_id}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * Add control to policy - * @description Associate a control with a policy. - * - * This operation is idempotent - adding the same control multiple times has no effect. - * Agents with this policy will immediately see the added control. - * - * Args: - * policy_id: ID of the policy - * control_id: ID of the control to add - * db: Database session (injected) - * - * Returns: - * AssocResponse with success flag - * - * Raises: - * HTTPException 404: Policy or control not found - * HTTPException 500: Database error - */ - post: operations["add_control_to_policy_api_v1_policies__policy_id__controls__control_id__post"]; - /** - * Remove control from policy - * @description Remove a control from a policy. - * - * This operation is idempotent - removing a non-associated control has no effect. - * Agents with this policy will immediately lose the removed control. - * - * Args: - * policy_id: ID of the policy - * control_id: ID of the control to remove - * db: Database session (injected) - * - * Returns: - * AssocResponse with success flag - * - * Raises: - * HTTPException 404: Policy or control not found - * HTTPException 500: Database error - */ - delete: operations["remove_control_from_policy_api_v1_policies__policy_id__controls__control_id__delete"]; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/health": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Health check - * @description Check if the server is running and responsive. - * - * This endpoint does not check database connectivity. - * - * Returns: - * HealthResponse with status and version - */ - get: operations["health_check_health_get"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; + '/api/config': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; }; + /** + * UI configuration + * @description Return configuration flags that drive UI behavior. + * + * If authentication is enabled, this also reports whether the current + * request has an active session (via header or cookie), allowing the UI + * to skip the login prompt on refresh when a valid cookie is present. + */ + get: operations['get_config_api_config_get']; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + '/api/login': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Login with API key + * @description Validate an API key and issue a signed JWT session cookie. + * + * The raw API key is transmitted only in this single request and is never + * stored in the cookie. Subsequent requests authenticate via the JWT. + */ + post: operations['login_api_login_post']; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + '/api/logout': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Logout (clear session cookie) + * @description Clear the session cookie. + */ + post: operations['logout_api_logout_post']; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + '/api/v1/agents': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List all agents + * @description List all registered agents with cursor-based pagination. + * + * Returns a summary of each agent including identifier, policy associations, + * and counts of registered steps and evaluators. + * + * Args: + * cursor: Optional cursor for pagination (last agent name from previous page) + * limit: Pagination limit (default 20, max 100) + * name: Optional name filter (case-insensitive partial match) + * db: Database session (injected) + * + * Returns: + * ListAgentsResponse with agent summaries and pagination info + */ + get: operations['list_agents_api_v1_agents_get']; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + '/api/v1/agents/initAgent': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Initialize or update an agent + * @description Register a new agent or update an existing agent's steps and metadata. + * + * This endpoint is idempotent: + * - If the agent name doesn't exist, creates a new agent + * - If the agent name exists, updates registration data in place + * + * conflict_mode controls registration conflict handling: + * - strict (default): preserve compatibility checks and conflict errors + * - overwrite: latest init payload replaces steps/evaluators and returns change summary + * + * Args: + * request: Agent metadata and step schemas + * db: Database session (injected) + * + * Returns: + * InitAgentResponse with created flag and active controls (policy-derived + direct) + */ + post: operations['init_agent_api_v1_agents_initAgent_post']; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + '/api/v1/agents/{agent_name}': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get agent details + * @description Retrieve agent metadata and all registered steps. + * + * Returns the latest version of each step (deduplicated by type+name). + * + * Args: + * agent_name: Agent identifier + * db: Database session (injected) + * + * Returns: + * GetAgentResponse with agent metadata and step list + * + * Raises: + * HTTPException 404: Agent not found + * HTTPException 422: Agent data is corrupted + */ + get: operations['get_agent_api_v1_agents__agent_name__get']; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + /** + * Modify agent (remove steps/evaluators) + * @description Remove steps and/or evaluators from an agent. + * + * This is the complement to initAgent which only adds items. + * Removals are idempotent - attempting to remove non-existent items is not an error. + * + * Args: + * agent_name: Agent identifier + * request: Lists of step/evaluator identifiers to remove + * db: Database session (injected) + * + * Returns: + * PatchAgentResponse with lists of actually removed items + * + * Raises: + * HTTPException 404: Agent not found + * HTTPException 500: Database error during update + */ + patch: operations['patch_agent_api_v1_agents__agent_name__patch']; + trace?: never; + }; + '/api/v1/agents/{agent_name}/controls': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List agent's active controls + * @description List all protection controls active for an agent. + * + * Controls include the union of policy-derived and directly associated controls. + * + * Args: + * agent_name: Agent identifier + * db: Database session (injected) + * + * Returns: + * AgentControlsResponse with list of active controls + * + * Raises: + * HTTPException 404: Agent not found + */ + get: operations['list_agent_controls_api_v1_agents__agent_name__controls_get']; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + '/api/v1/agents/{agent_name}/controls/{control_id}': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Associate control directly with agent + * @description Associate a control directly with an agent (idempotent). + */ + post: operations['add_agent_control_api_v1_agents__agent_name__controls__control_id__post']; + /** + * Remove direct control association from agent + * @description Remove a direct control association from an agent (idempotent). + */ + delete: operations['remove_agent_control_api_v1_agents__agent_name__controls__control_id__delete']; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + '/api/v1/agents/{agent_name}/evaluators': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List agent's registered evaluator schemas + * @description List all evaluator schemas registered with an agent. + * + * Evaluator schemas are registered via initAgent and used for: + * - Config validation when creating Controls + * - UI to display available config options + * + * Args: + * agent_name: Agent identifier + * cursor: Optional cursor for pagination (name of last evaluator from previous page) + * limit: Pagination limit (default 20, max 100) + * db: Database session (injected) + * + * Returns: + * ListEvaluatorsResponse with evaluator schemas and pagination + * + * Raises: + * HTTPException 404: Agent not found + */ + get: operations['list_agent_evaluators_api_v1_agents__agent_name__evaluators_get']; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + '/api/v1/agents/{agent_name}/evaluators/{evaluator_name}': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get specific evaluator schema + * @description Get a specific evaluator schema registered with an agent. + * + * Args: + * agent_name: Agent identifier + * evaluator_name: Name of the evaluator + * db: Database session (injected) + * + * Returns: + * EvaluatorSchemaItem with schema details + * + * Raises: + * HTTPException 404: Agent or evaluator not found + */ + get: operations['get_agent_evaluator_api_v1_agents__agent_name__evaluators__evaluator_name__get']; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + '/api/v1/agents/{agent_name}/policies': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List policies associated with agent + * @description List policy IDs associated with an agent. + */ + get: operations['get_agent_policies_api_v1_agents__agent_name__policies_get']; + put?: never; + post?: never; + /** + * Remove all policy associations from agent + * @description Remove all policy associations from an agent. + */ + delete: operations['remove_all_agent_policies_api_v1_agents__agent_name__policies_delete']; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + '/api/v1/agents/{agent_name}/policies/{policy_id}': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Associate policy with agent + * @description Associate a policy with an agent (idempotent). + */ + post: operations['add_agent_policy_api_v1_agents__agent_name__policies__policy_id__post']; + /** + * Remove policy association from agent + * @description Remove a policy association from an agent. + * + * Idempotent for existing resources: removing a non-associated link is a no-op. + * Missing agent/policy resources still return 404. + */ + delete: operations['remove_agent_policy_api_v1_agents__agent_name__policies__policy_id__delete']; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + '/api/v1/agents/{agent_name}/policy': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get agent's assigned policy (compatibility) + * @description Compatibility endpoint that returns the first associated policy. + */ + get: operations['get_agent_policy_api_v1_agents__agent_name__policy_get']; + put?: never; + post?: never; + /** + * Remove agent's policy assignment (compatibility) + * @description Compatibility endpoint that removes all policy associations. + */ + delete: operations['delete_agent_policy_api_v1_agents__agent_name__policy_delete']; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + '/api/v1/agents/{agent_name}/policy/{policy_id}': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Assign policy to agent (compatibility) + * @description Compatibility endpoint that replaces all policy associations with one policy. + */ + post: operations['set_agent_policy_api_v1_agents__agent_name__policy__policy_id__post']; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + '/api/v1/controls': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List all controls + * @description List all controls with optional filtering and cursor-based pagination. + * + * Controls are returned ordered by ID descending (newest first). + * + * Args: + * cursor: ID of the last control from the previous page (for pagination) + * limit: Maximum number of controls to return (default 20, max 100) + * name: Optional filter by name (partial, case-insensitive match) + * enabled: Optional filter by enabled status + * step_type: Optional filter by step type (built-ins: 'tool', 'llm') + * stage: Optional filter by stage ('pre' or 'post') + * execution: Optional filter by execution ('server' or 'sdk') + * tag: Optional filter by tag + * db: Database session (injected) + * + * Returns: + * ListControlsResponse with control summaries and pagination info + * + * Example: + * GET /controls?limit=10&enabled=true&step_type=tool + */ + get: operations['list_controls_api_v1_controls_get']; + /** + * Create a new control + * @description Create a new control with a unique name. + * + * Controls define protection logic and can be added to policies. + * Control data is required and is validated before anything is inserted. + * + * Args: + * request: Control creation request with unique name and data + * db: Database session (injected) + * + * Returns: + * CreateControlResponse with the new control's ID + * + * Raises: + * HTTPException 409: Control with this name already exists + * HTTPException 500: Database error during creation + */ + put: operations['create_control_api_v1_controls_put']; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + '/api/v1/controls/validate': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Validate control configuration + * @description Validate control configuration data without saving it. + * + * Args: + * request: Control configuration data to validate + * db: Database session (injected) + * + * Returns: + * ValidateControlDataResponse with success=True if valid + */ + post: operations['validate_control_data_api_v1_controls_validate_post']; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + '/api/v1/controls/{control_id}': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get control details + * @description Retrieve a control by ID including its name and configuration data. + * + * Args: + * control_id: ID of the control + * db: Database session (injected) + * + * Returns: + * GetControlResponse with control id, name, and data + * + * Raises: + * HTTPException 404: Control not found + */ + get: operations['get_control_api_v1_controls__control_id__get']; + put?: never; + post?: never; + /** + * Delete a control + * @description Delete a control by ID. + * + * By default, deletion fails if the control is associated with any policy or agent. + * Use force=true to automatically dissociate and delete. + * + * Args: + * control_id: ID of the control to delete + * force: If true, remove associations before deleting + * db: Database session (injected) + * + * Returns: + * DeleteControlResponse with success flag and dissociation details + * + * Raises: + * HTTPException 404: Control not found + * HTTPException 409: Control is in use (and force=false) + * HTTPException 500: Database error during deletion + */ + delete: operations['delete_control_api_v1_controls__control_id__delete']; + options?: never; + head?: never; + /** + * Update control metadata + * @description Update control metadata (name and/or enabled status). + * + * This endpoint allows partial updates: + * - To rename: provide 'name' field + * - To enable/disable: provide 'enabled' field (updates the control's data) + * + * Args: + * control_id: ID of the control to update + * request: Fields to update (name, enabled) + * db: Database session (injected) + * + * Returns: + * PatchControlResponse with current control state + * + * Raises: + * HTTPException 404: Control not found + * HTTPException 409: New name conflicts with existing control + * HTTPException 422: Cannot update enabled status (control has no data configured) + * HTTPException 500: Database error during update + */ + patch: operations['patch_control_api_v1_controls__control_id__patch']; + trace?: never; + }; + '/api/v1/controls/{control_id}/data': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get control configuration data + * @description Retrieve the configuration data for a control. + * + * Control data is a JSONB field that must follow the ControlDefinition schema. + * + * Args: + * control_id: ID of the control + * db: Database session (injected) + * + * Returns: + * GetControlDataResponse with validated ControlDefinition + * + * Raises: + * HTTPException 404: Control not found + * HTTPException 422: Control data is corrupted + */ + get: operations['get_control_data_api_v1_controls__control_id__data_get']; + /** + * Update control configuration data + * @description Update the configuration data for a control. + * + * This replaces the entire data payload. The data is validated against + * the ControlDefinition schema. + * + * Args: + * control_id: ID of the control + * request: New control data (replaces existing) + * db: Database session (injected) + * + * Returns: + * SetControlDataResponse with success flag + * + * Raises: + * HTTPException 404: Control not found + * HTTPException 500: Database error during update + */ + put: operations['set_control_data_api_v1_controls__control_id__data_put']; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + '/api/v1/evaluation': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Analyze content safety + * @description Analyze content for safety and control violations. + * + * Runs all controls assigned to the agent via policy through the + * evaluation engine. Controls are evaluated in parallel with + * cancel-on-deny for efficiency. + * + * Custom evaluators must be deployed as Evaluator classes + * with the engine. Their schemas are registered via initAgent. + * + * Optionally accepts X-Trace-Id and X-Span-Id headers for + * OpenTelemetry-compatible distributed tracing. + */ + post: operations['evaluate_api_v1_evaluation_post']; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + '/api/v1/evaluator-configs': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** List evaluator configs */ + get: operations['list_evaluator_configs_api_v1_evaluator_configs_get']; + put?: never; + /** Create evaluator config */ + post: operations['create_evaluator_config_api_v1_evaluator_configs_post']; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + '/api/v1/evaluator-configs/{config_id}': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Get evaluator config */ + get: operations['get_evaluator_config_api_v1_evaluator_configs__config_id__get']; + /** Update evaluator config */ + put: operations['update_evaluator_config_api_v1_evaluator_configs__config_id__put']; + post?: never; + /** Delete evaluator config */ + delete: operations['delete_evaluator_config_api_v1_evaluator_configs__config_id__delete']; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + '/api/v1/evaluators': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List available evaluators + * @description List all available evaluators. + * + * Returns metadata and JSON Schema for each built-in evaluator. + * + * Built-in evaluators: + * - **regex**: Regular expression pattern matching + * - **list**: List-based value matching with flexible logic + * - **json**: JSON validation with schema, types, constraints + * - **sql**: SQL query validation + * + * Custom evaluators are registered per-agent via initAgent. + * Use GET /agents/{agent_name}/evaluators to list agent-specific schemas. + */ + get: operations['get_evaluators_api_v1_evaluators_get']; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + '/api/v1/observability/events': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Ingest Events + * @description Ingest batched control execution events. + * + * Events are stored directly to the database with ~5-20ms latency. + * + * Args: + * request: Batch of events to ingest + * ingestor: Event ingestor (injected) + * + * Returns: + * BatchEventsResponse with counts of received/processed/dropped + */ + post: operations['ingest_events_api_v1_observability_events_post']; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + '/api/v1/observability/events/query': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Query Events + * @description Query raw control execution events. + * + * Supports filtering by: + * - trace_id: Get all events for a request + * - span_id: Get all events for a function call + * - control_execution_id: Get a specific event + * - agent_name: Filter by agent + * - control_ids: Filter by controls + * - actions: Filter by actions (allow, deny, warn, log) + * - matched: Filter by matched status + * - check_stages: Filter by check stage (pre, post) + * - applies_to: Filter by call type (llm_call, tool_call) + * - start_time/end_time: Filter by time range + * + * Results are paginated with limit/offset. + * + * Args: + * request: Query parameters + * store: Event store (injected) + * + * Returns: + * EventQueryResponse with matching events and pagination info + */ + post: operations['query_events_api_v1_observability_events_query_post']; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + '/api/v1/observability/stats': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get Stats + * @description Get agent-level aggregated statistics. + * + * Returns totals across all controls plus per-control breakdown. + * Use /stats/controls/{control_id} for single control stats. + * + * Args: + * agent_name: Agent to get stats for + * time_range: Time range (1m, 5m, 15m, 1h, 24h, 7d, 30d, 180d, 365d) + * include_timeseries: Include time-series data points for trend visualization + * store: Event store (injected) + * + * Returns: + * StatsResponse with agent-level totals and per-control breakdown + */ + get: operations['get_stats_api_v1_observability_stats_get']; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + '/api/v1/observability/stats/controls/{control_id}': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get Control Stats + * @description Get statistics for a single control. + * + * Returns stats for the specified control with optional time-series. + * + * Args: + * control_id: Control ID to get stats for + * agent_name: Agent to get stats for + * time_range: Time range (1m, 5m, 15m, 1h, 24h, 7d, 30d, 180d, 365d) + * include_timeseries: Include time-series data points for trend visualization + * store: Event store (injected) + * + * Returns: + * ControlStatsResponse with control stats and optional timeseries + */ + get: operations['get_control_stats_api_v1_observability_stats_controls__control_id__get']; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + '/api/v1/observability/status': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get Status + * @description Get observability system status. + * + * Returns basic health information. + */ + get: operations['get_status_api_v1_observability_status_get']; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + '/api/v1/policies': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + /** + * Create a new policy + * @description Create a new empty policy with a unique name. + * + * Policies contain controls and can be assigned to agents. + * A newly created policy has no controls until they are explicitly added. + * + * Args: + * request: Policy creation request with unique name + * db: Database session (injected) + * + * Returns: + * CreatePolicyResponse with the new policy's ID + * + * Raises: + * HTTPException 409: Policy with this name already exists + * HTTPException 500: Database error during creation + */ + put: operations['create_policy_api_v1_policies_put']; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + '/api/v1/policies/{policy_id}/controls': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List policy's controls + * @description List all controls associated with a policy. + * + * Args: + * policy_id: ID of the policy + * db: Database session (injected) + * + * Returns: + * GetPolicyControlsResponse with list of control IDs + * + * Raises: + * HTTPException 404: Policy not found + */ + get: operations['list_policy_controls_api_v1_policies__policy_id__controls_get']; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + '/api/v1/policies/{policy_id}/controls/{control_id}': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Add control to policy + * @description Associate a control with a policy. + * + * This operation is idempotent - adding the same control multiple times has no effect. + * Agents with this policy will immediately see the added control. + * + * Args: + * policy_id: ID of the policy + * control_id: ID of the control to add + * db: Database session (injected) + * + * Returns: + * AssocResponse with success flag + * + * Raises: + * HTTPException 404: Policy or control not found + * HTTPException 500: Database error + */ + post: operations['add_control_to_policy_api_v1_policies__policy_id__controls__control_id__post']; + /** + * Remove control from policy + * @description Remove a control from a policy. + * + * This operation is idempotent - removing a non-associated control has no effect. + * Agents with this policy will immediately lose the removed control. + * + * Args: + * policy_id: ID of the policy + * control_id: ID of the control to remove + * db: Database session (injected) + * + * Returns: + * AssocResponse with success flag + * + * Raises: + * HTTPException 404: Policy or control not found + * HTTPException 500: Database error + */ + delete: operations['remove_control_from_policy_api_v1_policies__policy_id__controls__control_id__delete']; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + '/health': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Health check + * @description Check if the server is running and responsive. + * + * This endpoint does not check database connectivity. + * + * Returns: + * HealthResponse with status and version + */ + get: operations['health_check_health_get']; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; } export type webhooks = Record; export interface components { - schemas: { - /** - * Agent - * @description Agent metadata for registration and tracking. - * - * An agent represents an AI system that can be protected and monitored. - * Each agent has a unique immutable name and can have multiple steps registered with it. - * @example { - * "agent_description": "Handles customer inquiries and support tickets", - * "agent_metadata": { - * "environment": "production", - * "team": "support" - * }, - * "agent_name": "customer-service-bot", - * "agent_version": "1.0.0" - * } - */ - Agent: { - /** - * Agent Created At - * @description ISO 8601 timestamp when agent was created - */ - agent_created_at?: string | null; - /** - * Agent Description - * @description Optional description of the agent's purpose - */ - agent_description?: string | null; - /** - * Agent Metadata - * @description Free-form metadata dictionary for custom properties - */ - agent_metadata?: { - [key: string]: unknown; - } | null; - /** - * Agent Name - * @description Unique immutable identifier for the agent - */ - agent_name: string; - /** - * Agent Updated At - * @description ISO 8601 timestamp when agent was last updated - */ - agent_updated_at?: string | null; - /** - * Agent Version - * @description Semantic version string (e.g. '1.0.0') - */ - agent_version?: string | null; - }; - /** AgentControlsResponse */ - AgentControlsResponse: { - /** - * Controls - * @description List of active controls associated with the agent - */ - controls: components["schemas"]["Control"][]; - }; - /** - * AgentRef - * @description Reference to an agent (for listing which agents use a control). - */ - AgentRef: { - /** - * Agent Name - * @description Agent name - */ - agent_name: string; - }; - /** - * AgentSummary - * @description Summary of an agent for list responses. - */ - AgentSummary: { - /** - * Active Controls Count - * @description Number of active controls for this agent - * @default 0 - */ - active_controls_count: number; - /** - * Agent Name - * @description Unique identifier of the agent - */ - agent_name: string; - /** - * Created At - * @description ISO 8601 timestamp when agent was created - */ - created_at?: string | null; - /** - * Evaluator Count - * @description Number of evaluators registered with the agent - * @default 0 - */ - evaluator_count: number; - /** - * Policy Ids - * @description IDs of policies associated with the agent - */ - policy_ids?: number[]; - /** - * Step Count - * @description Number of steps registered with the agent - * @default 0 - */ - step_count: number; - }; - /** AssocResponse */ - AssocResponse: { - /** - * Success - * @description Whether the association change succeeded - */ - success: boolean; - }; - /** - * AuthMode - * @description Authentication mode advertised to the UI. - * @enum {string} - */ - AuthMode: "none" | "api-key"; - /** - * BatchEventsRequest - * @description Request model for batch event ingestion. - * - * SDKs batch events and send them to the server periodically. - * This reduces HTTP overhead significantly (100x reduction). - * - * Attributes: - * events: List of control execution events to ingest - * @example { - * "events": [ - * { - * "action": "deny", - * "agent_name": "my-agent", - * "applies_to": "llm_call", - * "check_stage": "pre", - * "confidence": 0.95, - * "control_id": 123, - * "control_name": "sql-injection-check", - * "matched": true, - * "span_id": "00f067aa0ba902b7", - * "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736" - * } - * ] - * } - */ - BatchEventsRequest: { - /** - * Events - * @description List of events to ingest - */ - events: components["schemas"]["ControlExecutionEvent"][]; - }; - /** - * BatchEventsResponse - * @description Response model for batch event ingestion. - * - * Attributes: - * received: Number of events received - * enqueued: Number of events successfully enqueued - * dropped: Number of events dropped (queue full) - * status: Overall status ('queued', 'partial', 'failed') - */ - BatchEventsResponse: { - /** - * Dropped - * @description Number of events dropped - */ - dropped: number; - /** - * Enqueued - * @description Number of events enqueued - */ - enqueued: number; - /** - * Received - * @description Number of events received - */ - received: number; - /** - * Status - * @description Overall ingestion status - * @enum {string} - */ - status: "queued" | "partial" | "failed"; - }; - /** - * ConditionNode - * @description Recursive boolean condition tree for control evaluation. - * @example { - * "evaluator": { - * "config": { - * "pattern": "\\d{3}-\\d{2}-\\d{4}" - * }, - * "name": "regex" - * }, - * "selector": { - * "path": "output" - * } - * } - * @example { - * "and": [ - * { - * "evaluator": { - * "config": { - * "values": [ - * "high", - * "critical" - * ] - * }, - * "name": "list" - * }, - * "selector": { - * "path": "context.risk_level" - * } - * }, - * { - * "not": { - * "evaluator": { - * "config": { - * "values": [ - * "admin", - * "security" - * ] - * }, - * "name": "list" - * }, - * "selector": { - * "path": "context.user_role" - * } - * } - * } - * ] - * } - */ - "ConditionNode-Input": { - /** - * And - * @description Logical AND over child conditions. - */ - and?: components["schemas"]["ConditionNode-Input"][] | null; - /** @description Leaf evaluator. Must be provided together with selector. */ - evaluator?: components["schemas"]["EvaluatorSpec"] | null; - /** @description Logical NOT over a single child condition. */ - not?: components["schemas"]["ConditionNode-Input"] | null; - /** - * Or - * @description Logical OR over child conditions. - */ - or?: components["schemas"]["ConditionNode-Input"][] | null; - /** @description Leaf selector. Must be provided together with evaluator. */ - selector?: components["schemas"]["ControlSelector"] | null; - }; - /** - * ConditionNode - * @description Recursive boolean condition tree for control evaluation. - * @example { - * "evaluator": { - * "config": { - * "pattern": "\\d{3}-\\d{2}-\\d{4}" - * }, - * "name": "regex" - * }, - * "selector": { - * "path": "output" - * } - * } - * @example { - * "and": [ - * { - * "evaluator": { - * "config": { - * "values": [ - * "high", - * "critical" - * ] - * }, - * "name": "list" - * }, - * "selector": { - * "path": "context.risk_level" - * } - * }, - * { - * "not": { - * "evaluator": { - * "config": { - * "values": [ - * "admin", - * "security" - * ] - * }, - * "name": "list" - * }, - * "selector": { - * "path": "context.user_role" - * } - * } - * } - * ] - * } - */ - "ConditionNode-Output": { - /** - * And - * @description Logical AND over child conditions. - */ - and?: components["schemas"]["ConditionNode-Output"][] | null; - /** @description Leaf evaluator. Must be provided together with selector. */ - evaluator?: components["schemas"]["EvaluatorSpec"] | null; - /** @description Logical NOT over a single child condition. */ - not?: components["schemas"]["ConditionNode-Output"] | null; - /** - * Or - * @description Logical OR over child conditions. - */ - or?: components["schemas"]["ConditionNode-Output"][] | null; - /** @description Leaf selector. Must be provided together with evaluator. */ - selector?: components["schemas"]["ControlSelector"] | null; - }; - /** - * ConfigResponse - * @description Configuration surface exposed to the UI. - */ - ConfigResponse: { - auth_mode: components["schemas"]["AuthMode"]; - /** - * Has Active Session - * @default false - */ - has_active_session: boolean; - /** Requires Api Key */ - requires_api_key: boolean; - }; - /** - * ConflictMode - * @description Conflict handling mode for initAgent registration updates. - * - * STRICT preserves compatibility checks and raises conflicts on incompatible changes. - * OVERWRITE applies latest-init-wins replacement for steps and evaluators. - * @enum {string} - */ - ConflictMode: "strict" | "overwrite"; - /** - * Control - * @description A control with identity and configuration. - * - * Note: Only fully-configured controls (with valid ControlDefinition) - * are returned from API endpoints. Unconfigured controls are filtered out. - */ - Control: { - control: components["schemas"]["ControlDefinition-Output"]; - /** Id */ - id: number; - /** Name */ - name: string; - }; - /** - * ControlAction - * @description What to do when control matches. - */ - ControlAction: { - /** - * Decision - * @description Action to take when control is triggered - * @enum {string} - */ - decision: "allow" | "deny" | "steer" | "warn" | "log"; - /** @description Steering context object for steer actions. Strongly recommended when decision='steer' to provide correction suggestions. If not provided, the evaluator result message will be used as fallback. */ - steering_context?: components["schemas"]["SteeringContext"] | null; - }; - /** - * ControlDefinition - * @description A control definition to evaluate agent interactions. - * - * This model contains only the logic and configuration. - * Identity fields (id, name) are managed by the database. - * @example { - * "action": { - * "decision": "deny" - * }, - * "condition": { - * "evaluator": { - * "config": { - * "pattern": "\\b\\d{3}-\\d{2}-\\d{4}\\b" - * }, - * "name": "regex" - * }, - * "selector": { - * "path": "output" - * } - * }, - * "description": "Block outputs containing US Social Security Numbers", - * "enabled": true, - * "execution": "server", - * "scope": { - * "stages": [ - * "post" - * ], - * "step_types": [ - * "llm" - * ] - * }, - * "tags": [ - * "pii", - * "compliance" - * ] - * } - */ - "ControlDefinition-Input": { - /** @description What action to take when control matches */ - action: components["schemas"]["ControlAction"]; - /** @description Recursive boolean condition tree. Leaf nodes contain selector + evaluator; composite nodes contain and/or/not. */ - condition: components["schemas"]["ConditionNode-Input"]; - /** - * Description - * @description Detailed description of the control - */ - description?: string | null; - /** - * Enabled - * @description Whether this control is active - * @default true - */ - enabled: boolean; - /** - * Execution - * @description Where this control executes - * @enum {string} - */ - execution: "server" | "sdk"; - /** @description Which steps and stages this control applies to */ - scope?: components["schemas"]["ControlScope"]; - /** - * Tags - * @description Tags for categorization - */ - tags?: string[]; - }; - /** - * ControlDefinition - * @description A control definition to evaluate agent interactions. - * - * This model contains only the logic and configuration. - * Identity fields (id, name) are managed by the database. - * @example { - * "action": { - * "decision": "deny" - * }, - * "condition": { - * "evaluator": { - * "config": { - * "pattern": "\\b\\d{3}-\\d{2}-\\d{4}\\b" - * }, - * "name": "regex" - * }, - * "selector": { - * "path": "output" - * } - * }, - * "description": "Block outputs containing US Social Security Numbers", - * "enabled": true, - * "execution": "server", - * "scope": { - * "stages": [ - * "post" - * ], - * "step_types": [ - * "llm" - * ] - * }, - * "tags": [ - * "pii", - * "compliance" - * ] - * } - */ - "ControlDefinition-Output": { - /** @description What action to take when control matches */ - action: components["schemas"]["ControlAction"]; - /** @description Recursive boolean condition tree. Leaf nodes contain selector + evaluator; composite nodes contain and/or/not. */ - condition: components["schemas"]["ConditionNode-Output"]; - /** - * Description - * @description Detailed description of the control - */ - description?: string | null; - /** - * Enabled - * @description Whether this control is active - * @default true - */ - enabled: boolean; - /** - * Execution - * @description Where this control executes - * @enum {string} - */ - execution: "server" | "sdk"; - /** @description Which steps and stages this control applies to */ - scope?: components["schemas"]["ControlScope"]; - /** - * Tags - * @description Tags for categorization - */ - tags?: string[]; - }; - /** - * ControlExecutionEvent - * @description Represents a single control execution event. - * - * This is the core observability data model, capturing: - * - Identity: control_execution_id, trace_id, span_id (OpenTelemetry-compatible) - * - Context: agent, control, check stage, applies to - * - Result: action taken, whether matched, confidence score - * - Timing: when it happened, how long it took - * - Optional details: evaluator name, selector path, errors, metadata - * - * Attributes: - * control_execution_id: Unique ID for this specific control execution - * trace_id: OpenTelemetry-compatible trace ID (128-bit hex, 32 chars) - * span_id: OpenTelemetry-compatible span ID (64-bit hex, 16 chars) - * agent_name: Identifier of the agent that executed the control - * control_id: Database ID of the control - * control_name: Name of the control (denormalized for queries) - * check_stage: "pre" (before execution) or "post" (after execution) - * applies_to: "llm_call" or "tool_call" - * action: The action taken (allow, deny, warn, log) - * matched: Whether the control evaluator matched - * confidence: Confidence score from the evaluator (0.0-1.0) - * timestamp: When the control was executed (UTC) - * execution_duration_ms: How long the control evaluation took - * evaluator_name: Name of the evaluator used - * selector_path: The selector path used to extract data - * error_message: Error message if evaluation failed - * metadata: Additional metadata for extensibility - * @example { - * "action": "deny", - * "agent_name": "my-agent", - * "applies_to": "llm_call", - * "check_stage": "pre", - * "confidence": 0.95, - * "control_execution_id": "550e8400-e29b-41d4-a716-446655440000", - * "control_id": 123, - * "control_name": "sql-injection-check", - * "evaluator_name": "regex", - * "execution_duration_ms": 15.3, - * "matched": true, - * "selector_path": "input", - * "span_id": "00f067aa0ba902b7", - * "timestamp": "2025-01-09T10:30:00Z", - * "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736" - * } - */ - ControlExecutionEvent: { - /** - * Action - * @description Action taken by the control - * @enum {string} - */ - action: "allow" | "deny" | "steer" | "warn" | "log"; - /** - * Agent Name - * @description Identifier of the agent - */ - agent_name: string; - /** - * Applies To - * @description Type of call: 'llm_call' or 'tool_call' - * @enum {string} - */ - applies_to: "llm_call" | "tool_call"; - /** - * Check Stage - * @description Check stage: 'pre' or 'post' - * @enum {string} - */ - check_stage: "pre" | "post"; - /** - * Confidence - * @description Confidence score (0.0 to 1.0) - */ - confidence: number; - /** - * Control Execution Id - * @description Unique ID for this control execution - */ - control_execution_id?: string; - /** - * Control Id - * @description Database ID of the control - */ - control_id: number; - /** - * Control Name - * @description Name of the control (denormalized) - */ - control_name: string; - /** - * Error Message - * @description Error message if evaluation failed - */ - error_message?: string | null; - /** - * Evaluator Name - * @description Name of the evaluator used - */ - evaluator_name?: string | null; - /** - * Execution Duration Ms - * @description Execution duration in milliseconds - */ - execution_duration_ms?: number | null; - /** - * Matched - * @description Whether the evaluator matched (True) or not (False) - */ - matched: boolean; - /** - * Metadata - * @description Additional metadata - */ - metadata?: { - [key: string]: unknown; - }; - /** - * Selector Path - * @description Selector path used to extract data - */ - selector_path?: string | null; - /** - * Span Id - * @description Span ID for distributed tracing (SDK generates OTEL-compatible 16-char hex) - */ - span_id: string; - /** - * Timestamp - * Format: date-time - * @description When the control was executed (UTC) - */ - timestamp?: string; - /** - * Trace Id - * @description Trace ID for distributed tracing (SDK generates OTEL-compatible 32-char hex) - */ - trace_id: string; - }; - /** - * ControlMatch - * @description Represents a control evaluation result (match, non-match, or error). - */ - ControlMatch: { - /** - * Action - * @description Action configured for this control - * @enum {string} - */ - action: "allow" | "deny" | "steer" | "warn" | "log"; - /** - * Control Execution Id - * @description Unique ID for this control execution (generated by engine) - */ - control_execution_id?: string; - /** - * Control Id - * @description Database ID of the control - */ - control_id: number; - /** - * Control Name - * @description Name of the control - */ - control_name: string; - /** @description Evaluator result (confidence, message, metadata) */ - result: components["schemas"]["EvaluatorResult"]; - /** @description Steering context for steer actions if configured */ - steering_context?: components["schemas"]["SteeringContext"] | null; - }; - /** - * ControlScope - * @description Defines when a control applies to a Step. - * @example { - * "stages": [ - * "pre" - * ], - * "step_types": [ - * "tool" - * ] - * } - * @example { - * "step_names": [ - * "search_db", - * "fetch_user" - * ] - * } - * @example { - * "step_name_regex": "^db_.*" - * } - * @example { - * "stages": [ - * "post" - * ], - * "step_types": [ - * "llm" - * ] - * } - */ - ControlScope: { - /** - * Stages - * @description Evaluation stages this control applies to - */ - stages?: ("pre" | "post")[] | null; - /** - * Step Name Regex - * @description RE2 pattern matched with search() against step name - */ - step_name_regex?: string | null; - /** - * Step Names - * @description Exact step names this control applies to - */ - step_names?: string[] | null; - /** - * Step Types - * @description Step types this control applies to (omit to apply to all types). Built-in types are 'tool' and 'llm'. - */ - step_types?: string[] | null; - }; - /** - * ControlSelector - * @description Selects data from a Step payload. - * - * - path: which slice of the Step to feed into the evaluator. Optional, defaults to "*" - * meaning the entire Step object. - * @example { - * "path": "output" - * } - * @example { - * "path": "context.user_id" - * } - * @example { - * "path": "input" - * } - * @example { - * "path": "*" - * } - * @example { - * "path": "name" - * } - * @example { - * "path": "output" - * } - */ - ControlSelector: { - /** - * Path - * @description Path to data using dot notation. Examples: 'input', 'output', 'context.user_id', 'name', 'type', '*' - * @default * - */ - path: string | null; - }; - /** - * ControlStats - * @description Aggregated statistics for a single control. - * - * Attributes: - * control_id: Database ID of the control - * control_name: Name of the control - * execution_count: Total number of executions - * match_count: Number of times the control matched - * non_match_count: Number of times the control did not match - * allow_count: Number of allow actions - * deny_count: Number of deny actions - * steer_count: Number of steer actions - * warn_count: Number of warn actions - * log_count: Number of log actions - * error_count: Number of errors during evaluation - * avg_confidence: Average confidence score - * avg_duration_ms: Average execution duration in milliseconds - */ - ControlStats: { - /** - * Allow Count - * @description Allow actions - */ - allow_count: number; - /** - * Avg Confidence - * @description Average confidence - */ - avg_confidence: number; - /** - * Avg Duration Ms - * @description Average duration (ms) - */ - avg_duration_ms?: number | null; - /** - * Control Id - * @description Control ID - */ - control_id: number; - /** - * Control Name - * @description Control name - */ - control_name: string; - /** - * Deny Count - * @description Deny actions - */ - deny_count: number; - /** - * Error Count - * @description Evaluation errors - */ - error_count: number; - /** - * Execution Count - * @description Total executions - */ - execution_count: number; - /** - * Log Count - * @description Log actions - */ - log_count: number; - /** - * Match Count - * @description Total matches - */ - match_count: number; - /** - * Non Match Count - * @description Total non-matches - */ - non_match_count: number; - /** - * Steer Count - * @description Steer actions - */ - steer_count: number; - /** - * Warn Count - * @description Warn actions - */ - warn_count: number; - }; - /** - * ControlStatsResponse - * @description Response model for control-level statistics. - * - * Contains stats for a single control (with optional timeseries). - * - * Attributes: - * agent_name: Agent identifier - * time_range: Time range used - * control_id: Control ID - * control_name: Control name - * stats: Control statistics (includes timeseries when requested) - */ - ControlStatsResponse: { - /** - * Agent Name - * @description Agent identifier - */ - agent_name: string; - /** - * Control Id - * @description Control ID - */ - control_id: number; - /** - * Control Name - * @description Control name - */ - control_name: string; - /** @description Control statistics */ - stats: components["schemas"]["StatsTotals"]; - /** - * Time Range - * @description Time range used - */ - time_range: string; - }; - /** - * ControlSummary - * @description Summary of a control for list responses. - */ - ControlSummary: { - /** - * Description - * @description Control description - */ - description?: string | null; - /** - * Enabled - * @description Whether control is enabled - * @default true - */ - enabled: boolean; - /** - * Execution - * @description 'server' or 'sdk' - */ - execution?: string | null; - /** - * Id - * @description Control ID - */ - id: number; - /** - * Name - * @description Control name - */ - name: string; - /** - * Stages - * @description Evaluation stages in scope - */ - stages?: string[] | null; - /** - * Step Types - * @description Step types in scope - */ - step_types?: string[] | null; - /** - * Tags - * @description Control tags - */ - tags?: string[]; - /** @description Agent using this control */ - used_by_agent?: components["schemas"]["AgentRef"] | null; - /** - * Used By Agents Count - * @description Number of unique agents using this control - * @default 0 - */ - used_by_agents_count: number; - }; - /** CreateControlRequest */ - CreateControlRequest: { - /** @description Control definition to validate and store during creation */ - data: components["schemas"]["ControlDefinition-Input"]; - /** - * Name - * @description Unique control name (letters, numbers, hyphens, underscores) - */ - name: string; - }; - /** CreateControlResponse */ - CreateControlResponse: { - /** - * Control Id - * @description Identifier of the created control - */ - control_id: number; - }; - /** - * CreateEvaluatorConfigRequest - * @description Request to create an evaluator config template. - */ - CreateEvaluatorConfigRequest: { - /** - * Config - * @description Evaluator-specific configuration - */ - config: { - [key: string]: unknown; - }; - /** - * Description - * @description Optional description - */ - description?: string | null; - /** - * Evaluator - * @description Evaluator name (built-in or custom) - */ - evaluator: string; - /** - * Name - * @description Unique evaluator config name (letters, numbers, hyphens, underscores) - */ - name: string; - }; - /** CreatePolicyRequest */ - CreatePolicyRequest: { - /** - * Name - * @description Unique policy name (letters, numbers, hyphens, underscores) - */ - name: string; - }; - /** CreatePolicyResponse */ - CreatePolicyResponse: { - /** - * Policy Id - * @description Identifier of the created policy - */ - policy_id: number; - }; - /** - * DeleteControlResponse - * @description Response for deleting a control. - */ - DeleteControlResponse: { - /** - * Dissociated From - * @description Deprecated: policy IDs the control was removed from before deletion - */ - dissociated_from?: number[]; - /** - * Dissociated From Agents - * @description Agent names the control was removed from before deletion - */ - dissociated_from_agents?: string[]; - /** - * Dissociated From Policies - * @description Policy IDs the control was removed from before deletion - */ - dissociated_from_policies?: number[]; - /** - * Success - * @description Whether the control was deleted - */ - success: boolean; - }; - /** - * DeleteEvaluatorConfigResponse - * @description Response for deleting an evaluator config. - */ - DeleteEvaluatorConfigResponse: { - /** - * Success - * @description Whether the evaluator config was deleted - */ - success: boolean; - }; - /** - * DeletePolicyResponse - * @description Compatibility response for singular policy deletion endpoint. - */ - DeletePolicyResponse: { - /** - * Success - * @description Whether the request succeeded - */ - success: boolean; - }; - /** - * EvaluationRequest - * @description Request model for evaluation analysis. - * - * Used to analyze agent interactions for safety violations, - * policy compliance, and control rules. - * - * Attributes: - * agent_name: Unique identifier of the agent making the request - * step: Step payload for evaluation - * stage: 'pre' (before execution) or 'post' (after execution) - * @example { - * "agent_name": "customer-service-bot", - * "stage": "pre", - * "step": { - * "context": { - * "session_id": "abc123", - * "user_id": "user123" - * }, - * "input": "What is the customer's credit card number?", - * "name": "support-answer", - * "type": "llm" - * } - * } - * @example { - * "agent_name": "customer-service-bot", - * "stage": "post", - * "step": { - * "context": { - * "session_id": "abc123", - * "user_id": "user123" - * }, - * "input": "What is the customer's credit card number?", - * "name": "support-answer", - * "output": "I cannot share sensitive payment information.", - * "type": "llm" - * } - * } - * @example { - * "agent_name": "customer-service-bot", - * "stage": "pre", - * "step": { - * "context": { - * "user_id": "user123" - * }, - * "input": { - * "query": "SELECT * FROM users" - * }, - * "name": "search_database", - * "type": "tool" - * } - * } - * @example { - * "agent_name": "customer-service-bot", - * "stage": "post", - * "step": { - * "context": { - * "user_id": "user123" - * }, - * "input": { - * "query": "SELECT * FROM users" - * }, - * "name": "search_database", - * "output": { - * "results": [] - * }, - * "type": "tool" - * } - * } - */ - EvaluationRequest: { - /** - * Agent Name - * @description Identifier of the agent making the evaluation request - */ - agent_name: string; - /** - * Stage - * @description Evaluation stage: 'pre' or 'post' - * @enum {string} - */ - stage: "pre" | "post"; - /** @description Agent step payload to evaluate */ - step: components["schemas"]["Step"]; - }; - /** - * EvaluationResponse - * @description Response model from evaluation analysis (server-side). - * - * This is what the server returns. The SDK may transform this - * into an EvaluationResult for client convenience. - * - * Attributes: - * is_safe: Whether the content is considered safe - * confidence: Confidence score between 0.0 and 1.0 - * reason: Optional explanation for the decision - * matches: List of controls that matched/triggered (if any) - * errors: List of controls that failed during evaluation (if any) - * non_matches: List of controls that were evaluated but did not match (if any) - */ - EvaluationResponse: { - /** - * Confidence - * @description Confidence score (0.0 to 1.0) - */ - confidence: number; - /** - * Errors - * @description List of controls that failed during evaluation (if any) - */ - errors?: components["schemas"]["ControlMatch"][] | null; - /** - * Is Safe - * @description Whether content is safe - */ - is_safe: boolean; - /** - * Matches - * @description List of controls that matched/triggered (if any) - */ - matches?: components["schemas"]["ControlMatch"][] | null; - /** - * Non Matches - * @description List of controls that were evaluated but did not match (if any) - */ - non_matches?: components["schemas"]["ControlMatch"][] | null; - /** - * Reason - * @description Explanation for the decision - */ - reason?: string | null; - }; - /** - * EvaluatorConfigItem - * @description Evaluator config template stored in the server. - */ - EvaluatorConfigItem: { - /** - * Config - * @description Evaluator-specific configuration - */ - config: { - [key: string]: unknown; - }; - /** - * Created At - * @description ISO 8601 created timestamp - */ - created_at?: string | null; - /** - * Description - * @description Optional description - */ - description?: string | null; - /** - * Evaluator - * @description Evaluator name (built-in or custom) - */ - evaluator: string; - /** - * Id - * @description Evaluator config ID - */ - id: number; - /** - * Name - * @description Unique evaluator config name (letters, numbers, hyphens, underscores) - */ - name: string; - /** - * Updated At - * @description ISO 8601 updated timestamp - */ - updated_at?: string | null; - }; - /** - * EvaluatorInfo - * @description Information about a registered evaluator. - */ - EvaluatorInfo: { - /** - * Config Schema - * @description JSON Schema for config - */ - config_schema: { - [key: string]: unknown; - }; - /** - * Description - * @description Evaluator description - */ - description: string; - /** - * Name - * @description Evaluator name - */ - name: string; - /** - * Requires Api Key - * @description Whether evaluator requires API key - */ - requires_api_key: boolean; - /** - * Timeout Ms - * @description Default timeout in milliseconds - */ - timeout_ms: number; - /** - * Version - * @description Evaluator version - */ - version: string; - }; - /** - * EvaluatorResult - * @description Result from a control evaluator. - * - * The `error` field indicates evaluator failures, NOT validation failures: - * - Set `error` for: evaluator crashes, timeouts, missing dependencies, external service errors - * - Do NOT set `error` for: invalid input, syntax errors, schema violations, constraint failures - * - * When `error` is set, `matched` must be False (fail-open on evaluator errors). - * When `error` is None, `matched` reflects the actual validation result. - * - * This distinction allows: - * - Clients to distinguish "data violated rules" from "evaluator is broken" - * - Observability systems to monitor evaluator health separately from validation outcomes - */ - EvaluatorResult: { - /** - * Confidence - * @description Confidence in the evaluation - */ - confidence: number; - /** - * Error - * @description Error message if evaluation failed internally. When set, matched=False is due to error, not actual evaluation. - */ - error?: string | null; - /** - * Matched - * @description Whether the pattern matched - */ - matched: boolean; - /** - * Message - * @description Explanation of the result - */ - message?: string | null; - /** - * Metadata - * @description Additional result metadata - */ - metadata?: { - [key: string]: unknown; - } | null; - }; - /** - * EvaluatorSchema - * @description Schema for a custom evaluator registered with an agent. - * - * Custom evaluators are Evaluator classes deployed with the engine. - * This schema is registered via initAgent for validation and UI purposes. - */ - EvaluatorSchema: { - /** - * Config Schema - * @description JSON Schema for evaluator config validation - */ - config_schema?: { - [key: string]: unknown; - }; - /** - * Description - * @description Optional description - */ - description?: string | null; - /** - * Name - * @description Unique evaluator name - */ - name: string; - }; - /** - * EvaluatorSchemaItem - * @description Evaluator schema summary for list response. - */ - EvaluatorSchemaItem: { - /** Config Schema */ - config_schema: { - [key: string]: unknown; - }; - /** Description */ - description: string | null; - /** Name */ - name: string; - }; - /** - * EvaluatorSpec - * @description Evaluator specification. See GET /evaluators for available evaluators and schemas. - * - * Evaluator reference formats: - * - Built-in: "regex", "list", "json", "sql" - * - External: "galileo.luna2" (requires agent-control-evaluators[galileo]) - * - Agent-scoped: "my-agent:my-evaluator" (validated in endpoint, not here) - */ - EvaluatorSpec: { - /** - * Config - * @description Evaluator-specific configuration - * @example { - * "pattern": "\\d{3}-\\d{2}-\\d{4}" - * } - * @example { - * "logic": "any", - * "values": [ - * "admin" - * ] - * } - */ - config: { - [key: string]: unknown; - }; - /** - * Name - * @description Evaluator name or agent-scoped reference (agent:evaluator) - * @example regex - * @example list - * @example my-agent:pii-detector - */ - name: string; - }; - /** - * EventQueryRequest - * @description Request model for querying raw events. - * - * Supports filtering by various criteria and pagination. - * - * Attributes: - * trace_id: Filter by trace ID (get all events for a request) - * span_id: Filter by span ID (get all events for a function call) - * control_execution_id: Filter by specific event ID - * agent_name: Filter by agent identifier - * control_ids: Filter by control IDs - * actions: Filter by actions (allow, deny, steer, warn, log) - * matched: Filter by matched status - * check_stages: Filter by check stages (pre, post) - * applies_to: Filter by call type (llm_call, tool_call) - * start_time: Filter events after this time - * end_time: Filter events before this time - * limit: Maximum number of events to return - * offset: Offset for pagination - * @example { - * "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736" - * } - * @example { - * "actions": [ - * "deny", - * "warn" - * ], - * "agent_name": "my-agent", - * "limit": 50, - * "start_time": "2025-01-09T00:00:00Z" - * } - */ - EventQueryRequest: { - /** - * Actions - * @description Filter by actions - */ - actions?: ("allow" | "deny" | "steer" | "warn" | "log")[] | null; - /** - * Agent Name - * @description Filter by agent identifier - */ - agent_name?: string | null; - /** - * Applies To - * @description Filter by call types - */ - applies_to?: ("llm_call" | "tool_call")[] | null; - /** - * Check Stages - * @description Filter by check stages - */ - check_stages?: ("pre" | "post")[] | null; - /** - * Control Execution Id - * @description Filter by specific event ID - */ - control_execution_id?: string | null; - /** - * Control Ids - * @description Filter by control IDs - */ - control_ids?: number[] | null; - /** - * End Time - * @description Filter events before this time - */ - end_time?: string | null; - /** - * Limit - * @description Maximum events - * @default 100 - */ - limit: number; - /** - * Matched - * @description Filter by matched status - */ - matched?: boolean | null; - /** - * Offset - * @description Pagination offset - * @default 0 - */ - offset: number; - /** - * Span Id - * @description Filter by span ID (all events for a function) - */ - span_id?: string | null; - /** - * Start Time - * @description Filter events after this time - */ - start_time?: string | null; - /** - * Trace Id - * @description Filter by trace ID (all events for a request) - */ - trace_id?: string | null; - }; - /** - * EventQueryResponse - * @description Response model for event queries. - * - * Attributes: - * events: List of matching events - * total: Total number of matching events (for pagination) - * limit: Limit used in query - * offset: Offset used in query - */ - EventQueryResponse: { - /** - * Events - * @description Matching events - */ - events: components["schemas"]["ControlExecutionEvent"][]; - /** - * Limit - * @description Limit used in query - */ - limit: number; - /** - * Offset - * @description Offset used in query - */ - offset: number; - /** - * Total - * @description Total matching events - */ - total: number; - }; - /** GetAgentPoliciesResponse */ - GetAgentPoliciesResponse: { - /** - * Policy Ids - * @description IDs of policies associated with the agent - */ - policy_ids?: number[]; - }; - /** - * GetAgentResponse - * @description Response containing agent details and registered steps. - */ - GetAgentResponse: { - /** @description Agent metadata */ - agent: components["schemas"]["Agent"]; - /** - * Evaluators - * @description Custom evaluators registered with this agent - */ - evaluators?: components["schemas"]["EvaluatorSchema"][]; - /** - * Steps - * @description Steps registered with this agent - */ - steps: components["schemas"]["StepSchema"][]; - }; - /** GetControlDataResponse */ - GetControlDataResponse: { - /** @description Control data payload */ - data: components["schemas"]["ControlDefinition-Output"]; - }; - /** - * GetControlResponse - * @description Response containing control details. - */ - GetControlResponse: { - /** @description Control configuration data (None if not yet configured) */ - data?: components["schemas"]["ControlDefinition-Output"] | null; - /** - * Id - * @description Control ID - */ - id: number; - /** - * Name - * @description Control name - */ - name: string; - }; - /** - * GetPolicyControlsResponse - * @description Response containing control IDs associated with a policy. - */ - GetPolicyControlsResponse: { - /** - * Control Ids - * @description List of control IDs associated with the policy - */ - control_ids: number[]; - }; - /** - * GetPolicyResponse - * @description Compatibility response for singular policy retrieval endpoint. - */ - GetPolicyResponse: { - /** - * Policy Id - * @description Associated policy ID - */ - policy_id: number; - }; - /** HTTPValidationError */ - HTTPValidationError: { - /** Detail */ - detail?: components["schemas"]["ValidationError"][]; - }; - /** - * HealthResponse - * @description Health check response model. - * - * Attributes: - * status: Current health status (e.g., "healthy", "degraded", "unhealthy") - * version: Application version - */ - HealthResponse: { - /** Status */ - status: string; - /** Version */ - version: string; - }; - /** - * InitAgentEvaluatorRemoval - * @description Details for an evaluator removed during overwrite mode. - */ - InitAgentEvaluatorRemoval: { - /** - * Control Ids - * @description IDs of active controls referencing this evaluator - */ - control_ids?: number[]; - /** - * Control Names - * @description Names of active controls referencing this evaluator - */ - control_names?: string[]; - /** - * Name - * @description Evaluator name removed by overwrite - */ - name: string; - /** - * Referenced By Active Controls - * @description Whether this evaluator is still referenced by active controls - * @default false - */ - referenced_by_active_controls: boolean; - }; - /** - * InitAgentOverwriteChanges - * @description Detailed change summary for initAgent overwrite mode. - */ - InitAgentOverwriteChanges: { - /** - * Evaluator Removals - * @description Per-evaluator removal details, including active control references - */ - evaluator_removals?: components["schemas"]["InitAgentEvaluatorRemoval"][]; - /** - * Evaluators Added - * @description Evaluator names added by overwrite - */ - evaluators_added?: string[]; - /** - * Evaluators Removed - * @description Evaluator names removed by overwrite - */ - evaluators_removed?: string[]; - /** - * Evaluators Updated - * @description Existing evaluator names updated by overwrite - */ - evaluators_updated?: string[]; - /** - * Metadata Changed - * @description Whether agent metadata changed - * @default false - */ - metadata_changed: boolean; - /** - * Steps Added - * @description Steps added by overwrite - */ - steps_added?: components["schemas"]["StepKey"][]; - /** - * Steps Removed - * @description Steps removed by overwrite - */ - steps_removed?: components["schemas"]["StepKey"][]; - /** - * Steps Updated - * @description Existing steps updated by overwrite - */ - steps_updated?: components["schemas"]["StepKey"][]; - }; - /** - * InitAgentRequest - * @description Request to initialize or update an agent registration. - * @example { - * "agent": { - * "agent_description": "Handles customer inquiries", - * "agent_name": "customer-service-bot", - * "agent_version": "1.0.0" - * }, - * "evaluators": [ - * { - * "config_schema": { - * "properties": { - * "sensitivity": { - * "type": "string" - * } - * }, - * "type": "object" - * }, - * "description": "Detects PII in text", - * "name": "pii-detector" - * } - * ], - * "steps": [ - * { - * "input_schema": { - * "query": { - * "type": "string" - * } - * }, - * "name": "search_kb", - * "output_schema": { - * "results": { - * "type": "array" - * } - * }, - * "type": "tool" - * } - * ] - * } - */ - InitAgentRequest: { - /** @description Agent metadata including ID, name, and version */ - agent: components["schemas"]["Agent"]; - /** - * @description Conflict handling mode for init registration updates. 'strict' preserves existing compatibility checks. 'overwrite' applies latest-init-wins replacement for steps and evaluators. - * @default strict - */ - conflict_mode: components["schemas"]["ConflictMode"]; - /** - * Evaluators - * @description Custom evaluator schemas for config validation - */ - evaluators?: components["schemas"]["EvaluatorSchema"][]; - /** - * Force Replace - * @description If true, replace corrupted agent data instead of failing. Use only when agent data is corrupted and cannot be parsed. - * @default false - */ - force_replace: boolean; - /** - * Steps - * @description List of steps available to the agent - */ - steps?: components["schemas"]["StepSchema"][]; - }; - /** - * InitAgentResponse - * @description Response from agent initialization. - */ - InitAgentResponse: { - /** - * Controls - * @description Active protection controls for the agent - */ - controls?: components["schemas"]["Control"][]; - /** - * Created - * @description True if agent was newly created, False if updated - */ - created: boolean; - /** - * Overwrite Applied - * @description True if overwrite mode changed registration data on an existing agent - * @default false - */ - overwrite_applied: boolean; - /** @description Detailed list of changes applied in overwrite mode */ - overwrite_changes?: components["schemas"]["InitAgentOverwriteChanges"]; - }; - JSONObject: { - [key: string]: components["schemas"]["JSONValue"]; - }; - /** @description Any JSON value */ - JSONValue: unknown; - /** - * ListAgentsResponse - * @description Response for listing agents. - */ - ListAgentsResponse: { - /** - * Agents - * @description List of agent summaries - */ - agents: components["schemas"]["AgentSummary"][]; - /** @description Pagination metadata */ - pagination: components["schemas"]["PaginationInfo"]; - }; - /** - * ListControlsResponse - * @description Response for listing controls. - */ - ListControlsResponse: { - /** - * Controls - * @description List of control summaries - */ - controls: components["schemas"]["ControlSummary"][]; - /** @description Pagination metadata */ - pagination: components["schemas"]["PaginationInfo"]; - }; - /** - * ListEvaluatorConfigsResponse - * @description Response for listing evaluator configs. - */ - ListEvaluatorConfigsResponse: { - /** - * Evaluator Configs - * @description List of evaluator configs - */ - evaluator_configs: components["schemas"]["EvaluatorConfigItem"][]; - /** @description Pagination metadata */ - pagination: components["schemas"]["PaginationInfo"]; - }; - /** - * ListEvaluatorsResponse - * @description Response for listing agent's evaluator schemas. - */ - ListEvaluatorsResponse: { - /** Evaluators */ - evaluators: components["schemas"]["EvaluatorSchemaItem"][]; - pagination: components["schemas"]["PaginationInfo"]; - }; - /** - * LoginRequest - * @description Request body for the /login endpoint. - */ - LoginRequest: { - /** Api Key */ - api_key: string; - }; - /** - * LoginResponse - * @description Response body for the /login endpoint. - */ - LoginResponse: { - /** Authenticated */ - authenticated: boolean; - /** Is Admin */ - is_admin: boolean; - }; - /** - * PaginationInfo - * @description Pagination metadata for cursor-based pagination. - */ - PaginationInfo: { - /** - * Has More - * @description Whether there are more pages available - */ - has_more: boolean; - /** - * Limit - * @description Number of items per page - */ - limit: number; - /** - * Next Cursor - * @description Cursor for fetching the next page (null if no more pages) - */ - next_cursor?: string | null; - /** - * Total - * @description Total number of items - */ - total: number; - }; - /** - * PatchAgentRequest - * @description Request to modify an agent (remove steps/evaluators). - */ - PatchAgentRequest: { - /** - * Remove Evaluators - * @description Evaluator names to remove from the agent - */ - remove_evaluators?: string[]; - /** - * Remove Steps - * @description Step identifiers to remove from the agent - */ - remove_steps?: components["schemas"]["StepKey"][]; - }; - /** - * PatchAgentResponse - * @description Response from agent modification. - */ - PatchAgentResponse: { - /** - * Evaluators Removed - * @description Evaluator names that were removed - */ - evaluators_removed?: string[]; - /** - * Steps Removed - * @description Step identifiers that were removed - */ - steps_removed?: components["schemas"]["StepKey"][]; - }; - /** - * PatchControlRequest - * @description Request to update control metadata (name, enabled status). - */ - PatchControlRequest: { - /** - * Enabled - * @description Enable or disable the control - */ - enabled?: boolean | null; - /** - * Name - * @description New control name (letters, numbers, hyphens, underscores) - */ - name?: string | null; - }; - /** - * PatchControlResponse - * @description Response from control metadata update. - */ - PatchControlResponse: { - /** - * Enabled - * @description Current enabled status (if control has data configured) - */ - enabled?: boolean | null; - /** - * Name - * @description Current control name (may have changed) - */ - name: string; - /** - * Success - * @description Whether the update succeeded - */ - success: boolean; - }; - /** - * RemoveAgentControlResponse - * @description Response for removing a direct agent-control association. - */ - RemoveAgentControlResponse: { - /** - * Control Still Active - * @description True if the control remains active via policy association(s) - */ - control_still_active: boolean; - /** - * Removed Direct Association - * @description True if a direct agent-control link was removed - */ - removed_direct_association: boolean; - /** - * Success - * @description Whether the request succeeded - */ - success: boolean; - }; - /** - * SetControlDataRequest - * @description Request to update control configuration data. - */ - SetControlDataRequest: { - /** @description Control configuration data (replaces existing) */ - data: components["schemas"]["ControlDefinition-Input"]; - }; - /** SetControlDataResponse */ - SetControlDataResponse: { - /** - * Success - * @description Whether the control data was updated - */ - success: boolean; - }; - /** - * SetPolicyResponse - * @description Compatibility response for singular policy assignment endpoint. - */ - SetPolicyResponse: { - /** - * Old Policy Id - * @description Previously associated policy ID, if any - */ - old_policy_id?: number | null; - /** - * Success - * @description Whether the request succeeded - */ - success: boolean; - }; - /** - * StatsResponse - * @description Response model for agent-level aggregated statistics. - * - * Contains agent-level totals (with optional timeseries) and per-control breakdown. - * - * Attributes: - * agent_name: Agent identifier - * time_range: Time range used - * totals: Agent-level aggregate statistics (includes timeseries) - * controls: Per-control breakdown for discovery and detail - */ - StatsResponse: { - /** - * Agent Name - * @description Agent identifier - */ - agent_name: string; - /** - * Controls - * @description Per-control breakdown - */ - controls: components["schemas"]["ControlStats"][]; - /** - * Time Range - * @description Time range used - */ - time_range: string; - /** @description Agent-level aggregate statistics */ - totals: components["schemas"]["StatsTotals"]; - }; - /** - * StatsTotals - * @description Agent-level aggregate statistics. - * - * Invariant: execution_count = match_count + non_match_count + error_count - * - * Matches have actions (allow, deny, steer, warn, log) tracked in action_counts. - * sum(action_counts.values()) == match_count - * - * Attributes: - * execution_count: Total executions across all controls - * match_count: Total matches across all controls (evaluator matched) - * non_match_count: Total non-matches across all controls (evaluator didn't match) - * error_count: Total errors across all controls (evaluation failed) - * action_counts: Breakdown of actions for matched executions - * timeseries: Time-series data points (only when include_timeseries=true) - */ - StatsTotals: { - /** - * Action Counts - * @description Action breakdown for matches: {allow, deny, steer, warn, log} - */ - action_counts?: { - [key: string]: number; - }; - /** - * Error Count - * @description Total errors - * @default 0 - */ - error_count: number; - /** - * Execution Count - * @description Total executions - */ - execution_count: number; - /** - * Match Count - * @description Total matches - * @default 0 - */ - match_count: number; - /** - * Non Match Count - * @description Total non-matches - * @default 0 - */ - non_match_count: number; - /** - * Timeseries - * @description Time-series data points (only when include_timeseries=true) - */ - timeseries?: components["schemas"]["TimeseriesBucket"][] | null; - }; - /** - * SteeringContext - * @description Steering context for steer actions. - * - * This model provides an extensible structure for steering guidance. - * Future fields could include severity, categories, suggested_actions, etc. - * @example { - * "message": "This large transfer requires user verification. Request 2FA code from user, verify it, then retry the transaction with verified_2fa=True." - * } - * @example { - * "message": "Transfer exceeds daily limit. Steps: 1) Ask user for business justification, 2) Request manager approval with amount and justification, 3) If approved, retry with manager_approved=True and justification filled in." - * } - */ - SteeringContext: { - /** - * Message - * @description Guidance message explaining what needs to be corrected and how - */ - message: string; - }; - /** - * Step - * @description Runtime payload for an agent step invocation. - */ - Step: { - /** @description Optional context (conversation history, metadata, etc.) */ - context?: components["schemas"]["JSONObject"] | null; - /** @description Input content for this step */ - input: components["schemas"]["JSONValue"]; - /** - * Name - * @description Step name (tool name or model/chain id) - */ - name: string; - /** @description Output content for this step (None for pre-checks) */ - output?: components["schemas"]["JSONValue"] | null; - /** - * Type - * @description Step type (e.g., 'tool', 'llm') - */ - type: string; - }; - /** - * StepKey - * @description Identifies a registered step schema by type and name. - */ - StepKey: { - /** - * Name - * @description Registered step name - */ - name: string; - /** - * Type - * @description Step type - */ - type: string; - }; - /** - * StepSchema - * @description Schema for a registered agent step. - * @example { - * "description": "Search the internal knowledge base", - * "input_schema": { - * "query": { - * "description": "Search query", - * "type": "string" - * } - * }, - * "name": "search_knowledge_base", - * "output_schema": { - * "results": { - * "items": { - * "type": "object" - * }, - * "type": "array" - * } - * }, - * "type": "tool" - * } - * @example { - * "description": "Customer support response generation", - * "input_schema": { - * "messages": { - * "items": { - * "type": "object" - * }, - * "type": "array" - * } - * }, - * "name": "support-answer", - * "output_schema": { - * "text": { - * "type": "string" - * } - * }, - * "type": "llm" - * } - */ - StepSchema: { - /** - * Description - * @description Optional description of the step - */ - description?: string | null; - /** - * Input Schema - * @description JSON schema describing step input - */ - input_schema?: { - [key: string]: unknown; - } | null; - /** - * Metadata - * @description Additional metadata for the step - */ - metadata?: { - [key: string]: unknown; - } | null; - /** - * Name - * @description Unique name for the step - */ - name: string; - /** - * Output Schema - * @description JSON schema describing step output - */ - output_schema?: { - [key: string]: unknown; - } | null; - /** - * Type - * @description Step type for this schema (e.g., 'tool', 'llm') - */ - type: string; - }; - /** - * TimeseriesBucket - * @description Single data point in a time-series. - * - * Represents aggregated metrics for a single time bucket. - * - * Attributes: - * timestamp: Start time of the bucket (UTC, always timezone-aware) - * execution_count: Total executions in this bucket - * match_count: Number of matches in this bucket - * non_match_count: Number of non-matches in this bucket - * error_count: Number of errors in this bucket - * action_counts: Breakdown of actions for matched executions - * avg_confidence: Average confidence score (None if no executions) - * avg_duration_ms: Average execution duration in milliseconds (None if no data) - */ - TimeseriesBucket: { - /** - * Action Counts - * @description Action breakdown: {allow, deny, steer, warn, log} - */ - action_counts?: { - [key: string]: number; - }; - /** - * Avg Confidence - * @description Average confidence score - */ - avg_confidence?: number | null; - /** - * Avg Duration Ms - * @description Average duration (ms) - */ - avg_duration_ms?: number | null; - /** - * Error Count - * @description Errors in bucket - */ - error_count: number; - /** - * Execution Count - * @description Total executions in bucket - */ - execution_count: number; - /** - * Match Count - * @description Matches in bucket - */ - match_count: number; - /** - * Non Match Count - * @description Non-matches in bucket - */ - non_match_count: number; - /** - * Timestamp - * Format: date-time - * @description Start time of the bucket (UTC) - */ - timestamp: string; - }; - /** - * UpdateEvaluatorConfigRequest - * @description Request to replace an evaluator config template. - */ - UpdateEvaluatorConfigRequest: { - /** - * Config - * @description Evaluator-specific configuration - */ - config: { - [key: string]: unknown; - }; - /** - * Description - * @description Optional description - */ - description?: string | null; - /** - * Evaluator - * @description Evaluator name (built-in or custom) - */ - evaluator: string; - /** - * Name - * @description Unique evaluator config name (letters, numbers, hyphens, underscores) - */ - name: string; - }; - /** - * ValidateControlDataRequest - * @description Request to validate control configuration data without saving. - */ - ValidateControlDataRequest: { - /** @description Control configuration data to validate */ - data: components["schemas"]["ControlDefinition-Input"]; - }; - /** ValidateControlDataResponse */ - ValidateControlDataResponse: { - /** - * Success - * @description Whether the control data is valid - */ - success: boolean; - }; - /** ValidationError */ - ValidationError: { - /** Location */ - loc: (string | number)[]; - /** Message */ - msg: string; - /** Error Type */ - type: string; - }; - }; - responses: never; - parameters: never; - requestBodies: never; - headers: never; - pathItems: never; + schemas: { + /** + * Agent + * @description Agent metadata for registration and tracking. + * + * An agent represents an AI system that can be protected and monitored. + * Each agent has a unique immutable name and can have multiple steps registered with it. + * @example { + * "agent_description": "Handles customer inquiries and support tickets", + * "agent_metadata": { + * "environment": "production", + * "team": "support" + * }, + * "agent_name": "customer-service-bot", + * "agent_version": "1.0.0" + * } + */ + Agent: { + /** + * Agent Created At + * @description ISO 8601 timestamp when agent was created + */ + agent_created_at?: string | null; + /** + * Agent Description + * @description Optional description of the agent's purpose + */ + agent_description?: string | null; + /** + * Agent Metadata + * @description Free-form metadata dictionary for custom properties + */ + agent_metadata?: { + [key: string]: unknown; + } | null; + /** + * Agent Name + * @description Unique immutable identifier for the agent + */ + agent_name: string; + /** + * Agent Updated At + * @description ISO 8601 timestamp when agent was last updated + */ + agent_updated_at?: string | null; + /** + * Agent Version + * @description Semantic version string (e.g. '1.0.0') + */ + agent_version?: string | null; + }; + /** AgentControlsResponse */ + AgentControlsResponse: { + /** + * Controls + * @description List of active controls associated with the agent + */ + controls: components['schemas']['Control'][]; + }; + /** + * AgentRef + * @description Reference to an agent (for listing which agents use a control). + */ + AgentRef: { + /** + * Agent Name + * @description Agent name + */ + agent_name: string; + }; + /** + * AgentSummary + * @description Summary of an agent for list responses. + */ + AgentSummary: { + /** + * Active Controls Count + * @description Number of active controls for this agent + * @default 0 + */ + active_controls_count: number; + /** + * Agent Name + * @description Unique identifier of the agent + */ + agent_name: string; + /** + * Created At + * @description ISO 8601 timestamp when agent was created + */ + created_at?: string | null; + /** + * Evaluator Count + * @description Number of evaluators registered with the agent + * @default 0 + */ + evaluator_count: number; + /** + * Policy Ids + * @description IDs of policies associated with the agent + */ + policy_ids?: number[]; + /** + * Step Count + * @description Number of steps registered with the agent + * @default 0 + */ + step_count: number; + }; + /** AssocResponse */ + AssocResponse: { + /** + * Success + * @description Whether the association change succeeded + */ + success: boolean; + }; + /** + * AuthMode + * @description Authentication mode advertised to the UI. + * @enum {string} + */ + AuthMode: 'none' | 'api-key'; + /** + * BatchEventsRequest + * @description Request model for batch event ingestion. + * + * SDKs batch events and send them to the server periodically. + * This reduces HTTP overhead significantly (100x reduction). + * + * Attributes: + * events: List of control execution events to ingest + * @example { + * "events": [ + * { + * "action": "deny", + * "agent_name": "my-agent", + * "applies_to": "llm_call", + * "check_stage": "pre", + * "confidence": 0.95, + * "control_id": 123, + * "control_name": "sql-injection-check", + * "matched": true, + * "span_id": "00f067aa0ba902b7", + * "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736" + * } + * ] + * } + */ + BatchEventsRequest: { + /** + * Events + * @description List of events to ingest + */ + events: components['schemas']['ControlExecutionEvent'][]; + }; + /** + * BatchEventsResponse + * @description Response model for batch event ingestion. + * + * Attributes: + * received: Number of events received + * enqueued: Number of events successfully enqueued + * dropped: Number of events dropped (queue full) + * status: Overall status ('queued', 'partial', 'failed') + */ + BatchEventsResponse: { + /** + * Dropped + * @description Number of events dropped + */ + dropped: number; + /** + * Enqueued + * @description Number of events enqueued + */ + enqueued: number; + /** + * Received + * @description Number of events received + */ + received: number; + /** + * Status + * @description Overall ingestion status + * @enum {string} + */ + status: 'queued' | 'partial' | 'failed'; + }; + /** + * ConditionNode + * @description Recursive boolean condition tree for control evaluation. + * @example { + * "evaluator": { + * "config": { + * "pattern": "\\d{3}-\\d{2}-\\d{4}" + * }, + * "name": "regex" + * }, + * "selector": { + * "path": "output" + * } + * } + * @example { + * "and": [ + * { + * "evaluator": { + * "config": { + * "values": [ + * "high", + * "critical" + * ] + * }, + * "name": "list" + * }, + * "selector": { + * "path": "context.risk_level" + * } + * }, + * { + * "not": { + * "evaluator": { + * "config": { + * "values": [ + * "admin", + * "security" + * ] + * }, + * "name": "list" + * }, + * "selector": { + * "path": "context.user_role" + * } + * } + * } + * ] + * } + */ + 'ConditionNode-Input': { + /** + * And + * @description Logical AND over child conditions. + */ + and?: components['schemas']['ConditionNode-Input'][] | null; + /** @description Leaf evaluator. Must be provided together with selector. */ + evaluator?: components['schemas']['EvaluatorSpec'] | null; + /** @description Logical NOT over a single child condition. */ + not?: components['schemas']['ConditionNode-Input'] | null; + /** + * Or + * @description Logical OR over child conditions. + */ + or?: components['schemas']['ConditionNode-Input'][] | null; + /** @description Leaf selector. Must be provided together with evaluator. */ + selector?: components['schemas']['ControlSelector'] | null; + }; + /** + * ConditionNode + * @description Recursive boolean condition tree for control evaluation. + * @example { + * "evaluator": { + * "config": { + * "pattern": "\\d{3}-\\d{2}-\\d{4}" + * }, + * "name": "regex" + * }, + * "selector": { + * "path": "output" + * } + * } + * @example { + * "and": [ + * { + * "evaluator": { + * "config": { + * "values": [ + * "high", + * "critical" + * ] + * }, + * "name": "list" + * }, + * "selector": { + * "path": "context.risk_level" + * } + * }, + * { + * "not": { + * "evaluator": { + * "config": { + * "values": [ + * "admin", + * "security" + * ] + * }, + * "name": "list" + * }, + * "selector": { + * "path": "context.user_role" + * } + * } + * } + * ] + * } + */ + 'ConditionNode-Output': { + /** + * And + * @description Logical AND over child conditions. + */ + and?: components['schemas']['ConditionNode-Output'][] | null; + /** @description Leaf evaluator. Must be provided together with selector. */ + evaluator?: components['schemas']['EvaluatorSpec'] | null; + /** @description Logical NOT over a single child condition. */ + not?: components['schemas']['ConditionNode-Output'] | null; + /** + * Or + * @description Logical OR over child conditions. + */ + or?: components['schemas']['ConditionNode-Output'][] | null; + /** @description Leaf selector. Must be provided together with evaluator. */ + selector?: components['schemas']['ControlSelector'] | null; + }; + /** + * ConfigResponse + * @description Configuration surface exposed to the UI. + */ + ConfigResponse: { + auth_mode: components['schemas']['AuthMode']; + /** + * Has Active Session + * @default false + */ + has_active_session: boolean; + /** Requires Api Key */ + requires_api_key: boolean; + }; + /** + * ConflictMode + * @description Conflict handling mode for initAgent registration updates. + * + * STRICT preserves compatibility checks and raises conflicts on incompatible changes. + * OVERWRITE applies latest-init-wins replacement for steps and evaluators. + * @enum {string} + */ + ConflictMode: 'strict' | 'overwrite'; + /** + * Control + * @description A control with identity and configuration. + * + * Note: Only fully-configured controls (with valid ControlDefinition) + * are returned from API endpoints. Unconfigured controls are filtered out. + */ + Control: { + control: components['schemas']['ControlDefinition-Output']; + /** Id */ + id: number; + /** Name */ + name: string; + }; + /** + * ControlAction + * @description What to do when control matches. + */ + ControlAction: { + /** + * Decision + * @description Action to take when control is triggered + * @enum {string} + */ + decision: 'allow' | 'deny' | 'steer' | 'warn' | 'log'; + /** @description Steering context object for steer actions. Strongly recommended when decision='steer' to provide correction suggestions. If not provided, the evaluator result message will be used as fallback. */ + steering_context?: components['schemas']['SteeringContext'] | null; + }; + /** + * ControlDefinition + * @description A control definition to evaluate agent interactions. + * + * This model contains only the logic and configuration. + * Identity fields (id, name) are managed by the database. + * @example { + * "action": { + * "decision": "deny" + * }, + * "condition": { + * "evaluator": { + * "config": { + * "pattern": "\\b\\d{3}-\\d{2}-\\d{4}\\b" + * }, + * "name": "regex" + * }, + * "selector": { + * "path": "output" + * } + * }, + * "description": "Block outputs containing US Social Security Numbers", + * "enabled": true, + * "execution": "server", + * "scope": { + * "stages": [ + * "post" + * ], + * "step_types": [ + * "llm" + * ] + * }, + * "tags": [ + * "pii", + * "compliance" + * ] + * } + */ + 'ControlDefinition-Input': { + /** @description What action to take when control matches */ + action: components['schemas']['ControlAction']; + /** @description Recursive boolean condition tree. Leaf nodes contain selector + evaluator; composite nodes contain and/or/not. */ + condition: components['schemas']['ConditionNode-Input']; + /** + * Description + * @description Detailed description of the control + */ + description?: string | null; + /** + * Enabled + * @description Whether this control is active + * @default true + */ + enabled: boolean; + /** + * Execution + * @description Where this control executes + * @enum {string} + */ + execution: 'server' | 'sdk'; + /** @description Which steps and stages this control applies to */ + scope?: components['schemas']['ControlScope']; + /** + * Tags + * @description Tags for categorization + */ + tags?: string[]; + }; + /** + * ControlDefinition + * @description A control definition to evaluate agent interactions. + * + * This model contains only the logic and configuration. + * Identity fields (id, name) are managed by the database. + * @example { + * "action": { + * "decision": "deny" + * }, + * "condition": { + * "evaluator": { + * "config": { + * "pattern": "\\b\\d{3}-\\d{2}-\\d{4}\\b" + * }, + * "name": "regex" + * }, + * "selector": { + * "path": "output" + * } + * }, + * "description": "Block outputs containing US Social Security Numbers", + * "enabled": true, + * "execution": "server", + * "scope": { + * "stages": [ + * "post" + * ], + * "step_types": [ + * "llm" + * ] + * }, + * "tags": [ + * "pii", + * "compliance" + * ] + * } + */ + 'ControlDefinition-Output': { + /** @description What action to take when control matches */ + action: components['schemas']['ControlAction']; + /** @description Recursive boolean condition tree. Leaf nodes contain selector + evaluator; composite nodes contain and/or/not. */ + condition: components['schemas']['ConditionNode-Output']; + /** + * Description + * @description Detailed description of the control + */ + description?: string | null; + /** + * Enabled + * @description Whether this control is active + * @default true + */ + enabled: boolean; + /** + * Execution + * @description Where this control executes + * @enum {string} + */ + execution: 'server' | 'sdk'; + /** @description Which steps and stages this control applies to */ + scope?: components['schemas']['ControlScope']; + /** + * Tags + * @description Tags for categorization + */ + tags?: string[]; + }; + /** + * ControlExecutionEvent + * @description Represents a single control execution event. + * + * This is the core observability data model, capturing: + * - Identity: control_execution_id, trace_id, span_id (OpenTelemetry-compatible) + * - Context: agent, control, check stage, applies to + * - Result: action taken, whether matched, confidence score + * - Timing: when it happened, how long it took + * - Optional details: evaluator name, selector path, errors, metadata + * + * Attributes: + * control_execution_id: Unique ID for this specific control execution + * trace_id: OpenTelemetry-compatible trace ID (128-bit hex, 32 chars) + * span_id: OpenTelemetry-compatible span ID (64-bit hex, 16 chars) + * agent_name: Identifier of the agent that executed the control + * control_id: Database ID of the control + * control_name: Name of the control (denormalized for queries) + * check_stage: "pre" (before execution) or "post" (after execution) + * applies_to: "llm_call" or "tool_call" + * action: The action taken (allow, deny, warn, log) + * matched: Whether the control evaluator matched + * confidence: Confidence score from the evaluator (0.0-1.0) + * timestamp: When the control was executed (UTC) + * execution_duration_ms: How long the control evaluation took + * evaluator_name: Name of the evaluator used + * selector_path: The selector path used to extract data + * error_message: Error message if evaluation failed + * metadata: Additional metadata for extensibility + * @example { + * "action": "deny", + * "agent_name": "my-agent", + * "applies_to": "llm_call", + * "check_stage": "pre", + * "confidence": 0.95, + * "control_execution_id": "550e8400-e29b-41d4-a716-446655440000", + * "control_id": 123, + * "control_name": "sql-injection-check", + * "evaluator_name": "regex", + * "execution_duration_ms": 15.3, + * "matched": true, + * "selector_path": "input", + * "span_id": "00f067aa0ba902b7", + * "timestamp": "2025-01-09T10:30:00Z", + * "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736" + * } + */ + ControlExecutionEvent: { + /** + * Action + * @description Action taken by the control + * @enum {string} + */ + action: 'allow' | 'deny' | 'steer' | 'warn' | 'log'; + /** + * Agent Name + * @description Identifier of the agent + */ + agent_name: string; + /** + * Applies To + * @description Type of call: 'llm_call' or 'tool_call' + * @enum {string} + */ + applies_to: 'llm_call' | 'tool_call'; + /** + * Check Stage + * @description Check stage: 'pre' or 'post' + * @enum {string} + */ + check_stage: 'pre' | 'post'; + /** + * Confidence + * @description Confidence score (0.0 to 1.0) + */ + confidence: number; + /** + * Control Execution Id + * @description Unique ID for this control execution + */ + control_execution_id?: string; + /** + * Control Id + * @description Database ID of the control + */ + control_id: number; + /** + * Control Name + * @description Name of the control (denormalized) + */ + control_name: string; + /** + * Error Message + * @description Error message if evaluation failed + */ + error_message?: string | null; + /** + * Evaluator Name + * @description Name of the evaluator used + */ + evaluator_name?: string | null; + /** + * Execution Duration Ms + * @description Execution duration in milliseconds + */ + execution_duration_ms?: number | null; + /** + * Matched + * @description Whether the evaluator matched (True) or not (False) + */ + matched: boolean; + /** + * Metadata + * @description Additional metadata + */ + metadata?: { + [key: string]: unknown; + }; + /** + * Selector Path + * @description Selector path used to extract data + */ + selector_path?: string | null; + /** + * Span Id + * @description Span ID for distributed tracing (SDK generates OTEL-compatible 16-char hex) + */ + span_id: string; + /** + * Timestamp + * Format: date-time + * @description When the control was executed (UTC) + */ + timestamp?: string; + /** + * Trace Id + * @description Trace ID for distributed tracing (SDK generates OTEL-compatible 32-char hex) + */ + trace_id: string; + }; + /** + * ControlMatch + * @description Represents a control evaluation result (match, non-match, or error). + */ + ControlMatch: { + /** + * Action + * @description Action configured for this control + * @enum {string} + */ + action: 'allow' | 'deny' | 'steer' | 'warn' | 'log'; + /** + * Control Execution Id + * @description Unique ID for this control execution (generated by engine) + */ + control_execution_id?: string; + /** + * Control Id + * @description Database ID of the control + */ + control_id: number; + /** + * Control Name + * @description Name of the control + */ + control_name: string; + /** @description Evaluator result (confidence, message, metadata) */ + result: components['schemas']['EvaluatorResult']; + /** @description Steering context for steer actions if configured */ + steering_context?: components['schemas']['SteeringContext'] | null; + }; + /** + * ControlScope + * @description Defines when a control applies to a Step. + * @example { + * "stages": [ + * "pre" + * ], + * "step_types": [ + * "tool" + * ] + * } + * @example { + * "step_names": [ + * "search_db", + * "fetch_user" + * ] + * } + * @example { + * "step_name_regex": "^db_.*" + * } + * @example { + * "stages": [ + * "post" + * ], + * "step_types": [ + * "llm" + * ] + * } + */ + ControlScope: { + /** + * Stages + * @description Evaluation stages this control applies to + */ + stages?: ('pre' | 'post')[] | null; + /** + * Step Name Regex + * @description RE2 pattern matched with search() against step name + */ + step_name_regex?: string | null; + /** + * Step Names + * @description Exact step names this control applies to + */ + step_names?: string[] | null; + /** + * Step Types + * @description Step types this control applies to (omit to apply to all types). Built-in types are 'tool' and 'llm'. + */ + step_types?: string[] | null; + }; + /** + * ControlSelector + * @description Selects data from a Step payload. + * + * - path: which slice of the Step to feed into the evaluator. Optional, defaults to "*" + * meaning the entire Step object. + * @example { + * "path": "output" + * } + * @example { + * "path": "context.user_id" + * } + * @example { + * "path": "input" + * } + * @example { + * "path": "*" + * } + * @example { + * "path": "name" + * } + * @example { + * "path": "output" + * } + */ + ControlSelector: { + /** + * Path + * @description Path to data using dot notation. Examples: 'input', 'output', 'context.user_id', 'name', 'type', '*' + * @default * + */ + path: string | null; + }; + /** + * ControlStats + * @description Aggregated statistics for a single control. + * + * Attributes: + * control_id: Database ID of the control + * control_name: Name of the control + * execution_count: Total number of executions + * match_count: Number of times the control matched + * non_match_count: Number of times the control did not match + * allow_count: Number of allow actions + * deny_count: Number of deny actions + * steer_count: Number of steer actions + * warn_count: Number of warn actions + * log_count: Number of log actions + * error_count: Number of errors during evaluation + * avg_confidence: Average confidence score + * avg_duration_ms: Average execution duration in milliseconds + */ + ControlStats: { + /** + * Allow Count + * @description Allow actions + */ + allow_count: number; + /** + * Avg Confidence + * @description Average confidence + */ + avg_confidence: number; + /** + * Avg Duration Ms + * @description Average duration (ms) + */ + avg_duration_ms?: number | null; + /** + * Control Id + * @description Control ID + */ + control_id: number; + /** + * Control Name + * @description Control name + */ + control_name: string; + /** + * Deny Count + * @description Deny actions + */ + deny_count: number; + /** + * Error Count + * @description Evaluation errors + */ + error_count: number; + /** + * Execution Count + * @description Total executions + */ + execution_count: number; + /** + * Log Count + * @description Log actions + */ + log_count: number; + /** + * Match Count + * @description Total matches + */ + match_count: number; + /** + * Non Match Count + * @description Total non-matches + */ + non_match_count: number; + /** + * Steer Count + * @description Steer actions + */ + steer_count: number; + /** + * Warn Count + * @description Warn actions + */ + warn_count: number; + }; + /** + * ControlStatsResponse + * @description Response model for control-level statistics. + * + * Contains stats for a single control (with optional timeseries). + * + * Attributes: + * agent_name: Agent identifier + * time_range: Time range used + * control_id: Control ID + * control_name: Control name + * stats: Control statistics (includes timeseries when requested) + */ + ControlStatsResponse: { + /** + * Agent Name + * @description Agent identifier + */ + agent_name: string; + /** + * Control Id + * @description Control ID + */ + control_id: number; + /** + * Control Name + * @description Control name + */ + control_name: string; + /** @description Control statistics */ + stats: components['schemas']['StatsTotals']; + /** + * Time Range + * @description Time range used + */ + time_range: string; + }; + /** + * ControlSummary + * @description Summary of a control for list responses. + */ + ControlSummary: { + /** + * Description + * @description Control description + */ + description?: string | null; + /** + * Enabled + * @description Whether control is enabled + * @default true + */ + enabled: boolean; + /** + * Execution + * @description 'server' or 'sdk' + */ + execution?: string | null; + /** + * Id + * @description Control ID + */ + id: number; + /** + * Name + * @description Control name + */ + name: string; + /** + * Stages + * @description Evaluation stages in scope + */ + stages?: string[] | null; + /** + * Step Types + * @description Step types in scope + */ + step_types?: string[] | null; + /** + * Tags + * @description Control tags + */ + tags?: string[]; + /** @description Agent using this control */ + used_by_agent?: components['schemas']['AgentRef'] | null; + /** + * Used By Agents Count + * @description Number of unique agents using this control + * @default 0 + */ + used_by_agents_count: number; + }; + /** CreateControlRequest */ + CreateControlRequest: { + /** @description Control definition to validate and store during creation */ + data: components['schemas']['ControlDefinition-Input']; + /** + * Name + * @description Unique control name (letters, numbers, hyphens, underscores) + */ + name: string; + }; + /** CreateControlResponse */ + CreateControlResponse: { + /** + * Control Id + * @description Identifier of the created control + */ + control_id: number; + }; + /** + * CreateEvaluatorConfigRequest + * @description Request to create an evaluator config template. + */ + CreateEvaluatorConfigRequest: { + /** + * Config + * @description Evaluator-specific configuration + */ + config: { + [key: string]: unknown; + }; + /** + * Description + * @description Optional description + */ + description?: string | null; + /** + * Evaluator + * @description Evaluator name (built-in or custom) + */ + evaluator: string; + /** + * Name + * @description Unique evaluator config name (letters, numbers, hyphens, underscores) + */ + name: string; + }; + /** CreatePolicyRequest */ + CreatePolicyRequest: { + /** + * Name + * @description Unique policy name (letters, numbers, hyphens, underscores) + */ + name: string; + }; + /** CreatePolicyResponse */ + CreatePolicyResponse: { + /** + * Policy Id + * @description Identifier of the created policy + */ + policy_id: number; + }; + /** + * DeleteControlResponse + * @description Response for deleting a control. + */ + DeleteControlResponse: { + /** + * Dissociated From + * @description Deprecated: policy IDs the control was removed from before deletion + */ + dissociated_from?: number[]; + /** + * Dissociated From Agents + * @description Agent names the control was removed from before deletion + */ + dissociated_from_agents?: string[]; + /** + * Dissociated From Policies + * @description Policy IDs the control was removed from before deletion + */ + dissociated_from_policies?: number[]; + /** + * Success + * @description Whether the control was deleted + */ + success: boolean; + }; + /** + * DeleteEvaluatorConfigResponse + * @description Response for deleting an evaluator config. + */ + DeleteEvaluatorConfigResponse: { + /** + * Success + * @description Whether the evaluator config was deleted + */ + success: boolean; + }; + /** + * DeletePolicyResponse + * @description Compatibility response for singular policy deletion endpoint. + */ + DeletePolicyResponse: { + /** + * Success + * @description Whether the request succeeded + */ + success: boolean; + }; + /** + * EvaluationRequest + * @description Request model for evaluation analysis. + * + * Used to analyze agent interactions for safety violations, + * policy compliance, and control rules. + * + * Attributes: + * agent_name: Unique identifier of the agent making the request + * step: Step payload for evaluation + * stage: 'pre' (before execution) or 'post' (after execution) + * @example { + * "agent_name": "customer-service-bot", + * "stage": "pre", + * "step": { + * "context": { + * "session_id": "abc123", + * "user_id": "user123" + * }, + * "input": "What is the customer's credit card number?", + * "name": "support-answer", + * "type": "llm" + * } + * } + * @example { + * "agent_name": "customer-service-bot", + * "stage": "post", + * "step": { + * "context": { + * "session_id": "abc123", + * "user_id": "user123" + * }, + * "input": "What is the customer's credit card number?", + * "name": "support-answer", + * "output": "I cannot share sensitive payment information.", + * "type": "llm" + * } + * } + * @example { + * "agent_name": "customer-service-bot", + * "stage": "pre", + * "step": { + * "context": { + * "user_id": "user123" + * }, + * "input": { + * "query": "SELECT * FROM users" + * }, + * "name": "search_database", + * "type": "tool" + * } + * } + * @example { + * "agent_name": "customer-service-bot", + * "stage": "post", + * "step": { + * "context": { + * "user_id": "user123" + * }, + * "input": { + * "query": "SELECT * FROM users" + * }, + * "name": "search_database", + * "output": { + * "results": [] + * }, + * "type": "tool" + * } + * } + */ + EvaluationRequest: { + /** + * Agent Name + * @description Identifier of the agent making the evaluation request + */ + agent_name: string; + /** + * Stage + * @description Evaluation stage: 'pre' or 'post' + * @enum {string} + */ + stage: 'pre' | 'post'; + /** @description Agent step payload to evaluate */ + step: components['schemas']['Step']; + }; + /** + * EvaluationResponse + * @description Response model from evaluation analysis (server-side). + * + * This is what the server returns. The SDK may transform this + * into an EvaluationResult for client convenience. + * + * Attributes: + * is_safe: Whether the content is considered safe + * confidence: Confidence score between 0.0 and 1.0 + * reason: Optional explanation for the decision + * matches: List of controls that matched/triggered (if any) + * errors: List of controls that failed during evaluation (if any) + * non_matches: List of controls that were evaluated but did not match (if any) + */ + EvaluationResponse: { + /** + * Confidence + * @description Confidence score (0.0 to 1.0) + */ + confidence: number; + /** + * Errors + * @description List of controls that failed during evaluation (if any) + */ + errors?: components['schemas']['ControlMatch'][] | null; + /** + * Is Safe + * @description Whether content is safe + */ + is_safe: boolean; + /** + * Matches + * @description List of controls that matched/triggered (if any) + */ + matches?: components['schemas']['ControlMatch'][] | null; + /** + * Non Matches + * @description List of controls that were evaluated but did not match (if any) + */ + non_matches?: components['schemas']['ControlMatch'][] | null; + /** + * Reason + * @description Explanation for the decision + */ + reason?: string | null; + }; + /** + * EvaluatorConfigItem + * @description Evaluator config template stored in the server. + */ + EvaluatorConfigItem: { + /** + * Config + * @description Evaluator-specific configuration + */ + config: { + [key: string]: unknown; + }; + /** + * Created At + * @description ISO 8601 created timestamp + */ + created_at?: string | null; + /** + * Description + * @description Optional description + */ + description?: string | null; + /** + * Evaluator + * @description Evaluator name (built-in or custom) + */ + evaluator: string; + /** + * Id + * @description Evaluator config ID + */ + id: number; + /** + * Name + * @description Unique evaluator config name (letters, numbers, hyphens, underscores) + */ + name: string; + /** + * Updated At + * @description ISO 8601 updated timestamp + */ + updated_at?: string | null; + }; + /** + * EvaluatorInfo + * @description Information about a registered evaluator. + */ + EvaluatorInfo: { + /** + * Config Schema + * @description JSON Schema for config + */ + config_schema: { + [key: string]: unknown; + }; + /** + * Description + * @description Evaluator description + */ + description: string; + /** + * Name + * @description Evaluator name + */ + name: string; + /** + * Requires Api Key + * @description Whether evaluator requires API key + */ + requires_api_key: boolean; + /** + * Timeout Ms + * @description Default timeout in milliseconds + */ + timeout_ms: number; + /** + * Version + * @description Evaluator version + */ + version: string; + }; + /** + * EvaluatorResult + * @description Result from a control evaluator. + * + * The `error` field indicates evaluator failures, NOT validation failures: + * - Set `error` for: evaluator crashes, timeouts, missing dependencies, external service errors + * - Do NOT set `error` for: invalid input, syntax errors, schema violations, constraint failures + * + * When `error` is set, `matched` must be False (fail-open on evaluator errors). + * When `error` is None, `matched` reflects the actual validation result. + * + * This distinction allows: + * - Clients to distinguish "data violated rules" from "evaluator is broken" + * - Observability systems to monitor evaluator health separately from validation outcomes + */ + EvaluatorResult: { + /** + * Confidence + * @description Confidence in the evaluation + */ + confidence: number; + /** + * Error + * @description Error message if evaluation failed internally. When set, matched=False is due to error, not actual evaluation. + */ + error?: string | null; + /** + * Matched + * @description Whether the pattern matched + */ + matched: boolean; + /** + * Message + * @description Explanation of the result + */ + message?: string | null; + /** + * Metadata + * @description Additional result metadata + */ + metadata?: { + [key: string]: unknown; + } | null; + }; + /** + * EvaluatorSchema + * @description Schema for a custom evaluator registered with an agent. + * + * Custom evaluators are Evaluator classes deployed with the engine. + * This schema is registered via initAgent for validation and UI purposes. + */ + EvaluatorSchema: { + /** + * Config Schema + * @description JSON Schema for evaluator config validation + */ + config_schema?: { + [key: string]: unknown; + }; + /** + * Description + * @description Optional description + */ + description?: string | null; + /** + * Name + * @description Unique evaluator name + */ + name: string; + }; + /** + * EvaluatorSchemaItem + * @description Evaluator schema summary for list response. + */ + EvaluatorSchemaItem: { + /** Config Schema */ + config_schema: { + [key: string]: unknown; + }; + /** Description */ + description: string | null; + /** Name */ + name: string; + }; + /** + * EvaluatorSpec + * @description Evaluator specification. See GET /evaluators for available evaluators and schemas. + * + * Evaluator reference formats: + * - Built-in: "regex", "list", "json", "sql" + * - External: "galileo.luna2" (requires agent-control-evaluators[galileo]) + * - Agent-scoped: "my-agent:my-evaluator" (validated in endpoint, not here) + */ + EvaluatorSpec: { + /** + * Config + * @description Evaluator-specific configuration + * @example { + * "pattern": "\\d{3}-\\d{2}-\\d{4}" + * } + * @example { + * "logic": "any", + * "values": [ + * "admin" + * ] + * } + */ + config: { + [key: string]: unknown; + }; + /** + * Name + * @description Evaluator name or agent-scoped reference (agent:evaluator) + * @example regex + * @example list + * @example my-agent:pii-detector + */ + name: string; + }; + /** + * EventQueryRequest + * @description Request model for querying raw events. + * + * Supports filtering by various criteria and pagination. + * + * Attributes: + * trace_id: Filter by trace ID (get all events for a request) + * span_id: Filter by span ID (get all events for a function call) + * control_execution_id: Filter by specific event ID + * agent_name: Filter by agent identifier + * control_ids: Filter by control IDs + * actions: Filter by actions (allow, deny, steer, warn, log) + * matched: Filter by matched status + * check_stages: Filter by check stages (pre, post) + * applies_to: Filter by call type (llm_call, tool_call) + * start_time: Filter events after this time + * end_time: Filter events before this time + * limit: Maximum number of events to return + * offset: Offset for pagination + * @example { + * "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736" + * } + * @example { + * "actions": [ + * "deny", + * "warn" + * ], + * "agent_name": "my-agent", + * "limit": 50, + * "start_time": "2025-01-09T00:00:00Z" + * } + */ + EventQueryRequest: { + /** + * Actions + * @description Filter by actions + */ + actions?: ('allow' | 'deny' | 'steer' | 'warn' | 'log')[] | null; + /** + * Agent Name + * @description Filter by agent identifier + */ + agent_name?: string | null; + /** + * Applies To + * @description Filter by call types + */ + applies_to?: ('llm_call' | 'tool_call')[] | null; + /** + * Check Stages + * @description Filter by check stages + */ + check_stages?: ('pre' | 'post')[] | null; + /** + * Control Execution Id + * @description Filter by specific event ID + */ + control_execution_id?: string | null; + /** + * Control Ids + * @description Filter by control IDs + */ + control_ids?: number[] | null; + /** + * End Time + * @description Filter events before this time + */ + end_time?: string | null; + /** + * Limit + * @description Maximum events + * @default 100 + */ + limit: number; + /** + * Matched + * @description Filter by matched status + */ + matched?: boolean | null; + /** + * Offset + * @description Pagination offset + * @default 0 + */ + offset: number; + /** + * Span Id + * @description Filter by span ID (all events for a function) + */ + span_id?: string | null; + /** + * Start Time + * @description Filter events after this time + */ + start_time?: string | null; + /** + * Trace Id + * @description Filter by trace ID (all events for a request) + */ + trace_id?: string | null; + }; + /** + * EventQueryResponse + * @description Response model for event queries. + * + * Attributes: + * events: List of matching events + * total: Total number of matching events (for pagination) + * limit: Limit used in query + * offset: Offset used in query + */ + EventQueryResponse: { + /** + * Events + * @description Matching events + */ + events: components['schemas']['ControlExecutionEvent'][]; + /** + * Limit + * @description Limit used in query + */ + limit: number; + /** + * Offset + * @description Offset used in query + */ + offset: number; + /** + * Total + * @description Total matching events + */ + total: number; + }; + /** GetAgentPoliciesResponse */ + GetAgentPoliciesResponse: { + /** + * Policy Ids + * @description IDs of policies associated with the agent + */ + policy_ids?: number[]; + }; + /** + * GetAgentResponse + * @description Response containing agent details and registered steps. + */ + GetAgentResponse: { + /** @description Agent metadata */ + agent: components['schemas']['Agent']; + /** + * Evaluators + * @description Custom evaluators registered with this agent + */ + evaluators?: components['schemas']['EvaluatorSchema'][]; + /** + * Steps + * @description Steps registered with this agent + */ + steps: components['schemas']['StepSchema'][]; + }; + /** GetControlDataResponse */ + GetControlDataResponse: { + /** @description Control data payload */ + data: components['schemas']['ControlDefinition-Output']; + }; + /** + * GetControlResponse + * @description Response containing control details. + */ + GetControlResponse: { + /** @description Control configuration data (None if not yet configured) */ + data?: components['schemas']['ControlDefinition-Output'] | null; + /** + * Id + * @description Control ID + */ + id: number; + /** + * Name + * @description Control name + */ + name: string; + }; + /** + * GetPolicyControlsResponse + * @description Response containing control IDs associated with a policy. + */ + GetPolicyControlsResponse: { + /** + * Control Ids + * @description List of control IDs associated with the policy + */ + control_ids: number[]; + }; + /** + * GetPolicyResponse + * @description Compatibility response for singular policy retrieval endpoint. + */ + GetPolicyResponse: { + /** + * Policy Id + * @description Associated policy ID + */ + policy_id: number; + }; + /** HTTPValidationError */ + HTTPValidationError: { + /** Detail */ + detail?: components['schemas']['ValidationError'][]; + }; + /** + * HealthResponse + * @description Health check response model. + * + * Attributes: + * status: Current health status (e.g., "healthy", "degraded", "unhealthy") + * version: Application version + */ + HealthResponse: { + /** Status */ + status: string; + /** Version */ + version: string; + }; + /** + * InitAgentEvaluatorRemoval + * @description Details for an evaluator removed during overwrite mode. + */ + InitAgentEvaluatorRemoval: { + /** + * Control Ids + * @description IDs of active controls referencing this evaluator + */ + control_ids?: number[]; + /** + * Control Names + * @description Names of active controls referencing this evaluator + */ + control_names?: string[]; + /** + * Name + * @description Evaluator name removed by overwrite + */ + name: string; + /** + * Referenced By Active Controls + * @description Whether this evaluator is still referenced by active controls + * @default false + */ + referenced_by_active_controls: boolean; + }; + /** + * InitAgentOverwriteChanges + * @description Detailed change summary for initAgent overwrite mode. + */ + InitAgentOverwriteChanges: { + /** + * Evaluator Removals + * @description Per-evaluator removal details, including active control references + */ + evaluator_removals?: components['schemas']['InitAgentEvaluatorRemoval'][]; + /** + * Evaluators Added + * @description Evaluator names added by overwrite + */ + evaluators_added?: string[]; + /** + * Evaluators Removed + * @description Evaluator names removed by overwrite + */ + evaluators_removed?: string[]; + /** + * Evaluators Updated + * @description Existing evaluator names updated by overwrite + */ + evaluators_updated?: string[]; + /** + * Metadata Changed + * @description Whether agent metadata changed + * @default false + */ + metadata_changed: boolean; + /** + * Steps Added + * @description Steps added by overwrite + */ + steps_added?: components['schemas']['StepKey'][]; + /** + * Steps Removed + * @description Steps removed by overwrite + */ + steps_removed?: components['schemas']['StepKey'][]; + /** + * Steps Updated + * @description Existing steps updated by overwrite + */ + steps_updated?: components['schemas']['StepKey'][]; + }; + /** + * InitAgentRequest + * @description Request to initialize or update an agent registration. + * @example { + * "agent": { + * "agent_description": "Handles customer inquiries", + * "agent_name": "customer-service-bot", + * "agent_version": "1.0.0" + * }, + * "evaluators": [ + * { + * "config_schema": { + * "properties": { + * "sensitivity": { + * "type": "string" + * } + * }, + * "type": "object" + * }, + * "description": "Detects PII in text", + * "name": "pii-detector" + * } + * ], + * "steps": [ + * { + * "input_schema": { + * "query": { + * "type": "string" + * } + * }, + * "name": "search_kb", + * "output_schema": { + * "results": { + * "type": "array" + * } + * }, + * "type": "tool" + * } + * ] + * } + */ + InitAgentRequest: { + /** @description Agent metadata including ID, name, and version */ + agent: components['schemas']['Agent']; + /** + * @description Conflict handling mode for init registration updates. 'strict' preserves existing compatibility checks. 'overwrite' applies latest-init-wins replacement for steps and evaluators. + * @default strict + */ + conflict_mode: components['schemas']['ConflictMode']; + /** + * Evaluators + * @description Custom evaluator schemas for config validation + */ + evaluators?: components['schemas']['EvaluatorSchema'][]; + /** + * Force Replace + * @description If true, replace corrupted agent data instead of failing. Use only when agent data is corrupted and cannot be parsed. + * @default false + */ + force_replace: boolean; + /** + * Steps + * @description List of steps available to the agent + */ + steps?: components['schemas']['StepSchema'][]; + }; + /** + * InitAgentResponse + * @description Response from agent initialization. + */ + InitAgentResponse: { + /** + * Controls + * @description Active protection controls for the agent + */ + controls?: components['schemas']['Control'][]; + /** + * Created + * @description True if agent was newly created, False if updated + */ + created: boolean; + /** + * Overwrite Applied + * @description True if overwrite mode changed registration data on an existing agent + * @default false + */ + overwrite_applied: boolean; + /** @description Detailed list of changes applied in overwrite mode */ + overwrite_changes?: components['schemas']['InitAgentOverwriteChanges']; + }; + JSONObject: { + [key: string]: components['schemas']['JSONValue']; + }; + /** @description Any JSON value */ + JSONValue: unknown; + /** + * ListAgentsResponse + * @description Response for listing agents. + */ + ListAgentsResponse: { + /** + * Agents + * @description List of agent summaries + */ + agents: components['schemas']['AgentSummary'][]; + /** @description Pagination metadata */ + pagination: components['schemas']['PaginationInfo']; + }; + /** + * ListControlsResponse + * @description Response for listing controls. + */ + ListControlsResponse: { + /** + * Controls + * @description List of control summaries + */ + controls: components['schemas']['ControlSummary'][]; + /** @description Pagination metadata */ + pagination: components['schemas']['PaginationInfo']; + }; + /** + * ListEvaluatorConfigsResponse + * @description Response for listing evaluator configs. + */ + ListEvaluatorConfigsResponse: { + /** + * Evaluator Configs + * @description List of evaluator configs + */ + evaluator_configs: components['schemas']['EvaluatorConfigItem'][]; + /** @description Pagination metadata */ + pagination: components['schemas']['PaginationInfo']; + }; + /** + * ListEvaluatorsResponse + * @description Response for listing agent's evaluator schemas. + */ + ListEvaluatorsResponse: { + /** Evaluators */ + evaluators: components['schemas']['EvaluatorSchemaItem'][]; + pagination: components['schemas']['PaginationInfo']; + }; + /** + * LoginRequest + * @description Request body for the /login endpoint. + */ + LoginRequest: { + /** Api Key */ + api_key: string; + }; + /** + * LoginResponse + * @description Response body for the /login endpoint. + */ + LoginResponse: { + /** Authenticated */ + authenticated: boolean; + /** Is Admin */ + is_admin: boolean; + }; + /** + * PaginationInfo + * @description Pagination metadata for cursor-based pagination. + */ + PaginationInfo: { + /** + * Has More + * @description Whether there are more pages available + */ + has_more: boolean; + /** + * Limit + * @description Number of items per page + */ + limit: number; + /** + * Next Cursor + * @description Cursor for fetching the next page (null if no more pages) + */ + next_cursor?: string | null; + /** + * Total + * @description Total number of items + */ + total: number; + }; + /** + * PatchAgentRequest + * @description Request to modify an agent (remove steps/evaluators). + */ + PatchAgentRequest: { + /** + * Remove Evaluators + * @description Evaluator names to remove from the agent + */ + remove_evaluators?: string[]; + /** + * Remove Steps + * @description Step identifiers to remove from the agent + */ + remove_steps?: components['schemas']['StepKey'][]; + }; + /** + * PatchAgentResponse + * @description Response from agent modification. + */ + PatchAgentResponse: { + /** + * Evaluators Removed + * @description Evaluator names that were removed + */ + evaluators_removed?: string[]; + /** + * Steps Removed + * @description Step identifiers that were removed + */ + steps_removed?: components['schemas']['StepKey'][]; + }; + /** + * PatchControlRequest + * @description Request to update control metadata (name, enabled status). + */ + PatchControlRequest: { + /** + * Enabled + * @description Enable or disable the control + */ + enabled?: boolean | null; + /** + * Name + * @description New control name (letters, numbers, hyphens, underscores) + */ + name?: string | null; + }; + /** + * PatchControlResponse + * @description Response from control metadata update. + */ + PatchControlResponse: { + /** + * Enabled + * @description Current enabled status (if control has data configured) + */ + enabled?: boolean | null; + /** + * Name + * @description Current control name (may have changed) + */ + name: string; + /** + * Success + * @description Whether the update succeeded + */ + success: boolean; + }; + /** + * RemoveAgentControlResponse + * @description Response for removing a direct agent-control association. + */ + RemoveAgentControlResponse: { + /** + * Control Still Active + * @description True if the control remains active via policy association(s) + */ + control_still_active: boolean; + /** + * Removed Direct Association + * @description True if a direct agent-control link was removed + */ + removed_direct_association: boolean; + /** + * Success + * @description Whether the request succeeded + */ + success: boolean; + }; + /** + * SetControlDataRequest + * @description Request to update control configuration data. + */ + SetControlDataRequest: { + /** @description Control configuration data (replaces existing) */ + data: components['schemas']['ControlDefinition-Input']; + }; + /** SetControlDataResponse */ + SetControlDataResponse: { + /** + * Success + * @description Whether the control data was updated + */ + success: boolean; + }; + /** + * SetPolicyResponse + * @description Compatibility response for singular policy assignment endpoint. + */ + SetPolicyResponse: { + /** + * Old Policy Id + * @description Previously associated policy ID, if any + */ + old_policy_id?: number | null; + /** + * Success + * @description Whether the request succeeded + */ + success: boolean; + }; + /** + * StatsResponse + * @description Response model for agent-level aggregated statistics. + * + * Contains agent-level totals (with optional timeseries) and per-control breakdown. + * + * Attributes: + * agent_name: Agent identifier + * time_range: Time range used + * totals: Agent-level aggregate statistics (includes timeseries) + * controls: Per-control breakdown for discovery and detail + */ + StatsResponse: { + /** + * Agent Name + * @description Agent identifier + */ + agent_name: string; + /** + * Controls + * @description Per-control breakdown + */ + controls: components['schemas']['ControlStats'][]; + /** + * Time Range + * @description Time range used + */ + time_range: string; + /** @description Agent-level aggregate statistics */ + totals: components['schemas']['StatsTotals']; + }; + /** + * StatsTotals + * @description Agent-level aggregate statistics. + * + * Invariant: execution_count = match_count + non_match_count + error_count + * + * Matches have actions (allow, deny, steer, warn, log) tracked in action_counts. + * sum(action_counts.values()) == match_count + * + * Attributes: + * execution_count: Total executions across all controls + * match_count: Total matches across all controls (evaluator matched) + * non_match_count: Total non-matches across all controls (evaluator didn't match) + * error_count: Total errors across all controls (evaluation failed) + * action_counts: Breakdown of actions for matched executions + * timeseries: Time-series data points (only when include_timeseries=true) + */ + StatsTotals: { + /** + * Action Counts + * @description Action breakdown for matches: {allow, deny, steer, warn, log} + */ + action_counts?: { + [key: string]: number; + }; + /** + * Error Count + * @description Total errors + * @default 0 + */ + error_count: number; + /** + * Execution Count + * @description Total executions + */ + execution_count: number; + /** + * Match Count + * @description Total matches + * @default 0 + */ + match_count: number; + /** + * Non Match Count + * @description Total non-matches + * @default 0 + */ + non_match_count: number; + /** + * Timeseries + * @description Time-series data points (only when include_timeseries=true) + */ + timeseries?: components['schemas']['TimeseriesBucket'][] | null; + }; + /** + * SteeringContext + * @description Steering context for steer actions. + * + * This model provides an extensible structure for steering guidance. + * Future fields could include severity, categories, suggested_actions, etc. + * @example { + * "message": "This large transfer requires user verification. Request 2FA code from user, verify it, then retry the transaction with verified_2fa=True." + * } + * @example { + * "message": "Transfer exceeds daily limit. Steps: 1) Ask user for business justification, 2) Request manager approval with amount and justification, 3) If approved, retry with manager_approved=True and justification filled in." + * } + */ + SteeringContext: { + /** + * Message + * @description Guidance message explaining what needs to be corrected and how + */ + message: string; + }; + /** + * Step + * @description Runtime payload for an agent step invocation. + */ + Step: { + /** @description Optional context (conversation history, metadata, etc.) */ + context?: components['schemas']['JSONObject'] | null; + /** @description Input content for this step */ + input: components['schemas']['JSONValue']; + /** + * Name + * @description Step name (tool name or model/chain id) + */ + name: string; + /** @description Output content for this step (None for pre-checks) */ + output?: components['schemas']['JSONValue'] | null; + /** + * Type + * @description Step type (e.g., 'tool', 'llm') + */ + type: string; + }; + /** + * StepKey + * @description Identifies a registered step schema by type and name. + */ + StepKey: { + /** + * Name + * @description Registered step name + */ + name: string; + /** + * Type + * @description Step type + */ + type: string; + }; + /** + * StepSchema + * @description Schema for a registered agent step. + * @example { + * "description": "Search the internal knowledge base", + * "input_schema": { + * "query": { + * "description": "Search query", + * "type": "string" + * } + * }, + * "name": "search_knowledge_base", + * "output_schema": { + * "results": { + * "items": { + * "type": "object" + * }, + * "type": "array" + * } + * }, + * "type": "tool" + * } + * @example { + * "description": "Customer support response generation", + * "input_schema": { + * "messages": { + * "items": { + * "type": "object" + * }, + * "type": "array" + * } + * }, + * "name": "support-answer", + * "output_schema": { + * "text": { + * "type": "string" + * } + * }, + * "type": "llm" + * } + */ + StepSchema: { + /** + * Description + * @description Optional description of the step + */ + description?: string | null; + /** + * Input Schema + * @description JSON schema describing step input + */ + input_schema?: { + [key: string]: unknown; + } | null; + /** + * Metadata + * @description Additional metadata for the step + */ + metadata?: { + [key: string]: unknown; + } | null; + /** + * Name + * @description Unique name for the step + */ + name: string; + /** + * Output Schema + * @description JSON schema describing step output + */ + output_schema?: { + [key: string]: unknown; + } | null; + /** + * Type + * @description Step type for this schema (e.g., 'tool', 'llm') + */ + type: string; + }; + /** + * TimeseriesBucket + * @description Single data point in a time-series. + * + * Represents aggregated metrics for a single time bucket. + * + * Attributes: + * timestamp: Start time of the bucket (UTC, always timezone-aware) + * execution_count: Total executions in this bucket + * match_count: Number of matches in this bucket + * non_match_count: Number of non-matches in this bucket + * error_count: Number of errors in this bucket + * action_counts: Breakdown of actions for matched executions + * avg_confidence: Average confidence score (None if no executions) + * avg_duration_ms: Average execution duration in milliseconds (None if no data) + */ + TimeseriesBucket: { + /** + * Action Counts + * @description Action breakdown: {allow, deny, steer, warn, log} + */ + action_counts?: { + [key: string]: number; + }; + /** + * Avg Confidence + * @description Average confidence score + */ + avg_confidence?: number | null; + /** + * Avg Duration Ms + * @description Average duration (ms) + */ + avg_duration_ms?: number | null; + /** + * Error Count + * @description Errors in bucket + */ + error_count: number; + /** + * Execution Count + * @description Total executions in bucket + */ + execution_count: number; + /** + * Match Count + * @description Matches in bucket + */ + match_count: number; + /** + * Non Match Count + * @description Non-matches in bucket + */ + non_match_count: number; + /** + * Timestamp + * Format: date-time + * @description Start time of the bucket (UTC) + */ + timestamp: string; + }; + /** + * UpdateEvaluatorConfigRequest + * @description Request to replace an evaluator config template. + */ + UpdateEvaluatorConfigRequest: { + /** + * Config + * @description Evaluator-specific configuration + */ + config: { + [key: string]: unknown; + }; + /** + * Description + * @description Optional description + */ + description?: string | null; + /** + * Evaluator + * @description Evaluator name (built-in or custom) + */ + evaluator: string; + /** + * Name + * @description Unique evaluator config name (letters, numbers, hyphens, underscores) + */ + name: string; + }; + /** + * ValidateControlDataRequest + * @description Request to validate control configuration data without saving. + */ + ValidateControlDataRequest: { + /** @description Control configuration data to validate */ + data: components['schemas']['ControlDefinition-Input']; + }; + /** ValidateControlDataResponse */ + ValidateControlDataResponse: { + /** + * Success + * @description Whether the control data is valid + */ + success: boolean; + }; + /** ValidationError */ + ValidationError: { + /** Location */ + loc: (string | number)[]; + /** Message */ + msg: string; + /** Error Type */ + type: string; + }; + }; + responses: never; + parameters: never; + requestBodies: never; + headers: never; + pathItems: never; } export type $defs = Record; export interface operations { - get_config_api_config_get: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Configuration flags for UI behavior */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ConfigResponse"]; - }; - }; - }; - }; - login_api_login_post: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["LoginRequest"]; - }; - }; - responses: { - /** @description Authentication result; sets HttpOnly session cookie on success */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["LoginResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - logout_api_logout_post: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Successful Response */ - 204: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - }; - }; - list_agents_api_v1_agents_get: { - parameters: { - query?: { - cursor?: string | null; - limit?: number; - name?: string | null; - }; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Paginated list of agent summaries */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ListAgentsResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - init_agent_api_v1_agents_initAgent_post: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["InitAgentRequest"]; - }; - }; - responses: { - /** @description Agent registration status with active controls */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["InitAgentResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - get_agent_api_v1_agents__agent_name__get: { - parameters: { - query?: never; - header?: never; - path: { - agent_name: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Agent metadata and registered steps */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["GetAgentResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - patch_agent_api_v1_agents__agent_name__patch: { - parameters: { - query?: never; - header?: never; - path: { - agent_name: string; - }; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["PatchAgentRequest"]; - }; - }; - responses: { - /** @description Lists of removed items */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["PatchAgentResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - list_agent_controls_api_v1_agents__agent_name__controls_get: { - parameters: { - query?: never; - header?: never; - path: { - agent_name: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description List of controls from agent policy and direct associations */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["AgentControlsResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - add_agent_control_api_v1_agents__agent_name__controls__control_id__post: { - parameters: { - query?: never; - header?: never; - path: { - agent_name: string; - control_id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Success confirmation */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["AssocResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - remove_agent_control_api_v1_agents__agent_name__controls__control_id__delete: { - parameters: { - query?: never; - header?: never; - path: { - agent_name: string; - control_id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Success confirmation */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["RemoveAgentControlResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - list_agent_evaluators_api_v1_agents__agent_name__evaluators_get: { - parameters: { - query?: { - cursor?: string | null; - limit?: number; - }; - header?: never; - path: { - agent_name: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Evaluator schemas registered with this agent */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ListEvaluatorsResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - get_agent_evaluator_api_v1_agents__agent_name__evaluators__evaluator_name__get: { - parameters: { - query?: never; - header?: never; - path: { - agent_name: string; - evaluator_name: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Evaluator schema details */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["EvaluatorSchemaItem"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - get_agent_policies_api_v1_agents__agent_name__policies_get: { - parameters: { - query?: never; - header?: never; - path: { - agent_name: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description List of policy IDs */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["GetAgentPoliciesResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - remove_all_agent_policies_api_v1_agents__agent_name__policies_delete: { - parameters: { - query?: never; - header?: never; - path: { - agent_name: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Success confirmation */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["AssocResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - add_agent_policy_api_v1_agents__agent_name__policies__policy_id__post: { - parameters: { - query?: never; - header?: never; - path: { - agent_name: string; - policy_id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Success confirmation */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["AssocResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - remove_agent_policy_api_v1_agents__agent_name__policies__policy_id__delete: { - parameters: { - query?: never; - header?: never; - path: { - agent_name: string; - policy_id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Success confirmation */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["AssocResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - get_agent_policy_api_v1_agents__agent_name__policy_get: { - parameters: { - query?: never; - header?: never; - path: { - agent_name: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Policy ID */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["GetPolicyResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - delete_agent_policy_api_v1_agents__agent_name__policy_delete: { - parameters: { - query?: never; - header?: never; - path: { - agent_name: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Success confirmation */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["DeletePolicyResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - set_agent_policy_api_v1_agents__agent_name__policy__policy_id__post: { - parameters: { - query?: never; - header?: never; - path: { - agent_name: string; - policy_id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Success status with previous policy ID */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["SetPolicyResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - list_controls_api_v1_controls_get: { - parameters: { - query?: { - /** @description Control ID to start after */ - cursor?: number | null; - limit?: number; - /** @description Filter by name (partial, case-insensitive) */ - name?: string | null; - /** @description Filter by enabled status */ - enabled?: boolean | null; - /** @description Filter by step type (built-ins: 'tool', 'llm') */ - step_type?: string | null; - /** @description Filter by stage ('pre' or 'post') */ - stage?: string | null; - /** @description Filter by execution ('server' or 'sdk') */ - execution?: string | null; - /** @description Filter by tag */ - tag?: string | null; - }; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Paginated list of controls */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ListControlsResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - create_control_api_v1_controls_put: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["CreateControlRequest"]; - }; - }; - responses: { - /** @description Created control ID */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["CreateControlResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - validate_control_data_api_v1_controls_validate_post: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["ValidateControlDataRequest"]; - }; - }; - responses: { - /** @description Validation result */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ValidateControlDataResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - get_control_api_v1_controls__control_id__get: { - parameters: { - query?: never; - header?: never; - path: { - control_id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Control metadata and configuration */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["GetControlResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - delete_control_api_v1_controls__control_id__delete: { - parameters: { - query?: { - /** @description If true, dissociate from all policy/agent links before deleting. If false, fail if control is associated with any policy or agent. */ - force?: boolean; - }; - header?: never; - path: { - control_id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Deletion confirmation with dissociation info */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["DeleteControlResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - patch_control_api_v1_controls__control_id__patch: { - parameters: { - query?: never; - header?: never; - path: { - control_id: number; - }; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["PatchControlRequest"]; - }; - }; - responses: { - /** @description Updated control information */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["PatchControlResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - get_control_data_api_v1_controls__control_id__data_get: { - parameters: { - query?: never; - header?: never; - path: { - control_id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Control data payload */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["GetControlDataResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - set_control_data_api_v1_controls__control_id__data_put: { - parameters: { - query?: never; - header?: never; - path: { - control_id: number; - }; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["SetControlDataRequest"]; - }; - }; - responses: { - /** @description Success confirmation */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["SetControlDataResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - evaluate_api_v1_evaluation_post: { - parameters: { - query?: never; - header?: { - "X-Trace-Id"?: string | null; - "X-Span-Id"?: string | null; - }; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["EvaluationRequest"]; - }; - }; - responses: { - /** @description Safety analysis result */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["EvaluationResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - list_evaluator_configs_api_v1_evaluator_configs_get: { - parameters: { - query?: { - /** @description Evaluator config ID to start after */ - cursor?: number | null; - limit?: number; - /** @description Filter by name (partial, case-insensitive) */ - name?: string | null; - /** @description Filter by evaluator name */ - evaluator?: string | null; - }; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Paginated list of evaluator configs */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ListEvaluatorConfigsResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - create_evaluator_config_api_v1_evaluator_configs_post: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["CreateEvaluatorConfigRequest"]; - }; - }; - responses: { - /** @description Created evaluator config */ - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["EvaluatorConfigItem"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - get_evaluator_config_api_v1_evaluator_configs__config_id__get: { - parameters: { - query?: never; - header?: never; - path: { - config_id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Evaluator config details */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["EvaluatorConfigItem"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - update_evaluator_config_api_v1_evaluator_configs__config_id__put: { - parameters: { - query?: never; - header?: never; - path: { - config_id: number; - }; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["UpdateEvaluatorConfigRequest"]; - }; - }; - responses: { - /** @description Updated evaluator config */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["EvaluatorConfigItem"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - delete_evaluator_config_api_v1_evaluator_configs__config_id__delete: { - parameters: { - query?: never; - header?: never; - path: { - config_id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Deletion confirmation */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["DeleteEvaluatorConfigResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - get_evaluators_api_v1_evaluators_get: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Dictionary of evaluator name to evaluator info */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - [key: string]: components["schemas"]["EvaluatorInfo"]; - }; - }; - }; - }; - }; - ingest_events_api_v1_observability_events_post: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["BatchEventsRequest"]; - }; - }; - responses: { - /** @description Successful Response */ - 202: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["BatchEventsResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - query_events_api_v1_observability_events_query_post: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["EventQueryRequest"]; - }; - }; - responses: { - /** @description Successful Response */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["EventQueryResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - get_stats_api_v1_observability_stats_get: { - parameters: { - query: { - agent_name: string; - time_range?: "1m" | "5m" | "15m" | "1h" | "24h" | "7d" | "30d" | "180d" | "365d"; - include_timeseries?: boolean; - }; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Successful Response */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["StatsResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - get_control_stats_api_v1_observability_stats_controls__control_id__get: { - parameters: { - query: { - agent_name: string; - time_range?: "1m" | "5m" | "15m" | "1h" | "24h" | "7d" | "30d" | "180d" | "365d"; - include_timeseries?: boolean; - }; - header?: never; - path: { - control_id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Successful Response */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ControlStatsResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - get_status_api_v1_observability_status_get: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Successful Response */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - [key: string]: unknown; - }; - }; - }; - }; - }; - create_policy_api_v1_policies_put: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["CreatePolicyRequest"]; - }; - }; - responses: { - /** @description Created policy ID */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["CreatePolicyResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - list_policy_controls_api_v1_policies__policy_id__controls_get: { - parameters: { - query?: never; - header?: never; - path: { - policy_id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description List of control IDs */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["GetPolicyControlsResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - add_control_to_policy_api_v1_policies__policy_id__controls__control_id__post: { - parameters: { - query?: never; - header?: never; - path: { - policy_id: number; - control_id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Success confirmation */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["AssocResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - remove_control_from_policy_api_v1_policies__policy_id__controls__control_id__delete: { - parameters: { - query?: never; - header?: never; - path: { - policy_id: number; - control_id: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Success confirmation */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["AssocResponse"]; - }; - }; - /** @description Validation Error */ - 422: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HTTPValidationError"]; - }; - }; - }; - }; - health_check_health_get: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Server health status */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HealthResponse"]; - }; - }; + get_config_api_config_get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Configuration flags for UI behavior */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['ConfigResponse']; + }; + }; + }; + }; + login_api_login_post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + 'application/json': components['schemas']['LoginRequest']; + }; + }; + responses: { + /** @description Authentication result; sets HttpOnly session cookie on success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['LoginResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + logout_api_logout_post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + list_agents_api_v1_agents_get: { + parameters: { + query?: { + cursor?: string | null; + limit?: number; + name?: string | null; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Paginated list of agent summaries */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['ListAgentsResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + init_agent_api_v1_agents_initAgent_post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + 'application/json': components['schemas']['InitAgentRequest']; + }; + }; + responses: { + /** @description Agent registration status with active controls */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['InitAgentResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + get_agent_api_v1_agents__agent_name__get: { + parameters: { + query?: never; + header?: never; + path: { + agent_name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Agent metadata and registered steps */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['GetAgentResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + patch_agent_api_v1_agents__agent_name__patch: { + parameters: { + query?: never; + header?: never; + path: { + agent_name: string; + }; + cookie?: never; + }; + requestBody: { + content: { + 'application/json': components['schemas']['PatchAgentRequest']; + }; + }; + responses: { + /** @description Lists of removed items */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['PatchAgentResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + list_agent_controls_api_v1_agents__agent_name__controls_get: { + parameters: { + query?: never; + header?: never; + path: { + agent_name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description List of controls from agent policy and direct associations */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['AgentControlsResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + add_agent_control_api_v1_agents__agent_name__controls__control_id__post: { + parameters: { + query?: never; + header?: never; + path: { + agent_name: string; + control_id: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success confirmation */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['AssocResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + remove_agent_control_api_v1_agents__agent_name__controls__control_id__delete: { + parameters: { + query?: never; + header?: never; + path: { + agent_name: string; + control_id: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success confirmation */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['RemoveAgentControlResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + list_agent_evaluators_api_v1_agents__agent_name__evaluators_get: { + parameters: { + query?: { + cursor?: string | null; + limit?: number; + }; + header?: never; + path: { + agent_name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Evaluator schemas registered with this agent */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['ListEvaluatorsResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + get_agent_evaluator_api_v1_agents__agent_name__evaluators__evaluator_name__get: { + parameters: { + query?: never; + header?: never; + path: { + agent_name: string; + evaluator_name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Evaluator schema details */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['EvaluatorSchemaItem']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + get_agent_policies_api_v1_agents__agent_name__policies_get: { + parameters: { + query?: never; + header?: never; + path: { + agent_name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description List of policy IDs */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['GetAgentPoliciesResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + remove_all_agent_policies_api_v1_agents__agent_name__policies_delete: { + parameters: { + query?: never; + header?: never; + path: { + agent_name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success confirmation */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['AssocResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + add_agent_policy_api_v1_agents__agent_name__policies__policy_id__post: { + parameters: { + query?: never; + header?: never; + path: { + agent_name: string; + policy_id: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success confirmation */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['AssocResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + remove_agent_policy_api_v1_agents__agent_name__policies__policy_id__delete: { + parameters: { + query?: never; + header?: never; + path: { + agent_name: string; + policy_id: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success confirmation */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['AssocResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + get_agent_policy_api_v1_agents__agent_name__policy_get: { + parameters: { + query?: never; + header?: never; + path: { + agent_name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Policy ID */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['GetPolicyResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + delete_agent_policy_api_v1_agents__agent_name__policy_delete: { + parameters: { + query?: never; + header?: never; + path: { + agent_name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success confirmation */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['DeletePolicyResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + set_agent_policy_api_v1_agents__agent_name__policy__policy_id__post: { + parameters: { + query?: never; + header?: never; + path: { + agent_name: string; + policy_id: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success status with previous policy ID */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['SetPolicyResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + list_controls_api_v1_controls_get: { + parameters: { + query?: { + /** @description Control ID to start after */ + cursor?: number | null; + limit?: number; + /** @description Filter by name (partial, case-insensitive) */ + name?: string | null; + /** @description Filter by enabled status */ + enabled?: boolean | null; + /** @description Filter by step type (built-ins: 'tool', 'llm') */ + step_type?: string | null; + /** @description Filter by stage ('pre' or 'post') */ + stage?: string | null; + /** @description Filter by execution ('server' or 'sdk') */ + execution?: string | null; + /** @description Filter by tag */ + tag?: string | null; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Paginated list of controls */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['ListControlsResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + create_control_api_v1_controls_put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + 'application/json': components['schemas']['CreateControlRequest']; + }; + }; + responses: { + /** @description Created control ID */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['CreateControlResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + validate_control_data_api_v1_controls_validate_post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + 'application/json': components['schemas']['ValidateControlDataRequest']; + }; + }; + responses: { + /** @description Validation result */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['ValidateControlDataResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + get_control_api_v1_controls__control_id__get: { + parameters: { + query?: never; + header?: never; + path: { + control_id: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Control metadata and configuration */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['GetControlResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + delete_control_api_v1_controls__control_id__delete: { + parameters: { + query?: { + /** @description If true, dissociate from all policy/agent links before deleting. If false, fail if control is associated with any policy or agent. */ + force?: boolean; + }; + header?: never; + path: { + control_id: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Deletion confirmation with dissociation info */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['DeleteControlResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + patch_control_api_v1_controls__control_id__patch: { + parameters: { + query?: never; + header?: never; + path: { + control_id: number; + }; + cookie?: never; + }; + requestBody: { + content: { + 'application/json': components['schemas']['PatchControlRequest']; + }; + }; + responses: { + /** @description Updated control information */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['PatchControlResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + get_control_data_api_v1_controls__control_id__data_get: { + parameters: { + query?: never; + header?: never; + path: { + control_id: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Control data payload */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['GetControlDataResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + set_control_data_api_v1_controls__control_id__data_put: { + parameters: { + query?: never; + header?: never; + path: { + control_id: number; + }; + cookie?: never; + }; + requestBody: { + content: { + 'application/json': components['schemas']['SetControlDataRequest']; + }; + }; + responses: { + /** @description Success confirmation */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['SetControlDataResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + evaluate_api_v1_evaluation_post: { + parameters: { + query?: never; + header?: { + 'X-Trace-Id'?: string | null; + 'X-Span-Id'?: string | null; + }; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + 'application/json': components['schemas']['EvaluationRequest']; + }; + }; + responses: { + /** @description Safety analysis result */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['EvaluationResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + list_evaluator_configs_api_v1_evaluator_configs_get: { + parameters: { + query?: { + /** @description Evaluator config ID to start after */ + cursor?: number | null; + limit?: number; + /** @description Filter by name (partial, case-insensitive) */ + name?: string | null; + /** @description Filter by evaluator name */ + evaluator?: string | null; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Paginated list of evaluator configs */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['ListEvaluatorConfigsResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + create_evaluator_config_api_v1_evaluator_configs_post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + 'application/json': components['schemas']['CreateEvaluatorConfigRequest']; + }; + }; + responses: { + /** @description Created evaluator config */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['EvaluatorConfigItem']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + get_evaluator_config_api_v1_evaluator_configs__config_id__get: { + parameters: { + query?: never; + header?: never; + path: { + config_id: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Evaluator config details */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['EvaluatorConfigItem']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + update_evaluator_config_api_v1_evaluator_configs__config_id__put: { + parameters: { + query?: never; + header?: never; + path: { + config_id: number; + }; + cookie?: never; + }; + requestBody: { + content: { + 'application/json': components['schemas']['UpdateEvaluatorConfigRequest']; + }; + }; + responses: { + /** @description Updated evaluator config */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['EvaluatorConfigItem']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + delete_evaluator_config_api_v1_evaluator_configs__config_id__delete: { + parameters: { + query?: never; + header?: never; + path: { + config_id: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Deletion confirmation */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['DeleteEvaluatorConfigResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + get_evaluators_api_v1_evaluators_get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Dictionary of evaluator name to evaluator info */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': { + [key: string]: components['schemas']['EvaluatorInfo']; + }; + }; + }; + }; + }; + ingest_events_api_v1_observability_events_post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + 'application/json': components['schemas']['BatchEventsRequest']; + }; + }; + responses: { + /** @description Successful Response */ + 202: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['BatchEventsResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + query_events_api_v1_observability_events_query_post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + 'application/json': components['schemas']['EventQueryRequest']; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['EventQueryResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + get_stats_api_v1_observability_stats_get: { + parameters: { + query: { + agent_name: string; + time_range?: + | '1m' + | '5m' + | '15m' + | '1h' + | '24h' + | '7d' + | '30d' + | '180d' + | '365d'; + include_timeseries?: boolean; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['StatsResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + get_control_stats_api_v1_observability_stats_controls__control_id__get: { + parameters: { + query: { + agent_name: string; + time_range?: + | '1m' + | '5m' + | '15m' + | '1h' + | '24h' + | '7d' + | '30d' + | '180d' + | '365d'; + include_timeseries?: boolean; + }; + header?: never; + path: { + control_id: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['ControlStatsResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + get_status_api_v1_observability_status_get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': { + [key: string]: unknown; + }; + }; + }; + }; + }; + create_policy_api_v1_policies_put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + 'application/json': components['schemas']['CreatePolicyRequest']; + }; + }; + responses: { + /** @description Created policy ID */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['CreatePolicyResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + list_policy_controls_api_v1_policies__policy_id__controls_get: { + parameters: { + query?: never; + header?: never; + path: { + policy_id: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description List of control IDs */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['GetPolicyControlsResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + add_control_to_policy_api_v1_policies__policy_id__controls__control_id__post: { + parameters: { + query?: never; + header?: never; + path: { + policy_id: number; + control_id: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success confirmation */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['AssocResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + remove_control_from_policy_api_v1_policies__policy_id__controls__control_id__delete: { + parameters: { + query?: never; + header?: never; + path: { + policy_id: number; + control_id: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success confirmation */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['AssocResponse']; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPValidationError']; + }; + }; + }; + }; + health_check_health_get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Server health status */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HealthResponse']; }; + }; }; + }; } From 6a04da41bc914daf077ca7cdd9386edd36447949 Mon Sep 17 00:00:00 2001 From: Lev Neiman Date: Fri, 20 Mar 2026 15:11:38 -0700 Subject: [PATCH 5/5] fix: address pr review feedback --- examples/deepeval/setup_controls.py | 7 ++++++- server/tests/test_evaluation_error_handling.py | 12 ++++++------ server/tests/test_policy_integration.py | 8 ++++++-- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/examples/deepeval/setup_controls.py b/examples/deepeval/setup_controls.py index a7913326..faddb15e 100755 --- a/examples/deepeval/setup_controls.py +++ b/examples/deepeval/setup_controls.py @@ -203,11 +203,16 @@ async def setup_demo(quiet: bool = False): # Control exists, get its ID resp = await client.get("/api/v1/controls", params={"name": control_name}) resp.raise_for_status() - controls = resp.json().get("controls", []) + controls = [ + control + for control in resp.json().get("controls", []) + if control.get("name") == control_name + ] if controls: control_id = controls[0]["id"] controls_updated += 1 else: + print(f" ❌ Could not find exact control match for '{control_name}'") continue else: resp.raise_for_status() diff --git a/server/tests/test_evaluation_error_handling.py b/server/tests/test_evaluation_error_handling.py index 82549652..942dca66 100644 --- a/server/tests/test_evaluation_error_handling.py +++ b/server/tests/test_evaluation_error_handling.py @@ -17,11 +17,11 @@ def test_evaluation_with_agent_scoped_evaluator_missing(client: TestClient): - """Test that referencing missing agent evaluator fails at policy assignment. + """Test that referencing a missing agent evaluator fails during control creation. Given: A control referencing agent:evaluator that doesn't exist - When: Attempting to assign policy - Then: Returns 400 with clear error message + When: Creating the control + Then: Returns 422 EVALUATOR_NOT_FOUND """ # Given: an agent without evaluators agent_name = f"testagent-{uuid.uuid4().hex[:12]}" @@ -53,9 +53,9 @@ def test_evaluation_with_agent_scoped_evaluator_missing(client: TestClient): json={"name": f"control-{uuid.uuid4().hex[:8]}", "data": control_data}, ) - # Then: a validation or not-found error is returned - # This will fail because the agent doesn't exist yet - assert set_resp.status_code in [404, 422] + # Then: the missing evaluator is surfaced deterministically + assert set_resp.status_code == 422 + assert set_resp.json()["error_code"] == "EVALUATOR_NOT_FOUND" def test_evaluation_control_with_invalid_config_caught_early(client: TestClient): diff --git a/server/tests/test_policy_integration.py b/server/tests/test_policy_integration.py index a50a3510..f3f28f34 100644 --- a/server/tests/test_policy_integration.py +++ b/server/tests/test_policy_integration.py @@ -1,6 +1,8 @@ """Integration tests for the full policy → control chain.""" +import json import uuid +from copy import deepcopy from fastapi.testclient import TestClient @@ -38,8 +40,10 @@ def _create_policy(client: TestClient, name: str | None = None) -> int: def _create_control(client: TestClient, name: str | None = None, data: dict | None = None) -> int: """Helper: Create a control and return control_id.""" control_name = name or f"control-{uuid.uuid4()}" - payload = VALID_CONTROL_PAYLOAD.copy() - payload["description"] = f"Name: {control_name}, Data: {data}" + payload = deepcopy(VALID_CONTROL_PAYLOAD) + marker = json.dumps(data, sort_keys=True) if data is not None else control_name + payload["description"] = f"Name: {control_name}, Marker: {marker}" + payload["condition"]["evaluator"]["config"]["pattern"] = marker resp = client.put("/api/v1/controls", json={"name": control_name, "data": payload}) assert resp.status_code == 200 return resp.json()["control_id"]