# Proposed contract, version 1: endpoints, errors, paging, idempotency, security and the capability of every
# operation. Resource schemas were initialized from the data model (docs/06-data) and are kept aligned with it; input
# schemas (*Input, *Request) and views are specific to this contract. Status: proposal for review, not confirmed design.
# Conventions: docs/05-interfaces/choosing-an-interface.md. Vendor extensions: x-moonitoring-audience (who calls),
# x-moonitoring-capability (the capability checked), x-moonitoring-entitlement (the entitlement feature checked),
# x-moonitoring-requirements (the requirements of 1.requisiti-raffinati.txt the operation serves).
openapi: 3.1.0
info:
  title: MooChat Conversations API
  version: 1.0.0
  description: 'Threads between a user and an agent: conversations, their messages and the tool calls of each turn.
    A message is authorized as its own sender; a tool that writes waits for the user''s confirmation. Answers stream
    over the WebSocket `/conversations/v1/live`; this API loads the state and sends messages.'
servers:
- url: https://moochat.moonitoring.com/conversations/v1
  description: Prod
- url: https://stage-moochat.moonitoring.com/conversations/v1
  description: Stage, through IAP
security:
- bearer: []
tags:
- name: Conversations
  description: Threads
- name: Messages
  description: Turns
- name: Tool calls
  description: What the agent did, and confirmations
paths:
  /conversations:
    get:
      summary: List my conversations
      operationId: listConversations
      description: An Organization user sees the conversations of their active Organization; a staff member their
        own with staff agents.
      tags:
      - Conversations
      parameters:
      - name: agent
        in: query
        required: false
        schema:
          type: string
          format: uuid
        description: Only with this agent.
      - name: include_archived
        in: query
        required: false
        schema:
          type: boolean
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Cursor
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Limit
      responses:
        '200':
          description: One page of results.
          content:
            application/json:
              schema:
                type: object
                description: One page of items.
                properties:
                  items:
                    type: array
                    items:
                      $ref: '#/components/schemas/AgentConversation'
                  next_cursor:
                    type: string
                    description: Where the next page starts; absent on the last page.
                required:
                - items
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
      x-moonitoring-audience: any
      x-moonitoring-capability: moochat.moochat.access
      x-moonitoring-entitlement: moochat.chat
      x-moonitoring-requirements:
      - '124'
      - '1002.1'
    post:
      summary: Open a conversation
      operationId: createConversation
      tags:
      - Conversations
      parameters:
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/IdempotencyKey
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ConversationInput'
      responses:
        '201':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AgentConversation'
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '409':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Conflict
        '422':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/UnprocessableEntity
      x-moonitoring-audience: any
      x-moonitoring-capability: moochat.moochat.access
      x-moonitoring-entitlement: moochat.chat
      x-moonitoring-requirements:
      - '124'
      - '120.5'
      - '68'
      - '1002.1'
  /conversations/{conversation_id}:
    get:
      summary: Read a conversation
      operationId: getConversation
      tags:
      - Conversations
      parameters:
      - name: conversation_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AgentConversation'
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
      x-moonitoring-audience: any
      x-moonitoring-capability: moochat.moochat.access
      x-moonitoring-entitlement: moochat.chat
      x-moonitoring-requirements:
      - '124'
    patch:
      summary: Rename a conversation
      operationId: updateConversation
      tags:
      - Conversations
      parameters:
      - name: conversation_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ConversationUpdate'
      responses:
        '200':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AgentConversation'
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
        '409':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Conflict
        '422':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/UnprocessableEntity
      x-moonitoring-audience: any
      x-moonitoring-capability: moochat.moochat.access
      x-moonitoring-entitlement: moochat.chat
      x-moonitoring-requirements:
      - '124.6'
  /conversations/{conversation_id}/archive:
    post:
      summary: Archive a conversation
      operationId: archiveConversation
      tags:
      - Conversations
      parameters:
      - name: conversation_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AgentConversation'
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
        '409':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Conflict
      x-moonitoring-audience: any
      x-moonitoring-capability: moochat.moochat.access
      x-moonitoring-entitlement: moochat.chat
      x-moonitoring-requirements:
      - '124.7'
  /conversations/{conversation_id}/messages:
    get:
      summary: List messages
      operationId: listMessages
      tags:
      - Messages
      parameters:
      - name: conversation_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Cursor
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Limit
      responses:
        '200':
          description: One page of results.
          content:
            application/json:
              schema:
                type: object
                description: One page of items.
                properties:
                  items:
                    type: array
                    items:
                      $ref: '#/components/schemas/AgentMessage'
                  next_cursor:
                    type: string
                    description: Where the next page starts; absent on the last page.
                required:
                - items
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
      x-moonitoring-audience: any
      x-moonitoring-capability: moochat.moochat.access
      x-moonitoring-entitlement: moochat.chat
      x-moonitoring-requirements:
      - '125'
    post:
      summary: Send a message
      operationId: sendMessage
      description: The sender must be a member of the conversation's Organization, or a Moonitoring user for a staff
        agent. Tools are offered to the model only when the sender holds their capabilities and the Organization
        their features; usage is metered against the Organization's entitlement, and 429 says a limit was reached.
      tags:
      - Messages
      parameters:
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/IdempotencyKey
      - name: conversation_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MessageInput'
      responses:
        '202':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TurnAccepted'
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
        '409':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Conflict
        '422':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/UnprocessableEntity
        '429':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/TooManyRequests
      x-moonitoring-audience: any
      x-moonitoring-capability: moochat.moochat.access
      x-moonitoring-entitlement: moochat.chat
      x-moonitoring-requirements:
      - '125'
      - '125.4'
      - '125.10'
      - '122.4'
      - '122.5'
      - '69'
      - '1002.1'
  /messages/{message_id}/tool-calls:
    get:
      summary: List a message's tool calls
      operationId: listToolCalls
      tags:
      - Tool calls
      parameters:
      - name: message_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Cursor
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Limit
      responses:
        '200':
          description: One page of results.
          content:
            application/json:
              schema:
                type: object
                description: One page of items.
                properties:
                  items:
                    type: array
                    items:
                      $ref: '#/components/schemas/AgentToolCall'
                  next_cursor:
                    type: string
                    description: Where the next page starts; absent on the last page.
                required:
                - items
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
      x-moonitoring-audience: any
      x-moonitoring-capability: moochat.moochat.access
      x-moonitoring-entitlement: moochat.chat
      x-moonitoring-requirements:
      - '126'
  /tool-calls/{call_id}/confirm:
    post:
      summary: Confirm a write tool
      operationId: confirmToolCall
      description: The confirmation is the message that authorizes the call; a dangerous tool is also logged as
        a PlatformAuditEvent.
      tags:
      - Tool calls
      parameters:
      - name: call_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AgentToolCall'
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
        '409':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Conflict
      x-moonitoring-audience: any
      x-moonitoring-capability: moochat.moochat.access
      x-moonitoring-entitlement: moochat.chat
      x-moonitoring-requirements:
      - '126.5'
      - '122.7'
      - '123.5'
  /tool-calls/{call_id}/refuse:
    post:
      summary: Refuse a write tool
      operationId: refuseToolCall
      tags:
      - Tool calls
      parameters:
      - name: call_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AgentToolCall'
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
        '409':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Conflict
      x-moonitoring-audience: any
      x-moonitoring-capability: moochat.moochat.access
      x-moonitoring-entitlement: moochat.chat
      x-moonitoring-requirements:
      - '126.5'
components:
  schemas:
    AgentConversation:
      description: 'A thread between a user and an agent. It lives with the audience''s data: in the cell for an
        Organization, with the staff''s data in `access` for staff; an Organization''s erasure removes its conversations.'
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Key.
        agent:
          type: string
          format: uuid
          description: ID of the AgentDefinition.
        organization:
          type: string
          format: uuid
          description: ID of the Organization. Set for an Organization agent; erased with the Organization (see
            ErasureRequest).
        owner_user:
          type: string
          format: uuid
          description: ID of the User. Who opened it, for an Organization agent.
        owner_moonitoring_user:
          type: string
          format: uuid
          description: ID of the MoonitoringUser. Who opened it, for a staff agent. Exactly one of the two owners
            is set, and it matches the agent's audience.
        title:
          type: string
        archived_at:
          type: string
          format: date-time
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      required:
      - id
      - agent
      - created_at
      - updated_at
    AgentMessage:
      description: 'One message of a conversation: from the user, the assistant or a tool. Every tool call in the
        turn is authorized as the sender of this message, so a shared conversation never widens anyone''s rights.
        Assistant messages record the model profile and the tokens they cost. Immutable.'
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Key.
        conversation:
          type: string
          format: uuid
          description: ID of the AgentConversation.
        role:
          type: string
          enum:
          - user
          - assistant
          - tool
        sender_user:
          type: string
          format: uuid
          description: ID of the User. Who sent it, in an Organization conversation; empty for the assistant and
            for tools.
        sender_moonitoring_user:
          type: string
          format: uuid
          description: ID of the MoonitoringUser. Who sent it, in a staff conversation. Every tool call in the turn
            is authorized as the sender; the sender must be a member of the conversation's Organization, or a Moonitoring
            user for a staff agent.
        content:
          type: string
        model_profile:
          type: string
          format: uuid
          description: ID of the AgentModelProfile. The profile that produced an assistant message, as resolved
            for that request.
        input_tokens:
          type: integer
        output_tokens:
          type: integer
        request_id:
          type: string
        created_at:
          type: string
          format: date-time
      required:
      - id
      - conversation
      - role
      - content
      - created_at
    AgentToolCall:
      description: 'One invocation of a tool during a turn and its outcome: run, denied for lack of a capability
        or entitlement, refused by the user, or failed. It is the row the audit event and the usage ledger point
        to. Immutable.'
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Key.
        message:
          type: string
          format: uuid
          description: ID of the AgentMessage.
        tool:
          type: string
          format: uuid
          description: ID of the AgentTool.
        input_hash:
          type: string
          description: Hash of the arguments; the arguments themselves stay in the message.
        outcome:
          type: string
          enum:
          - ok
          - denied
          - confirmed
          - refused
          - failed
          description: '`denied`: the sender lacked the capability or entitlement; refused: the user did not confirm
            a write.'
        latency_ms:
          type: integer
        audit_event:
          type: string
          format: uuid
          description: ID of the PlatformAuditEvent. Set for dangerous tools and for every staff write.
        created_at:
          type: string
          format: date-time
      required:
      - id
      - message
      - tool
      - input_hash
      - outcome
      - created_at
    ConversationInput:
      type: object
      description: Opens a conversation with an agent. For an Organization agent the Organization is the token's
        active one.
      properties:
        agent:
          type: string
          format: uuid
        title:
          type: string
      required:
      - agent
    ConversationUpdate:
      type: object
      description: Renames a conversation.
      properties:
        title:
          type: string
      required:
      - title
    MessageInput:
      type: object
      description: 'A user message. The answer is produced asynchronously: the assistant message and its tool calls
        arrive on the live socket and are then readable here.'
      properties:
        content:
          type: string
        model_profile:
          type: string
          format: uuid
          description: A profile of a tier the plan allows; default the agent's resolution.
      required:
      - content
    TurnAccepted:
      type: object
      description: The user message as stored and the id of the assistant turn being produced.
      properties:
        message:
          $ref: '#/components/schemas/AgentMessage'
        assistant_message:
          type: string
          format: uuid
      required:
      - message
      - assistant_message
  securitySchemes:
    bearer:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: 'The short-lived token signed by `access`: an Organization user token, a staff token or a client
        token, as the operation''s audience says.'
