Skip to content

⚙️ Workflows

Council ships with three GitHub Actions workflows. Which one you use depends on who opened the PR, which provider key you want to use, and whether the target repo vendors Council source.


🔀 Quick Decision Guide

Who opened the PR?
   ┌────┴──────┐
   │              │
 You / your team   External / fork contributor
   │              │
   ▼              ▼
council-review.yml    council-byok.yml
(auto, on PR open)    (manual, workflow_dispatch)

For required gates across your own TS/JS repos, use council-openai-gate.yml.
Generate only that workflow with `council init --workflow-profile openai-gate`.

Action Pinning And Runner Compatibility

Council's checked-in and generated workflows pin official GitHub Actions to immutable commit SHAs with readable release comments. The current pins use Node.js 24 action releases.

GitHub-hosted runners are updated automatically. For self-hosted runners, use Actions Runner v2.327.1 or later. Authenticated Git commands launched from a container action with actions/checkout v6 require v2.329.0 or later. Do not replace the immutable pins with moving major tags.


Deterministic Quality Workflow

This repository also runs .github/workflows/quality.yml on pull requests and pushes to main. It does not require model-provider keys and provides the ordinary deterministic evidence that must sit beside Council review:

  • Full pytest suite on Python 3.12 and 3.13.
  • Ruff across the repository.
  • Strict MkDocs build.
  • Package wheel build.

For this repository, branch protection should require these stable checks after their first successful run:

  • Tests (Python 3.12)
  • Tests (Python 3.13)
  • Lint, docs, and package
  • council-review

Council is the evidence-based review gate. Deterministic CI proves the code, docs, and package still build and test as expected. Neither replaces the other.


📊 Side-by-Side Comparison

council-review.yml council-byok.yml
Trigger pull_request (automatic) workflow_dispatch (manual)
Secrets access Repository OPENAI_API_KEY or GOOGLE_API_KEY secret Fork/repo GOOGLE_API_KEY secret that you supply
Fork PRs ⚠️ Skips LLM step (no secrets) ✅ Full review (you trigger it)
Inputs None — runs on the PR branch base_ref, upstream_repo, audience
Input validation N/A ✅ Branch ref + repo format validated
Artifacts council-report.json council-report.json + council-review.md
Use case Every PR from your own branches Fork PRs, external contributors, targeted re-runs
council-openai-gate.yml
Trigger pull_request (automatic)
Secrets access Repository OPENAI_API_KEY secret
Fork PRs Fails closed when the key is unavailable
Install path Installs Council from COUNCIL_INSTALL_SPEC pinned to v0.3.0 by default
Chair model openai/gpt-5.5 with chair_reasoning_effort = "medium"
Use case Required branch-protection gate for other repos

🔄 PR Workflow — council-review.yml

This is the always-on review gate. It fires automatically when a PR is opened or updated.

What it does

  1. Checks out the PR branch
  2. Checks whether OPENAI_API_KEY or GOOGLE_API_KEY is available
  3. If OPENAI_API_KEY is available: writes a temporary OpenAI config and runs the full 5-stage pipeline, including Gate Zero
  4. Otherwise, if GOOGLE_API_KEY is available: writes a temporary Gemini config and runs the same pipeline
  5. If neither secret is available (fork PR or missing repo secret): skips LLM, uploads a report explaining the skip
  6. Posts a PR summary with deterministic next steps and accepted-finding guidance
  7. Uploads council-report.json as a workflow artifact

Where to find the artifact

Actions tab → [workflow run] → Artifacts → council-report

Fork PRs

Fork PRs cannot access repository secrets — this is GitHub's security model, not a Council bug. The PR workflow detects missing LLM provider keys, skips the LLM step, and uploads a council-report.json explaining the skip. Do not work around this. Use council-byok.yml with a fork-local GOOGLE_API_KEY to review fork contributor PRs.


🔑 BYOK Workflow — council-byok.yml

This is the manual, key-controlled review workflow. You trigger it explicitly from the Actions tab. It is also pinned to Gemini and fails fast if GOOGLE_API_KEY is not configured in the repository or fork where it runs.

Workflow dispatch inputs

Input Required Description
base_ref ✅ Yes The base branch to diff against (e.g. main)
upstream_repo ❌ Optional Full owner/repo if reviewing a fork (e.g. contributor/myrepo)
audience ❌ Optional Output audience: developer (default) or owner

Input validation

Before running, the BYOK workflow validates:

  • base_ref passes git check-ref-format (prevents injection via malformed ref)
  • upstream_repo matches owner/repo format if provided (prevents redirect attacks)
  • All file reads are contained within the repo root via is_relative_to() (prevents path traversal)

Use restricted keys

The BYOK workflow uses your repository secrets directly. Use inference-only API keys with no billing or admin access. See Security → API Key Hardening.

How to trigger

Actions tab → council-byok → Run workflow → fill inputs → Run

The Gemini workflows use gemini/gemini-2.5-flash in CI, set reviewer_timeout_seconds = 360, and run reviewers sequentially with reviewer_concurrency = 1 to reduce model timeout/rate-limit noise.


Required OpenAI PR Gate — council-openai-gate.yml

Use this workflow when you want Council to be a required PR check across your TS/JS repositories without vendoring the Council source into each repo.

What it does

  1. Checks out the PR branch with full history
  2. Installs Council from COUNCIL_INSTALL_SPEC
  3. Fails closed if OPENAI_API_KEY is missing
  4. Writes a temporary OpenAI CI config with:
  5. Chair: openai/gpt-5.5
  6. Chair reasoning effort: medium
  7. Reviewers: OpenAI GPT-5.2 family
  8. TS/JS analyzers enabled
  9. Runs council review --ci --github-pr --branch "$BASE_REF" with BASE_REF supplied from the PR base ref
  10. Uploads council-report.json

The scaffold defaults COUNCIL_INSTALL_SPEC to v0.3.0. Keep that value pinned to a release tag or commit SHA before making the check required across many repos; do not use a moving branch such as main for protected-branch rollout.

For a full rollout checklist and language-support matrix, see the Adoption Guide. For coding-agent repair loops that consume Council outputs, see the Agent Loop guide.

Before broad external rollout, run the manual Release Smoke workflow in this repo. It verifies that a release tag or commit SHA can install Council and generate an OpenAI gate scaffold pinned to that same ref.


📦 Artifacts Reference

Artifact File Workflow Contents
council-report council-report.json All workflows Machine-readable Chair verdict, findings, reviewer health, degraded reasons, and transport notes
council-report council-review.md BYOK only Human-readable markdown review with next steps and accepted-finding fix guidance (developer or owner format)

See the JSON Contract for automation-safe parsing rules.

Finding your artifacts

GitHub → Actions tab → Select workflow run → Artifacts section (bottom of summary page)

Getting council-review.md from a PR workflow run

The PR workflow currently only uploads council-report.json. To get the markdown review:

Option A — Run the BYOK workflow against the same branch

Option B — Run locally:

council review --branch main --output-md council-review.md

💻 Local Workflow

Local runs are always advisory by default — they never block a push.

Mode Command Blocks on FAIL?
Advisory council review --branch main No
Advisory + JSON council review --branch main --output-json report.json No
Advisory + Markdown council review --branch main --output-md review.md No
CI mode council review --ci --branch main Yes

CI mode (--ci) exits non-zero on FAIL. PASS WITH WARNINGS always exits zero.


  • Getting Started — install, init, first review, adding secrets
  • Agent Loop — use Council as feedback for Codex, Claude Code, OpenClaw, and similar agents
  • Security — BYOK threat model, input validation details, fork PR policy
  • Design — the 5-stage pipeline these workflows invoke
vishalshah.app