Repositories
After this page you can give an agent a repository to work in, know exactly what authority that requires and who has to provide it, and know what your integration must store to keep working when an administrator changes their mind.
A session’s source is chosen once
Section titled “A session’s source is chosen once”A session’s workspace comes from its source, set at creation and immutable
afterwards. There are three shapes:
source |
Workspace |
|---|---|
| omitted | An empty workspace. Useful for tasks that write from scratch. |
{ "kind": "public", "url": "https://…", "label": "…" } |
A public HTTPS clone. No authorization needed, http:// is rejected, and the URL may not embed credentials. |
{ "kind": "github", "grantId": "…", "repositoryId": "…", "baseBranch": "…" } |
A repository the organization has granted to your installation. repositoryId names which repository and is required for every current grant. baseBranch is optional and defaults to the repository’s default branch. |
PATCH cannot change it. A different repository, or a different base branch, is
a different session — which is the honest model, because the agent’s work is
relative to what it started from.
Read back, a GitHub source reports what was actually pinned:
{ "source": { "kind": "github", "grantId": "b41d0e2a-1f7c-4d3e-9a10-8c5b2f0d7e64", "label": "acme/invoices", "private": true, "baseBranch": "main", "baseOid": "3d5c1f9e8a7b6c5d4e3f2a1b0c9d8e7f6a5b4c3d" }}baseOid is the point. The base commit is resolved and recorded when the session
is created, so main moving underneath you does not silently change what the
agent was working from. Every later question — what did it change, what should be
published, is this diff still reviewable — is answered against that pin.
The grant is the authority model
Section titled “The grant is the authority model”A repository grant is a durable authorization created by a human administrator of the customer’s organization. It is made to one app installation inside one organization and reaches the repositories selected for its GitHub App installation on GitHub:
Every live grant names one GitHub App installation and stores no repository list — that is the point of it. Every git operation mints an installation token scoped to the single repository it is about, so a repository that has left the installation is refused by GitHub rather than by a snapshot here. Which repositories an installation covers is chosen on GitHub, and WAMP asks that question nowhere else.
A grant carries no operations. Reach is the only thing it says. Holding a live one lets the application do whatever the organization’s WAMP GitHub App installation can do on the repositories the grant reaches — clone them, push branches, open pull requests, merge them.
That is deliberate, and it means the limit on what an agent may land is
GitHub branch protection, not a field here. Protecting main — required
reviews, required checks, who may push — is expressed on the repository itself,
per branch, and it applies to the App exactly as it applies to anyone else. An
organization that wants an agent’s work reviewed before it lands protects the
branch; nothing in this API can grant an exception to that, and nothing in it
asks for one. What the two deliveries look like from your side is
Publications.
There is no way to widen a grant in place: a grant is immutable. Its lifecycle is two states.
active ──▶ revokedChanging what an installation may do means creating a new grant and revoking the
old one, which produces a new grantId. Three consequences shape how you store
one:
- Revocation is invisible as a field. A revoked grant is simply not returned
anymore. There is no
statusto interpret; presence in a list is the status. - One active grant per GitHub App installation. One WAMP application holds at most one active grant for each connected GitHub App installation.
- A grant backing a session cannot be deleted out from under it. The reference is protected in storage, so an existing session keeps a coherent record of the authority it was created with.
A grant resource is small on purpose:
{ "id": "5e8f0a71-6c24-4f1b-98d3-2a7be4c05f19"}Who GitHub records, and who may act
Section titled “Who GitHub records, and who may act”A person working in the WAMP Cloud web app on a granted repository works through the same grant, not through their own GitHub account. Two consequences follow, and both are deliberate.
GitHub records the App, not the person. Anything written with the App’s
credential is authored by the App — <app-slug>[bot], which is
wamp-cloud[bot] on the WAMP deployment — and no API changes that. So the human
WAMP knows about is written into the record WAMP controls instead: a
Requested-by: Ada Lovelace <ada@example.com> trailer on the commit message, and
the same line appended to the pull-request body. It rides every publication a
signed-in person makes through a grant. A publication your installation creates
carries no trailer — the actor there is the installation, and the publication
record is the attribution. If body plus trailer would pass 65 536 characters the
pull-request body goes out without it rather than the publication failing; the
commit message keeps it.
The gate on a person is their WAMP capability, not their GitHub access. Any
member of the organization who may create sessions in WAMP Cloud
(wamp.cloud.sessions:create) can start one on any repository the organization
has granted, whether or not they personally have access to it on GitHub. What
bounds this is the grant itself: one explicit act by an administrator,
attributable to them, revocable, and re-authorized against GitHub on every single
request.
No API connects a repository
Section titled “No API connects a repository”There is no endpoint that authorizes a repository, and this is deliberate rather than unfinished. Handing an agent write access to a private codebase is a decision a person with administrator rights makes, in a session they can see, on a surface they trust — not something a backend integration can arrange for them with a bearer token.
The flow your product plans for is therefore:
- An administrator opens Repository access. They can enter from the installation’s generic configuration action in Account Center or from the Cloud repository picker; both lead to the GitHub section in Cloud Settings.
- They allow one of the organization’s connected GitHub App installations for the WAMP application. That reaches every repository the GitHub App covers in that installation, as that set changes on GitHub. The grant uses the organization’s GitHub App installation; the administrator’s personal GitHub OAuth connection is not part of it.
- Your backend reads the usable repository projection and stores its exact
grantId+repositoryIdpair against whichever of your own records the work belongs to.
Plan for step 2 producing nothing: a customer who authorizes no repository can
still use sessions with no source or with a public clone. Design the empty case
as a normal state of your onboarding, not an error.
Reading usable repositories and healing stored grants
Section titled “Reading usable repositories and healing stored grants”The model exposes usable objects separately from authority records:
- Repository discovery —
GET /v1/repositoriesexpands every active grant against GitHub live and returns one row per repository the calling installation may actually use. Each row includes the exactgrantId+repositoryIdpair session admission requires. Grants therefore need no second GitHub integration in your product. - Grant inspection —
GET /v1/repository-grantslists the underlying authority records. This is useful for administration and diagnosis, not for a repository picker. - Replacement lookup — given a
grantIdyou already hold, get the grant that now replaces it, ornullif there is none. This is how agrantIdstored on your tenant record heals after an administrator re-grants the repository, without you asking them to paste anything again.
Both require wamp.cloud.repositories:read, which is grantable only to an
app installation. A human-delegated credential calling either one gets
403 installation_principal_required — grants belong to an app installation, and
there is nothing coherent to return for a person.
The discovery document answers the coarser questions without a second call.
GET /v1/capabilities reports whether the calling installation holds any grant
at all, and — separately — which deliveries the grants it holds can actually
reach:
{ "capabilities": { "repositories": { "sources": [ { "kind": "public_https", "available": true }, { "kind": "github_repository_grant", "available": true, "discovery": "/v1/repositories" } ], "publications": [ { "kind": "github_draft_pull_request", "available": true }, { "kind": "github_direct_branch_push", "available": true } ], "merges": [ { "kind": "github_pull_request_merge", "available": true, "strategies": ["merge", "squash", "rebase"], "modes": ["now", "when_ready"] } ] } }}Every available under repositories is scoped to the grants you hold, not to
what the platform implements. Every entry other than public_https turns on
one fact: at least one grant is active for your installation. One live grant
reaches all of them — github_repository_grant as a source,
github_draft_pull_request and github_direct_branch_push as deliveries,
github_pull_request_merge for the pull request a session opened — and an
installation holding none reaches none.
So capabilities.repositories answers “can I publish at all” before you create a
session, without enumerating grants. Which repository you may reach stays on
/v1/repositories.
Every available here is false for a human-delegated credential, because
grants name an installation and there is nothing coherent to report for a
person.
Attaching one to a session
Section titled “Attaching one to a session”SESSION_ID=$(uuidgen | tr 'A-Z' 'a-z')TURN_ID=$(uuidgen | tr 'A-Z' 'a-z')
curl -sS -X PUT "$WAMP_API/v1/sessions/$SESSION_ID" \ -H "Authorization: Bearer $WAMP_TOKEN" \ -H 'Content-Type: application/json' \ -d '{ "title": "T-142 · Invoice export", "initialTurn": { "id": "'$TURN_ID'", "message": "Fix the CSV export rounding bug and add a regression test." }, "model": "<model-id-from-/v1/capabilities>", "source": { "kind": "github", "grantId": "b41d0e2a-1f7c-4d3e-9a10-8c5b2f0d7e64", "repositoryId": "1029384756", "baseBranch": "main" } }'The grant is checked at creation, against the live authorization rather than a
cached copy. A grant that has been revoked, or that never covered the
repository, is 403 cloud_repository_grant_required at this call — before you
have submitted any work — and a baseBranch that does not resolve is
400 cloud_repository_branch_not_found: two different remedies, two different
codes.
A grant names no repository, so source.repositoryId — the GitHub repository id,
as a decimal string — is how you say which one you mean. Get the exact
grant/repository pair from GET /v1/repositories.
Get that exact pair from /v1/repositories; do not infer an installation from a
repository name or reuse a repository id with a different grant. The projection
is live: a repository removed from the GitHub App installation disappears even
if the stored grant still exists.
The checkout itself happens later, when a turn causes a sandbox to be provisioned. You do not choose a path, a clone depth, or a remote name; those are not part of the contract.
For a pull request published by a Cloud Session, the first-party Session read
includes followPullRequest (initially false). The first-party Session update
route can set it. When enabled, signed reviews, review comments, PR conversation
comments and failing checks are collected and coalesced into a raised Turn on
the same Session. The GitHub App must subscribe to pull_request_review,
pull_request_review_comment, issue_comment and check_suite, and have
Checks and Commit statuses read permissions. This opt-in is a first-party
Session setting; it is not accepted by the public /v1 Session update.
Reviewing what changed
Section titled “Reviewing what changed”Before publishing anything you read the review:
curl -sS "$WAMP_API/v1/sessions/$SESSION_ID/repository/review" \ -H "Authorization: Bearer $WAMP_TOKEN"{ "review": { "branch": "wamp/publications-v1/cloud-3f7d4f4c-2b6a-4a2e-9c1a-1f2b3c-6b031ca6", "baseRef": "origin/main", "revision": "5c1e…64 hex chars…", "files": [ { "path": "src/invoices/list.ts", "status": "modified", "additions": 42, "deletions": 6, "binary": false, "patch": "@@ …" } ], "additions": 42, "deletions": 6, "patchTruncated": false }}Two things to take from it:
revisionis a 64-character hex digest of the working tree — a content revision, not a git commit id. It is the “I reviewed exactly this” token, and publishing requires you to pass it back. If the tree changes after you read it, the revision changes with it.filesdescribes the changed files. Each entry is a strict object:path,status(added,modified,deletedorrenamed),additions,deletions,binary, and — except for binary files or when the patch budget is exhausted —patch. The full annotated shape is in Open a pull request.
Publishing that revision is Publications.
What you may assume, and what you must handle
Section titled “What you may assume, and what you must handle”Assume. A session’s source and base commit never change. A grant never changes; only its presence does. A grant in use by a session stays referenceable. Every delivery this API offers is reachable with any grant you can see.
Handle. Every grant together with source.repositoryId.
403 cloud_repository_grant_required when the grant was revoked between two of
your calls — including between creating a session and publishing from it. A
stored grantId that no longer appears anywhere, which means asking the
administrator to grant again. Customers with no repository at all. In every one
of those cases your code should degrade to “ask a human”, not to a stuck
queue.
Related
Section titled “Related”- Connect a repository — the end-to-end flow with the administrator step in place.
- Publications — turning a reviewed revision into a pull request, and merging it.
- Sessions, turns, runs — where
sourceis set. - Repository grants operations and Sessions operations — the generated endpoint reference; the API reference for the grant, source and review objects.