Skip to main content
The admin UI at /admin is the control panel for your AI-Implement orchestrator. It is enabled when either ADMIN_ACCESS_CODE or a sign-in provider is configured — with neither, the UI is disabled and all /admin and /api/* routes return 503, with a response body naming the missing configuration. Every panel below is also reachable programmatically through the JSON API at the bottom of this page. The sidebar organizes panels into groups:
  • Work — Overview, Issues, Pipelines, Pull requests, Blockers, Reports
  • Configure — Projects, Pipelines & steps, Models & providers, Triggers & channels, Policies & risk
  • Platform — Runners, Sessions, Deployments, Reaper, Secrets, Settings
  • Developer — MCP server, Webhooks, Audit log, Customizations, Updates
Some are placeholders for planned functionality and have no section below:
  • Triggers & channels
  • Policies & risk
  • MCP server
  • Webhooks
  • Updates.
Opening one tells you which panel does that job today.
The MCP server entry is a placeholder for a panel that does not exist. The endpoint it names does: /mcp already serves the knowledge graph and the orchestrator’s read-only diagnostic tools, covered in the MCP tools reference. The headings below follow the sidebar order, covering the panels that have a section of their own.

Work

Overview

The main dashboard. Shows real-time orchestrator health:
  • Running jobs (with duration)
  • Failed jobs in the last 24 hours
  • Capacity utilization across all projects
  • Projects at concurrency cap
  • Stale workflow templates in target repos
  • A 24-hour dispatch trend chart
Environment-status checks (ticketing connection, runner callback, gap-fill trigger) appear here too — this is the first place to look if a run hasn’t dispatched as expected.

Issues

The AI-Implement inbox. Shows every issue matched by the configured project mappings, its current state (started / completed / canceled), and whether each is ready for implementation or still has planning pending. A second table breaks down in-progress counts by project mapping for real-time visibility into which scopes are currently working.

Pipelines (jobs)

The dispatch log under its real internal name (jobs in the sidebar). Shows dispatch entries (timestamped) across all teams with full execution history:
  • Issue ID
  • Repo
  • Team (the teamKey shown in the row)
  • Runner mode (GitHub Actions or Fly Machines)
  • Session image
  • Combined planning-and-implementation statuses
  • Pull-request links
  • Dispatch number (for re-dispatches)
Planning and implementation dispatches for the same issue are grouped visually as a single job. Unfiltered, the panel shows the most recent 100 entries. Applying a time-range filter narrows the view to a chosen window, but shows the full retained history during that window rather than the newest 100.
Use this log to audit activity or diagnose why an issue was or was not picked up.
The log retains only the most recent 500 dispatches. Older entries are deleted permanently, so no filter will surface them.

Pull requests

Lists every bot-opened pull request the orchestrator is tracking, with the following information:
  • Issue link
  • Repo
  • Current job status (running / completed / failed / review_failed / timed_out)
  • Iteration count (the dispatch number)
  • Time since last dispatch
  • Direct links to GitHub
The issue link on this panel, and the equivalent links on the Blockers and Sessions panels below, currently always point at linear.app. For a Jira-mapped project, that link is wrong — use the issue identifier shown alongside it to find the ticket in Jira instead.
Useful for spotting PRs that are stalled or failing review without scanning each repo individually.

Blockers

Surfaces issues that a project mapping matched but the last poll did not dispatch. An issue held back by an open blocking link never appears here. Both ticketing systems drop those while building the snapshot this panel is computed from. The reasons it reports:
  • No mapping — the issue’s team or project has no project mapping.
  • Dedup — the issue already has a dedup entry, so the orchestrator treats it as in flight.
  • Concurrency cap — the mapping is at its limit of issues in progress.
  • File overlap — the issue declares files a sibling on the same grouping branch already claimed, so it waits for that sibling to merge.
KPI cards show:
  • Total blocked
  • Teams affected — distinct teams with at least one blocked issue
  • By concurrency cap
  • By dedup
Per-issue rows include:
  • Issue identifier
  • Project mapping
  • Blocking reason
  • Detail (further context on the blocking reason)
  • Direct link back to the ticket

Reports

Fleet-wide outcome analytics across every tracked repository, over a window you choose — the last 7, 30, or 90 days, defaulting to 30. Each card settles a different fleet-level question:
  • Fleet by repo — how repositories compare on throughput, completions, failures, merges, and cost, a row apiece.
  • Outcomes — how cleanly work lands: how often it is approved on the first dispatch versus eventually, and how often merged work needed a human edit afterward (the escape rate).
  • Planning A/B — whether planning pays for itself, setting issues that went through planning against those that did not on the same outcome and cost measures.
  • Runaways — which issues are consuming dispatches without landing: those with three or more dispatches, or three or more consecutive failures.
The Cost (USD) column, and the average cost in the Planning A/B card, are estimates computed from token usage at list prices — not billed spend. The estimate counts only each run’s implementation passes, not any other invocation the run makes.
The figure takes no account of how a run authenticated, so a subscription-authenticated run that bills nothing per run still reports a cost here.

Configure

Projects (team/repo mappings)

The Projects panel is where you connect ticketing scopes (Linear teams or Jira JQL clauses) to GitHub repositories and control exactly how AI-Implement dispatches runs for each scope.
See Configure project mappings for the full field reference and defaults.

Create a new project mapping

1

Open the stepper

Click Configure → Projects → + New project. The stepper walks through the configuration one step at a time.
2

Fill in Ticketing System and Source

Pick Linear or Jira as the ticketing system, fill in the provider-specific config (Linear team key, or Jira JQL + repo-field value), then enter the target repo’s GitHub Owner, Repository Name, and Default Branch.
Default Branch is required and must match the repo’s actual primary branch (commonly main, master, or development).
Once the owner and repository are filled in, Check installation confirms the GitHub App can reach that repo. It reports one of these outcomes:
  • The App is installed and can access the repository.
  • The App is not installed on that owner, with a link to install it.
  • The App is installed but the repository is not among its selected repositories, with a link to add it.
3

Step through the remaining configuration

Runner, Provider, Capacity, Secrets, and Review steps follow. For a first run, defaults are reasonable.The Capacity step here only sets the maximum number of issues this mapping can run in parallel. The per-run caps (maxTurns, maxIterations, maxJobMinutes) aren’t part of the stepper — set them afterward from the project’s Edit dialog. See Project mappings for those fields and their defaults.
Setting provider to bedrock requires awsRegion and is not compatible with executionMode: fly-machines.You must also add AWS_BEDROCK_ROLE_ARN as a secret in the target repo. Nothing else is needed for /ai-implement comment-triggered runs — they use this same mapping.
4

Create the project

Click Create project. The new mapping appears in the Projects table automatically — if it does not, reload the page.
Each row in the Projects table also exposes a Sync workflows action, which opens or updates a pull request in the target repo containing the workflow files and starter prompts. This is the normal way to push workflow updates from the orchestrator into target repos.Saving a project also syncs its workflows, so a newly created mapping gets its pull request without any extra step. Reach for the row action when a sync is all you need — saving runs a full mapping update alongside it.

Pipelines & steps

Shows the pipeline YAML definitions (the built-in src/pipeline/*.yml plus any custom/pipelines/*.yml overrides) as collapsible details, each listing the steps that run and their module IDs. A second table lists every step module with:
  • Built-in path
  • Custom override path (if present)
  • Status (built-in / override / additive)
Useful for visualizing the extension hierarchy when you’ve added custom steps. See Add custom pipeline steps for the override mechanism.

Models & providers

Read-only summary of model provider and region per project mapping.
Model IDs themselves live in each target repo’s WORKFLOW.md and PLANNING.md front matter — this page doesn’t edit them.
KPI cards show:
  • Projects (total)
  • Anthropic (count of projects using the Anthropic provider)
  • Bedrock (count of projects using the Bedrock provider)
  • Bedrock regions (count of distinct regions in use)
The table lists each project’s:
  • Team (the teamKey)
  • Repo
  • Provider badge (anthropic or bedrock)
  • Bedrock region (or a “missing” badge if required and unset)
  • Planning status
  • Runner mode

Platform

Runners

High-level runner-infrastructure dashboard. KPI cards show:
  • Current runner-mode override (default / gha / fly / local / shadow)
  • Live Fly session count
  • Capacity utilization (in-progress runs vs. total cap across mappings)
  • 24-hour reaper destructions

Runner mode

The toggle offers four options: default, gha, fly, and shadow. local is a valid runner mode too, but the toggle doesn’t expose it — set it through the environment or the API instead.
If the RUNNER_MODE environment variable is set on the orchestrator process, it takes precedence over this database value and the UI flags that an env-var lock is active.If you change runner mode via the UI or API while RUNNER_MODE is set in the environment, the new value is persisted to the database but has no effect until the env var is removed and the orchestrator is restarted.

Live Fly sessions

A table of the most recent eight, linking into the Sessions panel for the full list.

Per-project execution mode

A table shows each mapping’s:
  • Configured execution mode
  • Effective mode (after applying any global override)
  • Capacity-utilization meter

Parked issues

Issues the dispatch breaker has parked. This section renders at the top of the panel, above the runner-mode controls, and stays hidden while nothing is parked. An issue is parked once enough consecutive dispatches fail for the same issue and phase, and is skipped on every poll from then on. Planning and implementation are counted separately, so an issue can be parked in one while the other keeps running, and a successful dispatch resets the count — only an unbroken run of failures parks anything. Each row shows:
  • Issue identifier
  • Repo
  • Phase (planning or implementation)
  • Consecutive failure count
  • Last conclusion
  • How long ago it was parked
  • An Unpark action
Unpark is the only thing that releases a parked issue — a later successful dispatch resets the failure count but leaves the park in place. Unparking clears it for every phase and resets the counter, so the orchestrator dispatches the issue again on the next poll.

Sessions

Lists every Fly Machine session currently in started, starting, or created state. Each row shows:
  • Machine ID and name
  • Current state
  • Uptime duration
  • Associated issue identifier (linked to the ticketing system), where available
  • Target repo, where available
You can destroy a stuck session directly from this panel. Destroying a session also:
  • Removes the in-progress marker from the associated issue (the AI-Working label on Linear, or Implementing status on Jira)
  • Clears its dedup entry, so the orchestrator can pick it up again on the next poll
If a Fly Machine appears stuck and is not progressing, destroying it from the sessions panel is the cleanest recovery path.

Deployments

Where you release a new version of the orchestrator itself. Set up self-deployment covers what it needs and how releasing behaves. Cards report:
  • Availability — the repository and branch the running image was built from, and whether that build’s commit is behind the branch head (Available, Up to date, or Unknown when either commit can’t be read)
  • Last deploy — how the most recent release from this panel ended: Completed, Degraded (running, but without its knowledge graph), or Failed (nothing released, the running version untouched)
  • Deploy status, while one is running — whether it is waiting for in-flight work to drain, and what that work is, or building
Only a release from this panel is recorded there, so an orchestrator deployed by hand reads None yet until the first one. The controls are:
  • Deploy now, offered when a deployment is available and also when the last one was degraded or failed, since rebuilding the same commit is how a degraded release gets repaired. It asks for confirmation, then pauses new dispatches immediately and resumes them when the deploy ends, however it ends
  • The switches under When a deployment becomes available, deciding whether a new commit is released without being asked and whether it is announced to your notification webhook. Each states its current effect in place, and Let it deploy automatically covers the rule they share
On an orchestrator that can’t deploy itself, a Self-deploy not configured banner replaces all of it.

Reaper

The reconciliation-sweep dashboard. A summary card shows the 24-hour total of machines the reaper destroyed, broken down by rule:
  • orphan
  • stale-terminal-job
  • max-age-exceeded
  • issue-terminal
Plus the last sweep timestamp. A recent-actions table lists the latest destructions with:
  • Timestamp
  • Rule matched
  • Machine ID
  • Tenant
  • Associated issue
  • Age at destruction (in seconds)
  • dry-run or destroyed badge (indicating whether the action was a no-op or executed)

Secrets

The Secrets panel itself is a placeholder — a consolidated browse-and-rotate view is not built yet. Secrets are managed in two places today:
  • Global secrets on the Settings panel
  • Per-project secrets from each project’s row on the Projects panel.
Both are backed by the endpoints below.

Per-team secrets

Each project mapping has its own per-team secrets at /api/mappings/:teamKey/secrets. Secrets are stored as Fly app secrets with the team key as a prefix (e.g. a secret named MY_TOKEN for project ENG is stored as ENG_MY_TOKEN).
Secret names must contain only letters, digits, and underscores.

Global secrets

Global secrets are Fly app secrets that do not belong to any specific project mapping. They are listed, created, and deleted from /api/global-secrets.
Global secret names must not start with any project key prefix (to keep the per-team scoping unambiguous).

Settings

The settings panel manages orchestrator-level configuration:
  • flySessionsApp — the Fly.io app name used for Fly Machine sessions.
  • flySessionsRegion — the default region for new Fly Machine sessions.
Both values can be overridden at the environment level via FLY_SESSIONS_APP and FLY_SESSIONS_REGION. When an env override is active, the UI shows the runtime value alongside the database value and flags that the env var is winning.
Changes to settings that differ from the running process take effect after a restart.

Developer

Audit log

Shows the dispatch-deduplication ledger — every issue that currently has an entry. Each row includes:
  • Issue identifier and title
  • When the issue was dispatched
  • A delete button to remove the entry
An issue gets an entry when it’s dispatched, which stops the orchestrator from picking up the same issue again. Entries don’t expire on a timer. They’re cleared under any of these conditions:
  • The issue is completed or canceled. The orchestrator notices on its next poll, which is how an entry normally clears once the issue’s pull request merges and the issue closes.
  • No configured tracker returns the issue anymore, because it was deleted or moved out of scope.
  • The dispatch attempt fails before a run starts.
  • A run fails or times out while the issue is within its retry budget. Once the budget is used up, the entry stays and the issue is left for a person to investigate.
  • A session is destroyed from the Sessions panel.
  • The reaper ends a session that ran past the maximum session age, or whose issue was already completed or canceled.
  • An operator removes the entry with its delete button.
If none of these happens, the entry stays. The usual case is a successful run on an issue that is never completed or canceled. Remove an entry with its delete button so the orchestrator can pick the issue up again on the next poll.
The roadmap calls for richer audit-log content here over time; the current implementation is focused on the dedup ledger.

Customizations

Lists every file under the custom/ directory in the orchestrator’s working tree that overrides a built-in. The table shows each file’s:
  • Path
  • Category (pipeline / step / provider / other)
  • Status (override / additive / — for the other category)
  • Upstream counterpart path it shadows
  • File size
  • Last-modified time
A CI workflow (protect-custom.yml) flags upstream PRs that modify files under custom/ outside the allowed paths (custom/README.md and .gitkeep files). The check is currently advisory — it won’t hard-block a merge but will surface a warning in CI. The team has it tracked to restore as a hard fail.See Add custom pipeline steps for the resolution rules.

Admin API reference

Operator-facing /api/* endpoints require a signed-in session, which lasts 24 hours. A request carries it in the cookie the browser sets at sign-in, or in an Authorization: Bearer header when you are scripting. The session-machine endpoints at the end of this section are the exception — they authenticate by a per-session nonce instead.

Authentication

In the browser, sign in with single sign-on or the access code — the session lands in a cookie and nothing else is needed. For scripting, mint a token with the access code and pass it as a bearer header. This works only where an access code is configured: with single sign-on alone the orchestrator refuses access-code sign-in, so there is no bearer flow.
1

Obtain a bearer token

POST your access code to /api/auth:
The response contains a token field. Store it for subsequent requests.
2

Pass the token on subsequent requests

Include the token as a Bearer header:
Access-code sign-in is deprecated in favor of single sign-on, so this is not a supported basis for new tooling.

Endpoint reference

Authentication

The /api/auth/* sign-in endpoints above are reachable without a session — they are how you get one, and they stay open even when no access code is configured. Every other operator-facing endpoint on this page returns 401 Unauthorized when the session cookie or bearer token is missing or expired.
A session is not a blanket gate on /api/*: a separate handful of endpoints used by runner sessions authenticate by a different mechanism, and the GitHub webhook endpoint authenticates by signature. Account for all three when writing ingress rules. See Session-machine endpoints below.

Project mappings

Jira field helpers

Issues, jobs, and pull requests

Reports

Sessions, reaper, and deduplication

Dispatch breaker

Deployments

Runner mode and settings

Secrets

Orchestrator status

Session-machine endpoints

The /api/* endpoints below are called by Fly Machine and local Docker runner sessions, not by operators, and — unlike the rest of /api/* — do not require an operator session. Each authenticates with a per-session nonce instead, issued when the session starts and rejected once it expires.
These are internal to the orchestrator and its runner sessions. They are listed here so monitoring and ingress rules account for them correctly — not as an interface to build against. Their paths, payloads, and authentication may change without notice, and nothing outside a runner session should call them.

Runner callback endpoints

The endpoints below are called by runners (GitHub Actions workflow jobs, Fly Machine sessions, or local Docker containers running an issue), not by operators. Some sit outside the /api/* namespace and some inside it, but all are authenticated by a runner token rather than by an operator session. All of them respond 501 Not Implemented when the orchestrator has no RUNNER_TOKEN_SECRET configured, since none can validate tokens without it.
Operators do not normally call these directly. They’re documented here so that monitoring tools, ingress configurations, and debugging sessions can account for runner-side traffic correctly.

Webhook and trigger endpoints

These endpoints sit outside the operator API but are operator-configurable: you set their URLs and secrets in your target repos (or at the organization level), and the orchestrator validates incoming requests against those secrets. Documented here so monitoring tools, ingress rules, and integration testing can account for them.
Both endpoints require their corresponding secret to be configured on the orchestrator.See GITHUB_WEBHOOK_SECRET and GAP_FILL_TRIGGER_SECRET