> ## Documentation Index
> Fetch the complete documentation index at: https://docs.xpander.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Publish Skills

> Publish a batch of skills from a repository into your organization's skill registry, with each skill's visibility and access taken from its xpander.yaml.

Publish is the call a CI job makes when a skills repository merges. The repository holds one folder per skill, each with a `SKILL.md` (the instructions the agent reads) and an `xpander.yaml` (the registry contract). On merge, CI bundles every skill folder under `managed_by.path_prefix` and sends up to 25 skills per call, with the `managed_by` block naming the repo, ref, commit and run URL. The response holds one outcome per skill in `results`: `created`, `updated`, `unchanged`, `archived` or `error`, with its `skill_id` and a short `detail`. A matching `sha256` returns `unchanged`. `archive_missing` archives the skills this repo and prefix published earlier that the call no longer lists (their names come back in `archived`), `dry_run` computes every outcome without writing, and non-fatal notes arrive in `warnings`. Publishes and archives are audited as `PUBLISH_SKILL` and `ARCHIVE_SKILL`. Authenticate with an organization API key in `x-api-key`.

`xpander.yaml` carries the skill's access, and each skill's `metadata` mirrors it. `visibility` is `org` (any agent in the organization may hold the skill), `restricted` (only the agents listed in `agents`) or `agent` (one owner agent, the single entry in `agents`). `access_scope` is `organizational` for the organization's catalog or `personal` for the publisher's own. `users` and `groups` are the user and group audiences of Manage access: who sees the skill in the catalog. How the scope is enforced at runtime is on [Skill visibility](/resources/security-compliance/access-control#skill-visibility); how it looks to a builder is on [Skills](/use/skills#skill-visibility).


## OpenAPI

````yaml POST /v1/skills/publish
openapi: 3.1.0
info:
  title: xpander.ai API Service
  description: |2-

        The xpander.ai API Service provides a unified REST API for managing AI agents,
        executing tasks, managing knowledge bases, and integrating with external systems.
        
        Features:
        - Agent Management: Create, update, deploy, and delete AI agents
        - Task Execution: Invoke agents with support for sync, async, and streaming modes
        - Knowledge Bases: Manage knowledge bases and documents for RAG workflows
        - Tools: Discover, connect, and attach tools (connectors, custom functions, MCP servers, sub-agents, workflows) to agents and workflows
        - MCP Integration: Model Context Protocol support for standardized AI interactions
        
        Authentication: All endpoints require authentication via either an API key (`x-api-key`) or an OAuth2 JWT (`Authorization: Bearer <jwt>`).
        
  version: '0.001'
servers:
  - url: https://api.xpander.ai
security: []
paths:
  /v1/skills/publish:
    post:
      tags:
        - API v1
        - Skills
      summary: Publish Skills
      description: >-
        Publish up to 25 skills from a repository into the organization's skill
        registry. Each skill's visibility, allowlisted agents, access scope,
        users and groups come from its `xpander.yaml`. Returns one outcome per
        skill: created, updated, unchanged, archived or error.
      operationId: Publish_skills_v1_skills_publish_post
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PublishSkillsRequest'
            example:
              managed_by:
                repo: acme/agent-skills
                path_prefix: skills
                ref: refs/heads/main
                commit: 9f1c2d3e4b5a6978877665544332211009988776
                run_url: https://github.com/acme/agent-skills/actions/runs/123456789
              archive_missing: true
              dry_run: false
              skills:
                - name: quarterly-report
                  path: quarterly-report
                  skill_md: >-
                    ---

                    name: quarterly-report

                    description: Build the quarterly revenue report from the
                    finance warehouse.

                    ---


                    Read the report template, query the warehouse, and hand back
                    a PDF.
                  bundle_b64: >-
                    H4sIAAAAAAAAA+3BMQEAAADCoPVPbQwfoAAAAAAAAAAAAAAAAAAAAIC3AYbSVKsAKAAA
                  sha256: >-
                    4d1f8a3c0b9e7f6d5c4b3a2918273645f0e1d2c3b4a5968778695a4b3c2d1e0f
                  metadata:
                    visibility: restricted
                    agents:
                      - a1a1a1a1-b2b2-c3c3-d4d4-e5e5e5e5e5e5
                    access_scope: organizational
                    users: []
                    groups:
                      - finance
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublishSkillsResponse'
              example:
                results:
                  - name: quarterly-report
                    outcome: updated
                    skill_id: 5b5b5b5b-6c6c-7d7d-8e8e-9f9f9f9f9f9f
                    detail: bundle changed; visibility org -> restricted
                archived:
                  - legacy-invoice-check
                warnings: []
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
      security:
        - APIKeyHeader: []
components:
  schemas:
    PublishSkillsRequest:
      properties:
        managed_by:
          $ref: '#/components/schemas/PublishManagedBy'
        archive_missing:
          type: boolean
          title: Archive Missing
          default: false
          description: >-
            Archive skills that this repo and prefix published earlier and that
            are absent from `skills`. Their names are returned in `archived`.
        dry_run:
          type: boolean
          title: Dry Run
          default: false
          description: Compute every outcome without writing to the registry.
        skills:
          items:
            $ref: '#/components/schemas/PublishSkillItem'
          type: array
          minItems: 1
          maxItems: 25
          title: Skills
          description: Up to 25 skills per call.
      type: object
      required:
        - managed_by
        - skills
      title: PublishSkillsRequest
    PublishSkillsResponse:
      properties:
        results:
          items:
            $ref: '#/components/schemas/PublishSkillResult'
          type: array
          title: Results
          description: One entry per skill in the request, in request order.
        archived:
          items:
            type: string
          type: array
          title: Archived
          default: []
          description: Names of skills archived by `archive_missing`.
        warnings:
          items:
            type: string
          type: array
          title: Warnings
          default: []
          description: Non-fatal notes about the call.
      type: object
      required:
        - results
      title: PublishSkillsResponse
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    PublishManagedBy:
      properties:
        repo:
          type: string
          title: Repo
          description: Repository that owns the skills, as `owner/name`.
          examples:
            - acme/agent-skills
        path_prefix:
          type: string
          title: Path Prefix
          default: ''
          description: >-
            Folder inside the repo that holds the skill folders. Skills are
            matched for `archive_missing` by repo and prefix.
        ref:
          type: string
          title: Ref
          description: Git ref that was merged.
          examples:
            - refs/heads/main
        commit:
          type: string
          title: Commit
          description: Commit SHA the bundles were built from.
        run_url:
          anyOf:
            - type: string
            - type: 'null'
          title: Run Url
          description: Link to the CI run that made the call.
      type: object
      required:
        - repo
        - ref
        - commit
      title: PublishManagedBy
      description: >-
        Where the skills come from. Stored on each published skill so the
        registry knows which repository manages it.
    PublishSkillItem:
      properties:
        name:
          type: string
          title: Name
          description: >-
            Skill name, the `name` in `SKILL.md` frontmatter. It is the key used
            in `results` and `archived`.
        path:
          type: string
          title: Path
          description: Path of the skill folder inside the repo, relative to `path_prefix`.
        skill_md:
          type: string
          title: Skill Md
          description: Contents of `SKILL.md`.
        bundle_b64:
          type: string
          title: Bundle B64
          description: >-
            The skill folder as a base64-encoded tar.gz, `SKILL.md` and
            `xpander.yaml` included.
        sha256:
          type: string
          title: Sha256
          description: >-
            Hex SHA-256 of the decoded bundle. A matching value on an existing
            skill returns `unchanged`.
        metadata:
          $ref: '#/components/schemas/SkillPublishMetadata'
      type: object
      required:
        - name
        - path
        - skill_md
        - bundle_b64
        - sha256
        - metadata
      title: PublishSkillItem
    PublishSkillResult:
      properties:
        name:
          type: string
          title: Name
        outcome:
          $ref: '#/components/schemas/PublishSkillOutcome'
        skill_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Skill Id
          description: Registry id of the skill, when the registry holds one.
        detail:
          anyOf:
            - type: string
            - type: 'null'
          title: Detail
          description: >-
            Short human-readable note on the outcome, for example what changed
            or why it failed.
      type: object
      required:
        - name
        - outcome
      title: PublishSkillResult
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
      type: object
      required:
        - loc
        - msg
        - type
      title: ValidationError
    SkillPublishMetadata:
      properties:
        visibility:
          $ref: '#/components/schemas/SkillVisibility'
          default: org
        agents:
          items:
            type: string
          type: array
          title: Agents
          default: []
          description: >-
            Agent ids allowed to hold the skill. Required for `restricted` (one
            or more) and `agent` (exactly one); ignored for `org`.
        access_scope:
          $ref: '#/components/schemas/SkillAccessScope'
          default: organizational
        users:
          items:
            type: string
          type: array
          title: Users
          default: []
          description: >-
            User ids of the Manage access user audience: who sees the skill in
            the catalog.
        groups:
          items:
            type: string
          type: array
          title: Groups
          default: []
          description: >-
            Group ids of the Manage access group audience: who sees the skill in
            the catalog.
      type: object
      title: SkillPublishMetadata
      description: The access contract of one skill, mirrored from its `xpander.yaml`.
    PublishSkillOutcome:
      type: string
      enum:
        - created
        - updated
        - unchanged
        - archived
        - error
      title: PublishSkillOutcome
    SkillVisibility:
      type: string
      enum:
        - org
        - restricted
        - agent
      title: SkillVisibility
      description: >-
        Who may hold the skill: `org` is any agent in the organization,
        `restricted` is the agents listed in `agents`, `agent` is the one owner
        agent listed in `agents`.
    SkillAccessScope:
      type: string
      enum:
        - personal
        - organizational
      title: SkillAccessScope
      description: >-
        Which catalog the skill sits in: the publisher's personal catalog or the
        organization's.
  securitySchemes:
    APIKeyHeader:
      type: apiKey
      description: API Key for authentication
      in: header
      name: x-api-key

````