openapi: "3.1.0"
info:
  title: Agorai Platform API
  version: "0.1.0"
  description: REST API for the Agorai multi-agent orchestration platform.
  contact:
    name: Agorai
    url: https://agorai.team

servers:
  - url: https://api.agorai.team
    description: Production

security:
  - BearerAuth: []

tags:
  - name: health
    description: Service health probes
  - name: api-keys
    description: API key lifecycle management
  - name: agents
    description: Agent registry and presence
  - name: messages
    description: Inter-agent messaging
  - name: tasks
    description: Task queue with gated autonomy
  - name: usage
    description: Plan usage and metering
  - name: activity
    description: Workspace activity feed
  - name: context
    description: Shared key-value context store
  - name: embeddings
    description: Vector context search
  - name: artifacts
    description: File and artifact sharing
  - name: topics
    description: Pub/sub topic messaging
  - name: workspaces
    description: Workspace management
  - name: auth
    description: SSO/OIDC authentication (unauthenticated)
  - name: websocket
    description: Real-time event streaming

paths:
  /healthz:
    get:
      operationId: getHealth
      tags: [health]
      summary: Liveness probe
      security: []
      responses:
        "200":
          description: Service is alive
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HealthResponse"

  /readyz:
    get:
      operationId: getReady
      tags: [health]
      summary: Readiness probe
      security: []
      responses:
        "200":
          description: Service is ready
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HealthResponse"

  /v1/api-keys:
    post:
      operationId: createAPIKey
      tags: [api-keys]
      summary: Create a new API key
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateAPIKeyRequest"
      responses:
        "201":
          description: API key created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CreateAPIKeyResponse"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
    get:
      operationId: listAPIKeys
      tags: [api-keys]
      summary: List API keys for the authenticated user
      responses:
        "200":
          description: List of API keys
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/APIKeyListItem"
        "401":
          $ref: "#/components/responses/Unauthorized"

  /v1/api-keys/{id}/revoke:
    post:
      operationId: revokeAPIKey
      tags: [api-keys]
      summary: Revoke an API key
      parameters:
        - $ref: "#/components/parameters/ResourceID"
      responses:
        "200":
          description: Key revoked
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: revoked
        "401":
          $ref: "#/components/responses/Unauthorized"

  /v1/api-keys/{id}/rotate:
    post:
      operationId: rotateAPIKey
      tags: [api-keys]
      summary: Rotate an API key (revokes old, creates new)
      parameters:
        - $ref: "#/components/parameters/ResourceID"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RotateAPIKeyRequest"
      responses:
        "201":
          description: New key created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CreateAPIKeyResponse"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"

  /v1/agents:
    post:
      operationId: registerAgent
      tags: [agents]
      summary: Register a new agent
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RegisterAgentRequest"
      responses:
        "201":
          description: Agent registered
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Agent"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "422":
          $ref: "#/components/responses/UnprocessableEntity"
    get:
      operationId: listAgents
      tags: [agents]
      summary: List agents in the workspace
      parameters:
        - name: status
          in: query
          schema:
            type: string
            enum: [online, offline]
          description: Filter by agent status
      responses:
        "200":
          description: List of agents
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Agent"
        "401":
          $ref: "#/components/responses/Unauthorized"

  /v1/agents/{id}/heartbeat:
    post:
      operationId: agentHeartbeat
      tags: [agents]
      summary: Send agent heartbeat
      parameters:
        - $ref: "#/components/parameters/ResourceID"
      responses:
        "204":
          description: Heartbeat recorded
        "404":
          $ref: "#/components/responses/NotFound"

  /v1/agents/{id}/disconnect:
    post:
      operationId: disconnectAgent
      tags: [agents]
      summary: Mark agent as offline
      parameters:
        - $ref: "#/components/parameters/ResourceID"
      responses:
        "204":
          description: Agent disconnected
        "404":
          $ref: "#/components/responses/NotFound"

  /v1/messages:
    post:
      operationId: sendMessage
      tags: [messages]
      summary: Send a message to an agent or broadcast
      parameters:
        - $ref: "#/components/parameters/AgentIDHeader"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SendMessageRequest"
      responses:
        "201":
          description: Message sent
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Message"
        "400":
          $ref: "#/components/responses/BadRequest"
        "409":
          description: Duplicate message (idempotency key conflict)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
    get:
      operationId: listMessages
      tags: [messages]
      summary: List messages for the calling agent
      parameters:
        - $ref: "#/components/parameters/AgentIDHeader"
        - name: since
          in: query
          schema:
            type: string
            format: date-time
          description: Return messages created after this timestamp (RFC 3339)
        - name: limit
          in: query
          schema:
            type: integer
            default: 50
            minimum: 1
          description: Maximum number of messages to return
      responses:
        "200":
          description: List of messages
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Message"

  /v1/tasks:
    post:
      operationId: createTask
      tags: [tasks]
      summary: Create a new task
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateTaskRequest"
      responses:
        "201":
          description: Task created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Task"
        "422":
          $ref: "#/components/responses/UnprocessableEntity"
    get:
      operationId: listTasks
      tags: [tasks]
      summary: List tasks in the workspace
      parameters:
        - name: status
          in: query
          schema:
            type: string
            enum: [pending_approval, open, claimed, in_progress, done, failed]
          description: Filter by task status
      responses:
        "200":
          description: List of tasks
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Task"

  /v1/tasks/{id}:
    get:
      operationId: getTask
      tags: [tasks]
      summary: Get a task by ID
      parameters:
        - $ref: "#/components/parameters/ResourceID"
      responses:
        "200":
          description: Task details
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Task"
        "404":
          $ref: "#/components/responses/NotFound"
    patch:
      operationId: updateTask
      tags: [tasks]
      summary: Update a task's status or notes
      parameters:
        - $ref: "#/components/parameters/ResourceID"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateTaskRequest"
      responses:
        "200":
          description: Task updated
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Task"
        "422":
          $ref: "#/components/responses/UnprocessableEntity"

  /v1/tasks/{id}/approve:
    post:
      operationId: approveTask
      tags: [tasks]
      summary: Approve a pending task (gated autonomy)
      parameters:
        - $ref: "#/components/parameters/ResourceID"
      responses:
        "200":
          description: Task approved
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Task"
        "422":
          $ref: "#/components/responses/UnprocessableEntity"

  /v1/tasks/{id}/claim:
    post:
      operationId: claimTask
      tags: [tasks]
      summary: Claim an open task
      parameters:
        - $ref: "#/components/parameters/ResourceID"
        - $ref: "#/components/parameters/AgentIDHeader"
      responses:
        "200":
          description: Task claimed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Task"
        "422":
          $ref: "#/components/responses/UnprocessableEntity"

  /v1/usage:
    get:
      operationId: getUsage
      tags: [usage]
      summary: Get plan usage summary
      responses:
        "200":
          description: Usage summary
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UsageSummary"

  /v1/activity:
    get:
      operationId: getActivityFeed
      tags: [activity]
      summary: Get workspace activity feed
      parameters:
        - name: since
          in: query
          schema:
            type: string
            format: date-time
        - name: limit
          in: query
          schema:
            type: integer
            minimum: 1
        - name: action_type
          in: query
          schema:
            type: string
          description: Filter by action type
      responses:
        "200":
          description: Activity entries
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Activity"

  /v1/context/{key}:
    put:
      operationId: putContext
      tags: [context]
      summary: Set a context key-value pair
      parameters:
        - name: key
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PutContextRequest"
      responses:
        "200":
          description: Context entry stored
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContextEntry"
    get:
      operationId: getContext
      tags: [context]
      summary: Get a context value by key
      parameters:
        - name: key
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Context entry
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContextEntry"
        "404":
          $ref: "#/components/responses/NotFound"
    delete:
      operationId: deleteContext
      tags: [context]
      summary: Delete a context key
      parameters:
        - name: key
          in: path
          required: true
          schema:
            type: string
      responses:
        "204":
          description: Context entry deleted

  /v1/context:
    get:
      operationId: listContext
      tags: [context]
      summary: List all non-expired context entries
      responses:
        "200":
          description: Context entries
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/ContextEntry"

  /v1/context/embeddings:
    post:
      operationId: storeEmbedding
      tags: [embeddings]
      summary: Store content as a vector embedding
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/StoreEmbeddingRequest"
      responses:
        "201":
          description: Embedding stored
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Embedding"
        "422":
          $ref: "#/components/responses/UnprocessableEntity"
    get:
      operationId: listEmbeddings
      tags: [embeddings]
      summary: List stored embeddings
      parameters:
        - name: limit
          in: query
          schema:
            type: integer
            default: 50
            minimum: 1
      responses:
        "200":
          description: Embedding entries
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Embedding"

  /v1/context/search:
    post:
      operationId: searchContext
      tags: [embeddings]
      summary: Semantic search over stored embeddings
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SearchRequest"
      responses:
        "200":
          description: Search results ranked by similarity
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/SearchResult"

  /v1/artifacts:
    post:
      operationId: createArtifact
      tags: [artifacts]
      summary: Upload or reference an artifact
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateArtifactRequest"
      responses:
        "201":
          description: Artifact created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Artifact"
        "400":
          $ref: "#/components/responses/BadRequest"
        "413":
          description: Upload exceeds 100 MB limit
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
    get:
      operationId: listArtifacts
      tags: [artifacts]
      summary: List artifacts in the workspace
      parameters:
        - name: type
          in: query
          schema:
            type: string
          description: Filter by artifact type
      responses:
        "200":
          description: List of artifacts
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Artifact"

  /v1/artifacts/{id}:
    get:
      operationId: getArtifact
      tags: [artifacts]
      summary: Get an artifact by ID (includes download URL)
      parameters:
        - $ref: "#/components/parameters/ResourceID"
      responses:
        "200":
          description: Artifact details with download URL
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Artifact"
        "404":
          $ref: "#/components/responses/NotFound"

  /v1/topics/{name}/subscribe:
    post:
      operationId: subscribeTopic
      tags: [topics]
      summary: Subscribe to a topic
      parameters:
        - $ref: "#/components/parameters/TopicName"
        - $ref: "#/components/parameters/AgentIDHeader"
      responses:
        "201":
          description: Subscribed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TopicSubscription"
    delete:
      operationId: unsubscribeTopic
      tags: [topics]
      summary: Unsubscribe from a topic
      parameters:
        - $ref: "#/components/parameters/TopicName"
        - $ref: "#/components/parameters/AgentIDHeader"
      responses:
        "204":
          description: Unsubscribed

  /v1/topics/{name}/publish:
    post:
      operationId: publishToTopic
      tags: [topics]
      summary: Publish a message to a topic
      parameters:
        - $ref: "#/components/parameters/TopicName"
        - $ref: "#/components/parameters/AgentIDHeader"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PublishRequest"
      responses:
        "201":
          description: Message published
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TopicMessage"
        "400":
          $ref: "#/components/responses/BadRequest"

  /v1/topics/{name}/messages:
    get:
      operationId: getTopicMessages
      tags: [topics]
      summary: Get messages from a topic
      parameters:
        - $ref: "#/components/parameters/TopicName"
        - name: since
          in: query
          schema:
            type: string
            format: date-time
        - name: limit
          in: query
          schema:
            type: integer
            minimum: 1
      responses:
        "200":
          description: Topic messages
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/TopicMessage"

  /v1/topics:
    get:
      operationId: listSubscriptions
      tags: [topics]
      summary: List the calling agent's topic subscriptions
      parameters:
        - $ref: "#/components/parameters/AgentIDHeader"
      responses:
        "200":
          description: Subscriptions
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/TopicSubscription"

  /v1/workspaces:
    post:
      operationId: createWorkspace
      tags: [workspaces]
      summary: Create a workspace
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateWorkspaceRequest"
      responses:
        "201":
          description: Workspace created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Workspace"
        "422":
          $ref: "#/components/responses/UnprocessableEntity"
    get:
      operationId: listWorkspaces
      tags: [workspaces]
      summary: List workspaces for the tenant
      responses:
        "200":
          description: List of workspaces
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Workspace"

  /v1/workspaces/{id}:
    get:
      operationId: getWorkspace
      tags: [workspaces]
      summary: Get a workspace by ID
      parameters:
        - $ref: "#/components/parameters/ResourceID"
      responses:
        "200":
          description: Workspace details
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Workspace"
        "404":
          $ref: "#/components/responses/NotFound"

  /v1/workspaces/{id}/settings:
    patch:
      operationId: updateWorkspaceSettings
      tags: [workspaces]
      summary: Partial update of workspace capability settings
      parameters:
        - $ref: "#/components/parameters/ResourceID"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateWorkspaceSettingsRequest"
      responses:
        "200":
          description: Settings updated
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Workspace"
        "404":
          $ref: "#/components/responses/NotFound"
        "422":
          $ref: "#/components/responses/UnprocessableEntity"

  /v1/auth/sso/login:
    get:
      operationId: ssoLogin
      tags: [auth]
      summary: Initiate SSO login (redirects to IdP)
      security: []
      parameters:
        - name: tenant_id
          in: query
          required: true
          schema:
            type: string
      responses:
        "302":
          description: Redirect to identity provider
        "400":
          $ref: "#/components/responses/BadRequest"
        "404":
          $ref: "#/components/responses/NotFound"

  /v1/auth/sso/callback:
    get:
      operationId: ssoCallback
      tags: [auth]
      summary: SSO callback (exchanges code for session token)
      security: []
      parameters:
        - name: code
          in: query
          required: true
          schema:
            type: string
        - name: state
          in: query
          required: true
          schema:
            type: string
        - name: tenant_id
          in: query
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Session token issued
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SSOCallbackResponse"
        "400":
          $ref: "#/components/responses/BadRequest"

  /ws:
    get:
      operationId: websocketConnect
      tags: [websocket]
      summary: WebSocket connection for real-time events
      security: []
      parameters:
        - name: key
          in: query
          required: true
          schema:
            type: string
          description: API key for authentication
      responses:
        "101":
          description: WebSocket upgrade

  /v1/openapi.yaml:
    get:
      operationId: getOpenAPISpec
      tags: [health]
      summary: Serve the OpenAPI specification
      security: []
      responses:
        "200":
          description: OpenAPI 3.1 YAML specification
          content:
            application/yaml:
              schema:
                type: string

  /v1/teams:
    post:
      operationId: createTeam
      tags: [teams]
      summary: Create a team
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateTeamRequest"
      responses:
        "201":
          description: Team created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Team"
    get:
      operationId: listTeams
      tags: [teams]
      summary: List teams
      responses:
        "200":
          description: List of teams
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Team"

  /v1/teams/{id}:
    delete:
      operationId: deleteTeam
      tags: [teams]
      summary: Delete a team
      parameters:
        - $ref: "#/components/parameters/ResourceID"
      responses:
        "204":
          description: Team deleted

  /v1/teams/{id}/members:
    post:
      operationId: addTeamMember
      tags: [teams]
      summary: Add an agent to a team
      parameters:
        - $ref: "#/components/parameters/ResourceID"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AddTeamMemberRequest"
      responses:
        "201":
          description: Member added
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TeamMember"
    get:
      operationId: listTeamMembers
      tags: [teams]
      summary: List team members
      parameters:
        - $ref: "#/components/parameters/ResourceID"
      responses:
        "200":
          description: List of members
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/TeamMember"

  /v1/teams/{id}/members/{agentId}:
    delete:
      operationId: removeTeamMember
      tags: [teams]
      summary: Remove a member from a team
      parameters:
        - $ref: "#/components/parameters/ResourceID"
        - name: agentId
          in: path
          required: true
          schema:
            type: string
      responses:
        "204":
          description: Member removed

  /v1/teams/{id}/skills:
    get:
      operationId: listTeamSkills
      tags: [teams]
      summary: List skills for a team
      parameters:
        - $ref: "#/components/parameters/ResourceID"
      responses:
        "200":
          description: List of skills
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Skill"

  /v1/skills:
    post:
      operationId: createSkill
      tags: [skills]
      summary: Create a skill
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateSkillRequest"
      responses:
        "201":
          description: Skill created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Skill"
    get:
      operationId: listSkills
      tags: [skills]
      summary: List available skills
      responses:
        "200":
          description: List of skills
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Skill"

  /v1/skills/{id}:
    delete:
      operationId: deleteSkill
      tags: [skills]
      summary: Delete a skill
      parameters:
        - $ref: "#/components/parameters/ResourceID"
      responses:
        "204":
          description: Skill deleted

  /v1/skills/{id}/teams/{teamId}:
    post:
      operationId: grantSkillToTeam
      tags: [skills]
      summary: Grant a skill to a team
      parameters:
        - $ref: "#/components/parameters/ResourceID"
        - name: teamId
          in: path
          required: true
          schema:
            type: string
      responses:
        "204":
          description: Skill granted
    delete:
      operationId: revokeSkillFromTeam
      tags: [skills]
      summary: Revoke a skill from a team
      parameters:
        - $ref: "#/components/parameters/ResourceID"
        - name: teamId
          in: path
          required: true
          schema:
            type: string
      responses:
        "204":
          description: Skill revoked

  /v1/invitations:
    post:
      operationId: createInvitation
      tags: [invitations]
      summary: Create an invitation
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateInvitationRequest"
      responses:
        "201":
          description: Invitation created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Invitation"
    get:
      operationId: listInvitations
      tags: [invitations]
      summary: List invitations
      responses:
        "200":
          description: List of invitations
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Invitation"

  /v1/invitations/{token}:
    get:
      operationId: getInvitation
      tags: [invitations]
      summary: Get an invitation by token
      parameters:
        - name: token
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Invitation details
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Invitation"

  /v1/invitations/{id}:
    delete:
      operationId: deleteInvitation
      tags: [invitations]
      summary: Delete an invitation
      parameters:
        - $ref: "#/components/parameters/ResourceID"
      responses:
        "204":
          description: Invitation deleted

  /v1/webhooks:
    post:
      operationId: registerWebhook
      tags: [webhooks]
      summary: Register a webhook
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateWebhookRequest"
      responses:
        "201":
          description: Webhook registered
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Webhook"
    get:
      operationId: listWebhooks
      tags: [webhooks]
      summary: List webhooks
      responses:
        "200":
          description: List of webhooks
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Webhook"

  /v1/webhooks/{id}:
    delete:
      operationId: deleteWebhook
      tags: [webhooks]
      summary: Delete a webhook
      parameters:
        - $ref: "#/components/parameters/ResourceID"
      responses:
        "204":
          description: Webhook deleted

  /v1/webhooks/{id}/deliveries:
    get:
      operationId: listWebhookDeliveries
      tags: [webhooks]
      summary: List deliveries for a webhook
      parameters:
        - $ref: "#/components/parameters/ResourceID"
      responses:
        "200":
          description: Webhook deliveries
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/WebhookDelivery"

components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: API key passed as Bearer token

  parameters:
    ResourceID:
      name: id
      in: path
      required: true
      schema:
        type: string
    TopicName:
      name: name
      in: path
      required: true
      schema:
        type: string
    AgentIDHeader:
      name: X-Agent-ID
      in: header
      required: false
      schema:
        type: string
      description: Agent identifier

  responses:
    BadRequest:
      description: Invalid request
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    Unauthorized:
      description: Missing or invalid authentication
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    UnprocessableEntity:
      description: Validation or business rule error
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"

  schemas:
    CreateTeamRequest:
      type: object
      required:
        - name
      properties:
        name:
          type: string

    Team:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        created_at:
          type: string
          format: date-time

    AddTeamMemberRequest:
      type: object
      required:
        - agent_id
      properties:
        agent_id:
          type: string

    TeamMember:
      type: object
      properties:
        team_id:
          type: string
        agent_id:
          type: string
        joined_at:
          type: string
          format: date-time

    CreateSkillRequest:
      type: object
      required:
        - name
        - description
      properties:
        name:
          type: string
        description:
          type: string

    Skill:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        description:
          type: string
        created_at:
          type: string
          format: date-time

    CreateInvitationRequest:
      type: object
      required:
        - email
      properties:
        email:
          type: string

    Invitation:
      type: object
      properties:
        id:
          type: string
        email:
          type: string
        token:
          type: string
        created_at:
          type: string
          format: date-time

    CreateWebhookRequest:
      type: object
      required:
        - url
      properties:
        url:
          type: string

    Webhook:
      type: object
      properties:
        id:
          type: string
        url:
          type: string
        created_at:
          type: string
          format: date-time

    WebhookDelivery:
      type: object
      properties:
        id:
          type: string
        webhook_id:
          type: string
        status_code:
          type: integer
        delivered_at:
          type: string
          format: date-time

    ErrorResponse:
      type: object
      required: [error]
      properties:
        error:
          type: object
          required: [code, message]
          properties:
            code:
              type: string
            message:
              type: string

    HealthResponse:
      type: object
      properties:
        status:
          type: string
          example: ok
        version:
          type: string
          example: "0.1.0"

    CreateAPIKeyRequest:
      type: object
      required: [workspace_id]
      properties:
        workspace_id:
          type: string
        permission:
          type: string
          enum: [read_only, full, admin]
          default: full

    RotateAPIKeyRequest:
      type: object
      required: [workspace_id]
      properties:
        workspace_id:
          type: string
        permission:
          type: string
          enum: [read_only, full, admin]
          default: full

    CreateAPIKeyResponse:
      type: object
      properties:
        id:
          type: string
        plaintext:
          type: string
          description: The raw API key (only returned once)
        workspace_id:
          type: string
        permission:
          type: string
        created_at:
          type: string
          format: date-time

    APIKeyListItem:
      type: object
      properties:
        id:
          type: string
        workspace_id:
          type: string
        permission:
          type: string
        revoked_at:
          type: string
          format: date-time
          nullable: true
        created_at:
          type: string
          format: date-time

    RegisterAgentRequest:
      type: object
      required: [name]
      properties:
        name:
          type: string
        role_label:
          type: string
        tool_type:
          type: string
          default: custom

    Agent:
      type: object
      properties:
        id:
          type: string
        tenant_id:
          type: string
        workspace_id:
          type: string
        user_id:
          type: string
        name:
          type: string
        role_label:
          type: string
        tool_type:
          type: string
        status:
          type: string
          enum: [online, offline]
        last_seen_at:
          type: string
          format: date-time
        created_at:
          type: string
          format: date-time

    SendMessageRequest:
      type: object
      required: [body]
      properties:
        to:
          type: string
          description: Target agent ID or "all" for broadcast
        body:
          type: string
        priority:
          type: string
          enum: [low, normal, high, urgent]
          default: normal
        reply_to:
          type: string
          nullable: true
        idempotency_key:
          type: string
          nullable: true

    Message:
      type: object
      properties:
        id:
          type: string
        from_agent_id:
          type: string
        to_agent_id:
          type: string
          nullable: true
        body:
          type: string
        priority:
          type: string
        reply_to:
          type: string
          nullable: true
        created_at:
          type: string
          format: date-time

    CreateTaskRequest:
      type: object
      required: [title]
      properties:
        title:
          type: string
        description:
          type: string
        priority:
          type: string
          enum: [low, medium, high, critical]
          default: medium
        tags:
          type: array
          items:
            type: string

    UpdateTaskRequest:
      type: object
      properties:
        status:
          type: string
          nullable: true
        notes:
          type: string
          nullable: true

    Task:
      type: object
      properties:
        id:
          type: string
        tenant_id:
          type: string
        workspace_id:
          type: string
        title:
          type: string
        description:
          type: string
        status:
          type: string
          enum: [pending_approval, open, claimed, in_progress, done, failed]
        priority:
          type: string
        created_by:
          type: string
        claimed_by:
          type: string
          nullable: true
        tags:
          type: array
          items:
            type: string
        notes:
          type: string
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time

    UsageSummary:
      type: object
      properties:
        messages_used:
          type: integer
        messages_limit:
          type: integer
        api_calls_used:
          type: integer
        api_calls_limit:
          type: integer
        agents_used:
          type: integer
        agents_limit:
          type: integer

    Activity:
      type: object
      properties:
        id:
          type: string
        agent_id:
          type: string
        action_type:
          type: string
        payload:
          type: object
          additionalProperties: true
        created_at:
          type: string
          format: date-time

    PutContextRequest:
      type: object
      required: [value]
      properties:
        value:
          type: object
          additionalProperties: true
        ttl:
          type: integer
          nullable: true
          description: Time-to-live in seconds

    ContextEntry:
      type: object
      properties:
        id:
          type: string
        tenant_id:
          type: string
        workspace_id:
          type: string
        key:
          type: string
        value:
          type: object
          additionalProperties: true
        expires_at:
          type: string
          format: date-time
          nullable: true
        created_by:
          type: string
        updated_at:
          type: string
          format: date-time

    StoreEmbeddingRequest:
      type: object
      required: [content]
      properties:
        content:
          type: string
        metadata:
          type: object
          additionalProperties: true

    Embedding:
      type: object
      properties:
        id:
          type: string
        tenant_id:
          type: string
        workspace_id:
          type: string
        content_text:
          type: string
        metadata:
          type: object
          additionalProperties: true
        created_by:
          type: string
        created_at:
          type: string
          format: date-time

    SearchRequest:
      type: object
      required: [query]
      properties:
        query:
          type: string
        limit:
          type: integer
          default: 10
          minimum: 1

    SearchResult:
      type: object
      properties:
        entry:
          $ref: "#/components/schemas/Embedding"
        score:
          type: number
          format: float

    CreateArtifactRequest:
      type: object
      required: [name, mode]
      properties:
        name:
          type: string
        type:
          type: string
        mode:
          type: string
          enum: [managed, reference]
        content_base64:
          type: string
          description: Base64-encoded content (required for managed mode)
        external_url:
          type: string
          description: External URL (required for reference mode)

    Artifact:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        type:
          type: string
        storage_mode:
          type: string
          enum: [managed, reference]
        size_bytes:
          type: integer
          format: int64
        created_by:
          type: string
        created_at:
          type: string
          format: date-time
        download_url:
          type: string
          nullable: true
        external_url:
          type: string
          nullable: true

    PublishRequest:
      type: object
      required: [body]
      properties:
        body:
          type: string

    TopicSubscription:
      type: object
      properties:
        id:
          type: string
        topic_name:
          type: string
        agent_id:
          type: string
        subscribed_at:
          type: string
          format: date-time

    TopicMessage:
      type: object
      properties:
        id:
          type: string
        topic_name:
          type: string
        from_agent_id:
          type: string
        body:
          type: string
        created_at:
          type: string
          format: date-time

    CreateWorkspaceRequest:
      type: object
      required: [name, slug]
      properties:
        name:
          type: string
        slug:
          type: string

    UpdateWorkspaceSettingsRequest:
      type: object
      properties:
        task_queue_enabled:
          type: boolean
        task_autonomy:
          type: string
          enum: [gated, full, claim_only]
        messaging_enabled:
          type: boolean
        file_sharing_mode:
          type: string
          enum: [disabled, read_only, read_write]
        context_kv_enabled:
          type: boolean
        context_feed_enabled:
          type: boolean
        vector_search_enabled:
          type: boolean
        pub_sub_enabled:
          type: boolean

    WorkspaceSettings:
      type: object
      properties:
        task_queue_enabled:
          type: boolean
        task_autonomy:
          type: string
        messaging_enabled:
          type: boolean
        file_sharing_mode:
          type: string
        context_kv_enabled:
          type: boolean
        context_feed_enabled:
          type: boolean
        vector_search_enabled:
          type: boolean
        pub_sub_enabled:
          type: boolean

    Workspace:
      type: object
      properties:
        id:
          type: string
        tenant_id:
          type: string
        name:
          type: string
        slug:
          type: string
        settings:
          $ref: "#/components/schemas/WorkspaceSettings"
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time

    SSOCallbackResponse:
      type: object
      properties:
        token:
          type: string
        user_id:
          type: string
        tenant_id:
          type: string
        email:
          type: string
        name:
          type: string
        role:
          type: string
        expires_at:
          type: string
          format: date-time
