openapi: 3.0.3
info:
  title: AgentLens API
  description: REST API for the AgentLens AI agent observability platform.
  version: 0.12.1
  license:
    name: MIT

servers:
  - url: http://localhost:3400
    description: Local development server

security:
  - BearerAuth: []

components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer

  schemas:
    Event:
      type: object
      properties:
        id:
          type: string
        sessionId:
          type: string
        agentId:
          type: string
        eventType:
          type: string
        severity:
          type: string
        payload:
          type: object
        metadata:
          type: object
        timestamp:
          type: string
          format: date-time
        hash:
          type: string
        prevHash:
          type: string

    EventQueryResult:
      type: object
      required: [events, total, hasMore]
      properties:
        events:
          type: array
          items:
            $ref: '#/components/schemas/Event'
        total:
          type: integer
        hasMore:
          type: boolean

    Session:
      type: object
      properties:
        id:
          type: string
        agentId:
          type: string
        status:
          type: string
        startedAt:
          type: string
          format: date-time
        endedAt:
          type: string
          format: date-time
        eventCount:
          type: integer

    SessionQueryResult:
      type: object
      required: [sessions, total, hasMore]
      properties:
        sessions:
          type: array
          items:
            $ref: '#/components/schemas/Session'
        total:
          type: integer
        hasMore:
          type: boolean

    TimelineResult:
      type: object
      required: [events, chainValid]
      properties:
        events:
          type: array
          items:
            $ref: '#/components/schemas/Event'
        chainValid:
          type: boolean

    Agent:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        description:
          type: string
        status:
          type: string
        modelOverride:
          type: string
        pausedAt:
          type: string
          format: date-time
        config:
          type: object

    HealthResult:
      type: object
      required: [status, version]
      properties:
        status:
          type: string
        version:
          type: string

    HealthScore:
      type: object
      properties:
        agentId:
          type: string
        score:
          type: number
        status:
          type: string
        errorRate:
          type: number
        avgLatencyMs:
          type: number
        totalCalls:
          type: integer
        calculatedAt:
          type: string
          format: date-time

    HealthSnapshot:
      type: object
      properties:
        agentId:
          type: string
        score:
          type: number
        timestamp:
          type: string
          format: date-time
        totalCalls:
          type: integer
        errorRate:
          type: number
        avgLatencyMs:
          type: number

    LlmAnalyticsSummary:
      type: object
      properties:
        totalCalls:
          type: integer
        totalCostUsd:
          type: number
        totalInputTokens:
          type: integer
        totalOutputTokens:
          type: integer
        avgLatencyMs:
          type: number
        avgCostPerCall:
          type: number

    LlmAnalyticsResult:
      type: object
      properties:
        summary:
          $ref: '#/components/schemas/LlmAnalyticsSummary'
        byModel:
          type: array
          items:
            type: object
            properties:
              provider:
                type: string
              model:
                type: string
              calls:
                type: integer
              costUsd:
                type: number
              inputTokens:
                type: integer
              outputTokens:
                type: integer
              avgLatencyMs:
                type: number
        byTime:
          type: array
          items:
            type: object
            properties:
              bucket:
                type: string
              calls:
                type: integer
              costUsd:
                type: number
              inputTokens:
                type: integer
              outputTokens:
                type: integer
              avgLatencyMs:
                type: number

    RecallResult:
      type: object
      properties:
        matches:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
              score:
                type: number
              content:
                type: string
              metadata:
                type: object
        total:
          type: integer

    ReflectResult:
      type: object
      properties:
        patterns:
          type: array
          items:
            type: object
        summary:
          type: object

    ContextResult:
      type: object
      properties:
        context:
          type: array
          items:
            type: object
        summary:
          type: object

    OptimizationResult:
      type: object
      properties:
        recommendations:
          type: array
          items:
            type: object
            properties:
              type:
                type: string
              description:
                type: string
              estimatedSavings:
                type: number
              agentId:
                type: string
              details:
                type: object
        summary:
          type: object

    GuardrailRule:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        description:
          type: string
        conditionType:
          type: string
        conditionConfig:
          type: object
        actionType:
          type: string
        actionConfig:
          type: object
        agentId:
          type: string
        enabled:
          type: boolean
        dryRun:
          type: boolean
        cooldownMinutes:
          type: integer
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time

    GuardrailRuleListResult:
      type: object
      properties:
        rules:
          type: array
          items:
            $ref: '#/components/schemas/GuardrailRule'

    GuardrailTriggerHistory:
      type: object
      properties:
        id:
          type: string
        ruleId:
          type: string
        ruleName:
          type: string
        agentId:
          type: string
        sessionId:
          type: string
        actionTaken:
          type: string
        triggerContext:
          type: object
        triggeredAt:
          type: string
          format: date-time

    GuardrailTriggerHistoryResult:
      type: object
      properties:
        triggers:
          type: array
          items:
            $ref: '#/components/schemas/GuardrailTriggerHistory'
        total:
          type: integer

    GuardrailStatusResult:
      type: object
      properties:
        rule:
          $ref: '#/components/schemas/GuardrailRule'
        state:
          type: object
        recentTriggers:
          type: array
          items:
            $ref: '#/components/schemas/GuardrailTriggerHistory'

    VerificationReport:
      type: object
      required: [verified]
      properties:
        verified:
          type: boolean
        verifiedAt:
          type: string
        range:
          type: object
          properties:
            from:
              type: string
            to:
              type: string
        sessionId:
          type: string
        sessionsVerified:
          type: integer
        totalEvents:
          type: integer
        firstHash:
          type: string
        lastHash:
          type: string
        brokenChains:
          type: array
          items:
            type: object
            properties:
              sessionId:
                type: string
              failedAtIndex:
                type: integer
              failedEventId:
                type: string
              reason:
                type: string
        signature:
          type: string

    ErrorResponse:
      type: object
      required: [error]
      properties:
        error:
          type: string
        details:
          type: object

paths:
  /api/health:
    get:
      summary: Server health check
      operationId: health
      security: []
      responses:
        '200':
          description: Server is healthy
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HealthResult'

  /api/events:
    get:
      summary: Query events
      operationId: queryEvents
      parameters:
        - name: sessionId
          in: query
          schema:
            type: string
        - name: agentId
          in: query
          schema:
            type: string
        - name: eventType
          in: query
          schema:
            type: string
        - name: from
          in: query
          schema:
            type: string
        - name: to
          in: query
          schema:
            type: string
        - name: limit
          in: query
          schema:
            type: integer
        - name: offset
          in: query
          schema:
            type: integer
        - name: severity
          in: query
          description: Filter by severity (comma-separated for multiple)
          schema:
            type: string
        - name: search
          in: query
          description: Full-text search across event payloads
          schema:
            type: string
        - name: order
          in: query
          description: Sort order by timestamp
          schema:
            type: string
            enum: [asc, desc]
      responses:
        '200':
          description: Events matching query
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventQueryResult'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    post:
      summary: Ingest events (batch)
      operationId: ingestEvents
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [events]
              properties:
                events:
                  type: array
                  items:
                    type: object
                    properties:
                      sessionId:
                        type: string
                      agentId:
                        type: string
                      eventType:
                        type: string
                      severity:
                        type: string
                      payload:
                        type: object
                      metadata:
                        type: object
                      timestamp:
                        type: string
      responses:
        '200':
          description: Events ingested
        '400':
          description: Validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /api/events/{id}:
    get:
      summary: Get event by ID
      operationId: getEvent
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Event details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Event'
        '404':
          description: Event not found

  /api/sessions:
    get:
      summary: Query sessions
      operationId: getSessions
      parameters:
        - name: agentId
          in: query
          schema:
            type: string
        - name: status
          in: query
          schema:
            type: string
        - name: from
          in: query
          schema:
            type: string
        - name: to
          in: query
          schema:
            type: string
        - name: limit
          in: query
          schema:
            type: integer
        - name: offset
          in: query
          schema:
            type: integer
        - name: tags
          in: query
          description: Filter by tags (comma-separated)
          schema:
            type: string
      responses:
        '200':
          description: Sessions matching query
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SessionQueryResult'

  /api/sessions/{id}:
    get:
      summary: Get session by ID
      operationId: getSession
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Session details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Session'
        '404':
          description: Session not found

  /api/sessions/{id}/timeline:
    get:
      summary: Get session timeline
      operationId: getSessionTimeline
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Session timeline
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TimelineResult'
        '404':
          description: Session not found

  /api/agents/{id}:
    get:
      summary: Get agent by ID
      operationId: getAgent
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Agent details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Agent'
        '404':
          description: Agent not found

  /api/analytics/llm:
    get:
      summary: Get LLM analytics
      operationId: getLlmAnalytics
      parameters:
        - name: from
          in: query
          schema:
            type: string
        - name: to
          in: query
          schema:
            type: string
        - name: agentId
          in: query
          schema:
            type: string
        - name: model
          in: query
          schema:
            type: string
        - name: provider
          in: query
          schema:
            type: string
        - name: granularity
          in: query
          schema:
            type: string
            enum: [hour, day, week]
      responses:
        '200':
          description: LLM analytics data
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LlmAnalyticsResult'

  /api/recall:
    get:
      summary: Semantic search over embeddings
      operationId: recall
      parameters:
        - name: query
          in: query
          required: true
          schema:
            type: string
        - name: scope
          in: query
          schema:
            type: string
        - name: agentId
          in: query
          schema:
            type: string
        - name: from
          in: query
          schema:
            type: string
        - name: to
          in: query
          schema:
            type: string
        - name: limit
          in: query
          schema:
            type: integer
        - name: minScore
          in: query
          schema:
            type: number
      responses:
        '200':
          description: Recall search results
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RecallResult'

  /api/reflect:
    get:
      summary: Analyze patterns across sessions
      operationId: reflect
      parameters:
        - name: analysis
          in: query
          required: true
          schema:
            type: string
        - name: agentId
          in: query
          schema:
            type: string
        - name: from
          in: query
          schema:
            type: string
        - name: to
          in: query
          schema:
            type: string
        - name: limit
          in: query
          schema:
            type: integer
        - name: params
          in: query
          schema:
            type: string
          description: JSON-encoded parameters
      responses:
        '200':
          description: Pattern analysis results
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReflectResult'

  /api/context:
    get:
      summary: Get cross-session context
      operationId: getContext
      parameters:
        - name: topic
          in: query
          required: true
          schema:
            type: string
        - name: userId
          in: query
          schema:
            type: string
        - name: agentId
          in: query
          schema:
            type: string
        - name: from
          in: query
          schema:
            type: string
        - name: to
          in: query
          schema:
            type: string
        - name: limit
          in: query
          schema:
            type: integer
      responses:
        '200':
          description: Cross-session context
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContextResult'

  /api/agents/{id}/health:
    get:
      summary: Get agent health score
      operationId: getHealth
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
        - name: window
          in: query
          schema:
            type: integer
      responses:
        '200':
          description: Agent health score
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HealthScore'

  /api/health/overview:
    get:
      summary: Get health overview for all agents
      operationId: getHealthOverview
      parameters:
        - name: window
          in: query
          schema:
            type: integer
      responses:
        '200':
          description: Health scores for all agents
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/HealthScore'

  /api/health/history:
    get:
      summary: Get historical health snapshots
      operationId: getHealthHistory
      parameters:
        - name: agentId
          in: query
          required: true
          schema:
            type: string
        - name: days
          in: query
          schema:
            type: integer
      responses:
        '200':
          description: Historical health data
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/HealthSnapshot'

  /api/optimize/recommendations:
    get:
      summary: Get cost optimization recommendations
      operationId: getOptimizationRecommendations
      parameters:
        - name: agentId
          in: query
          schema:
            type: string
        - name: period
          in: query
          schema:
            type: integer
        - name: limit
          in: query
          schema:
            type: integer
      responses:
        '200':
          description: Optimization recommendations
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OptimizationResult'

  /api/guardrails:
    get:
      summary: List guardrail rules
      operationId: listGuardrails
      parameters:
        - name: agentId
          in: query
          schema:
            type: string
      responses:
        '200':
          description: List of guardrail rules
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GuardrailRuleListResult'
    post:
      summary: Create a guardrail rule
      operationId: createGuardrail
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [name, conditionType, conditionConfig, actionType, actionConfig]
              properties:
                name:
                  type: string
                description:
                  type: string
                conditionType:
                  type: string
                conditionConfig:
                  type: object
                actionType:
                  type: string
                actionConfig:
                  type: object
                agentId:
                  type: string
                enabled:
                  type: boolean
                dryRun:
                  type: boolean
                cooldownMinutes:
                  type: integer
      responses:
        '200':
          description: Created guardrail rule
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GuardrailRule'

  /api/guardrails/{id}:
    get:
      summary: Get a guardrail rule
      operationId: getGuardrail
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Guardrail rule
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GuardrailRule'
        '404':
          description: Rule not found
    put:
      summary: Update a guardrail rule
      operationId: updateGuardrail
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                description:
                  type: string
                conditionType:
                  type: string
                conditionConfig:
                  type: object
                actionType:
                  type: string
                actionConfig:
                  type: object
                enabled:
                  type: boolean
                dryRun:
                  type: boolean
                cooldownMinutes:
                  type: integer
      responses:
        '200':
          description: Updated guardrail rule
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GuardrailRule'
    delete:
      summary: Delete a guardrail rule
      operationId: deleteGuardrail
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Rule deleted
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean

  /api/guardrails/history:
    get:
      summary: Get guardrail trigger history
      operationId: getGuardrailHistory
      parameters:
        - name: ruleId
          in: query
          schema:
            type: string
        - name: limit
          in: query
          schema:
            type: integer
        - name: offset
          in: query
          schema:
            type: integer
      responses:
        '200':
          description: Trigger history
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GuardrailTriggerHistoryResult'

  /api/guardrails/{id}/status:
    get:
      summary: Get guardrail status with recent triggers
      operationId: getGuardrailStatus
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Guardrail status
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GuardrailStatusResult'

  /api/audit/verify:
    get:
      summary: Verify audit trail hash chain integrity
      operationId: verifyAudit
      parameters:
        - name: from
          in: query
          schema:
            type: string
        - name: to
          in: query
          schema:
            type: string
        - name: sessionId
          in: query
          schema:
            type: string
      responses:
        '200':
          description: Verification report
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VerificationReport'
