openapi: 3.0.3
info:
  title: Generations API
  version: 1.0.0
  description: >
    Generation records track individual LLM generation runs started by agents.
    Each record carries the lifecycle status ('in_progress', 'requires_action',
    'completed', or 'failed'), the stop reason, and — when the generation
    failed — a structured error payload for post-mortem debugging. Generations
    for a trace can be listed via GET /api/v1/generations?trace_id=.
  contact:
    name: SOAT API Support

servers:
  - url: '{baseUrl}'
    description: Base URL of your SOAT deployment (e.g. https://your-soat.com or http://localhost:5047)
    variables:
      baseUrl:
        description: The base URL of your SOAT deployment
        default: http://localhost:5047

tags:
  - name: Generations
    description: Inspect generation records

security:
  - bearerAuth: []

paths:
  /api/v1/generations:
    get:
      tags:
        - Generations
      summary: List generations
      description: >
        Returns generations the caller can access, optionally filtered by agent,
        trace, and status. Replaces the former per-trace generations endpoint
        (use the trace_id query filter).
      operationId: listGenerations
      parameters:
        - name: agent_id
          in: query
          required: false
          description: Filter by agent public ID
          schema:
            type: string
        - name: trace_id
          in: query
          required: false
          description: Filter by trace public ID
          schema:
            type: string
        - name: initiator_generation_id
          in: query
          required: false
          description: >
            Filter by the public ID of the parent generation. Returns all
            generations triggered by that generation — sub-agent invocations.
            Null-initiated (top-level) generations are not returned.
          schema:
            type: string
        - name: status
          in: query
          required: false
          description: Filter by lifecycle status
          schema:
            type: string
            enum: [in_progress, requires_action, completed, failed]
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            default: 50
        - name: offset
          in: query
          required: false
          schema:
            type: integer
            default: 0
      responses:
        '200':
          description: Paginated list of generations
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Generation'
                  total:
                    type: integer
                  limit:
                    type: integer
                  offset:
                    type: integer
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /api/v1/generations/{generation_id}:
    get:
      tags:
        - Generations
      summary: Get a generation
      description: >
        Returns a single generation record by ID, including its status and the
        structured `error` payload when the generation failed (e.g. because the
        upstream AI provider returned an error).
      operationId: getGeneration
      parameters:
        - name: generation_id
          in: path
          required: true
          schema:
            type: string
          description: Public ID of the generation
      responses:
        '200':
          description: Generation details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Generation'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Generation not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

  schemas:
    Generation:
      type: object
      properties:
        id:
          type: string
          description: Public ID of the generation
          example: gen_V1StGXR8Z5jdHi6B
        project_id:
          x-soat-ref: projects
          type: string
          description: Public ID of the project
        agent_id:
          x-soat-ref: agents
          type: string
          description: Public ID of the agent that ran this generation
        trace_id:
          x-soat-ref: traces
          type: string
          description: Public ID of the trace this generation belongs to
        initiator_generation_id:
          x-soat-ref: generations
          type: string
          nullable: true
          description: >
            Public ID of the generation that triggered this one. Set for
            sub-agent invocations. Null for top-level generations.
        started_by_principal_type:
          type: string
          nullable: true
          description: Type of the principal that started the generation
        started_by_principal_id:
          type: string
          nullable: true
          description: ID of the principal that started the generation
        status:
          type: string
          description: Lifecycle status of the generation
          enum: [in_progress, requires_action, completed, failed]
          example: failed
        started_at:
          type: string
          format: date-time
        completed_at:
          type: string
          format: date-time
          nullable: true
          description: When the generation reached a terminal state
        last_activity_at:
          type: string
          format: date-time
          nullable: true
        stop_reason:
          type: string
          nullable: true
          description: Why the generation stopped (e.g. 'stop', 'error')
          example: error
        error:
          type: object
          nullable: true
          description: >
            Structured error payload recorded when the generation failed.
            Contains at least `message`; `code` is set for mapped errors
            (e.g. AI_PROVIDER_ERROR for upstream provider failures).
          properties:
            code:
              type: string
              example: AI_PROVIDER_ERROR
            message:
              type: string
              example: 'Provider returned 402: insufficient credits'
            meta:
              type: object
        metadata:
          type: object
          nullable: true
          description: >
            Non-sensitive metadata recorded about the generation. May include
            `action_id` (the logical action label supplied on the generate
            request) and `trigger_id` (set when a trigger initiated the
            generation), plus `extraction` — set when the agent's
            `knowledge_config.extraction` produced a memory-extraction summary
            for this turn (`candidates`, `created`, `updated`, `skipped`).
            Internal recovery state is never included here.
          properties:
            action_id:
              type: string
              nullable: true
              description: Logical action label supplied on the generate request
            trigger_id:
              x-soat-ref: triggers
              type: string
              nullable: true
              description: Trigger that initiated the generation, when applicable
            extraction:
              type: object
              nullable: true
              description: Memory-extraction summary recorded for this generation
              properties:
                candidates:
                  type: integer
                  description: Number of extraction candidates considered
                created:
                  type: integer
                  description: Number of new memory entries created
                updated:
                  type: integer
                  description: Number of existing memory entries updated
                skipped:
                  type: integer
                  description: Number of candidates skipped (e.g. duplicates)
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time

    ErrorResponse:
      type: object
      properties:
        error:
          oneOf:
            - type: string
              description: Generic error message (e.g. "Internal Server Error")
            - type: object
              description: Structured domain error
              properties:
                code:
                  type: string
                  example: RESOURCE_NOT_FOUND
                message:
                  type: string
                meta:
                  type: object
