GitHub Action

Use ContextOwl/contextowl-action to publish Markdown docs, changelog entries, and an OpenAPI reference from a GitHub Actions workflow. The action calls the ContextOwl REST API with an agent key.

Quick start

  1. Create an agent key in Admin > Settings > API. Bind it to one workspace for the tightest scope.
  2. Store the key in a repository secret named CONTEXTOWL_PAT.
  3. Add .contextowl.yml to the repository root:
docs:
  dir: docs
changelog:
  file: CHANGELOG.md
openapi:
  spec: openapi.yaml
  1. Add .github/workflows/contextowl.yml:
name: Publish to ContextOwl

on:
  push:
    branches: [main]
    paths: ["docs/**", "CHANGELOG.md", "openapi.yaml", ".contextowl.yml"]

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: ContextOwl/contextowl-action@v1
        with:
          token: ${{ secrets.CONTEXTOWL_PAT }}

Push to main, and the action publishes the content that you configured. A workflow that passes a secret named CONTEXTOWL_TOKEN keeps working, because the action reads the key from the token input.

Inputs

Input Required Default Description
token yes none Agent key that starts with cowl_pat_. Always pass it from a secret.
server-url no https://contextowl.co Base URL of the ContextOwl instance. The action appends /api/v1.
config no .contextowl.yml Path to the config file, relative to the repository root.
workspace no none Target workspace. It overrides the config file. Leave it out for a workspace-bound key.
prune no false Remove content that is no longer in the repository. See Prune below.
dry-run no false Print the plan and make no changes.
fail-on-error no true Fail the job when an item fails to sync. Set it to false to report failed items as warnings.
allow-shrink no false Accept a new article body that removes most of the current text. See Large removals below.

The outputs created, updated, deleted, skipped, and failed hold the totals for all surfaces. A surface that stops before it finishes counts as 1 in failed. The action also writes a summary table to the workflow run.

Configuration

Every surface is optional. Configure only the surfaces that you use. The file needs at least one.

workspace: prod # optional for workspace-bound keys
docs:
  dir: docs # Markdown directory
changelog:
  file: CHANGELOG.md # Keep a Changelog file
openapi:
  spec: openapi.yaml # OpenAPI 3.x JSON or YAML
prune: false # also settable with the prune input

Docs

Each .md or .mdx file becomes one article. Front matter is optional:

---
title: Getting Started # defaults to the first H1, then the file name
section: Guides # defaults to the name of the parent directory
status: STABLE # DRAFT | IN REVIEW | BETA | STABLE | DEPRECATED
slug: getting-started # optional explicit URL slug
version: v2 # optional doc version label
---

# Getting Started

Changelog

A single Keep a Changelog file becomes one entry for each version heading:

## [1.4.0] - 2026-02-01

### Added

- Dark mode

### Fixed

- Export crash

Before the action sends an entry, it maps each ### subsection name to a ContextOwl tag. The match ignores case.

Subsection Tag
Added new
Changed improved
Deprecated deprecated
Removed deprecated
Fixed fixed
Security security

The tag names and the server aliases also work as subsection names: New, Improved, Feature, Features, Improvement, Improvements, Fix, Fixes, Bugfix, and Deprecation. Any other subsection name gets no tag. The action logs a warning for that name and still syncs the entry.

OpenAPI

The action uploads the spec to ContextOwl. ContextOwl generates the API reference pages again and removes the pages of endpoints that left the spec. An unchanged spec writes nothing. This needs openapi.attach.

Sync behavior

Failures and warnings

The action writes the job summary first. Then it sets the job result:

Large removals

The server refuses a new article body that removes more than half of the current text and more than 2,000 characters. This guards a live article against a truncated or broken file. The article keeps its current body and counts as a failed item.

To accept such a change, set allow-shrink to true. The action then sends the body again with allow_shrink and logs a warning.

Prune

Prune is off by default. When you turn it on with the input or with prune: true, the action removes content that is no longer in the repository:

[!WARNING] Prune treats the repository as the source of truth for the whole workspace. It can deprecate or delete content that somebody created in the ContextOwl editor. Always do a dry run first.

Surface Minimum Add for publish Add for prune
Docs article.read, article.create, article.update, section.create, article.place article.publish article.publish
Changelog changelog.read, changelog.create, changelog.update changelog.publish changelog.delete
OpenAPI openapi.read, openapi.attach, openapi.sync none none

Dry run

- uses: ContextOwl/contextowl-action@v1
  with:
    token: ${{ secrets.CONTEXTOWL_PAT }}
    dry-run: true

The action prints what it would create, update, skip, or remove, and makes no changes.