From 2f1391ff6b77bc68b9f78eeabe7976a24efd1a1b Mon Sep 17 00:00:00 2001 From: Saurav Kumar Date: Wed, 7 Oct 2026 19:50:37 +0530 Subject: [PATCH 1/8] Add Signals API endpoints to OpenAPI spec (FI-610) Add OpenAPI specifications for the 10 Signals and Consent public API endpoints exposed through doctl: Consent: - GET /v1/consent (list all consents) - GET /v1/consent/{agent_id} (get agent consent) - PUT /v1/consent/{agent_id} (set agent consent) Sessions: - GET /v1/signals/agents/{id}/sessions (list agent sessions) - GET /v1/signals/sessions/{id}/dialogues (list session dialogues) Exports: - GET /v1/signals/exports (list exports) - POST /v1/signals/exports (create export) - GET /v1/signals/exports/{id} (get export) - GET /v1/signals/exports/{id}/download (get export download URL) - GET /v1/signals/exports/options (get export options) Includes endpoint definitions, request/response models, parameters, curl examples, and response schemas following the existing patterns established by the Insights API (PR #1248). Co-authored-by: Cursor --- specification/DigitalOcean-public.v2.yaml | 50 +++++++++++ .../examples/curl/signals_create_export.yml | 7 ++ .../examples/curl/signals_get_consent.yml | 5 ++ .../examples/curl/signals_get_export.yml | 5 ++ .../curl/signals_get_export_download.yml | 5 ++ .../curl/signals_get_export_options.yml | 5 ++ .../examples/curl/signals_list_consents.yml | 5 ++ .../examples/curl/signals_list_dialogues.yml | 5 ++ .../examples/curl/signals_list_exports.yml | 5 ++ .../examples/curl/signals_list_sessions.yml | 5 ++ .../examples/curl/signals_set_consent.yml | 7 ++ .../signals/models/agent_consent.yml | 38 +++++++++ .../signals/models/consent_record.yml | 31 +++++++ .../signals/models/create_export_request.yml | 34 ++++++++ .../signals/models/export_download.yml | 15 ++++ .../resources/signals/models/export_job.yml | 64 ++++++++++++++ .../signals/models/export_options.yml | 28 ++++++ .../signals/models/list_consents.yml | 10 +++ .../resources/signals/models/session.yml | 27 ++++++ .../signals/models/session_dialogue.yml | 32 +++++++ .../resources/signals/parameters.yml | 85 +++++++++++++++++++ .../responses/agent_consent_response.yml | 21 +++++ .../responses/export_download_response.yml | 17 ++++ .../signals/responses/export_job_response.yml | 27 ++++++ .../responses/export_options_response.yml | 28 ++++++ .../responses/list_consents_response.yml | 26 ++++++ .../responses/list_dialogues_response.yml | 44 ++++++++++ .../responses/list_exports_response.yml | 49 +++++++++++ .../responses/list_sessions_response.yml | 42 +++++++++ .../responses/set_consent_response.yml | 26 ++++++ .../signals/signals_create_export.yml | 56 ++++++++++++ .../resources/signals/signals_get_consent.yml | 40 +++++++++ .../resources/signals/signals_get_export.yml | 39 +++++++++ .../signals/signals_get_export_download.yml | 40 +++++++++ .../signals/signals_get_export_options.yml | 34 ++++++++ .../signals/signals_list_consents.yml | 34 ++++++++ .../signals/signals_list_dialogues.yml | 46 ++++++++++ .../signals/signals_list_exports.yml | 38 +++++++++ .../signals/signals_list_sessions.yml | 42 +++++++++ .../resources/signals/signals_set_consent.yml | 55 ++++++++++++ 40 files changed, 1172 insertions(+) create mode 100644 specification/resources/signals/examples/curl/signals_create_export.yml create mode 100644 specification/resources/signals/examples/curl/signals_get_consent.yml create mode 100644 specification/resources/signals/examples/curl/signals_get_export.yml create mode 100644 specification/resources/signals/examples/curl/signals_get_export_download.yml create mode 100644 specification/resources/signals/examples/curl/signals_get_export_options.yml create mode 100644 specification/resources/signals/examples/curl/signals_list_consents.yml create mode 100644 specification/resources/signals/examples/curl/signals_list_dialogues.yml create mode 100644 specification/resources/signals/examples/curl/signals_list_exports.yml create mode 100644 specification/resources/signals/examples/curl/signals_list_sessions.yml create mode 100644 specification/resources/signals/examples/curl/signals_set_consent.yml create mode 100644 specification/resources/signals/models/agent_consent.yml create mode 100644 specification/resources/signals/models/consent_record.yml create mode 100644 specification/resources/signals/models/create_export_request.yml create mode 100644 specification/resources/signals/models/export_download.yml create mode 100644 specification/resources/signals/models/export_job.yml create mode 100644 specification/resources/signals/models/export_options.yml create mode 100644 specification/resources/signals/models/list_consents.yml create mode 100644 specification/resources/signals/models/session.yml create mode 100644 specification/resources/signals/models/session_dialogue.yml create mode 100644 specification/resources/signals/parameters.yml create mode 100644 specification/resources/signals/responses/agent_consent_response.yml create mode 100644 specification/resources/signals/responses/export_download_response.yml create mode 100644 specification/resources/signals/responses/export_job_response.yml create mode 100644 specification/resources/signals/responses/export_options_response.yml create mode 100644 specification/resources/signals/responses/list_consents_response.yml create mode 100644 specification/resources/signals/responses/list_dialogues_response.yml create mode 100644 specification/resources/signals/responses/list_exports_response.yml create mode 100644 specification/resources/signals/responses/list_sessions_response.yml create mode 100644 specification/resources/signals/responses/set_consent_response.yml create mode 100644 specification/resources/signals/signals_create_export.yml create mode 100644 specification/resources/signals/signals_get_consent.yml create mode 100644 specification/resources/signals/signals_get_export.yml create mode 100644 specification/resources/signals/signals_get_export_download.yml create mode 100644 specification/resources/signals/signals_get_export_options.yml create mode 100644 specification/resources/signals/signals_list_consents.yml create mode 100644 specification/resources/signals/signals_list_dialogues.yml create mode 100644 specification/resources/signals/signals_list_exports.yml create mode 100644 specification/resources/signals/signals_list_sessions.yml create mode 100644 specification/resources/signals/signals_set_consent.yml diff --git a/specification/DigitalOcean-public.v2.yaml b/specification/DigitalOcean-public.v2.yaml index a26d71aa6..0bcac7a53 100644 --- a/specification/DigitalOcean-public.v2.yaml +++ b/specification/DigitalOcean-public.v2.yaml @@ -577,6 +577,17 @@ tags: description: |- Security CSPM endpoints for scans, scan findings, and settings. + - name: Signals + description: |- + The DigitalOcean Signals API provides observability for GenAI agent + conversations, detecting behavioral signals such as user disengagement, + execution failures, and satisfaction indicators. + + Use the consent endpoints to manage whether signals collection is + enabled for each agent, the session endpoints to browse agent + conversations and their detected signals, and the export endpoints + to create downloadable archives of signals data for offline analysis. + - name: Sizes description: |- The sizes objects represent different packages of hardware resources that @@ -754,6 +765,7 @@ x-tagGroups: - Reserved IPv6 - Reserved IPv6 Actions - Security + - Signals - Sizes - Snapshots - Spaces Keys @@ -1827,6 +1839,44 @@ paths: post: $ref: "resources/insights/insights_post_logsSearch.yml" + /v1/consent: + get: + $ref: "resources/signals/signals_list_consents.yml" + + /v1/consent/{agent_id}: + get: + $ref: "resources/signals/signals_get_consent.yml" + + put: + $ref: "resources/signals/signals_set_consent.yml" + + /v1/signals/agents/{agent_id}/sessions: + get: + $ref: "resources/signals/signals_list_sessions.yml" + + /v1/signals/sessions/{session_id}/dialogues: + get: + $ref: "resources/signals/signals_list_dialogues.yml" + + /v1/signals/exports: + get: + $ref: "resources/signals/signals_list_exports.yml" + + post: + $ref: "resources/signals/signals_create_export.yml" + + /v1/signals/exports/options: + get: + $ref: "resources/signals/signals_get_export_options.yml" + + /v1/signals/exports/{export_id}: + get: + $ref: "resources/signals/signals_get_export.yml" + + /v1/signals/exports/{export_id}/download: + get: + $ref: "resources/signals/signals_get_export_download.yml" + /v2/kubernetes/clusters: get: $ref: "resources/kubernetes/kubernetes_list_clusters.yml" diff --git a/specification/resources/signals/examples/curl/signals_create_export.yml b/specification/resources/signals/examples/curl/signals_create_export.yml new file mode 100644 index 000000000..181f1f56b --- /dev/null +++ b/specification/resources/signals/examples/curl/signals_create_export.yml @@ -0,0 +1,7 @@ +lang: cURL +source: |- + curl -X POST \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \ + -d '{"agent_id":"01a0f3d5-b58d-7c99-a743-7ca0397b7f5d","signal_type":"ExecutionFailureToolNotFound"}' \ + "https://api.digitalocean.com/v1/signals/exports" diff --git a/specification/resources/signals/examples/curl/signals_get_consent.yml b/specification/resources/signals/examples/curl/signals_get_consent.yml new file mode 100644 index 000000000..f2bded985 --- /dev/null +++ b/specification/resources/signals/examples/curl/signals_get_consent.yml @@ -0,0 +1,5 @@ +lang: cURL +source: |- + curl -X GET \ + -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \ + "https://api.digitalocean.com/v1/consent/019fb3d2-8a56-72cc-8bf9-9d21510b2a99" diff --git a/specification/resources/signals/examples/curl/signals_get_export.yml b/specification/resources/signals/examples/curl/signals_get_export.yml new file mode 100644 index 000000000..c9e83853d --- /dev/null +++ b/specification/resources/signals/examples/curl/signals_get_export.yml @@ -0,0 +1,5 @@ +lang: cURL +source: |- + curl -X GET \ + -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \ + "https://api.digitalocean.com/v1/signals/exports/9f13c09c-c877-436b-9863-dcc39c9dd737" diff --git a/specification/resources/signals/examples/curl/signals_get_export_download.yml b/specification/resources/signals/examples/curl/signals_get_export_download.yml new file mode 100644 index 000000000..04e84a621 --- /dev/null +++ b/specification/resources/signals/examples/curl/signals_get_export_download.yml @@ -0,0 +1,5 @@ +lang: cURL +source: |- + curl -X GET \ + -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \ + "https://api.digitalocean.com/v1/signals/exports/9f13c09c-c877-436b-9863-dcc39c9dd737/download" diff --git a/specification/resources/signals/examples/curl/signals_get_export_options.yml b/specification/resources/signals/examples/curl/signals_get_export_options.yml new file mode 100644 index 000000000..0e895034c --- /dev/null +++ b/specification/resources/signals/examples/curl/signals_get_export_options.yml @@ -0,0 +1,5 @@ +lang: cURL +source: |- + curl -X GET \ + -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \ + "https://api.digitalocean.com/v1/signals/exports/options" diff --git a/specification/resources/signals/examples/curl/signals_list_consents.yml b/specification/resources/signals/examples/curl/signals_list_consents.yml new file mode 100644 index 000000000..aa7637298 --- /dev/null +++ b/specification/resources/signals/examples/curl/signals_list_consents.yml @@ -0,0 +1,5 @@ +lang: cURL +source: |- + curl -X GET \ + -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \ + "https://api.digitalocean.com/v1/consent" diff --git a/specification/resources/signals/examples/curl/signals_list_dialogues.yml b/specification/resources/signals/examples/curl/signals_list_dialogues.yml new file mode 100644 index 000000000..c39f0ef7f --- /dev/null +++ b/specification/resources/signals/examples/curl/signals_list_dialogues.yml @@ -0,0 +1,5 @@ +lang: cURL +source: |- + curl -X GET \ + -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \ + "https://api.digitalocean.com/v1/signals/sessions/01a0f3d5-d5f1-798a-9352-2cd8f8b81e78/dialogues?limit=20" diff --git a/specification/resources/signals/examples/curl/signals_list_exports.yml b/specification/resources/signals/examples/curl/signals_list_exports.yml new file mode 100644 index 000000000..1478c23d2 --- /dev/null +++ b/specification/resources/signals/examples/curl/signals_list_exports.yml @@ -0,0 +1,5 @@ +lang: cURL +source: |- + curl -X GET \ + -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \ + "https://api.digitalocean.com/v1/signals/exports?limit=20" diff --git a/specification/resources/signals/examples/curl/signals_list_sessions.yml b/specification/resources/signals/examples/curl/signals_list_sessions.yml new file mode 100644 index 000000000..35ba2ffe9 --- /dev/null +++ b/specification/resources/signals/examples/curl/signals_list_sessions.yml @@ -0,0 +1,5 @@ +lang: cURL +source: |- + curl -X GET \ + -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \ + "https://api.digitalocean.com/v1/signals/agents/019fb3d2-8a56-72cc-8bf9-9d21510b2a99/sessions?limit=20" diff --git a/specification/resources/signals/examples/curl/signals_set_consent.yml b/specification/resources/signals/examples/curl/signals_set_consent.yml new file mode 100644 index 000000000..a74162ec4 --- /dev/null +++ b/specification/resources/signals/examples/curl/signals_set_consent.yml @@ -0,0 +1,7 @@ +lang: cURL +source: |- + curl -X PUT \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \ + -d '{"enabled":true}' \ + "https://api.digitalocean.com/v1/consent/019fb3d2-8a56-72cc-8bf9-9d21510b2a99" diff --git a/specification/resources/signals/models/agent_consent.yml b/specification/resources/signals/models/agent_consent.yml new file mode 100644 index 000000000..2fe5a3293 --- /dev/null +++ b/specification/resources/signals/models/agent_consent.yml @@ -0,0 +1,38 @@ +type: object +description: Consent details for a specific agent, including an allowed flag. +properties: + id: + type: integer + description: The unique numeric identifier for the consent record. + example: 13 + team_id: + type: integer + description: The team ID that owns this consent record. + example: 39449946 + agent_id: + type: string + format: uuid + description: The unique identifier of the GenAI agent. + example: 019fb3d2-8a56-72cc-8bf9-9d21510b2a99 + enabled: + type: boolean + description: Whether signals collection is enabled for this agent. + example: true + allowed: + type: boolean + description: >- + Whether the team is permitted to use signals for this agent. This is + determined by the platform and cannot be set by the user. + example: true + updated_at: + type: string + format: date-time + description: A time value given in ISO8601 combined date and time format. + example: "2026-08-10T10:09:25.738533Z" +required: + - id + - team_id + - agent_id + - enabled + - allowed + - updated_at diff --git a/specification/resources/signals/models/consent_record.yml b/specification/resources/signals/models/consent_record.yml new file mode 100644 index 000000000..323162421 --- /dev/null +++ b/specification/resources/signals/models/consent_record.yml @@ -0,0 +1,31 @@ +type: object +description: A consent record indicating whether signals collection is enabled for an agent. +properties: + id: + type: integer + description: The unique numeric identifier for the consent record. + example: 13 + team_id: + type: integer + description: The team ID that owns this consent record. + example: 39449946 + agent_id: + type: string + format: uuid + description: The unique identifier of the GenAI agent. + example: 019fb3d2-8a56-72cc-8bf9-9d21510b2a99 + enabled: + type: boolean + description: Whether signals collection is enabled for this agent. + example: true + updated_at: + type: string + format: date-time + description: A time value given in ISO8601 combined date and time format. + example: "2026-08-10T10:09:25.738533Z" +required: + - id + - team_id + - agent_id + - enabled + - updated_at diff --git a/specification/resources/signals/models/create_export_request.yml b/specification/resources/signals/models/create_export_request.yml new file mode 100644 index 000000000..47d706e5c --- /dev/null +++ b/specification/resources/signals/models/create_export_request.yml @@ -0,0 +1,34 @@ +type: object +description: Request body to create a new signals data export. +properties: + agent_id: + type: string + format: uuid + description: The GenAI agent whose data should be exported. + example: 01a0f3d5-b58d-7c99-a743-7ca0397b7f5d + signal_type: + type: string + description: >- + Filter the export to only include the specified signal type. Use the + export options endpoint to list available values. + example: ExecutionFailureToolNotFound + session_ids: + type: array + description: Optional list of specific session IDs to include in the export. + items: + type: string + format: uuid + example: + - 01a0f3d5-d5f1-798a-9352-2cd8f8b81e78 + start_time: + type: string + format: date-time + description: Include only sessions that started at or after this timestamp. + example: "2026-09-01T00:00:00Z" + end_time: + type: string + format: date-time + description: Include only sessions that started at or before this timestamp. + example: "2026-10-01T00:00:00Z" +required: + - agent_id diff --git a/specification/resources/signals/models/export_download.yml b/specification/resources/signals/models/export_download.yml new file mode 100644 index 000000000..b8a370c1c --- /dev/null +++ b/specification/resources/signals/models/export_download.yml @@ -0,0 +1,15 @@ +type: object +description: A pre-signed download URL for a completed export. +properties: + url: + type: string + format: uri + description: A temporary pre-signed URL to download the export archive. + example: "https://storage.example.com/exports/9f13c09c.tar.gz?sig=abc123" + expires_at: + type: string + format: date-time + description: When the download URL expires. + example: "2026-10-15T00:00:00Z" +required: + - url diff --git a/specification/resources/signals/models/export_job.yml b/specification/resources/signals/models/export_job.yml new file mode 100644 index 000000000..0410975d2 --- /dev/null +++ b/specification/resources/signals/models/export_job.yml @@ -0,0 +1,64 @@ +type: object +description: An export job that produces a downloadable archive of signals data. +properties: + export_id: + type: string + format: uuid + description: The unique identifier for the export job. + example: 9f13c09c-c877-436b-9863-dcc39c9dd737 + agent_id: + type: string + format: uuid + description: The GenAI agent whose data is being exported. + example: 01a0f3d5-b58d-7c99-a743-7ca0397b7f5d + status: + type: string + description: The current status of the export job. + enum: + - pending + - processing + - complete + - failed + example: complete + filters: + type: object + description: The filters applied to this export. + properties: + signal_type: + type: array + items: + type: string + description: Signal types included in the export. + example: + - ExecutionFailureToolNotFound + session_ids: + type: array + items: + type: string + description: Specific session IDs included in the export. + example: + - 01a0f3d5-d5f1-798a-9352-2cd8f8b81e78 + created_at: + type: integer + description: Unix timestamp when the export was created. + example: 1791036405 + completed_at: + type: integer + nullable: true + description: Unix timestamp when the export completed, or null if still in progress. + example: 1791036405 + expires_at: + type: integer + nullable: true + description: Unix timestamp when the export download link expires. + example: 1791641205 + error_message: + type: string + nullable: true + description: Error message if the export failed, or null on success. + example: null +required: + - export_id + - agent_id + - status + - created_at diff --git a/specification/resources/signals/models/export_options.yml b/specification/resources/signals/models/export_options.yml new file mode 100644 index 000000000..8f1d303d3 --- /dev/null +++ b/specification/resources/signals/models/export_options.yml @@ -0,0 +1,28 @@ +type: object +description: Available filter options for creating exports. +properties: + filters: + type: object + properties: + signal_type: + type: array + description: The list of valid signal type values that can be used when creating an export. + items: + type: string + example: + - DisengagementEscalation + - DisengagementNegativeStance + - DisengagementQuit + - EnvironmentExhaustionApiError + - EnvironmentExhaustionContextOverflow + - ExecutionFailureToolNotFound + - ExecutionLoopsRetry + - MisalignmentCorrection + - SatisfactionConfirmation + - SatisfactionGratitude + - SatisfactionSuccess + - StagnationRepetition + required: + - signal_type +required: + - filters diff --git a/specification/resources/signals/models/list_consents.yml b/specification/resources/signals/models/list_consents.yml new file mode 100644 index 000000000..e0596bc86 --- /dev/null +++ b/specification/resources/signals/models/list_consents.yml @@ -0,0 +1,10 @@ +type: object +description: A wrapper for a list of consent records. +properties: + consents: + type: array + description: A list of consent records for the team's agents. + items: + $ref: 'consent_record.yml' +required: + - consents diff --git a/specification/resources/signals/models/session.yml b/specification/resources/signals/models/session.yml new file mode 100644 index 000000000..b51b670fb --- /dev/null +++ b/specification/resources/signals/models/session.yml @@ -0,0 +1,27 @@ +type: object +description: A signals session represents a conversation between a user and a GenAI agent. +properties: + session_id: + type: string + format: uuid + description: The unique identifier for the session. + example: 01a0f3d5-d5f1-798a-9352-2cd8f8b81e78 + total_turns: + type: integer + description: The total number of conversation turns in this session. + example: 5 + started_at: + type: string + format: date-time + description: When the session started. + example: "2026-09-15T14:30:00Z" + duration_seconds: + type: number + description: The duration of the session in seconds. + example: 120.5 + signal_count: + type: integer + description: The number of signals detected in this session. + example: 3 +required: + - session_id diff --git a/specification/resources/signals/models/session_dialogue.yml b/specification/resources/signals/models/session_dialogue.yml new file mode 100644 index 000000000..a1b884c14 --- /dev/null +++ b/specification/resources/signals/models/session_dialogue.yml @@ -0,0 +1,32 @@ +type: object +description: A dialogue entry within a session, representing a single turn of conversation. +properties: + id: + type: string + description: The unique identifier for the dialogue. + example: "01a0f3d6-1234-7abc-def0-123456789abc" + segment_id: + type: string + description: The segment identifier grouping related dialogues. + example: "01a0f3d6-5678-7abc-def0-123456789abc" + sequence: + type: integer + description: The sequence number of this dialogue within its segment. + example: 1 + run_status: + type: string + description: The execution status of this dialogue turn. + example: completed + user_message: + type: string + description: The user's message in this dialogue turn. + example: "How do I create a Droplet?" + signals: + type: array + description: A list of signal types detected in this dialogue. + items: + type: string + example: + - SatisfactionConfirmation +required: + - id diff --git a/specification/resources/signals/parameters.yml b/specification/resources/signals/parameters.yml new file mode 100644 index 000000000..84fa11779 --- /dev/null +++ b/specification/resources/signals/parameters.yml @@ -0,0 +1,85 @@ +agent_id: + in: path + name: agent_id + description: A unique identifier for a GenAI agent. + required: true + schema: + type: string + format: uuid + example: 019fb3d2-8a56-72cc-8bf9-9d21510b2a99 + +session_id: + in: path + name: session_id + description: A unique identifier for a signals session. + required: true + schema: + type: string + format: uuid + example: 01a0f3d5-d5f1-798a-9352-2cd8f8b81e78 + +export_id: + in: path + name: export_id + description: A unique identifier for an export job. + required: true + schema: + type: string + format: uuid + example: 9f13c09c-c877-436b-9863-dcc39c9dd737 + +limit: + in: query + name: limit + description: Maximum number of items to return per page. + required: false + schema: + type: integer + minimum: 1 + maximum: 100 + default: 20 + example: 20 + +after: + in: query + name: after + description: >- + An opaque cursor string returned from a previous page. Pass this value to + retrieve the next page of results. + required: false + schema: + type: string + example: eyJ0ZWFtX2lkIjozOTQ0OTk0Nn0= + +signal_type: + in: query + name: signal_type + description: >- + Filter results by signal type. Use the export options endpoint to list + available signal types. + required: false + schema: + type: string + example: DisengagementEscalation + +start_time: + in: query + name: start_time + description: >- + Filter results to those occurring at or after this timestamp (RFC 3339). + required: false + schema: + type: string + format: date-time + example: "2026-09-01T00:00:00Z" + +end_time: + in: query + name: end_time + description: >- + Filter results to those occurring at or before this timestamp (RFC 3339). + required: false + schema: + type: string + format: date-time + example: "2026-10-01T00:00:00Z" diff --git a/specification/resources/signals/responses/agent_consent_response.yml b/specification/resources/signals/responses/agent_consent_response.yml new file mode 100644 index 000000000..8e35c5f51 --- /dev/null +++ b/specification/resources/signals/responses/agent_consent_response.yml @@ -0,0 +1,21 @@ +description: A single agent consent record. + +headers: + ratelimit-limit: + $ref: '../../../shared/headers.yml#/ratelimit-limit' + ratelimit-remaining: + $ref: '../../../shared/headers.yml#/ratelimit-remaining' + ratelimit-reset: + $ref: '../../../shared/headers.yml#/ratelimit-reset' + +content: + application/json: + schema: + $ref: '../models/agent_consent.yml' + example: + id: 13 + team_id: 39449946 + agent_id: 019fb3d2-8a56-72cc-8bf9-9d21510b2a99 + enabled: true + allowed: true + updated_at: "2026-08-10T10:09:25.738533Z" diff --git a/specification/resources/signals/responses/export_download_response.yml b/specification/resources/signals/responses/export_download_response.yml new file mode 100644 index 000000000..b338ecc42 --- /dev/null +++ b/specification/resources/signals/responses/export_download_response.yml @@ -0,0 +1,17 @@ +description: A download URL for a completed export. + +headers: + ratelimit-limit: + $ref: '../../../shared/headers.yml#/ratelimit-limit' + ratelimit-remaining: + $ref: '../../../shared/headers.yml#/ratelimit-remaining' + ratelimit-reset: + $ref: '../../../shared/headers.yml#/ratelimit-reset' + +content: + application/json: + schema: + $ref: '../models/export_download.yml' + example: + url: "https://storage.example.com/exports/9f13c09c.tar.gz?sig=abc123" + expires_at: "2026-10-15T00:00:00Z" diff --git a/specification/resources/signals/responses/export_job_response.yml b/specification/resources/signals/responses/export_job_response.yml new file mode 100644 index 000000000..ada9e3a19 --- /dev/null +++ b/specification/resources/signals/responses/export_job_response.yml @@ -0,0 +1,27 @@ +description: A single export job. + +headers: + ratelimit-limit: + $ref: '../../../shared/headers.yml#/ratelimit-limit' + ratelimit-remaining: + $ref: '../../../shared/headers.yml#/ratelimit-remaining' + ratelimit-reset: + $ref: '../../../shared/headers.yml#/ratelimit-reset' + +content: + application/json: + schema: + $ref: '../models/export_job.yml' + example: + export_id: 9f13c09c-c877-436b-9863-dcc39c9dd737 + agent_id: 01a0f3d5-b58d-7c99-a743-7ca0397b7f5d + status: complete + filters: + signal_type: + - ExecutionFailureToolNotFound + session_ids: + - 01a0f3d5-d5f1-798a-9352-2cd8f8b81e78 + created_at: 1791036405 + completed_at: 1791036405 + expires_at: 1791641205 + error_message: null diff --git a/specification/resources/signals/responses/export_options_response.yml b/specification/resources/signals/responses/export_options_response.yml new file mode 100644 index 000000000..5c8ebfb40 --- /dev/null +++ b/specification/resources/signals/responses/export_options_response.yml @@ -0,0 +1,28 @@ +description: Available export filter options. + +headers: + ratelimit-limit: + $ref: '../../../shared/headers.yml#/ratelimit-limit' + ratelimit-remaining: + $ref: '../../../shared/headers.yml#/ratelimit-remaining' + ratelimit-reset: + $ref: '../../../shared/headers.yml#/ratelimit-reset' + +content: + application/json: + schema: + $ref: '../models/export_options.yml' + example: + filters: + signal_type: + - DisengagementEscalation + - DisengagementNegativeStance + - DisengagementQuit + - EnvironmentExhaustionApiError + - ExecutionFailureToolNotFound + - ExecutionLoopsRetry + - MisalignmentCorrection + - SatisfactionConfirmation + - SatisfactionGratitude + - SatisfactionSuccess + - StagnationRepetition diff --git a/specification/resources/signals/responses/list_consents_response.yml b/specification/resources/signals/responses/list_consents_response.yml new file mode 100644 index 000000000..98b5a1bc8 --- /dev/null +++ b/specification/resources/signals/responses/list_consents_response.yml @@ -0,0 +1,26 @@ +description: A list of consent records. + +headers: + ratelimit-limit: + $ref: '../../../shared/headers.yml#/ratelimit-limit' + ratelimit-remaining: + $ref: '../../../shared/headers.yml#/ratelimit-remaining' + ratelimit-reset: + $ref: '../../../shared/headers.yml#/ratelimit-reset' + +content: + application/json: + schema: + $ref: '../models/list_consents.yml' + example: + consents: + - id: 13 + team_id: 39449946 + agent_id: 019fb3d2-8a56-72cc-8bf9-9d21510b2a99 + enabled: true + updated_at: "2026-08-10T10:09:25.738533Z" + - id: 6 + team_id: 39449946 + agent_id: 019fb6b1-aad4-7d54-a74e-c5570d768148 + enabled: true + updated_at: "2026-08-07T10:10:16.385447Z" diff --git a/specification/resources/signals/responses/list_dialogues_response.yml b/specification/resources/signals/responses/list_dialogues_response.yml new file mode 100644 index 000000000..bc11413a2 --- /dev/null +++ b/specification/resources/signals/responses/list_dialogues_response.yml @@ -0,0 +1,44 @@ +description: A paginated list of session dialogues. + +headers: + ratelimit-limit: + $ref: '../../../shared/headers.yml#/ratelimit-limit' + ratelimit-remaining: + $ref: '../../../shared/headers.yml#/ratelimit-remaining' + ratelimit-reset: + $ref: '../../../shared/headers.yml#/ratelimit-reset' + +content: + application/json: + schema: + type: object + properties: + edges: + type: array + items: + type: object + properties: + cursor: + type: string + description: An opaque cursor for pagination. + node: + $ref: '../models/session_dialogue.yml' + page_info: + type: object + properties: + has_next_page: + type: boolean + description: Whether there are more results after this page. + example: + edges: + - cursor: eyJzZXF1ZW5jZSI6MX0= + node: + id: "01a0f3d6-1234-7abc-def0-123456789abc" + segment_id: "01a0f3d6-5678-7abc-def0-123456789abc" + sequence: 1 + run_status: completed + user_message: "How do I create a Droplet?" + signals: + - SatisfactionConfirmation + page_info: + has_next_page: false diff --git a/specification/resources/signals/responses/list_exports_response.yml b/specification/resources/signals/responses/list_exports_response.yml new file mode 100644 index 000000000..63806c5b0 --- /dev/null +++ b/specification/resources/signals/responses/list_exports_response.yml @@ -0,0 +1,49 @@ +description: A paginated list of export jobs. + +headers: + ratelimit-limit: + $ref: '../../../shared/headers.yml#/ratelimit-limit' + ratelimit-remaining: + $ref: '../../../shared/headers.yml#/ratelimit-remaining' + ratelimit-reset: + $ref: '../../../shared/headers.yml#/ratelimit-reset' + +content: + application/json: + schema: + type: object + properties: + edges: + type: array + items: + type: object + properties: + cursor: + type: string + description: An opaque cursor for pagination. + node: + $ref: '../models/export_job.yml' + page_info: + type: object + properties: + has_next_page: + type: boolean + description: Whether there are more results after this page. + example: + edges: + - cursor: eyJ0ZWFtX2lkIjozOTQ0OTk0Nn0= + node: + export_id: 9f13c09c-c877-436b-9863-dcc39c9dd737 + agent_id: 01a0f3d5-b58d-7c99-a743-7ca0397b7f5d + status: complete + filters: + signal_type: + - ExecutionFailureToolNotFound + session_ids: + - 01a0f3d5-d5f1-798a-9352-2cd8f8b81e78 + created_at: 1791036405 + completed_at: 1791036405 + expires_at: 1791641205 + error_message: null + page_info: + has_next_page: false diff --git a/specification/resources/signals/responses/list_sessions_response.yml b/specification/resources/signals/responses/list_sessions_response.yml new file mode 100644 index 000000000..5faa79c0c --- /dev/null +++ b/specification/resources/signals/responses/list_sessions_response.yml @@ -0,0 +1,42 @@ +description: A paginated list of sessions. + +headers: + ratelimit-limit: + $ref: '../../../shared/headers.yml#/ratelimit-limit' + ratelimit-remaining: + $ref: '../../../shared/headers.yml#/ratelimit-remaining' + ratelimit-reset: + $ref: '../../../shared/headers.yml#/ratelimit-reset' + +content: + application/json: + schema: + type: object + properties: + edges: + type: array + items: + type: object + properties: + cursor: + type: string + description: An opaque cursor for pagination. + node: + $ref: '../models/session.yml' + page_info: + type: object + properties: + has_next_page: + type: boolean + description: Whether there are more results after this page. + example: + edges: + - cursor: eyJ0ZWFtX2lkIjozOTQ0OTk0Nn0= + node: + session_id: 01a0f3d5-d5f1-798a-9352-2cd8f8b81e78 + total_turns: 5 + started_at: "2026-09-15T14:30:00Z" + duration_seconds: 120.5 + signal_count: 3 + page_info: + has_next_page: false diff --git a/specification/resources/signals/responses/set_consent_response.yml b/specification/resources/signals/responses/set_consent_response.yml new file mode 100644 index 000000000..0717d27ec --- /dev/null +++ b/specification/resources/signals/responses/set_consent_response.yml @@ -0,0 +1,26 @@ +description: The consent record was updated successfully. + +headers: + ratelimit-limit: + $ref: '../../../shared/headers.yml#/ratelimit-limit' + ratelimit-remaining: + $ref: '../../../shared/headers.yml#/ratelimit-remaining' + ratelimit-reset: + $ref: '../../../shared/headers.yml#/ratelimit-reset' + +content: + application/json: + schema: + type: object + properties: + consent: + $ref: '../models/consent_record.yml' + required: + - consent + example: + consent: + id: 13 + team_id: 39449946 + agent_id: 019fb3d2-8a56-72cc-8bf9-9d21510b2a99 + enabled: true + updated_at: "2026-10-07T11:06:32.280572Z" diff --git a/specification/resources/signals/signals_create_export.yml b/specification/resources/signals/signals_create_export.yml new file mode 100644 index 000000000..0b56ecbc7 --- /dev/null +++ b/specification/resources/signals/signals_create_export.yml @@ -0,0 +1,56 @@ +operationId: signals_create_export + +summary: Create an Export Job + +description: | + To create a new signals data export, send a POST request to + `/v1/signals/exports` with an `agent_id` in the request body. You may + optionally filter the export by `signal_type`, `session_ids`, `start_time`, + and `end_time`. Use the export options endpoint to discover available signal + types. + + The export job runs asynchronously. Poll the get export endpoint to check + its status. When complete, use the download endpoint to retrieve a + pre-signed URL. + +tags: + - Signals + +requestBody: + required: true + content: + application/json: + schema: + $ref: 'models/create_export_request.yml' + example: + agent_id: 01a0f3d5-b58d-7c99-a743-7ca0397b7f5d + signal_type: ExecutionFailureToolNotFound + +responses: + '201': + $ref: 'responses/export_job_response.yml' + + '400': + $ref: '../../shared/responses/bad_request.yml' + + '401': + $ref: '../../shared/responses/unauthorized.yml' + + '422': + $ref: '../../shared/responses/unprocessable_entity.yml' + + '429': + $ref: '../../shared/responses/too_many_requests.yml' + + '500': + $ref: '../../shared/responses/server_error.yml' + + default: + $ref: '../../shared/responses/unexpected_error.yml' + +x-codeSamples: + - $ref: 'examples/curl/signals_create_export.yml' + +security: + - bearer_auth: + - 'signals:read' diff --git a/specification/resources/signals/signals_get_consent.yml b/specification/resources/signals/signals_get_consent.yml new file mode 100644 index 000000000..755f03285 --- /dev/null +++ b/specification/resources/signals/signals_get_consent.yml @@ -0,0 +1,40 @@ +operationId: signals_get_consent + +summary: Retrieve Consent for an Agent + +description: | + To retrieve the consent record for a specific GenAI agent, send a GET + request to `/v1/consent/{agent_id}`. The response includes an `allowed` + field indicating whether the team is permitted to use signals for this agent. + +tags: + - Signals + +parameters: + - $ref: 'parameters.yml#/agent_id' + +responses: + '200': + $ref: 'responses/agent_consent_response.yml' + + '401': + $ref: '../../shared/responses/unauthorized.yml' + + '404': + $ref: '../../shared/responses/not_found.yml' + + '429': + $ref: '../../shared/responses/too_many_requests.yml' + + '500': + $ref: '../../shared/responses/server_error.yml' + + default: + $ref: '../../shared/responses/unexpected_error.yml' + +x-codeSamples: + - $ref: 'examples/curl/signals_get_consent.yml' + +security: + - bearer_auth: + - 'signals:read' diff --git a/specification/resources/signals/signals_get_export.yml b/specification/resources/signals/signals_get_export.yml new file mode 100644 index 000000000..e1f1e8f00 --- /dev/null +++ b/specification/resources/signals/signals_get_export.yml @@ -0,0 +1,39 @@ +operationId: signals_get_export + +summary: Retrieve an Export Job + +description: | + To retrieve the status and details of a signals export job, send a GET + request to `/v1/signals/exports/{export_id}`. + +tags: + - Signals + +parameters: + - $ref: 'parameters.yml#/export_id' + +responses: + '200': + $ref: 'responses/export_job_response.yml' + + '401': + $ref: '../../shared/responses/unauthorized.yml' + + '404': + $ref: '../../shared/responses/not_found.yml' + + '429': + $ref: '../../shared/responses/too_many_requests.yml' + + '500': + $ref: '../../shared/responses/server_error.yml' + + default: + $ref: '../../shared/responses/unexpected_error.yml' + +x-codeSamples: + - $ref: 'examples/curl/signals_get_export.yml' + +security: + - bearer_auth: + - 'signals:read' diff --git a/specification/resources/signals/signals_get_export_download.yml b/specification/resources/signals/signals_get_export_download.yml new file mode 100644 index 000000000..adc3137d5 --- /dev/null +++ b/specification/resources/signals/signals_get_export_download.yml @@ -0,0 +1,40 @@ +operationId: signals_get_export_download + +summary: Get Export Download URL + +description: | + To retrieve a pre-signed download URL for a completed export, send a GET + request to `/v1/signals/exports/{export_id}/download`. The export must have + a `complete` status. The URL is temporary and will expire. + +tags: + - Signals + +parameters: + - $ref: 'parameters.yml#/export_id' + +responses: + '200': + $ref: 'responses/export_download_response.yml' + + '401': + $ref: '../../shared/responses/unauthorized.yml' + + '404': + $ref: '../../shared/responses/not_found.yml' + + '429': + $ref: '../../shared/responses/too_many_requests.yml' + + '500': + $ref: '../../shared/responses/server_error.yml' + + default: + $ref: '../../shared/responses/unexpected_error.yml' + +x-codeSamples: + - $ref: 'examples/curl/signals_get_export_download.yml' + +security: + - bearer_auth: + - 'signals:read' diff --git a/specification/resources/signals/signals_get_export_options.yml b/specification/resources/signals/signals_get_export_options.yml new file mode 100644 index 000000000..6ee7cf844 --- /dev/null +++ b/specification/resources/signals/signals_get_export_options.yml @@ -0,0 +1,34 @@ +operationId: signals_get_export_options + +summary: Get Export Options + +description: | + To retrieve the available filter options for creating an export, send a GET + request to `/v1/signals/exports/options`. The response lists valid signal + types that can be used in the `signal_type` filter when creating an export. + +tags: + - Signals + +responses: + '200': + $ref: 'responses/export_options_response.yml' + + '401': + $ref: '../../shared/responses/unauthorized.yml' + + '429': + $ref: '../../shared/responses/too_many_requests.yml' + + '500': + $ref: '../../shared/responses/server_error.yml' + + default: + $ref: '../../shared/responses/unexpected_error.yml' + +x-codeSamples: + - $ref: 'examples/curl/signals_get_export_options.yml' + +security: + - bearer_auth: + - 'signals:read' diff --git a/specification/resources/signals/signals_list_consents.yml b/specification/resources/signals/signals_list_consents.yml new file mode 100644 index 000000000..77193101c --- /dev/null +++ b/specification/resources/signals/signals_list_consents.yml @@ -0,0 +1,34 @@ +operationId: signals_list_consents + +summary: List All Consent Records + +description: | + To list all signals consent records for your team, send a GET request to + `/v1/consent`. Each record indicates whether signals collection is enabled + for a specific GenAI agent. + +tags: + - Signals + +responses: + '200': + $ref: 'responses/list_consents_response.yml' + + '401': + $ref: '../../shared/responses/unauthorized.yml' + + '429': + $ref: '../../shared/responses/too_many_requests.yml' + + '500': + $ref: '../../shared/responses/server_error.yml' + + default: + $ref: '../../shared/responses/unexpected_error.yml' + +x-codeSamples: + - $ref: 'examples/curl/signals_list_consents.yml' + +security: + - bearer_auth: + - 'signals:read' diff --git a/specification/resources/signals/signals_list_dialogues.yml b/specification/resources/signals/signals_list_dialogues.yml new file mode 100644 index 000000000..9d6ef07e8 --- /dev/null +++ b/specification/resources/signals/signals_list_dialogues.yml @@ -0,0 +1,46 @@ +operationId: signals_list_session_dialogues + +summary: List Dialogues for a Session + +description: | + To list the dialogue turns within a specific session, send a GET request to + `/v1/signals/sessions/{session_id}/dialogues`. Each dialogue represents a + single turn of conversation between a user and the GenAI agent, along with + any signals detected. Results are paginated using cursor-based pagination. + +tags: + - Signals + +parameters: + - $ref: 'parameters.yml#/session_id' + - $ref: 'parameters.yml#/limit' + - $ref: 'parameters.yml#/after' + - $ref: 'parameters.yml#/start_time' + - $ref: 'parameters.yml#/end_time' + - $ref: 'parameters.yml#/signal_type' + +responses: + '200': + $ref: 'responses/list_dialogues_response.yml' + + '401': + $ref: '../../shared/responses/unauthorized.yml' + + '404': + $ref: '../../shared/responses/not_found.yml' + + '429': + $ref: '../../shared/responses/too_many_requests.yml' + + '500': + $ref: '../../shared/responses/server_error.yml' + + default: + $ref: '../../shared/responses/unexpected_error.yml' + +x-codeSamples: + - $ref: 'examples/curl/signals_list_dialogues.yml' + +security: + - bearer_auth: + - 'signals:read' diff --git a/specification/resources/signals/signals_list_exports.yml b/specification/resources/signals/signals_list_exports.yml new file mode 100644 index 000000000..fbf85311a --- /dev/null +++ b/specification/resources/signals/signals_list_exports.yml @@ -0,0 +1,38 @@ +operationId: signals_list_exports + +summary: List Export Jobs + +description: | + To list signals export jobs for your team, send a GET request to + `/v1/signals/exports`. Results are paginated using cursor-based pagination + with `limit` and `after` parameters. + +tags: + - Signals + +parameters: + - $ref: 'parameters.yml#/limit' + - $ref: 'parameters.yml#/after' + +responses: + '200': + $ref: 'responses/list_exports_response.yml' + + '401': + $ref: '../../shared/responses/unauthorized.yml' + + '429': + $ref: '../../shared/responses/too_many_requests.yml' + + '500': + $ref: '../../shared/responses/server_error.yml' + + default: + $ref: '../../shared/responses/unexpected_error.yml' + +x-codeSamples: + - $ref: 'examples/curl/signals_list_exports.yml' + +security: + - bearer_auth: + - 'signals:read' diff --git a/specification/resources/signals/signals_list_sessions.yml b/specification/resources/signals/signals_list_sessions.yml new file mode 100644 index 000000000..ae5e6a87c --- /dev/null +++ b/specification/resources/signals/signals_list_sessions.yml @@ -0,0 +1,42 @@ +operationId: signals_list_agent_sessions + +summary: List Sessions for an Agent + +description: | + To list signals sessions for a specific GenAI agent, send a GET request to + `/v1/signals/agents/{agent_id}/sessions`. Results are paginated using cursor-based + pagination with `limit` and `after` parameters. + +tags: + - Signals + +parameters: + - $ref: 'parameters.yml#/agent_id' + - $ref: 'parameters.yml#/limit' + - $ref: 'parameters.yml#/after' + - $ref: 'parameters.yml#/start_time' + - $ref: 'parameters.yml#/end_time' + - $ref: 'parameters.yml#/signal_type' + +responses: + '200': + $ref: 'responses/list_sessions_response.yml' + + '401': + $ref: '../../shared/responses/unauthorized.yml' + + '429': + $ref: '../../shared/responses/too_many_requests.yml' + + '500': + $ref: '../../shared/responses/server_error.yml' + + default: + $ref: '../../shared/responses/unexpected_error.yml' + +x-codeSamples: + - $ref: 'examples/curl/signals_list_sessions.yml' + +security: + - bearer_auth: + - 'signals:read' diff --git a/specification/resources/signals/signals_set_consent.yml b/specification/resources/signals/signals_set_consent.yml new file mode 100644 index 000000000..f0466e869 --- /dev/null +++ b/specification/resources/signals/signals_set_consent.yml @@ -0,0 +1,55 @@ +operationId: signals_set_consent + +summary: Update Consent for an Agent + +description: | + To enable or disable signals collection for a specific GenAI agent, send a + PUT request to `/v1/consent/{agent_id}` with an `enabled` boolean in the + request body. + +tags: + - Signals + +parameters: + - $ref: 'parameters.yml#/agent_id' + +requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + enabled: + type: boolean + description: Whether to enable signals collection for this agent. + required: + - enabled + example: + enabled: true + +responses: + '200': + $ref: 'responses/set_consent_response.yml' + + '401': + $ref: '../../shared/responses/unauthorized.yml' + + '404': + $ref: '../../shared/responses/not_found.yml' + + '429': + $ref: '../../shared/responses/too_many_requests.yml' + + '500': + $ref: '../../shared/responses/server_error.yml' + + default: + $ref: '../../shared/responses/unexpected_error.yml' + +x-codeSamples: + - $ref: 'examples/curl/signals_set_consent.yml' + +security: + - bearer_auth: + - 'signals:update' From a0adbbbb5cebf25e2ce697fbf9c81878940114c3 Mon Sep 17 00:00:00 2001 From: Saurav Kumar Date: Thu, 8 Oct 2026 17:44:20 +0530 Subject: [PATCH 2/8] Replace 'GenAI agent' with 'agent' and clarify Harness Runtime Environment Config ID MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update all 11 occurrences of 'GenAI agent' across Signals OpenAPI spec files. For agent_id fields, description now reads: 'For Harness Runtime, this is the Environment Config ID.' — aligning with product-docs terminology. Co-authored-by: Cursor --- specification/resources/signals/models/agent_consent.yml | 2 +- specification/resources/signals/models/consent_record.yml | 2 +- .../resources/signals/models/create_export_request.yml | 2 +- specification/resources/signals/models/export_job.yml | 2 +- specification/resources/signals/models/session.yml | 2 +- specification/resources/signals/parameters.yml | 2 +- specification/resources/signals/signals_get_consent.yml | 2 +- specification/resources/signals/signals_list_consents.yml | 2 +- specification/resources/signals/signals_list_dialogues.yml | 2 +- specification/resources/signals/signals_list_sessions.yml | 2 +- specification/resources/signals/signals_set_consent.yml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/specification/resources/signals/models/agent_consent.yml b/specification/resources/signals/models/agent_consent.yml index 2fe5a3293..a315c6278 100644 --- a/specification/resources/signals/models/agent_consent.yml +++ b/specification/resources/signals/models/agent_consent.yml @@ -12,7 +12,7 @@ properties: agent_id: type: string format: uuid - description: The unique identifier of the GenAI agent. + description: The unique identifier of the agent. For Harness Runtime, this is the Environment Config ID. example: 019fb3d2-8a56-72cc-8bf9-9d21510b2a99 enabled: type: boolean diff --git a/specification/resources/signals/models/consent_record.yml b/specification/resources/signals/models/consent_record.yml index 323162421..656c43297 100644 --- a/specification/resources/signals/models/consent_record.yml +++ b/specification/resources/signals/models/consent_record.yml @@ -12,7 +12,7 @@ properties: agent_id: type: string format: uuid - description: The unique identifier of the GenAI agent. + description: The unique identifier of the agent. For Harness Runtime, this is the Environment Config ID. example: 019fb3d2-8a56-72cc-8bf9-9d21510b2a99 enabled: type: boolean diff --git a/specification/resources/signals/models/create_export_request.yml b/specification/resources/signals/models/create_export_request.yml index 47d706e5c..9b0dc8958 100644 --- a/specification/resources/signals/models/create_export_request.yml +++ b/specification/resources/signals/models/create_export_request.yml @@ -4,7 +4,7 @@ properties: agent_id: type: string format: uuid - description: The GenAI agent whose data should be exported. + description: The agent whose data should be exported. For Harness Runtime, this is the Environment Config ID. example: 01a0f3d5-b58d-7c99-a743-7ca0397b7f5d signal_type: type: string diff --git a/specification/resources/signals/models/export_job.yml b/specification/resources/signals/models/export_job.yml index 0410975d2..48b978c23 100644 --- a/specification/resources/signals/models/export_job.yml +++ b/specification/resources/signals/models/export_job.yml @@ -9,7 +9,7 @@ properties: agent_id: type: string format: uuid - description: The GenAI agent whose data is being exported. + description: The agent whose data is being exported. For Harness Runtime, this is the Environment Config ID. example: 01a0f3d5-b58d-7c99-a743-7ca0397b7f5d status: type: string diff --git a/specification/resources/signals/models/session.yml b/specification/resources/signals/models/session.yml index b51b670fb..a76968deb 100644 --- a/specification/resources/signals/models/session.yml +++ b/specification/resources/signals/models/session.yml @@ -1,5 +1,5 @@ type: object -description: A signals session represents a conversation between a user and a GenAI agent. +description: A signals session represents a conversation between a user and an agent. properties: session_id: type: string diff --git a/specification/resources/signals/parameters.yml b/specification/resources/signals/parameters.yml index 84fa11779..30fd3db09 100644 --- a/specification/resources/signals/parameters.yml +++ b/specification/resources/signals/parameters.yml @@ -1,7 +1,7 @@ agent_id: in: path name: agent_id - description: A unique identifier for a GenAI agent. + description: A unique identifier for an agent. For Harness Runtime, this is the Environment Config ID. required: true schema: type: string diff --git a/specification/resources/signals/signals_get_consent.yml b/specification/resources/signals/signals_get_consent.yml index 755f03285..029e11a18 100644 --- a/specification/resources/signals/signals_get_consent.yml +++ b/specification/resources/signals/signals_get_consent.yml @@ -3,7 +3,7 @@ operationId: signals_get_consent summary: Retrieve Consent for an Agent description: | - To retrieve the consent record for a specific GenAI agent, send a GET + To retrieve the consent record for a specific agent, send a GET request to `/v1/consent/{agent_id}`. The response includes an `allowed` field indicating whether the team is permitted to use signals for this agent. diff --git a/specification/resources/signals/signals_list_consents.yml b/specification/resources/signals/signals_list_consents.yml index 77193101c..f2590c200 100644 --- a/specification/resources/signals/signals_list_consents.yml +++ b/specification/resources/signals/signals_list_consents.yml @@ -5,7 +5,7 @@ summary: List All Consent Records description: | To list all signals consent records for your team, send a GET request to `/v1/consent`. Each record indicates whether signals collection is enabled - for a specific GenAI agent. + for a specific agent. tags: - Signals diff --git a/specification/resources/signals/signals_list_dialogues.yml b/specification/resources/signals/signals_list_dialogues.yml index 9d6ef07e8..aed5013c5 100644 --- a/specification/resources/signals/signals_list_dialogues.yml +++ b/specification/resources/signals/signals_list_dialogues.yml @@ -5,7 +5,7 @@ summary: List Dialogues for a Session description: | To list the dialogue turns within a specific session, send a GET request to `/v1/signals/sessions/{session_id}/dialogues`. Each dialogue represents a - single turn of conversation between a user and the GenAI agent, along with + single turn of conversation between a user and the agent, along with any signals detected. Results are paginated using cursor-based pagination. tags: diff --git a/specification/resources/signals/signals_list_sessions.yml b/specification/resources/signals/signals_list_sessions.yml index ae5e6a87c..803935d28 100644 --- a/specification/resources/signals/signals_list_sessions.yml +++ b/specification/resources/signals/signals_list_sessions.yml @@ -3,7 +3,7 @@ operationId: signals_list_agent_sessions summary: List Sessions for an Agent description: | - To list signals sessions for a specific GenAI agent, send a GET request to + To list signals sessions for a specific agent, send a GET request to `/v1/signals/agents/{agent_id}/sessions`. Results are paginated using cursor-based pagination with `limit` and `after` parameters. diff --git a/specification/resources/signals/signals_set_consent.yml b/specification/resources/signals/signals_set_consent.yml index f0466e869..659e7faa0 100644 --- a/specification/resources/signals/signals_set_consent.yml +++ b/specification/resources/signals/signals_set_consent.yml @@ -3,7 +3,7 @@ operationId: signals_set_consent summary: Update Consent for an Agent description: | - To enable or disable signals collection for a specific GenAI agent, send a + To enable or disable signals collection for a specific agent, send a PUT request to `/v1/consent/{agent_id}` with an `enabled` boolean in the request body. From b81a43ee53dc2793e94ce8a82c71e2c2fb0e7d11 Mon Sep 17 00:00:00 2001 From: Saurav Kumar Date: Thu, 8 Oct 2026 17:57:04 +0530 Subject: [PATCH 3/8] Fix signal_type field type in create_export_request: string -> array The API accepts and returns signal_type as an array of strings, not a single string. Co-authored-by: Cursor --- .../resources/signals/models/create_export_request.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/specification/resources/signals/models/create_export_request.yml b/specification/resources/signals/models/create_export_request.yml index 9b0dc8958..1feffdab7 100644 --- a/specification/resources/signals/models/create_export_request.yml +++ b/specification/resources/signals/models/create_export_request.yml @@ -7,11 +7,14 @@ properties: description: The agent whose data should be exported. For Harness Runtime, this is the Environment Config ID. example: 01a0f3d5-b58d-7c99-a743-7ca0397b7f5d signal_type: - type: string + type: array + items: + type: string description: >- - Filter the export to only include the specified signal type. Use the + Filter the export to only include the specified signal types. Use the export options endpoint to list available values. - example: ExecutionFailureToolNotFound + example: + - ExecutionFailureToolNotFound session_ids: type: array description: Optional list of specific session IDs to include in the export. From e622cc31473a83385e2ff9856c1ca703b6bcbf1d Mon Sep 17 00:00:00 2001 From: Saurav Kumar Date: Thu, 8 Oct 2026 18:21:33 +0530 Subject: [PATCH 4/8] Fix export_download model, remove segment_id, clarify session description - export_download: rename 'url' to 'download_url', use Spaces URL pattern (.json.gz), change expires_at from ISO string to Unix timestamp integer - session_dialogue: remove segment_id property (internal detail), update sequence description to reference session instead of segment - session: update description to cover both Harness Runtime agent sessions and Serverless Inference chat completions - Update response examples to match Co-authored-by: Cursor --- .../resources/signals/models/export_download.yml | 14 +++++++------- specification/resources/signals/models/session.yml | 2 +- .../resources/signals/models/session_dialogue.yml | 6 +----- .../signals/responses/export_download_response.yml | 4 ++-- .../signals/responses/list_dialogues_response.yml | 1 - 5 files changed, 11 insertions(+), 16 deletions(-) diff --git a/specification/resources/signals/models/export_download.yml b/specification/resources/signals/models/export_download.yml index b8a370c1c..ad52261ed 100644 --- a/specification/resources/signals/models/export_download.yml +++ b/specification/resources/signals/models/export_download.yml @@ -1,15 +1,15 @@ type: object description: A pre-signed download URL for a completed export. properties: - url: + download_url: type: string format: uri description: A temporary pre-signed URL to download the export archive. - example: "https://storage.example.com/exports/9f13c09c.tar.gz?sig=abc123" + example: "https://example-bucket.nyc3.digitaloceanspaces.com/exports/3f2a1c4e-5b6d-4e7f-8a9b-0c1d2e3f4a5b/9f13c09c-c877-436b-9863-dcc39c9dd737.json.gz?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Signature=EXAMPLE" expires_at: - type: string - format: date-time - description: When the download URL expires. - example: "2026-10-15T00:00:00Z" + type: integer + description: Unix timestamp when the download URL expires. The URL is valid for 15 minutes. + example: 1791390640 required: - - url + - download_url + - expires_at diff --git a/specification/resources/signals/models/session.yml b/specification/resources/signals/models/session.yml index a76968deb..af4a7b75e 100644 --- a/specification/resources/signals/models/session.yml +++ b/specification/resources/signals/models/session.yml @@ -1,5 +1,5 @@ type: object -description: A signals session represents a conversation between a user and an agent. +description: A session represents a conversation monitored by Signals, such as a Harness Runtime agent session or a Serverless Inference chat completion. properties: session_id: type: string diff --git a/specification/resources/signals/models/session_dialogue.yml b/specification/resources/signals/models/session_dialogue.yml index a1b884c14..928cd3345 100644 --- a/specification/resources/signals/models/session_dialogue.yml +++ b/specification/resources/signals/models/session_dialogue.yml @@ -5,13 +5,9 @@ properties: type: string description: The unique identifier for the dialogue. example: "01a0f3d6-1234-7abc-def0-123456789abc" - segment_id: - type: string - description: The segment identifier grouping related dialogues. - example: "01a0f3d6-5678-7abc-def0-123456789abc" sequence: type: integer - description: The sequence number of this dialogue within its segment. + description: The sequence number of this dialogue within the session. example: 1 run_status: type: string diff --git a/specification/resources/signals/responses/export_download_response.yml b/specification/resources/signals/responses/export_download_response.yml index b338ecc42..e9a450ff8 100644 --- a/specification/resources/signals/responses/export_download_response.yml +++ b/specification/resources/signals/responses/export_download_response.yml @@ -13,5 +13,5 @@ content: schema: $ref: '../models/export_download.yml' example: - url: "https://storage.example.com/exports/9f13c09c.tar.gz?sig=abc123" - expires_at: "2026-10-15T00:00:00Z" + download_url: "https://example-bucket.nyc3.digitaloceanspaces.com/exports/3f2a1c4e-5b6d-4e7f-8a9b-0c1d2e3f4a5b/9f13c09c-c877-436b-9863-dcc39c9dd737.json.gz?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Signature=EXAMPLE" + expires_at: 1791390640 diff --git a/specification/resources/signals/responses/list_dialogues_response.yml b/specification/resources/signals/responses/list_dialogues_response.yml index bc11413a2..aca5945d3 100644 --- a/specification/resources/signals/responses/list_dialogues_response.yml +++ b/specification/resources/signals/responses/list_dialogues_response.yml @@ -34,7 +34,6 @@ content: - cursor: eyJzZXF1ZW5jZSI6MX0= node: id: "01a0f3d6-1234-7abc-def0-123456789abc" - segment_id: "01a0f3d6-5678-7abc-def0-123456789abc" sequence: 1 run_status: completed user_message: "How do I create a Droplet?" From f6f31b71b8c0a020038bad49c1e5105dce74a822 Mon Sep 17 00:00:00 2001 From: Saurav Kumar Date: Thu, 8 Oct 2026 18:24:38 +0530 Subject: [PATCH 5/8] Use placeholder-style download URL example for readability Replace UUID-based example URL with / placeholders to make the URL structure self-documenting. Co-authored-by: Cursor --- specification/resources/signals/models/export_download.yml | 2 +- .../resources/signals/responses/export_download_response.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/specification/resources/signals/models/export_download.yml b/specification/resources/signals/models/export_download.yml index ad52261ed..2904026ee 100644 --- a/specification/resources/signals/models/export_download.yml +++ b/specification/resources/signals/models/export_download.yml @@ -5,7 +5,7 @@ properties: type: string format: uri description: A temporary pre-signed URL to download the export archive. - example: "https://example-bucket.nyc3.digitaloceanspaces.com/exports/3f2a1c4e-5b6d-4e7f-8a9b-0c1d2e3f4a5b/9f13c09c-c877-436b-9863-dcc39c9dd737.json.gz?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Signature=EXAMPLE" + example: "https://example-bucket.nyc3.digitaloceanspaces.com/exports//.json.gz?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Signature=EXAMPLE" expires_at: type: integer description: Unix timestamp when the download URL expires. The URL is valid for 15 minutes. diff --git a/specification/resources/signals/responses/export_download_response.yml b/specification/resources/signals/responses/export_download_response.yml index e9a450ff8..efdc8e5e1 100644 --- a/specification/resources/signals/responses/export_download_response.yml +++ b/specification/resources/signals/responses/export_download_response.yml @@ -13,5 +13,5 @@ content: schema: $ref: '../models/export_download.yml' example: - download_url: "https://example-bucket.nyc3.digitaloceanspaces.com/exports/3f2a1c4e-5b6d-4e7f-8a9b-0c1d2e3f4a5b/9f13c09c-c877-436b-9863-dcc39c9dd737.json.gz?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Signature=EXAMPLE" + download_url: "https://example-bucket.nyc3.digitaloceanspaces.com/exports//.json.gz?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Signature=EXAMPLE" expires_at: 1791390640 From 51cf685f3bf7acfd62e8ccbdb18083399aa3fc96 Mon Sep 17 00:00:00 2001 From: Saurav Kumar Date: Thu, 8 Oct 2026 18:28:14 +0530 Subject: [PATCH 6/8] Fix signal_type to array in create export example and curl sample Co-authored-by: Cursor --- .../resources/signals/examples/curl/signals_create_export.yml | 2 +- specification/resources/signals/signals_create_export.yml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/specification/resources/signals/examples/curl/signals_create_export.yml b/specification/resources/signals/examples/curl/signals_create_export.yml index 181f1f56b..b99a68d39 100644 --- a/specification/resources/signals/examples/curl/signals_create_export.yml +++ b/specification/resources/signals/examples/curl/signals_create_export.yml @@ -3,5 +3,5 @@ source: |- curl -X POST \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \ - -d '{"agent_id":"01a0f3d5-b58d-7c99-a743-7ca0397b7f5d","signal_type":"ExecutionFailureToolNotFound"}' \ + -d '{"agent_id":"01a0f3d5-b58d-7c99-a743-7ca0397b7f5d","signal_type":["ExecutionFailureToolNotFound"]}' \ "https://api.digitalocean.com/v1/signals/exports" diff --git a/specification/resources/signals/signals_create_export.yml b/specification/resources/signals/signals_create_export.yml index 0b56ecbc7..89b2f74b7 100644 --- a/specification/resources/signals/signals_create_export.yml +++ b/specification/resources/signals/signals_create_export.yml @@ -24,7 +24,8 @@ requestBody: $ref: 'models/create_export_request.yml' example: agent_id: 01a0f3d5-b58d-7c99-a743-7ca0397b7f5d - signal_type: ExecutionFailureToolNotFound + signal_type: + - ExecutionFailureToolNotFound responses: '201': From ae67f3e4ecc98348104d9432350b728382fb3434 Mon Sep 17 00:00:00 2001 From: Saurav Kumar Date: Thu, 8 Oct 2026 18:35:24 +0530 Subject: [PATCH 7/8] Update Signals tag description: replace GenAI agent with generic coverage Now mentions both Harness Runtime sessions and Serverless Inference chat completions. Co-authored-by: Cursor --- specification/DigitalOcean-public.v2.yaml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/specification/DigitalOcean-public.v2.yaml b/specification/DigitalOcean-public.v2.yaml index 0bcac7a53..c1e38f723 100644 --- a/specification/DigitalOcean-public.v2.yaml +++ b/specification/DigitalOcean-public.v2.yaml @@ -579,9 +579,10 @@ tags: - name: Signals description: |- - The DigitalOcean Signals API provides observability for GenAI agent - conversations, detecting behavioral signals such as user disengagement, - execution failures, and satisfaction indicators. + The DigitalOcean Signals API provides observability for agent + conversations, such as Harness Runtime sessions and Serverless + Inference chat completions, detecting behavioral signals such as + user disengagement, execution failures, and satisfaction indicators. Use the consent endpoints to manage whether signals collection is enabled for each agent, the session endpoints to browse agent From 328de26b050d052bb58a0ac6b8473108da4fb6ae Mon Sep 17 00:00:00 2001 From: Saurav Kumar Date: Thu, 8 Oct 2026 19:12:34 +0530 Subject: [PATCH 8/8] Fix all 7 CI lint errors in Signals spec 1. export_download: use valid URI with fake UUIDs (not placeholders) 2. export_download_response: same fix for response example 3. list_dialogues_response: add example to cursor schema property 4. list_exports_response: add example to cursor schema property 5. list_sessions_response: add example to cursor schema property 6. signals_list_sessions: add missing 404 response 7. Rename signals_set_consent -> signals_update_consent (operationId naming convention requires 'update' for PUT) Co-authored-by: Cursor --- specification/DigitalOcean-public.v2.yaml | 2 +- .../{signals_set_consent.yml => signals_update_consent.yml} | 0 specification/resources/signals/models/export_download.yml | 2 +- .../signals/responses/export_download_response.yml | 2 +- .../resources/signals/responses/list_dialogues_response.yml | 1 + .../resources/signals/responses/list_exports_response.yml | 1 + .../resources/signals/responses/list_sessions_response.yml | 1 + ...set_consent_response.yml => update_consent_response.yml} | 0 specification/resources/signals/signals_list_sessions.yml | 3 +++ .../{signals_set_consent.yml => signals_update_consent.yml} | 6 +++--- 10 files changed, 12 insertions(+), 6 deletions(-) rename specification/resources/signals/examples/curl/{signals_set_consent.yml => signals_update_consent.yml} (100%) rename specification/resources/signals/responses/{set_consent_response.yml => update_consent_response.yml} (100%) rename specification/resources/signals/{signals_set_consent.yml => signals_update_consent.yml} (87%) diff --git a/specification/DigitalOcean-public.v2.yaml b/specification/DigitalOcean-public.v2.yaml index c1e38f723..51cb1b467 100644 --- a/specification/DigitalOcean-public.v2.yaml +++ b/specification/DigitalOcean-public.v2.yaml @@ -1849,7 +1849,7 @@ paths: $ref: "resources/signals/signals_get_consent.yml" put: - $ref: "resources/signals/signals_set_consent.yml" + $ref: "resources/signals/signals_update_consent.yml" /v1/signals/agents/{agent_id}/sessions: get: diff --git a/specification/resources/signals/examples/curl/signals_set_consent.yml b/specification/resources/signals/examples/curl/signals_update_consent.yml similarity index 100% rename from specification/resources/signals/examples/curl/signals_set_consent.yml rename to specification/resources/signals/examples/curl/signals_update_consent.yml diff --git a/specification/resources/signals/models/export_download.yml b/specification/resources/signals/models/export_download.yml index 2904026ee..ad52261ed 100644 --- a/specification/resources/signals/models/export_download.yml +++ b/specification/resources/signals/models/export_download.yml @@ -5,7 +5,7 @@ properties: type: string format: uri description: A temporary pre-signed URL to download the export archive. - example: "https://example-bucket.nyc3.digitaloceanspaces.com/exports//.json.gz?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Signature=EXAMPLE" + example: "https://example-bucket.nyc3.digitaloceanspaces.com/exports/3f2a1c4e-5b6d-4e7f-8a9b-0c1d2e3f4a5b/9f13c09c-c877-436b-9863-dcc39c9dd737.json.gz?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Signature=EXAMPLE" expires_at: type: integer description: Unix timestamp when the download URL expires. The URL is valid for 15 minutes. diff --git a/specification/resources/signals/responses/export_download_response.yml b/specification/resources/signals/responses/export_download_response.yml index efdc8e5e1..e9a450ff8 100644 --- a/specification/resources/signals/responses/export_download_response.yml +++ b/specification/resources/signals/responses/export_download_response.yml @@ -13,5 +13,5 @@ content: schema: $ref: '../models/export_download.yml' example: - download_url: "https://example-bucket.nyc3.digitaloceanspaces.com/exports//.json.gz?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Signature=EXAMPLE" + download_url: "https://example-bucket.nyc3.digitaloceanspaces.com/exports/3f2a1c4e-5b6d-4e7f-8a9b-0c1d2e3f4a5b/9f13c09c-c877-436b-9863-dcc39c9dd737.json.gz?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Signature=EXAMPLE" expires_at: 1791390640 diff --git a/specification/resources/signals/responses/list_dialogues_response.yml b/specification/resources/signals/responses/list_dialogues_response.yml index aca5945d3..d188c67f7 100644 --- a/specification/resources/signals/responses/list_dialogues_response.yml +++ b/specification/resources/signals/responses/list_dialogues_response.yml @@ -21,6 +21,7 @@ content: cursor: type: string description: An opaque cursor for pagination. + example: eyJzZXF1ZW5jZSI6MX0= node: $ref: '../models/session_dialogue.yml' page_info: diff --git a/specification/resources/signals/responses/list_exports_response.yml b/specification/resources/signals/responses/list_exports_response.yml index 63806c5b0..92c494b04 100644 --- a/specification/resources/signals/responses/list_exports_response.yml +++ b/specification/resources/signals/responses/list_exports_response.yml @@ -21,6 +21,7 @@ content: cursor: type: string description: An opaque cursor for pagination. + example: eyJ0ZWFtX2lkIjozOTQ0OTk0Nn0= node: $ref: '../models/export_job.yml' page_info: diff --git a/specification/resources/signals/responses/list_sessions_response.yml b/specification/resources/signals/responses/list_sessions_response.yml index 5faa79c0c..c89c84e70 100644 --- a/specification/resources/signals/responses/list_sessions_response.yml +++ b/specification/resources/signals/responses/list_sessions_response.yml @@ -21,6 +21,7 @@ content: cursor: type: string description: An opaque cursor for pagination. + example: eyJ0ZWFtX2lkIjozOTQ0OTk0Nn0= node: $ref: '../models/session.yml' page_info: diff --git a/specification/resources/signals/responses/set_consent_response.yml b/specification/resources/signals/responses/update_consent_response.yml similarity index 100% rename from specification/resources/signals/responses/set_consent_response.yml rename to specification/resources/signals/responses/update_consent_response.yml diff --git a/specification/resources/signals/signals_list_sessions.yml b/specification/resources/signals/signals_list_sessions.yml index 803935d28..c0bd6974f 100644 --- a/specification/resources/signals/signals_list_sessions.yml +++ b/specification/resources/signals/signals_list_sessions.yml @@ -25,6 +25,9 @@ responses: '401': $ref: '../../shared/responses/unauthorized.yml' + '404': + $ref: '../../shared/responses/not_found.yml' + '429': $ref: '../../shared/responses/too_many_requests.yml' diff --git a/specification/resources/signals/signals_set_consent.yml b/specification/resources/signals/signals_update_consent.yml similarity index 87% rename from specification/resources/signals/signals_set_consent.yml rename to specification/resources/signals/signals_update_consent.yml index 659e7faa0..5ad429a07 100644 --- a/specification/resources/signals/signals_set_consent.yml +++ b/specification/resources/signals/signals_update_consent.yml @@ -1,4 +1,4 @@ -operationId: signals_set_consent +operationId: signals_update_consent summary: Update Consent for an Agent @@ -30,7 +30,7 @@ requestBody: responses: '200': - $ref: 'responses/set_consent_response.yml' + $ref: 'responses/update_consent_response.yml' '401': $ref: '../../shared/responses/unauthorized.yml' @@ -48,7 +48,7 @@ responses: $ref: '../../shared/responses/unexpected_error.yml' x-codeSamples: - - $ref: 'examples/curl/signals_set_consent.yml' + - $ref: 'examples/curl/signals_update_consent.yml' security: - bearer_auth: