Skip to content
AXOWLDevelopers
Quickstart

Run Fledgeplan agents on GitHub Actions

Fledgeplan agents do their work through Axowl’s MCP tools: they read your repository and propose changes as pull requests. The agent itself — Claude Code — has to run somewhere. With this setup it runs on your repository’s GitHub Actions, started by Axowl whenever an agent has work. Nothing has to stay on at your desk.

Who pays for what. GitHub Actions minutes are billed to your GitHub account. Claude usage is billed to your own Anthropic account or Claude subscription. Axowl does not charge for, resell or relay Claude usage.

You need a GitHub account and the repository connected through the Axowl GitHub App (a pasted access token cannot start workflows for you).

  1. Allow GitHub Actions for the repository. Axowl asks in three places — they all change the same switch: when you connect the repository (client → Repository tab), when you connect Fledgeplan, and any time in App group → Settings → GitHub Actions. It is off by default; while it is off Axowl never writes or starts a workflow in that repository.

  2. Install the workflow file. In the same place, press Install. Axowl commits .github/workflows/fledgeplan-agent.yml to the default branch. Agents cannot change this file.

  3. Add your Claude credential to GitHub as a secret of the repository environment fledgeplan (repository → Settings → Environments). Either one:

    • ANTHROPIC_API_KEY — a key from Claude Console. Recommended for teams.
    • CLAUDE_CODE_OAUTH_TOKEN — from claude setup-token on your own computer (Claude Pro, Max, Team or Enterprise). Subscription limits assume ordinary individual use, so frequent agent runs can hit them.

    Axowl only checks that a secret with one of these names exists; it never sees the value. If both are set, the API key is used.

  4. Choose the runner (optional). GitHub-hosted is the default. Self-hosted runs on your own runner with the labels self-hosted and fledgeplan — use it when code must not leave your network. After changing the runner, install the workflow file again.

Triggerworkflow_dispatch only — started by Axowl. No pull_request, push or comment triggers, so a fork cannot run it.
Repository permissionsNone. permissions: id-token: write only, to prove its identity to Axowl.
CodeNot checked out. The agent reads and writes the repository through Axowl’s MCP tools, as pull requests.
ClaudeClaude Code, a pinned version, with --allowedTools mcp__axowl — no shell or file tools — and at most 60 turns per run.
Limits30 minutes per run. Duplicate wake-ups within 2 minutes are folded into one by Axowl.

The run asks GitHub for an OpenID Connect token with the audience axowl-fledgeplan and sends it to POST /mcp/github-oidc/token. Axowl checks GitHub’s signature and that the token comes from your connected repository (by numeric id), from fledgeplan-agent.yml on the default branch, started by workflow_dispatch. Only then does it return a 60-minute MCP token for that one run. When the run reports its result (POST /mcp/github-oidc/report) or is found stopped, that token stops working immediately, even if time is left.

Every stop is shown in App group → Settings → GitHub Actions with the reason, what to do, and buttons to open the right settings page or Run again. If the run belonged to a story, the story’s activity gets an agent_run entry, and the person testing that story is notified — the organization Owner when there is no story or tester. The same reason on the same repository is announced at most once an hour. Axowl operations is alerted as well.

ReasonMeaning
app_uninstalledThe Axowl GitHub App was removed, or the repository was taken out of it.
workflow_missingfledgeplan-agent.yml is missing or was changed. Install it again.
actions_disabledActions is turned off for the repository or the workflow.
permission_missingThe App’s updated permissions (Actions: read and write) are not approved yet.
dispatch_refusedGitHub refused to start the workflow for another reason.
actions_not_allowedAn agent had work but GitHub Actions is turned off for this repository in Axowl.
not_startedNo run appeared within 5 minutes of Axowl’s request.
queued_too_longThe run waited more than 10 minutes for a runner (self-hosted runner offline).
actions_billingGitHub did not start the job: Actions minutes or spending limit used up, or a payment failed.
oidc_refusedThe run could not prove which repository and workflow it came from.
claude_credential_missingNeither secret is set in the fledgeplan environment.
claude_authClaude rejected the credential (wrong or deleted key, expired or revoked token).
claude_limitCredit balance, usage limit or rate limit reached.
claude_errorClaude stopped with another error, including running out of turns.
runner_failedThe run failed on GitHub; the last log lines are shown.
timed_outThe run hit its 30-minute limit.
cancelledSomeone cancelled the run on GitHub.
no_reportThe run ended on GitHub without reporting its result.
ci_watch_gave_upAxowl could not see CI finish on the agent’s pull request for 3 hours, so the agent was not woken.
ended_silentlyThe run finished, but the agent put a question in its closing note instead of asking through Axowl. Read the note on the story card, answer it, then run again.

All under /api/org/{slug}/app-groups/{groupId}/agent-runner (signed-in organization member holding the permission shown):

  • GET / — per repository: the Actions switch, runner, workflow status, why it is blocked, the last stop; plus recent runs. Needs org.git_repository.list.
  • PUT /repos/{linkId} — { "actionsAllowed": true, "runner": "github" | "self-hosted" }. Needs org.git_repository.update.
  • POST /repos/{linkId}/install — install the workflow file. Refused with 409 and "code": "ACTIONS_NOT_ALLOWED" while the switch is off. Needs org.git_repository.update.
  • GET /repos/{linkId}/secrets — whether ANTHROPIC_API_KEY / CLAUDE_CODE_OAUTH_TOKEN exist (names only). Needs org.git_repository.read.
  • POST /runs/{runId}/retry — run a stopped run again. Needs org.git_repository.update.

The client’s repository switch is also at PUT /api/org/{slug}/applications/{appId}/repository/actions ({ "allowed": true }, org.git_repository.update).