GitHub integration
How repositories are selected, authenticated with a GitHub App, cloned server-side, and read by agents in a run.
GitHub is where an organization’s code and procedures live. The integration covers selecting repositories, authenticating to them, cloning them for server-side work, and exposing them to a run.
Repository selection
The composer and the platform read the organization’s repositories and branches:
| Operation | Endpoint |
|---|---|
| List repositories | GET /api/repos |
| List branches | GET /api/repos/:owner/:name/branches |
| Open pull requests | GET /api/pulls |
When GitHub is not configured at all, GET /api/repos returns
{ configured: false } rather than erroring, so the composer can degrade
gracefully.
Authenticated with a GitHub App
Access is configured through a GitHub App installation rather than a personal token, so private organization repositories are reachable without a human pasting a PAT. The backend mints an installation token for the organization and scopes access to it. Credential resolution has three distinct lanes:
- Backend-only GitHub calls use PAT over App over anonymous: an explicit token wins, then a configured App mints an installation token, then public access.
- The repository picker and branch browser deliberately prefer the App over a broader deployment PAT, so the offered catalog matches what a run can actually open.
- A retained sandbox only ever receives an exact-repository App installation token. Production refuses PAT-only deployments outright; local development keeps the PAT convenience behind the verified dev-mode gate.
Server-side clones
Work that needs the actual code, such as skill
import and wiki
generation, runs over a server-side shallow
clone, resolving the head with git ls-remote. This is deliberate: the REST
git-data surface is not dependable for organization installations.
In a run
Inside a run, GitHub is reached through gateway tools bound to the run’s repositories: pull-request and issue reads scoped to what the run is allowed to touch. Repository binding is validated against an allowlist, and the same allowlist governs binding whether a run starts from the web composer or from a Slack message.