openapi: 3.0.3
info:
  title: mobius API
  version: 0.1.0
  description: Mobius is a work coordination platform for mixed teams of humans, systems,
    and AI agents
servers:
- url: https://api.mobiusops.ai
  description: Production
- url: http://localhost:8080
  description: Local development
tags:
- name: channels
  x-displayName: channels
- name: audit-logs
  x-displayName: audit-logs
- name: api-keys
  x-displayName: api-keys
- name: workflows
  x-displayName: workflows
- name: runs
  x-displayName: runs
- name: actions
  x-displayName: actions
- name: jobs
  x-displayName: jobs
- name: triggers
  x-displayName: triggers
- name: workers
  x-displayName: workers
- name: projects
  x-displayName: projects
- name: webhooks
  x-displayName: webhooks
- name: integrations
  x-displayName: integrations
- name: metrics
  x-displayName: metrics
- name: roles
  x-displayName: roles
- name: interactions
  x-displayName: interactions
- name: groups
  x-displayName: groups
- name: agents
  x-displayName: agents
- name: tools
  x-displayName: tools
paths:
  /projects/{project}/channels:
    post:
      operationId: createChannel
      tags:
      - channels
      summary: Create a channel
      description: 'Creates a new channel or DM thread. The channel `name` must be

        URL-safe and unique within the project — it is immutable after

        creation. The creator is automatically added as an admin member.

        Supply `member_ids` to seed initial membership atomically.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateChannelRequest'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Channel'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
    get:
      operationId: listChannels
      tags:
      - channels
      summary: List channels
      description: Returns channels in the project, optionally filtered by kind or
        visibility.
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - name: kind
        in: query
        schema:
          type: string
          enum:
          - dm
          - channel
        description: Filter by channel kind.
      - name: private
        in: query
        schema:
          type: boolean
        description: Filter by private flag.
      - $ref: '#/components/parameters/CursorParam'
      - $ref: '#/components/parameters/LimitParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChannelListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /projects/{project}/channels/{id}:
    get:
      operationId: getChannel
      tags:
      - channels
      summary: Get a channel
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Channel'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    patch:
      operationId: updateChannel
      tags:
      - channels
      summary: Update a channel
      description: 'Updates `display_name`, `topic`, `private`, or `archived_at`.
        The

        `name` (handle) is immutable and cannot be changed after creation.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateChannelRequest'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Channel'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    delete:
      operationId: deleteChannel
      tags:
      - channels
      summary: Delete a channel
      description: Hard-deletes the channel and its message history.
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      responses:
        '204':
          description: No Content
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/channels/{id}/members:
    get:
      operationId: listChannelMembers
      tags:
      - channels
      summary: List channel members
      description: Returns the current live membership of the channel.
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      - $ref: '#/components/parameters/CursorParam'
      - $ref: '#/components/parameters/LimitParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChannelMemberListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    post:
      operationId: addChannelMember
      tags:
      - channels
      summary: Add a member to a channel
      description: Adds a user or agent to the channel. Returns 409 if already a member.
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AddChannelMemberRequest'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChannelMember'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/channels/{id}/members/{userId}:
    delete:
      operationId: removeChannelMember
      tags:
      - channels
      summary: Remove a member from a channel
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      - name: userId
        in: path
        required: true
        schema:
          type: string
        description: User or agent ID of the member to remove.
      responses:
        '204':
          description: No Content
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/channels/{id}/messages:
    get:
      operationId: listChannelMessages
      tags:
      - channels
      summary: List messages in a channel
      description: 'Returns messages in reverse chronological order (newest first).

        Use `reply_to` to fetch a thread. Use `cursor` for pagination.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      - name: sender_id
        in: query
        schema:
          type: string
        description: Filter by sender user or agent ID.
      - name: reply_to
        in: query
        schema:
          type: string
        description: Return only replies to this message ID (thread view).
      - name: pinned
        in: query
        schema:
          type: boolean
        description: Filter by pinned status.
      - $ref: '#/components/parameters/CursorParam'
      - $ref: '#/components/parameters/LimitParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChannelMessageListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    post:
      operationId: sendChannelMessage
      tags:
      - channels
      summary: Send a message to a channel
      description: 'Posts a message to the channel. For agent-sent messages, supply

        `sender_agent_id` (and optionally `sender_session_id`) to attribute

        the message to the agent rather than the authenticated user.

        Content is Markdown. Use `reply_to` for threading.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SendChannelMessageRequest'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChannelMessage'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/channels/{id}/messages/{messageId}:
    get:
      operationId: getChannelMessage
      tags:
      - channels
      summary: Get a channel message
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      - name: messageId
        in: path
        required: true
        description: ID of the channel message.
        schema:
          type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChannelMessage'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    patch:
      operationId: updateChannelMessage
      tags:
      - channels
      summary: Update a channel message
      description: Updates content, metadata, or pinned state of a message. Sets `edited_at`.
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      - name: messageId
        in: path
        required: true
        description: ID of the channel message.
        schema:
          type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateChannelMessageRequest'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChannelMessage'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /audit-logs:
    get:
      operationId: listAuditLogs
      tags:
      - audit-logs
      summary: List audit log entries
      description: 'Returns an immutable, append-only log of create/update/delete
        actions

        performed against org resources. Entries record both the durable actor

        identity (service account or user) and the credential used, enabling

        attribution even when keys are later revoked.


        Combine `actor_id` + `resource_type` to audit a specific identity''s

        writes to a resource class. Use `created_after` / `created_before` for

        time-bounded compliance exports.

        '
      parameters:
      - name: resource_type
        in: query
        schema:
          type: string
        description: Filter by resource type
      - name: project_id
        in: query
        schema:
          type: string
        description: Filter by project ID
      - name: resource_id
        in: query
        schema:
          type: string
        description: Filter by resource ID
      - name: user_id
        in: query
        schema:
          type: string
        description: Filter by user ID
      - name: actor_type
        in: query
        schema:
          type: string
        description: Filter by actor type
      - name: actor_id
        in: query
        schema:
          type: string
        description: Filter by actor ID
      - name: action
        in: query
        schema:
          type: string
        description: Filter by action (create, update, delete)
      - name: created_after
        in: query
        schema:
          type: string
          format: date-time
        description: Filter to entries created after this timestamp
      - name: created_before
        in: query
        schema:
          type: string
          format: date-time
        description: Filter to entries created before this timestamp
      - $ref: '#/components/parameters/CursorParam'
      - $ref: '#/components/parameters/LimitParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuditLogListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /api-keys:
    post:
      operationId: createAPIKey
      tags:
      - api-keys
      summary: Create an org-scoped API key
      description: 'Creates a key valid for any project in the org. The raw key value
        is

        returned in `key` and is never retrievable again after this response.

        '
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateAPIKeyRequest'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIKeyCreateResult'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
    get:
      operationId: listAPIKeys
      tags:
      - api-keys
      summary: List org-scoped API keys
      description: Returns all non-revoked org-level keys. Project-pinned keys are
        not included; use the project endpoint.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIKeyListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /api-keys/{id}:
    get:
      operationId: getAPIKey
      tags:
      - api-keys
      summary: Get an org-scoped API key
      parameters:
      - $ref: '#/components/parameters/IDParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIKey'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    delete:
      operationId: revokeAPIKey
      tags:
      - api-keys
      summary: Revoke an org-scoped API key
      description: Permanently revokes the key. In-flight requests using this key
        will immediately start receiving 401.
      parameters:
      - $ref: '#/components/parameters/IDParam'
      responses:
        '204':
          description: No Content
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/api-keys:
    post:
      operationId: createProjectAPIKey
      tags:
      - api-keys
      summary: Create a project-pinned API key
      description: 'Creates a key scoped to this project only. The key cannot be used
        to

        access other projects even if the permissions would otherwise allow it.

        The raw key value is returned in `key` and is never retrievable again.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateAPIKeyRequest'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIKeyCreateResult'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
    get:
      operationId: listProjectAPIKeys
      tags:
      - api-keys
      summary: List project-pinned API keys
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIKeyListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /projects/{project}/api-keys/{id}:
    get:
      operationId: getProjectAPIKey
      tags:
      - api-keys
      summary: Get a project-pinned API key
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIKey'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    delete:
      operationId: revokeProjectAPIKey
      tags:
      - api-keys
      summary: Revoke a project-pinned API key
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      responses:
        '204':
          description: No Content
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/workflows:
    get:
      operationId: listWorkflows
      tags:
      - workflows
      summary: List workflow definitions
      description: Returns workflow definitions with their latest version number.
        Spec is not included in list responses; use getWorkflow for the full spec.
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - name: cursor
        in: query
        description: Opaque pagination cursor returned from the previous response.
        schema:
          type: string
      - name: limit
        in: query
        description: Maximum number of results to return per page.
        schema:
          type: integer
          minimum: 1
          maximum: 200
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowDefinitionListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    post:
      operationId: createWorkflow
      tags:
      - workflows
      summary: Create a workflow definition
      description: 'Creates a workflow definition with an initial version (version
        1). The

        `handle` is auto-derived from `name` if omitted and must be unique within

        the org. Every call to `updateWorkflow` with a new `spec` creates a new

        version; version numbers are monotonically increasing.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateWorkflowRequest'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowDefinition'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
  /projects/{project}/workflows/{id}:
    get:
      operationId: getWorkflow
      tags:
      - workflows
      summary: Get a workflow definition
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowDefinition'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    patch:
      operationId: updateWorkflow
      tags:
      - workflows
      summary: Update a workflow definition
      description: 'Updating `spec` atomically creates a new immutable version (version
        N+1)

        and advances `latest_version`. Runs always execute the version they were

        started with; updating the definition does not affect running instances.

        Updating `name`, `description`, or `published_as_tool` without a `spec`

        does not create a new version.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateWorkflowRequest'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowDefinition'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    delete:
      operationId: deleteWorkflow
      tags:
      - workflows
      summary: Delete a workflow definition
      description: Hard-deletes the definition and all its versions. In-flight runs
        are not affected.
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      responses:
        '204':
          description: No Content
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/workflows/{id}/versions:
    get:
      operationId: listWorkflowVersions
      tags:
      - workflows
      summary: List versions of a workflow definition
      description: Returns all versions newest-first. Pass `include_spec=true` to
        include the full workflow spec for each version.
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      - name: include_spec
        in: query
        required: false
        description: When true, include the full workflow spec for each version.
        schema:
          type: boolean
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowVersionListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/workflows/{id}/runs:
    get:
      operationId: listWorkflowRuns
      tags:
      - workflows
      - runs
      summary: List runs for a workflow definition
      description: Returns runs for a specific workflow definition, newest first.
        Includes all statuses unless filtered.
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowRunListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
    post:
      operationId: startWorkflowRun
      tags:
      - workflows
      - runs
      summary: Start a new workflow run against a saved definition
      description: 'Enqueues a run using the latest version of the specified workflow

        definition. Equivalent to POST /projects/{project}/runs with

        `definition_id` set to this workflow''s ID. The `spec` field is

        forbidden on this path-bound endpoint.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StartRunRequest'
      responses:
        '202':
          description: Accepted
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowRun'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/runs:
    post:
      operationId: startRun
      tags:
      - runs
      summary: Start a new workflow run
      description: 'Starts a workflow run. Exactly one of `definition_id` or `spec`

        must be provided on the request body. When `spec` is provided,

        the run is ephemeral — no `WorkflowDefinition` is created, and

        the returned run carries an empty `definition_id` and a zero

        `definition_version`.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StartRunRequest'
      responses:
        '202':
          description: Accepted
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowRun'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    get:
      operationId: listRuns
      tags:
      - runs
      summary: List workflow runs
      description: 'Supports cursor-based pagination and keyset filtering by

        status, workflow type, queue, parent run, and

        initiator. Returns `{data, next_cursor?}`; pass `next_cursor`

        back in the next call to walk the result set.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - name: status
        in: query
        description: Filter by run status.
        schema:
          $ref: '#/components/schemas/WorkflowRunStatus'
      - name: workflow_type
        in: query
        description: Filter by workflow type name.
        schema:
          type: string
      - name: queue
        in: query
        description: Filter by queue name.
        schema:
          type: string
      - name: parent_run_id
        in: query
        description: Filter to child runs of the specified parent run.
        schema:
          type: string
      - name: initiated_by
        in: query
        description: Filter by the initiator label (e.g. trigger name, API key name).
        schema:
          type: string
      - name: external_id
        in: query
        description: Filter by caller-supplied external ID or correlation key.
        schema:
          type: string
      - $ref: '#/components/parameters/CursorParam'
      - $ref: '#/components/parameters/LimitParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowRunListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /projects/{project}/runs/cancellations:
    post:
      operationId: bulkCancelRuns
      tags:
      - runs
      summary: Request cancellation for a batch of runs
      description: 'Sets `cancel_requested` on every listed run. Workers receive

        `directives.should_cancel: true` on their next heartbeat and are

        expected to stop cooperatively. Per-run errors are reported inline;

        the response always returns 200 even on partial failures.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkRunRequest'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BulkRunResult'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /projects/{project}/runs/retries:
    post:
      operationId: bulkRetryRuns
      tags:
      - runs
      summary: Re-enqueue a batch of failed runs
      description: 'Flips every listed run from `failed` back to `queued`, clearing

        the error message. Only runs in terminal `failed` status can be

        retried; runs in other states produce per-run errors. Per-run errors

        are reported inline; the response always returns 200 on partial failures.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkRunRequest'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BulkRunResult'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /projects/{project}/runs/{id}:
    get:
      operationId: getRun
      tags:
      - runs
      summary: Get a workflow run
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowRunDetail'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/runs/{id}/action-log:
    get:
      operationId: getRunActionLog
      tags:
      - runs
      summary: List action log entries for a run
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ActionLogListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/runs/{id}/jobs:
    get:
      operationId: getRunJobs
      tags:
      - runs
      summary: List jobs for a run
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JobListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/runs/events:
    get:
      operationId: streamProjectRunEvents
      tags:
      - runs
      summary: Subscribe to a project-wide stream of run events (SSE)
      description: 'Opens a Server-Sent Events connection. Each frame carries a

        JSON envelope `{type, run_id, seq, timestamp, data}` where

        `type` is one of `run_updated`, `job_updated`, or

        `action_appended`, and `seq` is a monotonic durable

        cursor.


        Pass `?since=<seq>` on reconnect to replay any durable

        events the server has recorded past that cursor before

        switching back to live updates; clients should record the

        largest `seq` they have observed. Comment frames

        (`:keepalive`) are emitted every ~15s to keep intermediaries

        from closing the connection.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - name: since
        in: query
        description: Durable event seq cursor to replay from.
        schema:
          type: integer
          format: int64
      responses:
        '200':
          description: OK (text/event-stream)
          content:
            text/event-stream:
              schema:
                type: string
        '401':
          $ref: '#/components/responses/Unauthorized'
  /projects/{project}/runs/{id}/cancellations:
    post:
      operationId: cancelRun
      tags:
      - runs
      summary: Request cancellation of an in-flight run
      description: 'Sets the cancel_requested flag on the run. The next heartbeat

        response includes `directives.should_cancel: true`, and the

        worker is expected to drop the run cooperatively.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      responses:
        '204':
          description: No Content
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/runs/{id}/resumptions:
    post:
      operationId: resumeRun
      tags:
      - runs
      summary: Resume a suspended run
      description: Transitions the run from `suspended` back to `queued` so the next
        worker poll picks it up.
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      responses:
        '204':
          description: No Content
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/runs/{id}/signals:
    post:
      operationId: sendRunSignal
      tags:
      - runs
      summary: Deliver a signal to a suspended run
      description: 'Durably enqueues a signal keyed by (run_id, name). If the run

        is currently suspended waiting on that topic it is flipped

        back to queued so the next poll picks it up. Otherwise the

        signal sits in the store until a future suspended branch

        receives it.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SendRunSignalRequest'
      responses:
        '202':
          description: Accepted
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RunSignal'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/runs/{id}/events:
    get:
      operationId: streamRunEvents
      tags:
      - runs
      summary: Subscribe to a stream of events for a single run (SSE)
      description: 'Same envelope as `/projects/{project}/runs/events` but filtered
        to a single run.

        The server writes one seed `run_updated` frame on connection

        so reconnects do not miss the latest state, and supports

        `?since=<seq>` replay for durable events recorded since the

        given seq cursor.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      - name: since
        in: query
        description: Durable event seq cursor to replay from.
        schema:
          type: integer
          format: int64
      responses:
        '200':
          description: OK (text/event-stream)
          content:
            text/event-stream:
              schema:
                type: string
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/actions:
    get:
      operationId: listActions
      tags:
      - actions
      summary: List actions
      description: Returns project-owned actions only; use `/catalog` for all available
        actions including platform integrations.
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/CursorParam'
      - $ref: '#/components/parameters/LimitParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ActionListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
    post:
      operationId: createAction
      tags:
      - actions
      summary: Create an action
      description: 'Creates a project-scoped action. `name` is the stable identifier
        used

        in workflow step definitions and must be unique within the project.

        A signing secret is generated automatically and returned in the response;

        this is the only time the raw secret is exposed — store it securely.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateActionRequest'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Action'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '409':
          $ref: '#/components/responses/Conflict'
  /projects/{project}/actions/{actionName}:
    get:
      operationId: getAction
      tags:
      - actions
      summary: Get an action by name
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/ActionNameParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Action'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    patch:
      operationId: updateAction
      tags:
      - actions
      summary: Update an action
      description: 'Patches action metadata and schemas. All fields are optional;
        omitted

        fields are unchanged. Updating `annotations` replaces the entire

        annotations object — pass `null` to clear all annotation flags.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/ActionNameParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateActionRequest'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Action'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    delete:
      operationId: deleteAction
      tags:
      - actions
      summary: Delete an action
      description: 'Rejected with 409 if any workflow step currently references this
        action

        by name (`ErrActionInUse`). Remove all references before deleting.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/ActionNameParam'
      responses:
        '204':
          $ref: '#/components/responses/NoContent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
  /projects/{project}/actions/{actionName}/secret/rotate:
    post:
      operationId: rotateActionSecret
      tags:
      - actions
      summary: Rotate an action signing secret
      description: 'Generates a new HMAC-SHA256 signing secret for the action. The
        previous

        secret is retained as `previous_signing_secret` for a brief grace period

        (typically minutes) so in-flight requests signed with the old key are

        not immediately rejected. Store the returned secret — it cannot be

        retrieved again.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/ActionNameParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RotateSecretResult'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/action-audit-log:
    get:
      operationId: listActionAuditLog
      tags:
      - actions
      summary: List action invocation audit records
      description: 'Returns per-invocation records for all action executions in the
        project.

        Each record captures the action name, input parameters, output summary,

        final status, error details, and retry count. Filter by `run_id` to

        inspect all action calls within a single workflow run, or by

        `action_name` for cross-run analysis.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/CursorParam'
      - $ref: '#/components/parameters/LimitParam'
      - name: run_id
        in: query
        description: Filter to invocations from a specific workflow run.
        schema:
          type: string
      - name: action_name
        in: query
        description: Filter to invocations of a specific action.
        schema:
          type: string
      - name: status
        in: query
        description: Filter by terminal status (e.g. "success", "failed").
        schema:
          type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ActionAuditLogListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/actions/catalog:
    get:
      operationId: listCatalogActions
      tags:
      - actions
      summary: List the action catalog
      description: 'Returns the full catalog of actions available to this project:
        project-owned

        actions plus platform-provided integration actions (Slack, GitHub, etc.).

        The `available` flag indicates whether the action can currently be invoked
        —

        false if a required integration is not connected or the caller lacks

        permissions.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ActionCatalogListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /projects/{project}/actions/catalog/{actionName}:
    get:
      operationId: getCatalogAction
      tags:
      - actions
      summary: Get one catalog action by name
      description: Returns availability status, schemas, and metadata for a single
        catalog entry.
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/ActionNameParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ActionCatalogEntry'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/jobs/claim:
    post:
      operationId: claimJob
      tags:
      - jobs
      summary: Long-poll for the next claimable workflow job
      description: 'Atomically claims the next pending workflow job whose queue name
        is

        in the worker''s `queues` subscription and whose action is in the

        worker''s `actions` filter when provided. If no job is immediately

        available and `wait_seconds > 0`, the server holds the request open

        for up to `wait_seconds` (capped at 30). Returns 204 when the poll

        window closes empty.


        Each successful call also registers or refreshes the worker in the

        worker registry (used by `GET /projects/{project}/workers`), so no

        separate registration step is needed.


        The returned `JobClaim` includes the `heartbeat_interval_seconds`

        the worker should use for subsequent heartbeat calls.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/JobClaimRequest'
      responses:
        '200':
          description: Job claimed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JobClaim'
        '204':
          description: No jobs available within the poll window
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/jobs/{id}/heartbeat:
    post:
      operationId: heartbeatJob
      tags:
      - jobs
      summary: Refresh the lease on a claimed workflow job
      description: 'Extends the worker''s lease on the job and returns server directives.

        Must include the `worker_id` + `attempt` fence from the original

        claim — a stale fence (e.g., from a previous attempt) is rejected

        with 409.


        Returns a small JSON envelope rather than 204 so the server can

        attach directives (e.g., `should_cancel`) without an additional

        round trip. Workers should call this at the interval specified in

        `JobClaim.heartbeat_interval_seconds` (recommended: 30s).


        When `directives.should_cancel` is true, the run has received a

        cancellation request; the worker must stop processing and call

        `POST /jobs/{id}/complete` with `status: failed`.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/JobFenceRequest'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JobHeartbeat'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
  /projects/{project}/jobs/{id}/complete:
    post:
      operationId: completeJob
      tags:
      - jobs
      summary: Report terminal status for a claimed workflow job
      description: 'Marks the job as completed or failed and advances workflow

        progression. Must include the `worker_id` + `attempt` fence from

        the claim — a stale fence is rejected with 409.


        On `status: completed`, `result_b64` (if provided) is base64-

        decoded and stored as the job''s output bytes, which the workflow

        engine may pass as input to downstream steps.


        On `status: failed`, the workflow engine checks the step''s retry

        configuration. If `attempt < max_attempts`, a new job is created

        with `attempt + 1`; otherwise the run is transitioned to `failed`.

        Use `error_type` and `error_message` to distinguish retryable

        failures from permanent ones in observability tooling.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/JobCompleteRequest'
      responses:
        '204':
          description: No Content
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
  /projects/{project}/jobs/{id}/events:
    post:
      operationId: emitJobEvents
      tags:
      - jobs
      summary: Emit one or more custom events from a claimed workflow job
      description: 'Publishes a batch of custom run events on behalf of the worker

        holding the job''s current lease. Events are appended to the

        durable run event store (so they replay via `?since=<seq>`) and

        fanned out to any live SSE subscribers on the run.


        Authorization requires `mobius.job.emit_event`. Each event must

        present the active lease fence (`worker_id` + `attempt`); stale

        fences are rejected with 409.


        `type` is a caller-chosen identifier. The `mobius.` prefix is

        reserved for future server-emitted well-known kinds and is

        rejected with 400.


        Validation is atomic: if any event in the batch is invalid, the

        whole request is rejected and nothing is published. Successful

        batches return 204.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/JobEventsRequest'
      responses:
        '204':
          description: Events accepted
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '413':
          description: Payload Too Large
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: Too Many Requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /projects/{project}/jobs/{id}/interactions:
    post:
      operationId: createJobInteraction
      tags:
      - jobs
      summary: Create a human-in-the-loop interaction from a claimed workflow job
      description: 'Job-scoped form of interaction creation for the step-claim runtime.

        The server derives the owning run and project scope from the job,

        so workers do not need to pass `run_id` explicitly. Prefer this

        route over `POST /projects/{project}/interactions` from within a

        job context. The optional `topic` field overrides the server-

        derived signal topic; when omitted the server derives the topic

        from `step_name` or uses a default interaction topic.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateJobInteractionRequest'
      responses:
        '201':
          description: Interaction created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Interaction'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
  /projects/{project}/jobs/{id}/actions/{actionName}:
    post:
      operationId: runJobAction
      tags:
      - jobs
      summary: Execute one server-side action for a claimed workflow job
      description: 'Executes a named action in the context of the currently claimed
        job.

        The action must be registered in the project or catalog. The

        `dry_run` flag invokes the action without side effects when the

        action supports it. Results are returned synchronously; for long-

        running actions use `timeout_seconds` to extend the deadline.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      - $ref: '#/components/parameters/ActionNameParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RunActionRequest'
      responses:
        '200':
          description: Action executed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RunActionResult'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/triggers:
    get:
      operationId: listTriggers
      tags:
      - triggers
      summary: List triggers
      description: Returns all triggers for the project, optionally filtered by kind
        or enabled state.
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - name: kind
        in: query
        description: Filter by trigger kind.
        schema:
          $ref: '#/components/schemas/TriggerKind'
      - name: enabled
        in: query
        description: Filter to enabled or disabled triggers.
        schema:
          type: boolean
      - name: cursor
        in: query
        description: Opaque pagination cursor returned from the previous response.
        schema:
          type: string
      - name: limit
        in: query
        description: Maximum number of results to return per page.
        schema:
          type: integer
          minimum: 1
          maximum: 200
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TriggerListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    post:
      operationId: createTrigger
      tags:
      - triggers
      summary: Create a trigger
      description: 'Creates a trigger. For `schedule` triggers, `source_config.cron`
        is

        required. For `webhook` triggers, `webhook_handle` is required and

        must be unique within the project; the `receive_url` for posting events

        is returned in the response.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateTriggerRequest'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Trigger'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/triggers/{id}:
    get:
      operationId: getTrigger
      tags:
      - triggers
      summary: Get a trigger
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Trigger'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    patch:
      operationId: updateTrigger
      tags:
      - triggers
      summary: Update a trigger
      description: All fields are optional; omitted fields are unchanged.
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateTriggerRequest'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Trigger'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    delete:
      operationId: deleteTrigger
      tags:
      - triggers
      summary: Delete a trigger
      description: Hard-deletes the trigger and its fire history. In-flight runs started
        by this trigger are not affected.
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      responses:
        '204':
          description: No Content
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/triggers/{id}/fires:
    get:
      operationId: listTriggerFires
      tags:
      - triggers
      summary: List fire history for a trigger
      description: 'Returns a paginated history of trigger fires newest-first. Each
        entry

        records whether the fire succeeded, was skipped (e.g. by `forbid`

        concurrency policy), or failed, along with the resulting run ID.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      - name: status
        in: query
        description: Filter by fire outcome.
        schema:
          $ref: '#/components/schemas/TriggerFireStatus'
      - name: cursor
        in: query
        description: Opaque pagination cursor returned from the previous response.
        schema:
          type: string
      - name: limit
        in: query
        description: Maximum number of results to return per page.
        schema:
          type: integer
          minimum: 1
          maximum: 200
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TriggerFireListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/workers:
    get:
      operationId: listWorkers
      tags:
      - workers
      summary: List workers
      description: 'Returns workers that have polled for jobs within the project.
        Each

        worker''s `stale` flag is computed at read time: if `last_seen_at`

        is older than 2 minutes (or absent), the worker is considered stale.

        Stale workers are retained for display but will not receive new job

        claims.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkerListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects:
    get:
      operationId: listProjects
      tags:
      - projects
      summary: List projects
      description: Returns up to 100 projects. Use `search` for prefix-match filtering
        by name or handle.
      parameters:
      - name: search
        in: query
        description: Prefix-match filter applied to project name and handle.
        schema:
          type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProjectListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
    post:
      operationId: createProject
      tags:
      - projects
      summary: Create a project
      description: 'Creates a project within the authenticated org. If `handle` is
        omitted

        it is auto-derived from `name` (lowercased, spaces replaced with

        hyphens). Returns 409 if the handle already exists in the org.

        '
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateProjectRequest'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Project'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '409':
          $ref: '#/components/responses/Conflict'
  /projects/{id}:
    get:
      operationId: getProject
      tags:
      - projects
      summary: Get a project
      description: Requires the `project.read` permission for the project.
      parameters:
      - $ref: '#/components/parameters/IDParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Project'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    patch:
      operationId: updateProject
      tags:
      - projects
      summary: Update a project
      description: 'Updates `name` and/or `description`. The project handle is immutable

        and cannot be changed after creation.

        '
      parameters:
      - $ref: '#/components/parameters/IDParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateProjectRequest'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Project'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    delete:
      operationId: deleteProject
      tags:
      - projects
      summary: Delete a project
      description: 'Permanently deletes the project and all child resources (workflows,
        runs,

        jobs, triggers, webhooks, groups, interactions, actions, agents, service

        accounts). This operation is irreversible.

        '
      parameters:
      - $ref: '#/components/parameters/IDParam'
      responses:
        '204':
          description: No Content
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/webhooks:
    get:
      operationId: listWebhooks
      tags:
      - webhooks
      summary: List webhooks
      description: Returns all outgoing webhook subscriptions for the project.
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - name: enabled
        in: query
        schema:
          type: boolean
        description: Filter by enabled/disabled state.
      - name: cursor
        in: query
        description: Opaque pagination cursor returned from the previous response.
        schema:
          type: string
      - name: limit
        in: query
        description: Maximum number of results to return per page.
        schema:
          type: integer
          minimum: 1
          maximum: 200
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    post:
      operationId: createWebhook
      tags:
      - webhooks
      summary: Create a webhook
      description: 'Creates a new outgoing webhook subscription. Webhook names must
        be

        unique within the project. Returns 409 if the name already exists.


        The signing `secret` (if provided) is stored in plaintext — treat

        it as a shared secret and rotate it via `PATCH` if compromised.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateWebhookRequest'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Webhook'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
  /projects/{project}/webhooks/{id}:
    get:
      operationId: getWebhook
      tags:
      - webhooks
      summary: Get a webhook
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Webhook'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    patch:
      operationId: updateWebhook
      tags:
      - webhooks
      summary: Update a webhook
      description: 'Updates the webhook URL, event subscriptions, enabled state, or

        signing secret. Setting `secret` to an empty string clears the

        current secret and disables signing. Omitting `secret` leaves the

        current value unchanged.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateWebhookRequest'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Webhook'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    delete:
      operationId: deleteWebhook
      tags:
      - webhooks
      summary: Delete a webhook
      description: Deletes the webhook and its delivery history.
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      responses:
        '204':
          description: No Content
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/webhooks/{id}/deliveries:
    get:
      operationId: listWebhookDeliveries
      tags:
      - webhooks
      summary: List webhook deliveries
      description: 'Lists the delivery history for a webhook, newest first. Each entry

        records the event type, current status, attempt count, and any last

        error message. Deliveries are retried up to 10 times (5xx, 408,

        429 are retryable; other 4xx are not). A delivery transitions to

        `failed` only after exhausting all retry attempts.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      - name: cursor
        in: query
        description: Opaque pagination cursor returned from the previous response.
        schema:
          type: string
      - name: limit
        in: query
        description: Maximum number of results to return per page.
        schema:
          type: integer
          minimum: 1
          maximum: 200
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookDeliveryListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/integrations:
    get:
      operationId: listIntegrations
      tags:
      - integrations
      summary: List integrations
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - name: provider
        in: query
        schema:
          type: string
        description: Filter by provider string (exact match).
      - name: status
        in: query
        schema:
          $ref: '#/components/schemas/IntegrationStatus'
        description: Filter by integration status.
      - name: cursor
        in: query
        description: Opaque pagination cursor returned from the previous response.
        schema:
          type: string
      - name: limit
        in: query
        description: Maximum number of results to return per page.
        schema:
          type: integer
          minimum: 1
          maximum: 200
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IntegrationListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
    post:
      operationId: createIntegration
      tags:
      - integrations
      summary: Create an integration
      description: 'Creates a new integration record. The `provider` + `name` pair
        must

        be unique within the project. Returns 400 if validation fails (e.g.,

        missing required fields).

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateIntegrationRequest'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Integration'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /projects/{project}/integrations/{id}:
    get:
      operationId: getIntegration
      tags:
      - integrations
      summary: Get an integration
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Integration'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    put:
      operationId: updateIntegration
      tags:
      - integrations
      summary: Update an integration
      description: 'Replaces the integration''s `name`, `config`, and/or `status`.
        Use

        `status: inactive` to disable an integration without deleting it.

        Use `status: active` to re-enable. The `provider` field is

        immutable after creation.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateIntegrationRequest'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Integration'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    delete:
      operationId: deleteIntegration
      tags:
      - integrations
      summary: Delete an integration
      description: Hard-deletes the integration record and its stored config.
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      responses:
        '204':
          description: No Content
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/integrations/copy:
    post:
      operationId: copyIntegration
      tags:
      - integrations
      summary: Copy an integration from another project
      description: 'Clones an integration from another project within the same org
        into

        this project. The full `config` blob is copied as-is. The source

        and destination projects must both belong to the same org.


        The `(provider, name)` pair must be unique in the destination project;

        supply a different `name` to avoid conflicts with an existing

        integration of the same provider and name.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CopyIntegrationRequest'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Integration'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/metrics:
    get:
      operationId: getProjectMetrics
      tags:
      - metrics
      summary: Get operational metrics for a project
      description: 'Returns a snapshot of current execution health for the project.

        All rate and duration metrics are computed over a rolling window

        (default: 60 minutes). P95 step duration is computed from the

        40 most recent completed jobs.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProjectMetrics'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /roles:
    get:
      operationId: listRoles
      tags:
      - roles
      summary: List roles
      description: Returns system-defined roles plus custom roles for the org. Use
        `project_id` to narrow results to project-scoped roles.
      parameters:
      - name: limit
        in: query
        description: Maximum number of results to return per page.
        schema:
          type: integer
          minimum: 1
          maximum: 200
      - name: project_id
        in: query
        description: Filter to roles scoped to a specific project.
        schema:
          type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RoleListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
    post:
      operationId: createRole
      tags:
      - roles
      summary: Create a role
      description: 'Creates a custom role for the org. Supply `project_id` to scope
        the

        role to a specific project. Roles with an empty `project_id` are

        org-wide and can be assigned across all projects.

        '
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateRoleRequest'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Role'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '409':
          $ref: '#/components/responses/Conflict'
  /roles/{id}:
    get:
      operationId: getRole
      tags:
      - roles
      summary: Get a role
      parameters:
      - $ref: '#/components/parameters/IDParam'
      - name: project_id
        in: query
        description: Provide to resolve a project-scoped role.
        schema:
          type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Role'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
    patch:
      operationId: updateRole
      tags:
      - roles
      summary: Update a role
      description: 'Updates name, description, or permissions of a custom role. System-defined

        roles (system_defined=true) cannot be updated and return 403.

        '
      parameters:
      - $ref: '#/components/parameters/IDParam'
      - name: project_id
        in: query
        description: Scope to change this role to. Cannot change an org-scoped role
          to project-scoped after creation.
        schema:
          type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateRoleRequest'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Role'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
    delete:
      operationId: deleteRole
      tags:
      - roles
      summary: Delete a role
      description: Hard-deletes the role and all its assignments. System-defined roles
        cannot be deleted.
      parameters:
      - $ref: '#/components/parameters/IDParam'
      - name: project_id
        in: query
        description: Scope to change this role to. Cannot change an org-scoped role
          to project-scoped after creation.
        schema:
          type: string
      responses:
        '204':
          description: No Content
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
  /role-assignments:
    get:
      operationId: listRoleAssignments
      tags:
      - roles
      summary: List role assignments
      description: Returns assignments optionally filtered by actor, role, or project
        scope.
      parameters:
      - name: actor_type
        in: query
        description: Filter by the type of actor receiving the assignment.
        schema:
          type: string
          enum:
          - user
          - service_account
      - name: actor_id
        in: query
        description: Filter to assignments for a specific actor.
        schema:
          type: string
      - name: role_id
        in: query
        description: Filter to assignments for a specific role.
        schema:
          type: string
      - name: project_id
        in: query
        description: Filter to project-scoped assignments for this project.
        schema:
          type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RoleAssignmentListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
    post:
      operationId: createRoleAssignment
      tags:
      - roles
      summary: Assign a role to an actor
      description: 'Binds a role to a user or service account. Supply `project_id`
        to create

        a project-scoped assignment; omit it for an org-wide assignment.

        The assignment records the creating actor in `granted_by_actor_type` /

        `granted_by_actor_id` for audit purposes.

        '
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateRoleAssignmentRequest'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RoleAssignment'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
  /role-assignments/{id}:
    delete:
      operationId: deleteRoleAssignment
      tags:
      - roles
      summary: Remove a role assignment
      parameters:
      - $ref: '#/components/parameters/IDParam'
      responses:
        '204':
          description: No Content
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/interactions:
    post:
      operationId: createInteraction
      tags:
      - interactions
      summary: Create an interaction
      description: 'Creates a standalone or run-backed interaction. When `run_id`
        is

        provided, `topic` is also required and completing the interaction

        automatically delivers a signal that resumes the suspended run.

        Omit both for a standalone interaction that completes with no

        workflow side effect. Workers creating interactions from within a

        job should use the job-scoped route (`POST /jobs/{id}/interactions`)

        instead, which derives the run and topic automatically.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateInteractionRequest'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Interaction'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    get:
      operationId: listInteractions
      tags:
      - interactions
      summary: List interactions
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - name: status
        in: query
        schema:
          type: string
          enum:
          - pending
          - completed
          - expired
        description: Filter by status
      - name: run_id
        in: query
        schema:
          type: string
        description: Filter by originating run ID
      - name: target_actor_type
        in: query
        schema:
          type: string
          enum:
          - member
          - agent
          - group
        description: Filter by target actor type
      - name: target_actor_id
        in: query
        schema:
          type: string
        description: Filter by target actor ID
      - name: inbox
        in: query
        schema:
          type: boolean
        description: When true, returns only interactions visible to the authenticated
          user (direct + group membership)
      - $ref: '#/components/parameters/CursorParam'
      - $ref: '#/components/parameters/LimitParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InteractionListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /projects/{project}/interactions/{id}:
    get:
      operationId: getInteraction
      tags:
      - interactions
      summary: Get an interaction
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Interaction'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/interactions/{id}/respond:
    post:
      operationId: respondToInteraction
      tags:
      - interactions
      summary: Submit a response to an interaction
      description: 'Canonical interaction response endpoint for both human responders
        and

        agent workers. When the authenticated request is not associated with a

        member user and the interaction targets an agent queue, the server

        attributes the response to that target agent automatically.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RespondToInteractionRequest'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Interaction'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
  /projects/{project}/interactions/{id}/claim:
    post:
      operationId: claimInteraction
      tags:
      - interactions
      summary: Claim a pending first-responder group interaction
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Interaction'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/interactions/{id}/release:
    post:
      operationId: releaseInteraction
      tags:
      - interactions
      summary: Release a claimed first-responder group interaction
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Interaction'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/groups:
    post:
      operationId: createGroup
      tags:
      - groups
      summary: Create a group
      description: 'Creates a group within the project. The `handle` is auto-derived
        from

        `name` if omitted. Returns 409 if the handle already exists in the project.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateGroupRequest'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Group'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '409':
          $ref: '#/components/responses/Conflict'
    get:
      operationId: listGroups
      tags:
      - groups
      summary: List groups
      description: Returns groups with live member counts (queried separately from
        the group record).
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/CursorParam'
      - $ref: '#/components/parameters/LimitParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GroupWithCountListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /projects/{project}/groups/{groupId}:
    get:
      operationId: getGroup
      tags:
      - groups
      summary: Get a group
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/GroupIDParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GroupWithCount'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    patch:
      operationId: updateGroup
      tags:
      - groups
      summary: Update a group
      description: 'Updates name, description, or routing policy. Handle is immutable
        after

        creation. Changing `routing_policy` only affects future interactions —

        in-flight interactions retain the policy that was snapshotted at creation.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/GroupIDParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateGroupRequest'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Group'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    delete:
      operationId: deleteGroup
      tags:
      - groups
      summary: Delete a group
      description: 'Rejected with 400 if any pending interaction currently targets
        this

        group. Resolve or expire those interactions before deleting.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/GroupIDParam'
      responses:
        '204':
          description: No Content
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/groups/{groupId}/members:
    get:
      operationId: listGroupMembers
      tags:
      - groups
      summary: List members of a group
      description: Returns the current live membership, which may differ from membership
        snapshots in existing interactions.
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/GroupIDParam'
      - $ref: '#/components/parameters/CursorParam'
      - $ref: '#/components/parameters/LimitParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GroupMemberListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    post:
      operationId: addGroupMember
      tags:
      - groups
      summary: Add a member to a group
      description: The user must be an org member. Returns 409 if already a member.
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/GroupIDParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AddGroupMemberRequest'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GroupMember'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
  /projects/{project}/groups/{groupId}/members/{userId}:
    delete:
      operationId: removeGroupMember
      tags:
      - groups
      summary: Remove a member from a group
      description: Does not affect the member snapshot in existing interactions.
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/GroupIDParam'
      - name: userId
        in: path
        required: true
        description: User ID of the member to remove.
        schema:
          type: string
      responses:
        '204':
          description: No Content
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/members/{userId}/groups:
    get:
      operationId: listMemberGroups
      tags:
      - groups
      summary: List groups a member belongs to
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - name: userId
        in: path
        required: true
        description: User ID of the org member.
        schema:
          type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GroupListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /projects/{project}/agents:
    post:
      operationId: createAgent
      tags:
      - agents
      summary: Create an agent
      description: 'Creates an agent bound to `service_account_id`. A service account
        can

        back multiple agents, but each agent belongs to exactly one service

        account for the lifetime of the agent.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateAgentRequest'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Agent'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
    get:
      operationId: listAgents
      tags:
      - agents
      summary: List agents
      description: Returns agents with computed presence. Filter by service_account_id
        to find all agents owned by a specific identity.
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - name: service_account_id
        in: query
        description: Filter to agents backed by this service account.
        schema:
          type: string
      - name: status
        in: query
        description: Filter by administrative status (active/inactive), independent
          of presence.
        schema:
          $ref: '#/components/schemas/AgentStatus'
      - $ref: '#/components/parameters/LimitParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AgentListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/agents/{id}:
    get:
      operationId: getAgent
      tags:
      - agents
      summary: Get an agent
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Agent'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    patch:
      operationId: updateAgent
      tags:
      - agents
      summary: Update an agent
      description: 'Updates mutable agent fields. The backing `service_account_id`
        cannot

        be changed after creation. Setting `status` to `inactive` prevents

        the agent from claiming new jobs but does not terminate active sessions.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateAgentRequest'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Agent'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    delete:
      operationId: deleteAgent
      tags:
      - agents
      summary: Delete an agent
      description: Hard-deletes the agent and all associated sessions. In-flight jobs
        claiming this agent are not automatically cancelled.
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      responses:
        '204':
          description: No Content
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/agents/{id}/sessions:
    post:
      operationId: createAgentSession
      tags:
      - agents
      summary: Register a new agent session
      description: 'Called by a worker at startup to register a live connection. `transport`

        identifies the connection mechanism (e.g. "sse", "polling"). The session

        transitions to `connected` and should be kept alive via heartbeats.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateAgentSessionRequest'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AgentSession'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    get:
      operationId: listAgentSessions
      tags:
      - agents
      summary: List sessions for an agent
      description: 'Returns sessions newest-first. The agent''s `presence` is derived
        from

        the most recent 20 sessions across all transports: `online` if any

        connected session has a fresh heartbeat, `stale` if heartbeats are

        overdue, `offline` otherwise.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - $ref: '#/components/parameters/IDParam'
      - name: status
        in: query
        description: Filter by session status.
        schema:
          $ref: '#/components/schemas/AgentSessionStatus'
      - name: transport
        in: query
        description: Filter by transport type (e.g. "sse", "polling").
        schema:
          type: string
      - $ref: '#/components/parameters/LimitParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AgentSessionListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/agents/sessions/{sessionId}:
    get:
      operationId: getAgentSession
      tags:
      - agents
      summary: Get an agent session
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - name: sessionId
        in: path
        required: true
        description: ID of the agent session.
        schema:
          type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AgentSession'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/agents/sessions/{sessionId}/heartbeat:
    post:
      operationId: heartbeatAgentSession
      tags:
      - agents
      summary: Refresh an agent session heartbeat
      description: 'Updates `last_seen_at` on the session and keeps the agent''s computed

        presence as `online`. Workers should call this at a regular interval

        (typically every 30s). Sessions that miss heartbeats become `stale`.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - name: sessionId
        in: path
        required: true
        description: ID of the agent session.
        schema:
          type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AgentSession'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/agents/sessions/{sessionId}/disconnect:
    post:
      operationId: disconnectAgentSession
      tags:
      - agents
      summary: Mark an agent session as disconnected
      description: 'Explicitly closes a session, setting status to `disconnected`
        and

        recording `disconnected_at`. Prefer this over letting sessions go stale

        on graceful shutdown.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - name: sessionId
        in: path
        required: true
        description: ID of the agent session.
        schema:
          type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AgentSession'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/tools:
    get:
      operationId: listTools
      tags:
      - tools
      summary: List workflow tools
      description: 'Returns all workflow definitions that have been published as tools

        for the project. Each entry includes the tool name, description, and

        JSON Schema for the input — compatible with the Anthropic and OpenAI

        tool use APIs.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolDefinitionListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/tools/{handle}/runs:
    post:
      operationId: runTool
      tags:
      - tools
      summary: Invoke a workflow tool
      description: 'Starts a workflow run for the named tool (workflow handle) and
        waits

        for it to complete up to `timeout_seconds` (default 30s, max 120s).

        Returns the run output directly when the workflow completes within

        the timeout. On timeout the response includes the run ID and

        `status: pending` so the caller can switch to polling via

        `GET /projects/{project}/tools/{handle}/runs/{run_id}`.

        '
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - name: handle
        in: path
        required: true
        description: Workflow handle identifying the tool to invoke.
        schema:
          type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ToolRunRequest'
      responses:
        '200':
          description: OK — run completed synchronously
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolRun'
        '202':
          description: Accepted — run is pending; poll for result
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolRun'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /projects/{project}/tools/{handle}/runs/{runId}:
    get:
      operationId: getToolRun
      tags:
      - tools
      summary: Get an async tool run result
      parameters:
      - $ref: '#/components/parameters/ProjectHandleParam'
      - name: handle
        in: path
        required: true
        description: Workflow handle identifying the tool.
        schema:
          type: string
      - name: runId
        in: path
        required: true
        description: ID of the tool run to poll.
        schema:
          type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolRun'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: API key passed as Bearer token
  parameters:
    ProjectHandleParam:
      name: project
      in: path
      required: true
      schema:
        type: string
      description: Project handle (unique per organization)
    IDParam:
      name: id
      in: path
      required: true
      description: Resource ID.
      schema:
        type: string
    ActionNameParam:
      name: actionName
      in: path
      required: true
      schema:
        type: string
    CursorParam:
      name: cursor
      in: query
      description: Cursor for pagination (opaque string from previous response)
      schema:
        type: string
    LimitParam:
      name: limit
      in: query
      description: Maximum number of items to return
      schema:
        type: integer
        default: 50
        minimum: 1
        maximum: 200
    GroupIDParam:
      name: groupId
      in: path
      required: true
      description: Group ID or handle.
      schema:
        type: string
  responses:
    BadRequest:
      description: Bad Request
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Unauthorized:
      description: Unauthorized
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    NotFound:
      description: Not Found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Conflict:
      description: Conflict
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    ServiceUnavailable:
      description: Service Unavailable
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Forbidden:
      description: Forbidden
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    NoContent:
      description: No Content
  schemas:
    ErrorResponse:
      type: object
      required:
      - error
      properties:
        error:
          type: object
          description: Error detail.
          required:
          - code
          - message
          properties:
            code:
              type: string
              description: Machine-readable error code
            message:
              type: string
              description: Human-readable error message
    HealthResponse:
      type: object
      required:
      - status
      properties:
        status:
          type: string
          description: Current server status. `ok` when all dependencies are reachable.
    Metadata:
      type: object
      additionalProperties: true
    ChannelMessageSenderType:
      type: string
      enum:
      - member
      - agent
      description: Whether the message was sent by a human org member or an agent
        worker.
    Channel:
      type: object
      required:
      - id
      - name
      - display_name
      - kind
      - private
      - created_by
      - created_at
      - updated_at
      properties:
        id:
          type: string
          description: Unique identifier for this channel.
        name:
          type: string
          description: 'URL-safe channel handle, unique within the project. Immutable

            after creation.

            '
        display_name:
          type: string
          description: Human-facing display name shown in the UI.
        topic:
          type: string
          description: Optional topic or description shown at the top of the channel.
        kind:
          type: string
          enum:
          - dm
          - channel
          description: '`channel` — persistent named room.

            `dm` — direct-message thread, typically between a small fixed set of participants.

            '
        private:
          type: boolean
          description: When true, the channel is invite-only and not visible in public
            listings.
        created_by:
          type: string
          description: User ID of the org member who created the channel.
        archived_at:
          type: string
          format: date-time
          nullable: true
          description: 'Set when the channel is archived. Archived channels are hidden
            in

            the UI but their message history remains accessible.

            '
        created_at:
          type: string
          format: date-time
          description: Timestamp when this channel was created.
        updated_at:
          type: string
          format: date-time
          description: Timestamp when this channel was last updated.
    ChannelListResponse:
      type: object
      required:
      - items
      properties:
        items:
          type: array
          description: The list of results for this page.
          items:
            $ref: '#/components/schemas/Channel'
        has_more:
          type: boolean
          description: Whether additional pages are available.
        next_cursor:
          type: string
          description: Opaque cursor to pass as `cursor` on the next request. Absent
            when `has_more` is false.
    ChannelMember:
      type: object
      required:
      - id
      - channel_id
      - user_id
      - role
      - joined_at
      properties:
        id:
          type: string
          description: Unique identifier for this membership record.
        channel_id:
          type: string
          description: ID of the channel this membership belongs to.
        user_id:
          type: string
          description: ID of the user or agent who is a member.
        role:
          type: string
          enum:
          - member
          - admin
          description: '`admin` — can update channel settings and manage members.

            `member` — can post messages and view history.

            Creators are automatically assigned `admin`.

            '
        last_read_message_id:
          type: string
          nullable: true
          description: ID of the last message this member has read (used for unread
            badge counts).
        muted:
          type: boolean
          description: When true, notifications for this channel are suppressed for
            this member.
        starred:
          type: boolean
          description: Whether this member has starred the channel for quick access.
        joined_at:
          type: string
          format: date-time
          description: Timestamp when this member joined the channel.
    ChannelMemberListResponse:
      type: object
      required:
      - items
      properties:
        items:
          type: array
          description: The list of results for this page.
          items:
            $ref: '#/components/schemas/ChannelMember'
        has_more:
          type: boolean
          description: Whether additional pages are available.
        next_cursor:
          type: string
          description: Opaque cursor to pass as `cursor` on the next request. Absent
            when `has_more` is false.
    ChannelMessage:
      type: object
      required:
      - id
      - channel_id
      - sender_type
      - sender_id
      - type
      - content
      - created_at
      properties:
        id:
          type: string
          description: Unique identifier for this message.
        channel_id:
          type: string
          description: ID of the channel this message was posted in.
        sender_type:
          $ref: '#/components/schemas/ChannelMessageSenderType'
        sender_id:
          type: string
          description: User ID (for `member`) or agent ID (for `agent`) of the message
            sender.
        sender_session_id:
          type: string
          nullable: true
          description: Live agent session that posted the message, when applicable.
        display:
          type: string
          enum:
          - message
          - notice
          - card
          description: 'Rendering hint for the UI.

            `message` — standard chat bubble.

            `notice` — system/informational notice (no attribution).

            `card` — structured card layout.

            '
        type:
          type: string
          description: 'Dot-namespaced message type identifier, e.g. `user.message`,

            `ai.response`. Used for filtering and display logic.

            '
        content:
          type: string
          description: Message body in Markdown.
        reply_to:
          type: string
          nullable: true
          description: ID of the parent message this reply belongs to (threading).
        metadata:
          $ref: '#/components/schemas/Metadata'
        pinned:
          type: boolean
          description: Whether this message is pinned in the channel.
        pinned_by:
          type: string
          nullable: true
          description: User ID of the member who pinned this message.
        edited_at:
          type: string
          format: date-time
          nullable: true
          description: Set when the message content has been updated after initial
            send.
        created_at:
          type: string
          format: date-time
          description: Timestamp when this message was posted.
    ChannelMessageListResponse:
      type: object
      required:
      - items
      properties:
        items:
          type: array
          description: The list of results for this page.
          items:
            $ref: '#/components/schemas/ChannelMessage'
        has_more:
          type: boolean
          description: Whether additional pages are available.
        next_cursor:
          type: string
          description: Opaque cursor to pass as `cursor` on the next request. Absent
            when `has_more` is false.
    CreateChannelRequest:
      type: object
      required:
      - name
      - display_name
      - kind
      properties:
        name:
          type: string
          description: 'URL-safe handle, unique within the project. Immutable after

            creation — choose carefully.

            '
        display_name:
          type: string
          description: Human-facing display name shown in the UI.
        topic:
          type: string
          description: Optional channel topic or description.
        kind:
          type: string
          enum:
          - dm
          - channel
          description: Channel kind. Cannot be changed after creation.
        private:
          type: boolean
          default: false
          description: When true, the channel is invite-only.
        member_ids:
          type: array
          items:
            type: string
          description: 'Optional list of user or agent IDs to add as members at creation

            time. All receive the `member` role; the creator is added as

            `admin` separately.

            '
    UpdateChannelRequest:
      type: object
      properties:
        display_name:
          type: string
          description: Updated display name.
        topic:
          type: string
          description: Updated topic or description.
        private:
          type: boolean
          description: Toggle invite-only visibility.
    AddChannelMemberRequest:
      type: object
      required:
      - user_id
      properties:
        user_id:
          type: string
          description: User or agent ID to add to the channel.
        role:
          type: string
          enum:
          - member
          - admin
          default: member
          description: Role to assign the new member.
    SendChannelMessageRequest:
      type: object
      required:
      - content
      properties:
        sender_agent_id:
          type: string
          description: 'Durable agent identity to attribute the message to. When set,

            `sender_type` on the resulting message is `agent`.

            '
        sender_session_id:
          type: string
          description: Live agent session to associate with the message.
        content:
          type: string
          description: Message body in Markdown.
        display:
          type: string
          enum:
          - message
          - notice
          - card
          default: message
          description: Rendering hint for the UI.
        type:
          type: string
          default: user.message
          description: Dot-namespaced message type identifier.
        reply_to:
          type: string
          description: Parent message ID for threading (creates a reply).
        metadata:
          $ref: '#/components/schemas/Metadata'
    UpdateChannelMessageRequest:
      type: object
      properties:
        content:
          type: string
          description: Updated Markdown content. Sets `edited_at` on the message.
        metadata:
          $ref: '#/components/schemas/Metadata'
        pinned:
          type: boolean
          description: Pin or unpin the message. Sets/clears `pinned_by`.
    AuditLogEntry:
      type: object
      required:
      - id
      - action
      - resource_type
      - resource_id
      - created_at
      properties:
        id:
          type: string
          description: Unique audit log entry ID
        user_id:
          type: string
          description: ID of the user who performed the action, when a human user
            is attributable
        project_id:
          type: string
          description: Project ID when the audited resource is project-scoped
        actor_type:
          type: string
          description: Durable actor type that performed the action
        actor_id:
          type: string
          description: Durable actor ID that performed the action
        credential_id:
          type: string
          description: Credential ID used for the request, when applicable
        action:
          type: string
          enum:
          - create
          - update
          - delete
          description: Type of action performed
        resource_type:
          type: string
          description: Type of resource affected (e.g., job, channel, document)
        resource_id:
          type: string
          description: ID of the affected resource
        resource_name:
          type: string
          description: Human-readable name of the affected resource
        changes:
          type: object
          additionalProperties: true
          description: Object containing before/after changes for update actions
        ip_address:
          type: string
          description: IP address of the request
        user_agent:
          type: string
          description: User agent of the request
        created_at:
          type: string
          format: date-time
          description: Timestamp when the action was performed
    AuditLogListResponse:
      type: object
      required:
      - data
      - has_more
      properties:
        items:
          type: array
          description: The list of results for this page.
          items:
            $ref: '#/components/schemas/AuditLogEntry'
        next_cursor:
          type: string
          description: Cursor for fetching next page of results
        has_more:
          type: boolean
          description: Whether more results are available
    APIKey:
      type: object
      required:
      - id
      - name
      - key_prefix
      - scope
      - created_at
      - updated_at
      properties:
        id:
          type: string
          description: Unique identifier for this API key.
        name:
          type: string
          description: Human-readable label, unique within the org (or org+project
            for project-pinned keys).
        key_prefix:
          type: string
          description: First 8 characters of the key, used to identify it without
            exposing the secret.
        scope:
          type: string
          enum:
          - org
          - system
          description: '`org` for standard API keys; `system` is reserved for platform-level
            access.'
        permissions:
          type: array
          items:
            type: string
          description: Explicit permission set granted to this key (e.g. "mobius.job.claim").
        project_id:
          type: string
          description: Set for project-pinned keys; empty for org-scoped keys.
        service_account_id:
          type: string
          description: Optional service account for attribution and quota tracking.
        expires_at:
          type: string
          format: date-time
          description: Hard expiry timestamp. Requests using an expired key receive
            401.
        last_used_at:
          type: string
          format: date-time
          description: Timestamp of the most recent authenticated request using this
            key.
        created_at:
          type: string
          format: date-time
          description: Timestamp when this key was created.
        updated_at:
          type: string
          format: date-time
          description: Timestamp when this key was last updated.
    APIKeyCreateResult:
      type: object
      required:
      - id
      - name
      - key_prefix
      - scope
      - created_at
      - updated_at
      - key
      description: Returned only on key creation. Contains the raw `key` value which
        is not retrievable after this response.
      properties:
        id:
          type: string
          description: Unique identifier for the created API key.
        name:
          type: string
          description: Human-readable name for the key.
        key_prefix:
          type: string
          description: First 8 characters of the key for identification.
        scope:
          type: string
          enum:
          - org
          - system
          description: 'Scope of the key: `org` for org-wide keys, `project` for project-pinned
            keys.'
        permissions:
          type: array
          items:
            type: string
          description: List of permissions granted to this key.
        project_id:
          type: string
          description: ID of the pinned project. Null for org-scoped keys.
        service_account_id:
          type: string
          description: ID of the service account this key belongs to.
        expires_at:
          type: string
          format: date-time
          description: Timestamp when this key expires. Null if it does not expire.
        last_used_at:
          type: string
          format: date-time
          description: Timestamp of the most recent authenticated request using this
            key.
        created_at:
          type: string
          format: date-time
          description: Timestamp when this key was created.
        updated_at:
          type: string
          format: date-time
          description: Timestamp when this key was last updated.
        key:
          type: string
          description: The raw API key. Returned only once at creation — store it
            securely immediately.
    APIKeyListResponse:
      type: object
      required:
      - items
      properties:
        items:
          type: array
          description: The list of results for this page.
          items:
            $ref: '#/components/schemas/APIKey'
    CreateAPIKeyRequest:
      type: object
      required:
      - name
      properties:
        name:
          type: string
          description: Human-readable label, unique within the org (or project for
            project-pinned keys).
        scope:
          type: string
          enum:
          - org
          - system
          default: org
          description: Key scope. Use `org` for standard API access.
        permissions:
          type: array
          items:
            type: string
          description: 'Permissions to grant. Each permission must be held by the
            creating

            caller — you cannot grant more than you have.

            '
        service_account_id:
          type: string
          description: Associate this key with a service account for attribution.
        expires_at:
          type: string
          format: date-time
          description: Optional hard expiry. Omit for a non-expiring key.
    AuthContext:
      type: object
      required:
      - user_id
      - auth_type
      - is_admin
      properties:
        user_id:
          type: string
          description: Resolved user ID for this request (may be a service account
            ID for API-key auth).
        org_id:
          type: string
          description: Org ID resolved from the authentication credential.
        role:
          type: string
          description: Org member role (owner, admin, member) — empty for API-key
            auth.
        auth_type:
          type: string
          description: 'How the caller authenticated: `clerk` (browser JWT), `api_key`,
            or `cli_token`.'
        is_admin:
          type: boolean
          description: True for Mobius platform admins only; not an org-level flag.
    ConfirmDeviceCodeRequest:
      type: object
      required:
      - user_code
      properties:
        user_code:
          type: string
          description: The user code displayed in the CLI during the device authorization
            flow.
        label:
          type: string
          description: Optional label to identify this credential in the CLI credentials
            list.
    ConfirmDeviceCodeResult:
      type: object
      required:
      - confirmed
      properties:
        confirmed:
          type: boolean
          description: True when the device code was successfully confirmed and a
            CLI credential has been issued.
    CLICredentialStatus:
      type: string
      enum:
      - active
      - revoked
    CLICredential:
      type: object
      required:
      - id
      - org_id
      - user_id
      - label
      - token_prefix
      - status
      - created_at
      - updated_at
      properties:
        id:
          type: string
          description: Unique identifier for this credential.
        org_id:
          type: string
          description: ID of the organization this credential is scoped to.
        user_id:
          type: string
          description: ID of the user who authorized this credential.
        label:
          type: string
          description: Human-readable label identifying this credential.
        token_prefix:
          type: string
          description: First few characters of the token, shown for identification
            without exposing the secret.
        status:
          $ref: '#/components/schemas/CLICredentialStatus'
        created_at:
          type: string
          format: date-time
          description: Timestamp when this credential was created.
        updated_at:
          type: string
          format: date-time
          description: Timestamp when this credential was last updated.
        last_used_at:
          type: string
          format: date-time
          description: Timestamp of the most recent authenticated request using this
            credential.
        expires_at:
          type: string
          format: date-time
          description: Timestamp when this credential expires. Null if it does not
            expire.
    CLICredentialListResponse:
      type: object
      required:
      - items
      properties:
        items:
          type: array
          description: The list of credentials issued to the current user.
          items:
            $ref: '#/components/schemas/CLICredential'
    WorkflowSpec:
      type: object
      required:
      - name
      - steps
      description: 'Workflow definition shaped like `workflow.Options`.


        Authoring rule: `action` is the canonical field for executable steps.

        When `action_kind` is omitted, `action` uses worker/job semantics.

        Use `action_kind: "server"` for Mobius-managed server actions such as

        platform integrations or custom HTTP-backed actions.

        '
      additionalProperties: false
      properties:
        name:
          type: string
          description: Workflow name.
        description:
          type: string
          description: Optional description of the workflow's purpose.
        start_at:
          type: string
          description: Step name to start execution from. Defaults to the first step.
        inputs:
          type: array
          description: Declared input parameters accepted by this workflow.
          items:
            $ref: '#/components/schemas/WorkflowInput'
        outputs:
          type: array
          description: Declared output values produced by this workflow.
          items:
            $ref: '#/components/schemas/WorkflowOutput'
        state:
          type: object
          additionalProperties: true
          description: Initial workflow state.
        steps:
          type: array
          description: Ordered list of steps that make up this workflow.
          items:
            $ref: '#/components/schemas/WorkflowStep'
    WorkflowInput:
      type: object
      required:
      - name
      - type
      additionalProperties: false
      properties:
        name:
          type: string
          description: Input parameter name referenced in step expressions.
        type:
          type: string
          description: Data type of the input (e.g. string, integer, boolean, object).
        description:
          type: string
          description: Human-readable description of this input parameter.
        default:
          description: Optional default value.
    WorkflowOutput:
      type: object
      required:
      - name
      - variable
      additionalProperties: false
      properties:
        name:
          type: string
          description: Output name exposed to callers and downstream steps.
        variable:
          type: string
          description: State variable name whose value is mapped to this output.
        branch:
          type: string
          description: Defaults to `main` when omitted.
        description:
          type: string
          description: Human-readable description of this output value.
    WorkflowStep:
      description: 'A workflow step. Exactly one step shape should be used.

        '
      oneOf:
      - $ref: '#/components/schemas/WorkflowExecutableStep'
      - $ref: '#/components/schemas/WorkflowJoinStep'
      - $ref: '#/components/schemas/WorkflowWaitSignalStep'
      - $ref: '#/components/schemas/WorkflowSleepStep'
      - $ref: '#/components/schemas/WorkflowPauseStep'
      - $ref: '#/components/schemas/WorkflowInteractionStep'
    WorkflowStepBase:
      type: object
      required:
      - name
      properties:
        name:
          type: string
          description: Unique step name within the workflow, used for routing and
            logging.
        description:
          type: string
          description: Optional human-readable description of what this step does.
        next:
          type: array
          description: Outbound edges controlling which step executes after this one.
          items:
            $ref: '#/components/schemas/WorkflowEdge'
        edge_matching_strategy:
          $ref: '#/components/schemas/WorkflowEdgeMatchingStrategy'
        each:
          $ref: '#/components/schemas/WorkflowEach'
        layout:
          $ref: '#/components/schemas/WorkflowStepLayout'
    WorkflowStepLayout:
      type: object
      description: 'Optional presentation hint for the visual editor. Ignored by the

        execution engine; when absent, editors auto-lay out the step.

        '
      properties:
        x:
          type: number
          description: Horizontal position of the step in the editor canvas.
        y:
          type: number
          description: Vertical position of the step in the editor canvas.
    WorkflowExecutableStep:
      allOf:
      - $ref: '#/components/schemas/WorkflowStepBase'
      - type: object
        required:
        - action
        properties:
          action:
            type: string
            description: 'Canonical executable-step field.

              When `action_kind` is omitted, the engine treats this as a worker action.

              Use `action_kind: server` for Mobius-managed server actions.

              '
          action_kind:
            $ref: '#/components/schemas/WorkflowActionKind'
          store:
            type: string
            description: State variable name where the action result is stored.
          parameters:
            type: object
            additionalProperties: true
            description: Input parameters passed to the action, supporting expression
              interpolation.
          retry:
            type: array
            description: Retry policies applied when the action fails.
            items:
              $ref: '#/components/schemas/WorkflowRetry'
          catch:
            type: array
            description: Error catch clauses that redirect execution on specific failures.
            items:
              $ref: '#/components/schemas/WorkflowCatch'
      example:
        name: summarize
        action: summarize-document
        parameters:
          doc_id: ${inputs.doc_id}
    WorkflowJoinStep:
      allOf:
      - $ref: '#/components/schemas/WorkflowStepBase'
      - type: object
        required:
        - join
        properties:
          join:
            $ref: '#/components/schemas/WorkflowJoinConfig'
    WorkflowWaitSignalStep:
      allOf:
      - $ref: '#/components/schemas/WorkflowStepBase'
      - type: object
        required:
        - wait_signal
        properties:
          wait_signal:
            $ref: '#/components/schemas/WorkflowWaitSignalConfig'
    WorkflowSleepStep:
      allOf:
      - $ref: '#/components/schemas/WorkflowStepBase'
      - type: object
        required:
        - sleep
        properties:
          sleep:
            $ref: '#/components/schemas/WorkflowSleepConfig'
    WorkflowPauseStep:
      allOf:
      - $ref: '#/components/schemas/WorkflowStepBase'
      - type: object
        required:
        - pause
        properties:
          pause:
            $ref: '#/components/schemas/WorkflowPauseConfig'
    WorkflowInteractionStep:
      allOf:
      - $ref: '#/components/schemas/WorkflowStepBase'
      - type: object
        required:
        - interaction
        properties:
          interaction:
            $ref: '#/components/schemas/WorkflowInteractionConfig'
    WorkflowActionKind:
      type: string
      enum:
      - worker
      - server
      description: 'Execution mode for `action` steps.

        Omit for the current default of `worker`.

        '
    WorkflowEdgeMatchingStrategy:
      type: string
      enum:
      - all
      - first
    WorkflowEdge:
      type: object
      required:
      - step
      additionalProperties: false
      properties:
        step:
          type: string
          description: Name of the step to transition to.
        condition:
          type: string
          description: Expression that must evaluate to true for this edge to be followed.
        branch:
          type: string
          description: Branch name assigned to parallel execution started by this
            edge.
    WorkflowEach:
      type: object
      required:
      - items
      additionalProperties: false
      properties:
        items:
          description: Expression or literal collection to iterate over.
        as:
          type: string
          description: Variable name bound to the current iteration element.
    WorkflowRetry:
      type: object
      additionalProperties: false
      properties:
        error_equals:
          type: array
          description: Error class names this policy applies to. Retries all errors
            when omitted.
          items:
            type: string
        max_retries:
          type: integer
          minimum: 0
          description: Maximum number of retry attempts. Zero disables retries.
        base_delay:
          type: string
          description: Go duration string.
        max_delay:
          type: string
          description: Go duration string.
        backoff_rate:
          type: number
          description: Exponential backoff multiplier applied to the delay after each
            attempt.
        jitter_strategy:
          type: string
          enum:
          - NONE
          - FULL
          description: 'Jitter strategy to apply to the computed delay: NONE or FULL.'
        timeout:
          type: string
          description: Go duration string.
    WorkflowCatch:
      type: object
      required:
      - error_equals
      - next
      additionalProperties: false
      properties:
        error_equals:
          type: array
          description: Error class names this catch clause handles.
          items:
            type: string
        next:
          type: string
          description: Step name to transition to when this clause is matched.
        store:
          type: string
          description: State variable name where the caught error is stored.
    WorkflowJoinConfig:
      type: object
      description: Waits for one or more parallel branches to complete before proceeding.
      properties:
        branches:
          type: array
          items:
            type: string
          description: Branch names to wait for. Defaults to all branches if omitted.
        count:
          type: integer
          minimum: 0
          description: Minimum number of branches that must complete. Defaults to
            all listed branches.
        branch_mappings:
          type: object
          additionalProperties:
            type: string
          description: Maps branch names to variable names for storing per-branch
            results.
    WorkflowWaitSignalConfig:
      type: object
      required:
      - topic
      - timeout
      additionalProperties: false
      description: Suspends the run until a signal with the matching topic arrives.
      properties:
        topic:
          type: string
          description: Signal topic to wait on. Must match the `name` field in POST
            /runs/{id}/signals.
        timeout:
          type: string
          description: Maximum wait duration as a Go duration string (e.g. "24h",
            "30m").
        store:
          type: string
          description: Variable name to store the signal payload in after resumption.
        on_timeout:
          type: string
          description: Step name to transition to if the timeout elapses without a
            signal. Fails the run if omitted.
    WorkflowSleepConfig:
      type: object
      required:
      - duration
      additionalProperties: false
      properties:
        duration:
          type: string
          description: Go duration string.
    WorkflowPauseConfig:
      type: object
      additionalProperties: false
      properties:
        reason:
          type: string
          description: Optional human-readable reason displayed when the run is paused.
    WorkflowInteractionConfig:
      type: object
      required:
      - type
      - message
      - target
      - timeout
      additionalProperties: false
      properties:
        type:
          type: string
          enum:
          - approval
          - review
          - input
          description: 'Interaction kind: approval requires a yes/no decision, review
            requests acknowledgement, input collects free-form data.'
        message:
          type: string
          description: Prompt message shown to the interaction recipient.
        context:
          type: object
          additionalProperties: true
          description: Arbitrary key-value context passed alongside the interaction
            for rendering.
        spec:
          $ref: '#/components/schemas/WorkflowInteractionSpec'
        timeout:
          type: string
          description: Go duration string.
        target:
          $ref: '#/components/schemas/WorkflowInteractionTarget'
    WorkflowInteractionSpec:
      type: object
      required:
      - mode
      additionalProperties: false
      description: 'Declarative interaction UI contract embedded in a workflow definition.

        This mirrors the persisted interaction spec used at runtime and is

        intentionally portable across web, email, and agent experiences.

        '
      properties:
        mode:
          type: string
          enum:
          - confirm
          - select
          - multi_select
          - input
          description: 'UI rendering mode: confirm shows yes/no, select and multi_select
            show option lists, input shows a text field.'
        options:
          type: array
          description: Required for `select` and `multi_select` modes.
          items:
            $ref: '#/components/schemas/WorkflowInteractionOption'
        default_value:
          type: string
          description: Default selected option for `select` mode.
        default_values:
          type: array
          description: Default selected options for `multi_select` mode.
          items:
            type: string
        default_text:
          type: string
          description: Initial text value for `input` mode.
        default_confirmed:
          type: boolean
          description: Initial yes/no value for `confirm` mode.
        placeholder:
          type: string
          description: Hint text shown for `input` mode.
        multiline:
          type: boolean
          description: When true, render `input` mode as a multiline text area.
    WorkflowInteractionOption:
      type: object
      required:
      - value
      - label
      additionalProperties: false
      properties:
        value:
          type: string
          description: Machine-readable option value stored in the interaction response.
        label:
          type: string
          description: Human-readable option label displayed to the recipient.
        description:
          type: string
          description: Optional supplementary text shown alongside the option.
    WorkflowInteractionTarget:
      type: object
      required:
      - type
      - id
      additionalProperties: false
      properties:
        type:
          type: string
          enum:
          - user
          - group
          description: Whether the target is an individual user or a group.
        id:
          type: string
          description: ID of the target user or group.
        require_all:
          type: boolean
          description: When true, all group members must respond before the interaction
            completes.
    WorkflowDefinition:
      type: object
      required:
      - id
      - name
      - handle
      - latest_version
      - created_by
      - created_at
      - updated_at
      properties:
        id:
          type: string
          description: Unique identifier for this workflow definition.
        name:
          type: string
          description: Human-readable workflow name.
        handle:
          type: string
          description: URL-safe slug, unique within the org. Used to reference this
            workflow in triggers and tools.
        description:
          type: string
          description: Optional description of the workflow's purpose.
        latest_version:
          type: integer
          description: The current highest version number. Starts at 1 and increments
            with each spec update.
        published_as_tool:
          type: boolean
          description: When true, this workflow is exposed as a callable tool via
            /api/tools.
        spec:
          $ref: '#/components/schemas/WorkflowSpec'
        created_by:
          type: string
          description: User ID of the org member who created this workflow definition.
        created_at:
          type: string
          format: date-time
          description: Timestamp when this workflow definition was created.
        updated_at:
          type: string
          format: date-time
          description: Timestamp when this workflow definition was last updated.
    WorkflowDefinitionListResponse:
      type: object
      required:
      - data
      - has_more
      properties:
        items:
          type: array
          description: The list of results for this page.
          items:
            $ref: '#/components/schemas/WorkflowDefinition'
        next_cursor:
          type: string
          description: Opaque cursor to pass as `cursor` on the next request. Absent
            when `has_more` is false.
        has_more:
          type: boolean
          description: Whether additional pages are available.
    CreateWorkflowRequest:
      type: object
      required:
      - name
      - spec
      properties:
        name:
          type: string
          description: Human-readable workflow name, unique within the project.
        handle:
          type: string
          description: URL-safe handle for this workflow. Auto-derived from name if
            omitted.
        description:
          type: string
          description: Optional description of the workflow's purpose.
        published_as_tool:
          type: boolean
          description: When true, expose this workflow as a callable tool via /api/tools.
        spec:
          $ref: '#/components/schemas/WorkflowSpec'
    UpdateWorkflowRequest:
      type: object
      properties:
        name:
          type: string
          description: Replacement human-readable workflow name.
        description:
          type: string
          description: Replacement description. Omit to leave unchanged.
        published_as_tool:
          type: boolean
          description: When true, expose this workflow as a callable tool via /api/tools.
        spec:
          $ref: '#/components/schemas/WorkflowSpec'
    WorkflowVersion:
      type: object
      required:
      - id
      - version
      - created_by
      - created_at
      properties:
        id:
          type: string
          description: Unique identifier for this workflow version.
        version:
          type: integer
          description: Monotonically increasing version number. Starts at 1.
        spec:
          $ref: '#/components/schemas/WorkflowSpec'
        created_by:
          type: string
          description: User ID of the org member who created this version.
        created_at:
          type: string
          format: date-time
          description: Timestamp when this version was created.
    WorkflowVersionListResponse:
      type: object
      required:
      - items
      properties:
        items:
          type: array
          description: The list of workflow versions, newest first.
          items:
            $ref: '#/components/schemas/WorkflowVersion'
    WorkflowRunStatus:
      type: string
      enum:
      - queued
      - running
      - completed
      - failed
      - suspended
      description: 'Run lifecycle: `queued` → `running` → `completed` | `failed` |
        `suspended`.

        A `suspended` run is waiting on a signal or interaction; it resumes

        automatically when the signal is delivered or the interaction is responded
        to.

        '
    WorkflowRun:
      type: object
      required:
      - id
      - workflow_name
      - status
      - attempt
      - created_at
      - updated_at
      properties:
        id:
          type: string
          description: Unique identifier for this run.
        queue:
          type: string
          description: Queue this run was enqueued on.
        parent_run_id:
          type: string
          description: ID of the parent run, when this is a child run spawned by a
            fan-out step.
        definition_id:
          type: string
          description: 'ID of the workflow definition this run was started from.

            Empty for ephemeral runs started from an inline spec.

            '
        definition_version:
          type: integer
          description: Zero for ephemeral runs.
        ephemeral:
          type: boolean
          description: 'True when the run was started from an inline spec rather

            than a saved workflow definition. Equivalent to

            `definition_id == ""`.

            '
        workflow_name:
          type: string
          description: Name of the workflow as recorded at run creation time.
        status:
          $ref: '#/components/schemas/WorkflowRunStatus'
        attempt:
          type: integer
          description: Retry attempt number (1-based). Increments each time the run
            is retried.
        inputs:
          type: object
          additionalProperties: true
          description: Input values provided when the run was started.
        metadata:
          type: object
          additionalProperties:
            type: string
          description: Caller-supplied string metadata attached to the run.
        error_message:
          type: string
          description: Error message from the most recent failure. Present when status
            is failed.
        actor_type:
          type: string
          description: Type of the actor that started this run (user, service_account,
            system).
        actor_id:
          type: string
          description: ID of the actor that started this run.
        initiated_by:
          type: string
          description: Human-readable label for the initiator (e.g. trigger name,
            API key name).
        external_id:
          type: string
          description: Caller-supplied idempotency key or correlation ID.
        created_at:
          type: string
          format: date-time
          description: Timestamp when this run was created.
        started_at:
          type: string
          format: date-time
          description: Timestamp when a worker first claimed this run.
        completed_at:
          type: string
          format: date-time
          description: Timestamp when this run reached a terminal state.
        updated_at:
          type: string
          format: date-time
          description: Timestamp when this run was last updated.
    WorkflowRunListResponse:
      type: object
      required:
      - data
      - has_more
      properties:
        items:
          type: array
          description: The list of results for this page.
          items:
            $ref: '#/components/schemas/WorkflowRun'
        has_more:
          type: boolean
          description: True when more pages are available.
        next_cursor:
          type: string
          description: 'Opaque cursor for fetching the next page. Present only when

            has_more is true.

            '
    WorkflowRunDetail:
      allOf:
      - $ref: '#/components/schemas/WorkflowRun'
      - type: object
        properties:
          spec:
            $ref: '#/components/schemas/WorkflowSpec'
          result_b64:
            type: string
            description: Base64-encoded terminal result blob
          jobs:
            type: array
            description: Jobs spawned by this run.
            items:
              $ref: '#/components/schemas/Job'
    StartRunRequest:
      type: object
      description: 'Start a workflow run. Provide exactly one of `definition_id` or

        `spec` — they are mutually exclusive. When both are absent on

        the path-less `POST /projects/{project}/runs` endpoint, or when both

        are present, the request is rejected with 400. On the

        definition-bound endpoint (`POST /projects/{project}/workflows/{id}/runs`)

        `definition_id` is implied by the path and `spec` is forbidden.

        '
      properties:
        definition_id:
          type: string
          description: 'ID of an existing workflow definition to run. Mutually

            exclusive with `spec`. On the definition-bound path this is

            ignored (the path segment wins) but must not conflict.

            '
        spec:
          $ref: '#/components/schemas/WorkflowSpec'
        queue:
          type: string
          description: 'Queue name to enqueue the run on. Defaults to "default".

            '
        inputs:
          type: object
          additionalProperties: true
          description: Input values to pass to the workflow. Must conform to the workflow's
            declared input schema.
        metadata:
          type: object
          additionalProperties:
            type: string
          description: Caller-supplied string metadata attached to the run for filtering
            and display.
        external_id:
          type: string
          description: Caller-supplied idempotency key or correlation ID attached
            to the run.
    ActionLogEntry:
      type: object
      required:
      - id
      - action
      - step_name
      - branch_id
      - started_at
      - duration_ms
      properties:
        id:
          type: string
          description: Unique identifier for this action log entry.
        action:
          type: string
          description: Action name that was executed.
        step_name:
          type: string
          description: Workflow step name that produced this action log entry.
        branch_id:
          type: string
          description: Execution branch this entry belongs to.
        parameters:
          type: object
          additionalProperties: true
          description: Input parameters that were passed to the action.
        result:
          type: object
          additionalProperties: true
          description: Output returned by the action. Present on success.
        error:
          type: string
          description: Error message when the action failed.
        started_at:
          type: string
          format: date-time
          description: Timestamp when the action execution started.
        duration_ms:
          type: integer
          description: Elapsed time in milliseconds from start to completion.
    ActionLogListResponse:
      type: object
      required:
      - items
      properties:
        items:
          type: array
          description: The list of action log entries for this run.
          items:
            $ref: '#/components/schemas/ActionLogEntry'
    Job:
      type: object
      required:
      - id
      - run_id
      - step_name
      - action
      - queue
      - status
      - attempt
      - max_attempts
      - scheduled_at
      - created_at
      - updated_at
      description: A claimable unit of work derived from a single workflow step execution.
      properties:
        id:
          type: string
          description: Unique identifier for this job.
        run_id:
          type: string
          description: The workflow run this job belongs to.
        parent_job_id:
          type: string
          description: Set when this job is a child of a fan-out (each) step.
        path_id:
          type: string
          description: Opaque identifier for the execution path within the run (used
            for fan-out deduplication).
        step_name:
          type: string
          description: Workflow step name this job was created for.
        action:
          type: string
          description: Action name the worker must execute to complete this job.
        queue:
          type: string
          description: Queue the job was placed in. Workers subscribe to queues to
            receive jobs.
        parameters:
          type: object
          additionalProperties: true
          description: Resolved input parameters to pass to the action.
        status:
          type: string
          description: 'Job lifecycle: pending → claimed → completed | failed.'
        claimed_by:
          type: string
          description: Worker ID that claimed this job.
        agent_id:
          type: string
          description: Agent ID the claiming worker is acting on behalf of.
        agent_session_id:
          type: string
          description: Agent session ID provided during the claim.
        claimed_at:
          type: string
          format: date-time
          description: Timestamp when this job was claimed by a worker.
        heartbeat_at:
          type: string
          format: date-time
          description: Timestamp of the most recent heartbeat. Used to detect stale
            claims.
        attempt:
          type: integer
          description: Current attempt number (1-based). Increments on each retry.
        max_attempts:
          type: integer
          description: Maximum number of attempts before the job is permanently failed.
        scheduled_at:
          type: string
          format: date-time
          description: Earliest time at which this job may be claimed.
        last_error:
          type: string
          description: Error detail from the most recent failed attempt.
        created_at:
          type: string
          format: date-time
          description: Timestamp when this job was created.
        updated_at:
          type: string
          format: date-time
          description: Timestamp when this job was last updated.
    JobListResponse:
      type: object
      required:
      - items
      properties:
        items:
          type: array
          description: The list of jobs for this run.
          items:
            $ref: '#/components/schemas/Job'
    SendRunSignalRequest:
      type: object
      required:
      - name
      properties:
        name:
          type: string
          description: Signal topic (e.g. "approval", "webhook").
        payload:
          type: object
          additionalProperties: true
          description: Arbitrary payload delivered to the waiting step when the signal
            is received.
    RunSignal:
      type: object
      required:
      - id
      - run_id
      - name
      properties:
        id:
          type: string
          description: Unique identifier for this signal.
        run_id:
          type: string
          description: ID of the run this signal was delivered to.
        name:
          type: string
          description: Signal topic name matching the wait_signal step's topic.
    BulkRunRequest:
      type: object
      required:
      - run_ids
      properties:
        run_ids:
          type: array
          description: IDs of the runs to operate on.
          items:
            type: string
    BulkRunResult:
      type: object
      required:
      - succeeded
      properties:
        succeeded:
          type: array
          description: IDs of runs that were successfully processed.
          items:
            type: string
        failures:
          type: object
          additionalProperties:
            type: string
          description: Map of run_id -> error message for per-run failures.
    ActionAnnotations:
      type: object
      description: 'Hints that describe the safe-use properties of the action. Used
        by the

        engine and tooling to decide retry behavior, dry-run eligibility, etc.

        '
      properties:
        idempotent:
          type: boolean
          description: The action produces the same result when called with the same
            inputs; safe to retry automatically.
        destructive:
          type: boolean
          description: The action has irreversible side effects (deletion, financial
            transactions, etc.). Surfaced as a warning in UI.
        read_only:
          type: boolean
          description: The action has no side effects; safe to call in dry-run scenarios.
    CreateActionRequest:
      type: object
      required:
      - name
      - endpoint_url
      properties:
        name:
          type: string
          description: 'Project-scoped identifier used in workflow step definitions.

            Lowercase alphanumeric + hyphens, e.g. "send-email". Must be

            unique within the project. Cannot start with "mobius." (reserved prefix).

            '
        title:
          type: string
          description: Human-readable display name shown in the UI and catalog.
        description:
          type: string
          description: Markdown-safe description of what the action does.
        endpoint_url:
          type: string
          format: uri
          description: HTTP/HTTPS URL Mobius will POST to when invoking the action.
        input_schema:
          type: object
          additionalProperties: true
          description: JSON Schema describing the expected input parameters.
        output_schema:
          type: object
          additionalProperties: true
          description: JSON Schema describing the expected output shape.
        annotations:
          $ref: '#/components/schemas/ActionAnnotations'
    UpdateActionRequest:
      type: object
      properties:
        title:
          type: string
          description: Replacement display title.
        description:
          type: string
          description: Replacement Markdown description.
        endpoint_url:
          type: string
          format: uri
          description: Replacement endpoint URL.
        input_schema:
          type: object
          additionalProperties: true
          description: Replacement JSON Schema for inputs. Replaces the existing schema.
        output_schema:
          type: object
          additionalProperties: true
          description: Replacement JSON Schema for outputs. Replaces the existing
            schema.
        annotations:
          $ref: '#/components/schemas/ActionAnnotations'
          nullable: true
          description: Pass null to clear all annotation flags.
    Action:
      type: object
      required:
      - id
      - org_id
      - name
      - endpoint_url
      - created_at
      - updated_at
      properties:
        id:
          type: string
          description: Unique identifier for this action.
        org_id:
          type: string
          description: ID of the organization this action belongs to.
        name:
          type: string
          description: Project-scoped stable identifier used in workflow step definitions.
        title:
          type: string
          description: Human-readable display title for the action.
        description:
          type: string
          description: Markdown description of what the action does.
        endpoint_url:
          type: string
          format: uri
          description: HTTP/HTTPS URL Mobius POSTs to when invoking this action.
        input_schema:
          type: object
          additionalProperties: true
          description: JSON Schema describing expected input parameters.
        output_schema:
          type: object
          additionalProperties: true
          description: JSON Schema describing the expected output shape.
        annotations:
          $ref: '#/components/schemas/ActionAnnotations'
        signing_secret:
          type: string
          description: 'Raw HMAC-SHA256 signing secret. Only populated on create and
            rotate

            responses; null on all other reads. Store this value securely on

            first receipt — it cannot be retrieved again.

            '
        created_at:
          type: string
          format: date-time
          description: Timestamp when this action was created.
        updated_at:
          type: string
          format: date-time
          description: Timestamp when this action was last updated.
    ActionListResponse:
      type: object
      required:
      - data
      - has_more
      properties:
        items:
          type: array
          description: The list of results for this page.
          items:
            $ref: '#/components/schemas/Action'
        next_cursor:
          type: string
          description: Opaque cursor to pass as `cursor` on the next request. Absent
            when `has_more` is false.
        has_more:
          type: boolean
          description: Whether additional pages are available.
    RotateSecretResult:
      type: object
      required:
      - signing_secret
      properties:
        signing_secret:
          type: string
          description: The new raw signing secret. Store it immediately — this is
            the only time it is returned.
    ActionCatalogEntry:
      type: object
      required:
      - name
      - source
      - available
      properties:
        name:
          type: string
          description: Action name as used in workflow step definitions.
        title:
          type: string
          description: Human-readable display title for the action.
        description:
          type: string
          description: Markdown description of what the action does.
        integration:
          type: string
          description: Integration slug this action belongs to (e.g. "slack"), if
            platform-provided.
        source:
          type: string
          description: 'Origin of this action: "project" for project-owned actions,
            or the

            integration slug for platform-provided actions.

            '
        available:
          type: boolean
          description: 'Whether this action can currently be invoked. False if the
            required

            integration is not connected or the caller lacks permission.

            '
        annotations:
          $ref: '#/components/schemas/ActionAnnotations'
        input_schema:
          type: object
          additionalProperties: true
          description: JSON Schema describing expected input parameters.
        output_schema:
          type: object
          additionalProperties: true
          description: JSON Schema describing the expected output shape.
        endpoint_url:
          type: string
          format: uri
          description: Endpoint URL (populated for project-owned actions only).
    ActionCatalogListResponse:
      type: object
      required:
      - items
      properties:
        items:
          type: array
          description: The full list of catalog entries.
          items:
            $ref: '#/components/schemas/ActionCatalogEntry'
    ActionAuditLogEntry:
      type: object
      required:
      - id
      - action_name
      - source
      - status
      - retry_count
      - started_at
      - finished_at
      properties:
        id:
          type: string
          description: Unique identifier for this audit log entry.
        run_id:
          type: string
          description: Workflow run that triggered this invocation, if run-backed.
        step_name:
          type: string
          description: Workflow step name that triggered this invocation.
        action_name:
          type: string
          description: Name of the action that was invoked.
        source:
          type: string
          description: Invocation source ("workflow", "direct", etc.).
        parameters:
          type: object
          additionalProperties: true
          description: Input parameters passed to the action.
        output_summary:
          type: object
          additionalProperties: true
          description: Truncated or summarized action output for audit purposes.
        status:
          type: string
          description: Terminal invocation status ("success", "failed", etc.).
        retry_count:
          type: integer
          description: Number of retry attempts before this terminal status was reached.
        started_at:
          type: string
          format: date-time
          description: Timestamp when this invocation started.
        finished_at:
          type: string
          format: date-time
          description: Timestamp when this invocation completed.
        error_type:
          type: string
          description: Machine-readable error classification when status is "failed".
        error_message:
          type: string
          description: Human-readable error detail when status is "failed".
    ActionAuditLogListResponse:
      type: object
      required:
      - data
      - has_more
      properties:
        items:
          type: array
          description: The list of results for this page.
          items:
            $ref: '#/components/schemas/ActionAuditLogEntry'
        next_cursor:
          type: string
          description: Opaque cursor to pass as `cursor` on the next request. Absent
            when `has_more` is false.
        has_more:
          type: boolean
          description: Whether additional pages are available.
    JobClaimRequest:
      type: object
      required:
      - worker_id
      properties:
        worker_id:
          type: string
          description: 'Caller-assigned stable identifier for this worker process.
            Used

            as the lease fence and for worker registry tracking.

            '
        agent_id:
          type: string
          description: Durable agent identity the worker is acting on behalf of.
        agent_session_id:
          type: string
          description: Live agent session the worker is acting on behalf of.
        worker_name:
          type: string
          description: Optional human-readable name shown in the worker list.
        worker_version:
          type: string
          description: Optional version string shown in the worker list.
        queues:
          type: array
          description: 'Queue names the worker subscribes to. When empty the worker

            claims from any queue in the project. Workflow runs default

            to the "default" queue when not otherwise specified.

            '
          items:
            type: string
        actions:
          type: array
          description: 'Action names this worker can execute. When provided, only
            jobs

            whose `action` is in this list are returned. When empty, action

            filtering is skipped.

            '
          items:
            type: string
        wait_seconds:
          type: integer
          minimum: 0
          maximum: 30
          description: 'How long to hold the request open waiting for a job to surface.

            0 returns immediately. Capped at 30 by the server.

            '
    JobClaim:
      type: object
      required:
      - job_id
      - run_id
      - workflow_name
      - step_name
      - action
      - attempt
      - queue
      - parameters
      properties:
        job_id:
          type: string
          description: Job ID — use as the `{id}` path parameter for heartbeat, complete,
            and events.
        run_id:
          type: string
          description: Parent workflow run ID.
        workflow_name:
          type: string
          description: Handle of the workflow definition that owns this run.
        step_name:
          type: string
          description: Step label from the workflow spec — used for UI and interaction
            topic derivation.
        action:
          type: string
          description: Action name the worker must execute for this step.
        agent_id:
          type: string
          description: Agent that should execute this job, when the step is agent-targeted.
        agent_session_id:
          type: string
          description: Agent session the job was routed to, when applicable.
        parameters:
          type: object
          additionalProperties: true
          description: Input parameters for this step, resolved from the workflow
            spec and prior step outputs.
        attempt:
          type: integer
          description: '1-based attempt counter. Incremented on each automatic retry.

            Include in the fence for all subsequent heartbeat and complete calls.

            '
        queue:
          type: string
          description: Queue name the job was claimed from.
        heartbeat_interval_seconds:
          type: integer
          description: 'Recommended heartbeat interval in seconds. Workers should
            call

            `POST /jobs/{id}/heartbeat` at this cadence to keep the lease

            alive. Typically 30 seconds.

            '
    JobHeartbeatDirectives:
      type: object
      properties:
        should_cancel:
          type: boolean
          default: false
          description: 'When true, the run has received a cancellation request. The

            worker must stop processing immediately and call complete with

            `status: failed`.

            '
    JobHeartbeat:
      type: object
      required:
      - ok
      - directives
      properties:
        ok:
          type: boolean
          description: True when the lease was successfully refreshed.
        directives:
          $ref: '#/components/schemas/JobHeartbeatDirectives'
    JobFenceRequest:
      type: object
      required:
      - worker_id
      - attempt
      properties:
        worker_id:
          type: string
          description: Must match the `worker_id` from the original claim.
        attempt:
          type: integer
          description: Must match the `attempt` from the original claim.
    JobCompleteRequest:
      type: object
      required:
      - worker_id
      - attempt
      - status
      properties:
        worker_id:
          type: string
          description: Must match the `worker_id` from the original claim.
        attempt:
          type: integer
          description: Must match the `attempt` from the original claim.
        status:
          type: string
          enum:
          - completed
          - failed
          description: 'Terminal status for this job attempt. `failed` triggers the

            workflow engine''s retry logic if `attempt < max_attempts`.

            '
        result_b64:
          type: string
          description: 'Base64-encoded (standard encoding) bytes representing the
            job''s

            output. The workflow engine decodes this and may pass it as input

            to downstream steps. Omit if the step produces no output.

            '
        error_type:
          type: string
          description: 'Short error class identifier (e.g. "TimeoutError"). Used for

            observability and retry classification. Only relevant when

            `status: failed`.

            '
        error_message:
          type: string
          description: Human-readable error detail. Only relevant for failed status.
    RunActionRequest:
      type: object
      properties:
        parameters:
          type: object
          additionalProperties: true
          description: Input parameters passed to the action handler.
        timeout_seconds:
          type: integer
          minimum: 0
          description: Override the default action execution timeout.
        dry_run:
          type: boolean
          description: 'When true, invokes the action without side effects. Only

            effective for actions that support dry-run mode.

            '
    RunActionResult:
      type: object
      required:
      - output
      properties:
        output:
          oneOf:
          - type: object
            additionalProperties: true
          - type: array
            items: {}
          - type: string
          - type: number
          - type: integer
          - type: boolean
          description: Free-form output returned by the action handler.
    JobEventsRequest:
      type: object
      required:
      - worker_id
      - attempt
      - events
      description: 'Fenced batch of custom run events published by the worker holding

        a job''s lease. The fence is per-request: every event in `events`

        is published under the same `worker_id` + `attempt` pair.

        '
      properties:
        worker_id:
          type: string
          description: Must match the `worker_id` from the original claim.
        attempt:
          type: integer
          description: Must match the `attempt` from the original claim.
        events:
          type: array
          description: The batch of events to publish. All events are validated atomically.
          minItems: 1
          maxItems: 100
          items:
            $ref: '#/components/schemas/JobEventEntry'
    JobEventEntry:
      type: object
      required:
      - type
      - payload
      properties:
        type:
          type: string
          minLength: 1
          maxLength: 64
          pattern: ^[a-zA-Z0-9_.-]+$
          description: 'Caller-chosen event type identifier. The `mobius.` prefix
            is

            reserved for server-emitted well-known kinds and is rejected

            with 400.

            '
        payload:
          type: object
          additionalProperties: true
          description: 'Free-form JSON payload. Bounded by the server-side byte limit

            (default 16 KiB per event); oversize payloads are rejected

            with 413.

            '
    ActorRef:
      type: object
      required:
      - type
      - id
      properties:
        type:
          type: string
          enum:
          - member
          - agent
          - group
          description: 'Actor type: `user` or `service_account`.'
        id:
          type: string
          description: User ID for member; queue name for agent; group ID/handle for
            group
    InteractionType:
      type: string
      enum:
      - approval
      - review
      - input
    InteractionSpecMode:
      type: string
      description: 'Declarative UI/input primitive for collecting the response. This
        is a

        portable rendering contract, not executable code.

        '
      enum:
      - confirm
      - select
      - multi_select
      - input
    InteractionOption:
      type: object
      required:
      - value
      - label
      additionalProperties: false
      description: Selectable option for `select` and `multi_select` modes.
      properties:
        value:
          type: string
          description: Machine-readable value submitted when this option is chosen.
        label:
          type: string
          description: Human-readable label displayed for this option.
        description:
          type: string
          description: Optional additional context shown beneath the label.
    InteractionSpec:
      type: object
      required:
      - mode
      additionalProperties: false
      description: 'Declarative dialog contract for rendering and validating an interaction.

        `type` defines the semantic intent; `mode` defines the input affordance.

        Compatibility rules are enforced server-side:

        - `approval` requires `mode = confirm`

        - `review` requires `mode = select`

        - `input` supports `input`, `select`, or `multi_select`

        '
      properties:
        mode:
          $ref: '#/components/schemas/InteractionSpecMode'
        options:
          type: array
          description: Required for `select` and `multi_select` modes.
          items:
            $ref: '#/components/schemas/InteractionOption'
        default_value:
          type: string
          description: Default selected option for `select` mode.
        default_values:
          type: array
          description: Default selected options for `multi_select` mode.
          items:
            type: string
        default_text:
          type: string
          description: Initial text value for `input` mode.
        default_confirmed:
          type: boolean
          description: Initial yes/no value for `confirm` mode.
        placeholder:
          type: string
          description: Hint text shown for `input` mode.
        multiline:
          type: boolean
          description: When true, render `input` mode as a multiline text area.
    CreateJobInteractionRequest:
      type: object
      required:
      - target_actor
      - type
      - message
      description: 'Creates an interaction from a claimed job context. The server
        derives

        the owning run from the job and may derive the topic when omitted.

        '
      properties:
        target_actor:
          $ref: '#/components/schemas/ActorRef'
        type:
          $ref: '#/components/schemas/InteractionType'
        message:
          type: string
          description: Message shown to the responder.
        topic:
          type: string
          description: 'Optional signal topic override. When omitted, the server derives

            the topic from step_name or falls back to a default interaction topic.

            '
        step_name:
          type: string
          description: Optional workflow step label for UI/debugging context
        context:
          type: object
          additionalProperties: true
          description: Additional key-value context surfaced in the UI alongside the
            message.
        spec:
          $ref: '#/components/schemas/InteractionSpec'
        require_all:
          type: boolean
          default: false
          description: 'When target_actor.type is "group", setting require_all=true

            means all snapshotted group members must respond before the

            interaction is considered complete. Ignored for non-group targets.

            '
        timeout:
          type: string
          description: 'Optional duration string (e.g. "24h", "30m") specifying how
            long

            the interaction should remain open before expiring. When absent

            the caller is responsible for setting expires_at directly.

            '
        expires_at:
          type: string
          format: date-time
          description: Timestamp after which this interaction expires.
    InteractionValue:
      description: Free-form JSON payload supplied by the responder.
      oneOf:
      - type: object
        additionalProperties: true
      - type: array
        items: {}
      - type: string
      - type: number
      - type: integer
      - type: boolean
    InteractionResponse:
      type: object
      required:
      - value
      - at
      properties:
        value:
          $ref: '#/components/schemas/InteractionValue'
        comment:
          type: string
          nullable: true
          description: Optional free-text comment from the responder.
        at:
          type: string
          format: date-time
          description: When the response was submitted
    InteractionPartialResponse:
      type: object
      required:
      - user_id
      - value
      - responded_at
      properties:
        user_id:
          type: string
          description: ID of the user who submitted this partial response.
        value:
          $ref: '#/components/schemas/InteractionValue'
        comment:
          type: string
          nullable: true
          description: Optional free-text comment from this responder.
        responded_at:
          type: string
          format: date-time
          description: Timestamp when this response was submitted.
    Interaction:
      type: object
      required:
      - id
      - org_id
      - type
      - status
      - target_actor
      - created_at
      - updated_at
      properties:
        id:
          type: string
          description: Unique identifier for this interaction.
        org_id:
          type: string
          description: ID of the organization this interaction belongs to.
        run_id:
          type: string
          nullable: true
          description: Originating workflow run when the interaction is run-backed.
        topic:
          type: string
          nullable: true
          description: Signal topic used to resume the originating run when run-backed.
        type:
          $ref: '#/components/schemas/InteractionType'
        status:
          type: string
          enum:
          - pending
          - completed
          - expired
          description: Current status of the interaction.
        message:
          type: string
          nullable: true
          description: Human-readable message shown to the responder
        context:
          type: object
          additionalProperties: true
          nullable: true
          description: Additional key-value context surfaced in the UI alongside the
            message.
        spec:
          $ref: '#/components/schemas/InteractionSpec'
        target_actor:
          $ref: '#/components/schemas/ActorRef'
        responder_actor:
          $ref: '#/components/schemas/ActorRef'
          nullable: true
        response:
          $ref: '#/components/schemas/InteractionResponse'
          nullable: true
        expires_at:
          type: string
          format: date-time
          nullable: true
          description: Timestamp when this interaction expires if not responded to.
        completed_at:
          type: string
          format: date-time
          nullable: true
          description: Timestamp when the interaction received a terminal response.
        created_at:
          type: string
          format: date-time
          description: Timestamp when this interaction was created.
        updated_at:
          type: string
          format: date-time
          description: Timestamp when this interaction was last updated.
        target_group_id:
          type: string
          nullable: true
          description: Resolved group ID (set when target_actor.type = group)
        target_member_snapshot:
          type: array
          items:
            type: string
          nullable: true
          description: User IDs of group members at the time of creation
        routing_policy_snapshot:
          type: string
          enum:
          - first_responder
          - all_members
          nullable: true
          description: Group routing policy captured at creation time
        require_all:
          type: boolean
          description: When true, all snapshotted members must respond before completion
        claimed_by:
          type: string
          nullable: true
          description: User ID of the member who claimed this interaction (first_responder
            only)
        claimed_at:
          type: string
          format: date-time
          nullable: true
          description: Timestamp when a first-responder member claimed this interaction.
        partial_responses:
          type: array
          items:
            $ref: '#/components/schemas/InteractionPartialResponse'
          nullable: true
          description: Per-member responses for all_members routing
    TriggerKind:
      type: string
      enum:
      - schedule
      - webhook
      - event
      description: Determines the event source and required `source_config` shape.
    ConcurrencyPolicy:
      type: string
      enum:
      - allow
      - forbid
      - replace
      description: 'Controls overlapping runs from the same trigger:

        - `allow` — start new runs unconditionally.

        - `forbid` — skip the new fire if a run from this trigger is still active.

        - `replace` — cancel the active run before starting a new one.

        '
    TriggerFireStatus:
      type: string
      enum:
      - success
      - failed
      - skipped
      description: '`skipped` means the fire was suppressed by the concurrency policy
        or a target condition evaluated to false.'
    TriggerTarget:
      type: object
      required:
      - workflow_id
      description: A workflow to start when this trigger fires.
      properties:
        workflow_id:
          type: string
          description: ID of the workflow definition to run.
        condition:
          type: string
          description: 'Expression evaluated against the event payload. The target
            is

            skipped if this evaluates to false. Omit to always run.

            '
        input_mapping:
          type: object
          additionalProperties:
            type: string
          description: 'Maps workflow input names to JSONPath expressions evaluated
            against

            the event payload. Example: `{"user_id": "$.event.actor.id"}`.

            '
    Trigger:
      type: object
      required:
      - id
      - org_id
      - name
      - kind
      - concurrency_policy
      - enabled
      - created_at
      - updated_at
      properties:
        id:
          type: string
          description: Unique identifier for this trigger.
        org_id:
          type: string
          description: ID of the organization this trigger belongs to.
        name:
          type: string
          description: Human-readable trigger name, unique within the project.
        kind:
          $ref: '#/components/schemas/TriggerKind'
        source_config:
          type: object
          additionalProperties: true
          description: 'Kind-specific source configuration. For `schedule`: `{"cron":
            "0 * * * *"}`.

            For `webhook` and `event`: contains event type filters.

            '
        filter_config:
          type: object
          additionalProperties: true
          description: Additional payload filters applied before targets are evaluated.
        targets:
          type: array
          items:
            $ref: '#/components/schemas/TriggerTarget'
          description: Workflows to start when this trigger fires.
        concurrency_policy:
          $ref: '#/components/schemas/ConcurrencyPolicy'
        enabled:
          type: boolean
          description: When false, the trigger is paused and will not fire.
        last_fire_at:
          type: string
          format: date-time
          description: Timestamp of the most recent fire attempt.
        next_fire_at:
          type: string
          format: date-time
          description: Computed next scheduled fire time (schedule triggers only).
        webhook_handle:
          type: string
          description: URL-safe handle for the inbound receive endpoint (webhook triggers
            only). Unique within the project.
        receive_url:
          type: string
          readOnly: true
          description: Full URL for posting inbound events (webhook triggers only).
            Computed from `webhook_handle`.
        created_by:
          type: string
          description: User ID of the org member who created this trigger.
        created_at:
          type: string
          format: date-time
          description: Timestamp when this trigger was created.
        updated_at:
          type: string
          format: date-time
          description: Timestamp when this trigger was last updated.
    TriggerListResponse:
      type: object
      required:
      - data
      - has_more
      properties:
        items:
          type: array
          description: The list of results for this page.
          items:
            $ref: '#/components/schemas/Trigger'
        next_cursor:
          type: string
          description: Opaque cursor to pass as `cursor` on the next request. Absent
            when `has_more` is false.
        has_more:
          type: boolean
          description: Whether additional pages are available.
    TriggerFire:
      type: object
      required:
      - id
      - org_id
      - project_id
      - trigger_id
      - fired_at
      - status
      - created_at
      description: A single trigger fire event and its outcome.
      properties:
        id:
          type: string
          description: Unique identifier for this fire record.
        org_id:
          type: string
          description: ID of the organization this trigger belongs to.
        project_id:
          type: string
          description: ID of the project this trigger belongs to.
        trigger_id:
          type: string
          description: ID of the trigger that fired.
        scheduled_at:
          type: string
          format: date-time
          description: When the trigger was scheduled to fire (schedule triggers only).
        fired_at:
          type: string
          format: date-time
          description: When the fire was actually processed.
        run_id:
          type: string
          description: Workflow run created by this fire. Absent when status is `skipped`
            or `failed` before run creation.
        status:
          $ref: '#/components/schemas/TriggerFireStatus'
        error:
          type: string
          description: Error detail when status is `failed`.
        dedup_key:
          type: string
          description: Deduplication key used to prevent duplicate fires for the same
            scheduled slot.
        created_at:
          type: string
          format: date-time
          description: Timestamp when this fire record was created.
    TriggerFireListResponse:
      type: object
      required:
      - data
      - has_more
      properties:
        items:
          type: array
          description: The list of results for this page.
          items:
            $ref: '#/components/schemas/TriggerFire'
        next_cursor:
          type: string
          description: Opaque cursor to pass as `cursor` on the next request. Absent
            when `has_more` is false.
        has_more:
          type: boolean
          description: Whether additional pages are available.
    CreateTriggerRequest:
      type: object
      required:
      - name
      - kind
      properties:
        name:
          type: string
          description: Human-readable trigger name, unique within the project.
        kind:
          $ref: '#/components/schemas/TriggerKind'
        source_config:
          type: object
          additionalProperties: true
          description: 'Kind-specific configuration. Required for `schedule` triggers:

            `{"cron": "0 9 * * 1-5"}`. For `event` triggers: event type and

            filter expressions.

            '
        filter_config:
          type: object
          additionalProperties: true
          description: Additional payload filters evaluated before targets.
        targets:
          type: array
          description: Workflows to start when this trigger fires.
          items:
            $ref: '#/components/schemas/TriggerTarget'
        concurrency_policy:
          $ref: '#/components/schemas/ConcurrencyPolicy'
        enabled:
          type: boolean
          default: true
          description: Whether the trigger starts enabled. Defaults to true.
        webhook_handle:
          type: string
          description: 'URL-safe handle that determines the inbound receive URL. Required

            for `webhook` triggers. Must be unique within the project.

            '
        webhook_secret:
          type: string
          description: 'Optional HMAC-SHA256 secret for verifying inbound webhook
            payloads.

            When set, Mobius validates the `X-Mobius-Signature` header on

            incoming requests.

            '
    UpdateTriggerRequest:
      type: object
      properties:
        name:
          type: string
          description: Replacement human-readable name.
        source_config:
          type: object
          additionalProperties: true
          description: Replacement kind-specific source configuration.
        filter_config:
          type: object
          additionalProperties: true
          description: Replacement payload filter configuration.
        targets:
          type: array
          items:
            $ref: '#/components/schemas/TriggerTarget'
          description: Replaces the entire targets array.
        concurrency_policy:
          $ref: '#/components/schemas/ConcurrencyPolicy'
        enabled:
          type: boolean
          description: Set to false to pause the trigger without deleting it.
        webhook_handle:
          type: string
          description: Changing this changes the `receive_url`; update any upstream
            integrations.
        webhook_secret:
          type: string
          description: Replace or clear the inbound signature verification secret.
    Worker:
      type: object
      required:
      - worker_id
      - stale
      properties:
        worker_id:
          type: string
          description: Caller-assigned stable identifier for this worker process.
        name:
          type: string
          description: Optional human-readable name supplied in the claim request.
        version:
          type: string
          description: Optional version string supplied in the claim request.
        last_seen_at:
          type: string
          format: date-time
          description: 'Timestamp of the worker''s most recent job claim poll. Updated
            on

            every `POST /jobs/claim` call regardless of whether a job was

            returned. Used to compute `stale`.

            '
        capabilities:
          type: array
          items:
            type: string
          description: Reserved for future capability-based job routing. Not currently
            used for filtering.
        stale:
          type: boolean
          description: 'True when `last_seen_at` is older than 2 minutes or absent.

            Computed at read time, not stored.

            '
    WorkerListResponse:
      type: object
      required:
      - items
      properties:
        items:
          type: array
          description: The list of recently seen workers.
          items:
            $ref: '#/components/schemas/Worker'
    Project:
      type: object
      required:
      - id
      - name
      - handle
      - created_at
      - updated_at
      properties:
        id:
          type: string
          description: Unique identifier for this project.
        name:
          type: string
          description: Human-readable project name.
        handle:
          type: string
          description: 'URL-safe slug used as a path segment in all project-scoped
            API routes.

            Unique within the org. Immutable after creation.

            '
        description:
          type: string
          description: Optional human-readable description.
        created_by:
          type: string
          description: User ID of the org member who created this project.
        created_at:
          type: string
          format: date-time
          description: Timestamp when this project was created.
        updated_at:
          type: string
          format: date-time
          description: Timestamp when this project was last updated.
    ProjectListResponse:
      type: object
      required:
      - items
      properties:
        items:
          type: array
          description: The list of results for this page.
          items:
            $ref: '#/components/schemas/Project'
    CreateProjectRequest:
      type: object
      required:
      - name
      properties:
        name:
          type: string
          description: Human-readable project name.
        handle:
          type: string
          description: 'URL-safe slug for API routes. Auto-derived from name if omitted.

            Must be unique within the org. Cannot be changed after creation.

            '
        description:
          type: string
          description: Optional human-readable description.
    UpdateProjectRequest:
      type: object
      properties:
        name:
          type: string
          description: Replacement human-readable name.
        description:
          type: string
          description: Replacement description.
    WebhookDeliveryStatus:
      type: string
      enum:
      - pending
      - processing
      - delivered
      - failed
      description: '`pending` — queued, not yet attempted.

        `processing` — currently being delivered.

        `delivered` — recipient returned 2xx.

        `failed` — all retry attempts exhausted.

        '
    Webhook:
      type: object
      required:
      - id
      - org_id
      - project_id
      - name
      - url
      - events
      - enabled
      - created_at
      - updated_at
      description: 'A project-level outgoing webhook subscription. When a subscribed

        event fires, Mobius POSTs the event payload to `url`.

        '
      properties:
        id:
          type: string
          description: Unique identifier for this webhook.
        org_id:
          type: string
          description: ID of the organization this webhook belongs to.
        project_id:
          type: string
          description: ID of the project this webhook belongs to.
        name:
          type: string
          description: Human-readable name, unique within the project.
        url:
          type: string
          description: The customer endpoint Mobius POSTs event payloads to.
        events:
          type: array
          items:
            type: string
          description: 'Subscribed event types. Use dot notation (`run.completed`,

            `run.failed`) or wildcards (`run.*` for all run events).

            '
        enabled:
          type: boolean
          description: When false, matching events are not delivered.
        created_by:
          type: string
          description: User ID of the org member who created this webhook.
        created_at:
          type: string
          format: date-time
          description: Timestamp when this webhook was created.
        updated_at:
          type: string
          format: date-time
          description: Timestamp when this webhook was last updated.
    WebhookListResponse:
      type: object
      required:
      - has_more
      properties:
        items:
          type: array
          description: The list of results for this page.
          items:
            $ref: '#/components/schemas/Webhook'
        next_cursor:
          type: string
          description: Opaque cursor to pass as `cursor` on the next request. Absent
            when `has_more` is false.
        has_more:
          type: boolean
          description: Whether additional pages are available.
    WebhookDelivery:
      type: object
      required:
      - id
      - webhook_id
      - org_id
      - event_type
      - status
      - attempts
      - created_at
      description: 'One delivery record for a webhook event. The daemon claims pending

        rows, POSTs the payload, and transitions to `delivered` or retries

        on failure. A delivery reaches `failed` only after exhausting all

        10 retry attempts.

        '
      properties:
        id:
          type: string
          description: Unique identifier for this delivery record.
        webhook_id:
          type: string
          description: ID of the webhook this delivery belongs to.
        org_id:
          type: string
          description: ID of the organization this delivery belongs to.
        run_id:
          type: string
          description: Run that triggered the event, when applicable.
        event_type:
          type: string
          description: The event type that triggered this delivery (e.g. `run.completed`).
        status:
          $ref: '#/components/schemas/WebhookDeliveryStatus'
        attempts:
          type: integer
          description: Number of delivery attempts made so far. Max 10.
        last_error:
          type: string
          description: Error message from the most recent failed attempt.
        created_at:
          type: string
          format: date-time
          description: Timestamp when this delivery was first attempted.
        delivered_at:
          type: string
          format: date-time
          description: Timestamp of the successful delivery. Absent until delivered.
    WebhookDeliveryListResponse:
      type: object
      required:
      - has_more
      properties:
        items:
          type: array
          description: The list of results for this page.
          items:
            $ref: '#/components/schemas/WebhookDelivery'
        next_cursor:
          type: string
          description: Opaque cursor to pass as `cursor` on the next request. Absent
            when `has_more` is false.
        has_more:
          type: boolean
          description: Whether additional pages are available.
    CreateWebhookRequest:
      type: object
      required:
      - name
      - url
      - events
      properties:
        name:
          type: string
          description: Human-readable name, unique within the project.
        url:
          type: string
          description: The endpoint Mobius will POST event payloads to.
        secret:
          type: string
          description: 'Optional shared secret. When set, Mobius signs each POST body

            with HMAC-SHA256 and includes `X-Mobius-Signature: sha256=<hex>`

            in the request headers.

            '
        events:
          type: array
          items:
            type: string
          description: 'Event types to subscribe to. Use wildcards for broad

            subscriptions, e.g. `["run.*"]` for all run events.

            '
        enabled:
          type: boolean
          default: true
          description: Whether the webhook starts enabled. Defaults to true.
    UpdateWebhookRequest:
      type: object
      properties:
        name:
          type: string
          description: Replacement human-readable name.
        url:
          type: string
          description: Replacement endpoint URL.
        secret:
          type: string
          description: 'Replace the current signing secret. Set to empty string to

            disable signing. Omit to leave the current secret unchanged.

            '
        events:
          type: array
          items:
            type: string
          description: Replacement event subscriptions. Replaces the entire current
            list.
        enabled:
          type: boolean
          description: Set to false to disable delivery without deleting the webhook.
    IntegrationStatus:
      type: string
      enum:
      - active
      - inactive
      - expired
      description: '`active` — integration is enabled and usable by workflows.

        `inactive` — manually disabled; no automatic expiry behavior.

        `expired` — token/credential has expired (e.g., OAuth token not refreshed).

        '
    Integration:
      type: object
      required:
      - id
      - org_id
      - name
      - provider
      - status
      - created_at
      - updated_at
      properties:
        id:
          type: string
          description: Unique identifier for this integration.
        org_id:
          type: string
          description: ID of the organization this integration belongs to.
        name:
          type: string
          description: Human-readable name, unique per `(project, provider)` tuple.
        provider:
          type: string
          description: 'Free-form provider identifier (e.g. `openai`, `slack`, `github`).

            Immutable after creation.

            '
        config:
          type: object
          additionalProperties: true
          description: 'Provider-specific credential and configuration blob stored
            as

            JSON. The shape is provider-defined.

            '
        status:
          $ref: '#/components/schemas/IntegrationStatus'
        created_by:
          type: string
          description: User ID of the org member who created this integration.
        created_at:
          type: string
          format: date-time
          description: Timestamp when this integration was created.
        updated_at:
          type: string
          format: date-time
          description: Timestamp when this integration was last updated.
    IntegrationListResponse:
      type: object
      required:
      - data
      - has_more
      properties:
        items:
          type: array
          description: The list of results for this page.
          items:
            $ref: '#/components/schemas/Integration'
        next_cursor:
          type: string
          description: Opaque cursor to pass as `cursor` on the next request. Absent
            when `has_more` is false.
        has_more:
          type: boolean
          description: Whether additional pages are available.
    CreateIntegrationRequest:
      type: object
      required:
      - name
      - provider
      properties:
        name:
          type: string
          description: Human-readable name. Must be unique per `(project, provider)`
            tuple.
        provider:
          type: string
          description: Provider identifier string (e.g. `openai`, `github`). Immutable
            after creation.
        credentials:
          type: object
          additionalProperties: true
          description: Sensitive credentials (API keys, tokens, secrets). Stored encrypted
            and never returned in API responses.
        config:
          type: object
          additionalProperties: true
          description: Non-sensitive provider-specific settings (e.g. default bucket,
            from address).
    UpdateIntegrationRequest:
      type: object
      properties:
        name:
          type: string
          description: Updated display name.
        credentials:
          type: object
          additionalProperties: true
          description: Replacement credentials blob (full replace). Stored encrypted
            and never returned in API responses.
        config:
          type: object
          additionalProperties: true
          description: Replacement config blob (full replace, not merge).
        status:
          $ref: '#/components/schemas/IntegrationStatus'
    CopyIntegrationRequest:
      type: object
      required:
      - source_project_id
      - source_integration_id
      properties:
        source_project_id:
          type: string
          description: ID of the source project. Must be in the same org.
        source_integration_id:
          type: string
          description: ID of the integration to copy from the source project.
        name:
          type: string
          description: 'Name for the copied integration in the destination project.

            Defaults to the source integration''s name. Required if the

            source name conflicts with an existing `(provider, name)` in

            this project.

            '
    BillingSubscription:
      type: object
      required:
      - id
      - org_id
      - plan_type
      - status
      - seat_count
      - current_period_start
      - current_period_end
      - trial_days_remaining
      - trial_warning
      - monthly_credit_cap
      - per_run_step_cap
      - alert_thresholds_percent
      - cancel_at_period_end
      - created_at
      - updated_at
      properties:
        id:
          type: string
          description: Unique identifier for this subscription.
        org_id:
          type: string
          description: ID of the organization this subscription belongs to.
        plan_type:
          type: string
          description: 'Active plan: `trial`, `free`, `pro`, or `business`. New orgs

            start on `trial`; the plan downgrades to `free` when the trial

            expires.

            '
        status:
          type: string
          description: 'Stripe subscription status: `active`, `trialing`, `past_due`,

            `canceled`, `unpaid`, or `incomplete`.

            '
        seat_count:
          type: integer
          description: Number of licensed seats included in the subscription.
        current_period_start:
          type: string
          format: date-time
          description: Start of the current billing period.
        current_period_end:
          type: string
          format: date-time
          description: End of the current billing period. Usage resets at this timestamp.
        trial_ends_at:
          type: string
          format: date-time
          description: When the trial period expires. Only set for `trial` plan.
        grace_ends_at:
          type: string
          format: date-time
          description: 'When the post-expiry grace period ends. During grace, the
            org

            retains access but is prompted to upgrade.

            '
        trial_days_remaining:
          type: integer
          description: Days remaining in the trial. 0 when the trial has ended.
        trial_warning:
          type: boolean
          description: True when fewer than 7 days remain in the trial period.
        monthly_credit_cap:
          type: integer
          format: int64
          description: 'Maximum usage credits allowed per billing period. Workflow

            execution is blocked when this cap is reached.

            '
        per_run_step_cap:
          type: integer
          description: 'Maximum number of job steps allowed per individual workflow
            run.

            Default: 10,000 (pro/trial), 50,000 (business).

            '
        alert_thresholds_percent:
          type: array
          items:
            type: integer
          description: 'Percentage levels (1–100) of `monthly_credit_cap` at which
            usage

            alert notifications are sent. Up to `max_alert_thresholds` from

            the plan.

            '
        cancel_at_period_end:
          type: boolean
          description: When true, the subscription will not renew at `current_period_end`.
        created_at:
          type: string
          format: date-time
          description: Timestamp when this subscription was created.
        updated_at:
          type: string
          format: date-time
          description: Timestamp when this subscription was last updated.
    BillingPlan:
      type: object
      required:
      - plan_type
      - price_cents
      - included_credits
      - seat_limit
      - default_monthly_credit_cap
      - default_per_run_step_cap
      - max_alert_thresholds
      - trial_days
      - credit_card_required
      properties:
        plan_type:
          type: string
          description: Plan name — `trial`, `pro`, or `business`.
        price_cents:
          type: integer
          description: Monthly price in cents (USD).
        included_credits:
          type: integer
          format: int64
          description: Usage credits included in the base price.
        seat_limit:
          type: integer
          description: Maximum org members on this plan. 0 means unlimited.
        default_monthly_credit_cap:
          type: integer
          format: int64
          description: Default `monthly_credit_cap` applied to new subscriptions on
            this plan.
        default_per_run_step_cap:
          type: integer
          description: Default `per_run_step_cap` applied to new subscriptions on
            this plan.
        max_alert_thresholds:
          type: integer
          description: Maximum number of alert thresholds configurable on this plan.
        trial_days:
          type: integer
          description: Trial period length in days. 0 for plans without a trial.
        credit_card_required:
          type: boolean
          description: When true, a payment method is required to start this plan.
    BillingPlanListResponse:
      type: object
      required:
      - items
      properties:
        items:
          type: array
          description: The list of available plans.
          items:
            $ref: '#/components/schemas/BillingPlan'
    BillingUsageKeySummary:
      type: object
      required:
      - api_key_id
      - count
      properties:
        api_key_id:
          type: string
          description: The API key responsible for this usage.
        count:
          type: integer
          description: Number of usage records attributed to this key in the current
            period.
    BillingUsageSummary:
      type: object
      required:
      - current_period_start
      - current_period_end
      - current_usage
      - included_limit
      - overage_calls
      - overage_cost
      - by_category
      - by_api_key
      properties:
        current_period_start:
          type: string
          format: date-time
          description: Start of the current billing period.
        current_period_end:
          type: string
          format: date-time
          description: End of the current billing period.
        current_usage:
          type: integer
          description: Total usage credits consumed in the current billing period.
        included_limit:
          type: integer
          description: Included credits from the plan before overage applies.
        overage_calls:
          type: integer
          description: Number of usage records that exceed the included limit.
        overage_cost:
          type: integer
          description: Estimated overage cost in cents for the current period.
        by_category:
          type: object
          additionalProperties:
            type: integer
          description: Usage breakdown by resource category (e.g. `run`, `job`).
        by_api_key:
          type: array
          items:
            $ref: '#/components/schemas/BillingUsageKeySummary'
          description: Per-API-key usage breakdown for cost attribution.
    Invoice:
      type: object
      required:
      - id
      - status
      - currency
      - amount_due
      - amount_paid
      - created_at
      properties:
        id:
          type: string
          description: Stripe invoice ID.
        status:
          type: string
          description: Stripe invoice status (`draft`, `open`, `paid`, `void`, `uncollectible`).
        currency:
          type: string
          description: ISO 4217 currency code (e.g. `usd`).
        amount_due:
          type: integer
          description: Total amount due in the smallest currency unit (e.g. cents).
        amount_paid:
          type: integer
          description: Amount already paid against this invoice.
        hosted_invoice_url:
          type: string
          format: uri
          description: Stripe-hosted invoice page URL for the customer.
        invoice_pdf:
          type: string
          format: uri
          description: Direct link to the invoice PDF.
        created_at:
          type: string
          format: date-time
          description: Timestamp when this invoice was created by Stripe.
    InvoiceListResponse:
      type: object
      required:
      - items
      properties:
        items:
          type: array
          description: The list of recent invoices, newest first.
          items:
            $ref: '#/components/schemas/Invoice'
    CreateCheckoutRequest:
      type: object
      required:
      - success_url
      - cancel_url
      properties:
        success_url:
          type: string
          format: uri
          description: URL Stripe redirects to after a successful checkout.
        cancel_url:
          type: string
          format: uri
          description: URL Stripe redirects to when the user cancels checkout.
    CreatePortalRequest:
      type: object
      required:
      - return_url
      properties:
        return_url:
          type: string
          format: uri
          description: URL Stripe redirects to after the user exits the customer portal.
    BillingURLResult:
      type: object
      required:
      - url
      properties:
        url:
          type: string
          format: uri
          description: Stripe-hosted URL to redirect the user's browser to.
    UpdateBillingLimitsRequest:
      type: object
      properties:
        monthly_credit_cap:
          type: integer
          format: int64
          description: 'New monthly credit ceiling. When reached, workflow execution
            is

            blocked until the next billing period.

            '
        per_run_step_cap:
          type: integer
          description: 'Maximum job steps per workflow run. Prevents runaway runs
            from

            consuming unbounded credits.

            '
        alert_thresholds_percent:
          type: array
          items:
            type: integer
          description: 'Replacement list of alert threshold percentages (1–100). Replaces

            the full existing list. Must not exceed the plan''s

            `max_alert_thresholds`.

            '
    OnboardingStatus:
      type: object
      required:
      - completed
      properties:
        completed:
          type: boolean
          description: Whether the user has completed onboarding and has an org
        org_id:
          type: string
          description: The user's org ID (present only when completed is true)
        org_name:
          type: string
          description: The user's org display name (present only when completed is
            true)
    OnboardingResult:
      type: object
      required:
      - org_id
      - org_name
      properties:
        org_id:
          type: string
          description: ID of the newly created (or existing) org
        org_name:
          type: string
          description: Display name of the org
    ProjectMetrics:
      type: object
      required:
      - generated_at
      - window_minutes
      - runs_per_minute
      - total_runs_window
      - failure_rate
      - avg_run_seconds
      - p95_step_seconds
      - queue_depth
      - running_count
      - active_workers
      - stale_workers
      - status_breakdown
      properties:
        generated_at:
          type: string
          format: date-time
          description: Timestamp when this metrics snapshot was computed.
        window_minutes:
          type: integer
          description: Rolling window width used for rate and failure metrics. Default
            is 60 minutes.
        runs_per_minute:
          type: number
          format: double
          description: Average number of new workflow runs started per minute within
            the window.
        total_runs_window:
          type: integer
          description: Total number of workflow runs started within the window.
        failure_rate:
          type: number
          format: double
          description: 'Fraction of completed runs that ended in `failed` status within

            the window. Range 0.0–1.0.

            '
        avg_run_seconds:
          type: number
          format: double
          description: 'Mean wall-clock duration of completed runs within the window,

            in seconds.

            '
        p95_step_seconds:
          type: number
          format: double
          description: '95th-percentile job duration (claim time to terminal state)

            computed across the 40 most recent completed jobs, in seconds.

            Use this to detect slow or stuck steps.

            '
        queue_depth:
          type: integer
          description: Number of jobs currently in `pending` state waiting to be claimed.
        running_count:
          type: integer
          description: Number of workflow runs currently in `running` or `suspended`
            state.
        active_workers:
          type: integer
          description: Number of workers whose `last_seen_at` is within the 2-minute
            staleness threshold.
        stale_workers:
          type: integer
          description: Number of workers whose `last_seen_at` has exceeded the 2-minute
            staleness threshold.
        status_breakdown:
          type: object
          additionalProperties:
            type: integer
          description: 'Map of workflow run status → count across all runs in the
            project

            (not windowed). Includes all terminal and in-progress statuses.

            '
    PreviewPermissionsRequest:
      type: object
      properties:
        service_account_default_role:
          type: string
          description: 'Role name assigned as a fallback to service accounts that
            have no

            explicit assignment at the time of preview.

            '
    EnablePermissionsRequest:
      type: object
      properties:
        service_account_default_role:
          type: string
          description: 'Fallback role name for service accounts with no existing assignment.

            Applied only to service accounts not covered by the `assignments` list.

            '
        assignments:
          type: array
          description: Explicit role assignments to create as part of the enable operation.
          items:
            $ref: '#/components/schemas/PermissionsAssignmentInput'
    PermissionsAssignmentInput:
      type: object
      required:
      - actor_type
      - actor_id
      properties:
        actor_type:
          type: string
          enum:
          - user
          - service_account
          description: 'Actor type: `user` or `service_account`.'
        actor_id:
          type: string
          description: ID of the user or service account.
        role_id:
          type: string
          description: Mutually exclusive with `role_name`.
        role_name:
          type: string
          description: Resolved to a role ID server-side. Mutually exclusive with
            `role_id`.
        project_id:
          type: string
          description: Scope this assignment to a project. Omit for org-wide.
    PermissionsAssignmentProposal:
      type: object
      required:
      - actor_type
      - actor_id
      - role_id
      - role_name
      properties:
        actor_type:
          type: string
          enum:
          - user
          - service_account
          description: 'Actor type: `user` or `service_account`.'
        actor_id:
          type: string
          description: ID of the user or service account.
        role_id:
          type: string
          description: ID of the role that would be assigned.
        role_name:
          type: string
          description: Name of the role that would be assigned.
        project_id:
          type: string
          description: Project scope for the assignment. Null for org-wide assignments.
    PermissionsPlan:
      type: object
      required:
      - permissions_enabled
      - assignments
      description: Current or proposed permissions state, including the full set of
        role assignments.
      properties:
        permissions_enabled:
          type: boolean
          description: Whether enforcement is currently (or will be after enable)
            active.
        assignments:
          type: array
          description: The set of role assignments that will be created on enable.
          items:
            $ref: '#/components/schemas/PermissionsAssignmentProposal'
    PermissionsState:
      type: object
      required:
      - permissions_enabled
      properties:
        permissions_enabled:
          type: boolean
          description: Whether enforcement is currently active for the org.
    Role:
      type: object
      required:
      - id
      - name
      - description
      - permissions
      - system_defined
      - created_at
      - updated_at
      properties:
        id:
          type: string
          description: Unique identifier for this role.
        org_id:
          type: string
          description: Owning org. Empty for system-defined roles.
        project_id:
          type: string
          description: Scoping project. Empty for org-wide roles.
        name:
          type: string
          description: Human-readable role name, unique within org+project scope.
        description:
          type: string
          description: Optional human-readable description of what this role grants.
        permissions:
          type: array
          items:
            type: string
          description: Permission strings granted by this role (e.g. "mobius.job.claim").
        system_defined:
          type: boolean
          description: True for built-in platform roles that cannot be modified or
            deleted.
        created_at:
          type: string
          format: date-time
          description: Timestamp when this role was created.
        updated_at:
          type: string
          format: date-time
          description: Timestamp when this role was last updated.
    RoleAssignment:
      type: object
      required:
      - id
      - org_id
      - actor_type
      - actor_id
      - role_id
      - role_name
      - created_at
      properties:
        id:
          type: string
          description: Unique identifier for this role assignment.
        org_id:
          type: string
          description: ID of the organization this assignment belongs to.
        actor_type:
          type: string
          enum:
          - user
          - service_account
          description: 'Type of actor this assignment applies to: `user` or `service_account`.'
        actor_id:
          type: string
          description: User ID or service account ID receiving the role.
        role_id:
          type: string
          description: ID of the assigned role.
        role_name:
          type: string
          description: Name of the assigned role.
        project_id:
          type: string
          description: Set for project-scoped assignments; empty for org-wide.
        granted_by_actor_type:
          type: string
          description: Actor type of the caller who created this assignment.
        granted_by_actor_id:
          type: string
          description: Actor ID of the caller who created this assignment.
        created_at:
          type: string
          format: date-time
          description: Timestamp when this assignment was created.
    RoleListResponse:
      type: object
      required:
      - items
      properties:
        items:
          type: array
          description: The list of results for this page.
          items:
            $ref: '#/components/schemas/Role'
    RoleAssignmentListResponse:
      type: object
      required:
      - items
      properties:
        items:
          type: array
          description: The list of results for this page.
          items:
            $ref: '#/components/schemas/RoleAssignment'
    CreateRoleRequest:
      type: object
      required:
      - name
      - permissions
      properties:
        project_id:
          type: string
          description: Scope the role to a project. Omit for an org-wide role.
        name:
          type: string
          description: Unique name within the org+project scope.
        description:
          type: string
          description: Optional human-readable description of what this role grants.
        permissions:
          type: array
          items:
            type: string
          description: Permission strings to include (e.g. "mobius.workflow.create").
    UpdateRoleRequest:
      type: object
      properties:
        project_id:
          type: string
          description: Scope to change this role to. Cannot change an org-scoped role
            to project-scoped after creation.
        name:
          type: string
          description: Replacement role name.
        description:
          type: string
          description: Replacement description.
        permissions:
          type: array
          items:
            type: string
          description: Replaces the existing permissions array entirely.
    CreateRoleAssignmentRequest:
      type: object
      required:
      - actor_type
      - actor_id
      properties:
        actor_type:
          type: string
          enum:
          - user
          - service_account
          description: 'Type of actor to assign the role to: `user` or `service_account`.'
        actor_id:
          type: string
          description: User ID or service account ID to assign the role to.
        role_id:
          type: string
          description: Mutually exclusive with `role_name`.
        role_name:
          type: string
          description: Resolved to a role ID server-side. Mutually exclusive with
            `role_id`.
        project_id:
          type: string
          description: Scope this assignment to a project. Omit for org-wide assignment.
    User:
      type: object
      required:
      - id
      - email
      - created_at
      - updated_at
      properties:
        id:
          type: string
          description: Clerk user ID. Stable and globally unique across all orgs.
        email:
          type: string
          description: Primary email address from Clerk.
        first_name:
          type: string
          description: User's first name from their Clerk profile.
        last_name:
          type: string
          description: User's last name from their Clerk profile.
        avatar_url:
          type: string
          description: Profile avatar URL from Clerk (may be a Gravatar or uploaded
            image).
        created_at:
          type: string
          format: date-time
          description: When the user record was first mirrored into Mobius.
        updated_at:
          type: string
          format: date-time
          description: Timestamp when this user record was last synced from Clerk.
    Org:
      type: object
      required:
      - id
      - name
      - handle
      - created_at
      - updated_at
      properties:
        id:
          type: string
          description: Unique identifier for this organization.
        name:
          type: string
          description: Human-readable org name.
        handle:
          type: string
          description: URL-safe slug used in API routes and display. Unique across
            all orgs.
        metadata:
          type: object
          additionalProperties: true
          description: Arbitrary key-value metadata stored alongside the org.
        created_at:
          type: string
          format: date-time
          description: Timestamp when this organization was created.
        updated_at:
          type: string
          format: date-time
          description: Timestamp when this organization was last updated.
    OrgListResponse:
      type: object
      required:
      - items
      properties:
        items:
          type: array
          description: The list of results for this page.
          items:
            $ref: '#/components/schemas/Org'
        has_more:
          type: boolean
          description: Whether additional pages are available.
        next_cursor:
          type: string
          description: Opaque cursor to pass as `cursor` on the next request. Absent
            when `has_more` is false.
    CreateOrgRequest:
      type: object
      required:
      - name
      - handle
      properties:
        name:
          type: string
          description: Human-readable organization name.
        handle:
          type: string
          description: URL-safe slug. Must be globally unique across all orgs.
        metadata:
          type: object
          additionalProperties: true
          description: Arbitrary metadata to attach to the organization.
    UpdateOrgRequest:
      type: object
      properties:
        name:
          type: string
          description: Must be non-empty if provided.
        handle:
          type: string
          description: Must be non-empty if provided. Changing the handle affects
            all API route URLs for this org.
        metadata:
          type: object
          additionalProperties: true
          description: Replacement metadata.
    OrgMember:
      type: object
      required:
      - id
      - org_id
      - user_id
      - role
      - created_at
      - updated_at
      properties:
        id:
          type: string
          description: Unique identifier for this membership record.
        org_id:
          type: string
          description: ID of the organization.
        user_id:
          type: string
          description: ID of the user who is a member.
        role:
          type: string
          enum:
          - owner
          - admin
          - member
          description: '`owner` has full control including org deletion; `admin` can
            manage members and settings; `member` has read-only org access.'
        created_at:
          type: string
          format: date-time
          description: Timestamp when this member joined.
        updated_at:
          type: string
          format: date-time
          description: Timestamp when this membership was last updated.
        user:
          $ref: '#/components/schemas/User'
    OrgMemberListResponse:
      type: object
      required:
      - items
      properties:
        items:
          type: array
          description: The list of results for this page.
          items:
            $ref: '#/components/schemas/OrgMember'
        has_more:
          type: boolean
          description: Whether additional pages are available.
        next_cursor:
          type: string
          description: Opaque cursor to pass as `cursor` on the next request. Absent
            when `has_more` is false.
    AddOrgMemberRequest:
      type: object
      required:
      - user_id
      - role
      properties:
        user_id:
          type: string
          description: Clerk user ID of the user to add.
        role:
          type: string
          enum:
          - owner
          - admin
          - member
          description: 'Role to assign the new member: `owner`, `admin`, or `member`.'
    UpdateOrgMemberRoleRequest:
      type: object
      required:
      - role
      properties:
        role:
          type: string
          enum:
          - owner
          - admin
          - member
          description: 'New role to assign: `owner`, `admin`, or `member`.'
    InteractionListResponse:
      type: object
      required:
      - items
      properties:
        items:
          type: array
          description: The list of results for this page.
          items:
            $ref: '#/components/schemas/Interaction'
    CreateInteractionRequest:
      type: object
      required:
      - type
      - target_actor
      - message
      description: 'Creates an interaction directly. When `run_id` is provided, `topic`
        is

        also required and the interaction is linked to that run. When both are

        omitted, the interaction is standalone and completes with no workflow

        resume side effect. For worker/job usage, prefer the job-scoped route

        so the server can derive the owning run from the claimed job context.

        '
      properties:
        run_id:
          type: string
          nullable: true
          description: ID of the workflow run to resume when this interaction is completed.
        topic:
          type: string
          nullable: true
          description: Signal topic the interaction will complete against when run-backed.
        target_actor:
          $ref: '#/components/schemas/ActorRef'
        type:
          $ref: '#/components/schemas/InteractionType'
        message:
          type: string
          description: Message shown to the responder describing what response is
            needed.
        context:
          type: object
          additionalProperties: true
          description: Additional key-value context surfaced in the UI alongside the
            message.
        spec:
          $ref: '#/components/schemas/InteractionSpec'
        require_all:
          type: boolean
          default: false
          description: 'When target_actor.type is "group", setting require_all=true

            means all snapshotted group members must respond before the

            interaction is considered complete. Ignored for non-group targets.

            '
        expires_at:
          type: string
          format: date-time
          description: Timestamp after which this interaction expires if not responded
            to.
    RespondToInteractionRequest:
      type: object
      properties:
        value:
          $ref: '#/components/schemas/InteractionValue'
        comment:
          type: string
          description: Optional free-text comment accompanying the response.
    SlackInstall:
      type: object
      required:
      - authorize_url
      properties:
        authorize_url:
          type: string
          description: The Slack OAuth authorize URL to redirect the user to.
    Group:
      type: object
      required:
      - id
      - org_id
      - handle
      - name
      - routing_policy
      - created_at
      - updated_at
      properties:
        id:
          type: string
          description: Unique identifier for this group.
        org_id:
          type: string
          description: ID of the organization this group belongs to.
        handle:
          type: string
          description: URL-safe identifier, unique within the project. Immutable after
            creation.
        name:
          type: string
          description: Human-readable display name.
        description:
          type: string
          description: Optional human-readable description.
        routing_policy:
          type: string
          enum:
          - first_responder
          - all_members
          description: 'How interactions targeting this group collect responses.

            `first_responder`: first member to claim or respond wins.

            `all_members`: every snapshotted member must respond.

            '
        created_at:
          type: string
          format: date-time
          description: Timestamp when this group was created.
        updated_at:
          type: string
          format: date-time
          description: Timestamp when this group was last updated.
    GroupListResponse:
      type: object
      required:
      - items
      properties:
        items:
          type: array
          description: The list of results for this page.
          items:
            $ref: '#/components/schemas/Group'
    GroupWithCount:
      allOf:
      - $ref: '#/components/schemas/Group'
      - type: object
        required:
        - member_count
        properties:
          member_count:
            type: integer
            description: Current live member count. May differ from interaction membership
              snapshots.
    GroupWithCountListResponse:
      type: object
      required:
      - items
      properties:
        items:
          type: array
          description: The list of results for this page.
          items:
            $ref: '#/components/schemas/GroupWithCount'
        has_more:
          type: boolean
          description: Whether additional pages are available.
        next_cursor:
          type: string
          description: Opaque cursor to pass as `cursor` on the next request. Absent
            when `has_more` is false.
    GroupMember:
      type: object
      required:
      - id
      - group_id
      - org_id
      - user_id
      - added_at
      properties:
        id:
          type: string
          description: Unique identifier for this membership record.
        group_id:
          type: string
          description: ID of the group this membership belongs to.
        org_id:
          type: string
          description: ID of the organization this group belongs to.
        user_id:
          type: string
          description: ID of the user who is a member.
        added_by:
          type: string
          nullable: true
          description: User ID of the org member who added this person to the group.
        added_at:
          type: string
          format: date-time
          description: Timestamp when this member was added to the group.
    GroupMemberListResponse:
      type: object
      required:
      - items
      properties:
        items:
          type: array
          description: The list of results for this page.
          items:
            $ref: '#/components/schemas/GroupMember'
        has_more:
          type: boolean
          description: Whether additional pages are available.
        next_cursor:
          type: string
          description: Opaque cursor to pass as `cursor` on the next request. Absent
            when `has_more` is false.
    CreateGroupRequest:
      type: object
      required:
      - name
      properties:
        handle:
          type: string
          description: URL-safe handle, unique within the project. Auto-derived from
            name if omitted.
        name:
          type: string
          description: Display name (1–64 chars).
        description:
          type: string
          description: Optional human-readable description.
        routing_policy:
          type: string
          enum:
          - first_responder
          - all_members
          default: first_responder
          description: How responses are collected from group members. Defaults to
            `first_responder`.
    UpdateGroupRequest:
      type: object
      properties:
        name:
          type: string
          description: Replacement human-readable name.
        description:
          type: string
          description: Replacement description.
        routing_policy:
          type: string
          enum:
          - first_responder
          - all_members
          description: Affects future interactions only; in-flight interactions retain
            the snapshotted policy.
    AddGroupMemberRequest:
      type: object
      required:
      - user_id
      properties:
        user_id:
          type: string
          description: Org member user ID to add. Must be a current org member.
    AgentStatus:
      type: string
      enum:
      - active
      - inactive
      description: Administrative status. Inactive agents cannot claim new jobs.
    AgentPresence:
      type: string
      enum:
      - online
      - offline
      - stale
      description: 'Computed from the most recent 20 sessions. `online` means a connected

        session with a fresh heartbeat; `stale` means heartbeats are overdue;

        `offline` means no connected sessions.

        '
    AgentSessionStatus:
      type: string
      enum:
      - connected
      - disconnected
      - stale
    Agent:
      type: object
      required:
      - id
      - org_id
      - service_account_id
      - name
      - display_name
      - status
      - presence
      - created_at
      - updated_at
      properties:
        id:
          type: string
          description: Unique identifier for this agent.
        org_id:
          type: string
          description: ID of the organization this agent belongs to.
        service_account_id:
          type: string
          description: The service account whose credentials this agent uses to authenticate.
            Immutable after creation.
        name:
          type: string
          description: Unique name within the project, used for targeting in job claims.
        display_name:
          type: string
          description: Human-readable label shown in the UI.
        description:
          type: string
          description: Optional human-readable description.
        kind:
          type: string
          description: Freeform agent classification for tooling and filtering (e.g.
            "llm", "rpa").
        capabilities:
          type: object
          additionalProperties: true
          description: Arbitrary capability map used by orchestrators to select suitable
            agents.
        config:
          type: object
          additionalProperties: true
          description: Agent-specific configuration blob stored and returned opaquely.
        status:
          $ref: '#/components/schemas/AgentStatus'
        presence:
          $ref: '#/components/schemas/AgentPresence'
        created_at:
          type: string
          format: date-time
          description: Timestamp when this agent was created.
        updated_at:
          type: string
          format: date-time
          description: Timestamp when this agent was last updated.
    AgentSession:
      type: object
      required:
      - id
      - org_id
      - agent_id
      - status
      - transport
      - created_at
      - updated_at
      properties:
        id:
          type: string
          description: Unique identifier for this session.
        org_id:
          type: string
          description: ID of the organization this session belongs to.
        agent_id:
          type: string
          description: ID of the agent this session belongs to.
        status:
          $ref: '#/components/schemas/AgentSessionStatus'
        transport:
          type: string
          description: Connection mechanism identifier (e.g. "sse", "polling").
        metadata:
          type: object
          additionalProperties: true
          description: Caller-supplied metadata (e.g. hostname, version, region).
        connected_at:
          type: string
          format: date-time
          nullable: true
          description: Timestamp when this session was established.
        last_seen_at:
          type: string
          format: date-time
          nullable: true
          description: Timestamp of the most recent heartbeat.
        disconnected_at:
          type: string
          format: date-time
          nullable: true
          description: Timestamp when this session was closed. Null while connected.
        created_at:
          type: string
          format: date-time
          description: Timestamp when this session record was created.
        updated_at:
          type: string
          format: date-time
          description: Timestamp when this session was last updated.
    AgentListResponse:
      type: object
      required:
      - items
      properties:
        items:
          type: array
          description: The list of results for this page.
          items:
            $ref: '#/components/schemas/Agent'
    AgentSessionListResponse:
      type: object
      required:
      - items
      properties:
        items:
          type: array
          description: The list of results for this page.
          items:
            $ref: '#/components/schemas/AgentSession'
    CreateAgentRequest:
      type: object
      required:
      - service_account_id
      - name
      properties:
        service_account_id:
          type: string
          description: Service account that backs this agent. Must belong to the same
            org.
        name:
          type: string
          description: Project-scoped unique identifier for this agent.
        display_name:
          type: string
          description: Human-readable label shown in the UI.
        description:
          type: string
          description: Optional human-readable description.
        kind:
          type: string
          description: Freeform classification (e.g. "llm", "rpa", "integration").
        capabilities:
          type: object
          additionalProperties: true
          description: Arbitrary capability map used by orchestrators to select suitable
            agents.
        config:
          type: object
          additionalProperties: true
          description: Agent-specific configuration stored and returned opaquely.
    UpdateAgentRequest:
      type: object
      properties:
        display_name:
          type: string
          description: Replacement human-readable label.
        description:
          type: string
          description: Replacement description.
        kind:
          type: string
          description: Replacement freeform agent classification (e.g. `llm`, `rpa`).
        capabilities:
          type: object
          additionalProperties: true
          description: Replacement capability map.
        config:
          type: object
          additionalProperties: true
          description: Replacement configuration blob.
        status:
          $ref: '#/components/schemas/AgentStatus'
    CreateAgentSessionRequest:
      type: object
      required:
      - transport
      properties:
        transport:
          type: string
          description: Connection mechanism identifier (e.g. "sse", "polling").
        metadata:
          type: object
          additionalProperties: true
          description: Optional metadata such as hostname, SDK version, or region.
    ServiceAccountStatus:
      type: string
      enum:
      - active
      - disabled
      description: '`disabled` blocks authentication and job claims but preserves
        the record and its assignments.'
    ServiceAccount:
      type: object
      required:
      - id
      - org_id
      - name
      - display_name
      - status
      - created_at
      - updated_at
      properties:
        id:
          type: string
          description: Unique identifier for this service account.
        org_id:
          type: string
          description: ID of the organization this service account belongs to.
        name:
          type: string
          description: Stable machine-readable identifier, unique within the project.
            Immutable after creation.
        display_name:
          type: string
          description: Human-readable label shown in the UI.
        description:
          type: string
          description: Optional human-readable description.
        status:
          $ref: '#/components/schemas/ServiceAccountStatus'
        owner_user_id:
          type: string
          description: Optional org member responsible for this service account.
        metadata:
          type: object
          additionalProperties: true
          description: Arbitrary key-value metadata. Subject to size and nesting depth
            limits.
        created_at:
          type: string
          format: date-time
          description: Timestamp when this service account was created.
        updated_at:
          type: string
          format: date-time
          description: Timestamp when this service account was last updated.
    ServiceAccountListResponse:
      type: object
      required:
      - items
      properties:
        items:
          type: array
          description: The list of results for this page.
          items:
            $ref: '#/components/schemas/ServiceAccount'
    CreateServiceAccountRequest:
      type: object
      required:
      - name
      properties:
        name:
          type: string
          description: Stable machine-readable identifier, unique within the project.
        display_name:
          type: string
          description: Human-readable label shown in the UI.
        description:
          type: string
          description: Optional human-readable description.
        owner_user_id:
          type: string
          description: Org member responsible for this service account.
        metadata:
          type: object
          additionalProperties: true
          description: Arbitrary metadata to attach to the service account.
        role_id:
          type: string
          description: 'Role to assign at creation time. Mutually exclusive with `role_name`.

            Requires `permission.manage`. The role must belong to this project

            or be org-scoped (project_id empty).

            '
        role_name:
          type: string
          description: 'Role name to assign at creation time (resolved to a role ID
            server-side).

            Mutually exclusive with `role_id`. Requires `permission.manage`.

            '
    UpdateServiceAccountRequest:
      type: object
      properties:
        display_name:
          type: string
          description: Replacement human-readable label.
        description:
          type: string
          description: Replacement description.
        status:
          $ref: '#/components/schemas/ServiceAccountStatus'
        owner_user_id:
          type: string
          description: ID of the org member responsible for this service account.
        metadata:
          type: object
          additionalProperties: true
          description: Replacement metadata.
    ToolDefinition:
      type: object
      required:
      - name
      - description
      - input_schema
      properties:
        name:
          type: string
          description: Tool name (workflow handle). Stable across publish/unpublish
            cycles.
        description:
          type: string
          description: Human-readable description of what the tool does.
        input_schema:
          type: object
          description: JSON Schema Draft 7 object describing the tool inputs.
          additionalProperties: true
    ToolDefinitionListResponse:
      type: object
      required:
      - items
      properties:
        items:
          type: array
          description: The list of published workflow tools.
          items:
            $ref: '#/components/schemas/ToolDefinition'
    ToolRunRequest:
      type: object
      properties:
        input:
          type: object
          description: Input values matching the tool's input_schema.
          additionalProperties: true
        timeout_seconds:
          type: integer
          description: 'How long (in seconds) to wait for synchronous completion.

            Default 30, max 120. If the run does not complete within this

            window the response is 202 with status pending.

            '
          minimum: 1
          maximum: 120
    ToolRun:
      type: object
      required:
      - run_id
      - status
      properties:
        run_id:
          type: string
          description: Unique run identifier for polling.
        status:
          type: string
          description: Run status — "pending", "running", "completed", or "failed".
          enum:
          - pending
          - running
          - completed
          - failed
          - suspended
        output:
          type: object
          description: Run output. Present when status is "completed".
          additionalProperties: true
        error:
          type: string
          description: Error message. Present when status is "failed".
x-tagGroups:
- name: Channels
  tags:
  - channels
- name: Audit Logs
  tags:
  - audit-logs
- name: API Keys
  tags:
  - api-keys
- name: Workflows
  tags:
  - workflows
  - runs
- name: Actions
  tags:
  - actions
- name: Jobs (Worker Protocol)
  tags:
  - jobs
- name: Triggers
  tags:
  - triggers
- name: Workers
  tags:
  - workers
- name: Projects
  tags:
  - projects
- name: Webhooks
  tags:
  - webhooks
- name: Integrations
  tags:
  - integrations
- name: Metrics
  tags:
  - metrics
- name: Roles
  tags:
  - roles
- name: Interactions
  tags:
  - interactions
- name: Groups
  tags:
  - groups
- name: Agents
  tags:
  - agents
- name: Tools
  tags:
  - tools
