Skip to Content
Platform
GuidesWork with repositories

Work with repositories

Grant a runtime access to repositories other than its own recipe, clone them into a task’s workspace, and let the agent read, change, and ship code through your normal review process.

An agent frequently needs source code that is not its recipe: the service it reviews, the monorepo it migrates, the docs site it edits. A task boots with an empty workspace/repos/, and nothing is cloned until you say so.

Access is split across four layers, each owning exactly one decision. Nothing below it can widen what a layer above it allows.

LayerWho sets itDecides
GitHub App installationA GitHub organization adminWhat Introspection can see
Project repositoriesAn Introspection memberWhat is registered
runtime.github in the recipe manifestThe recipe authorThe grant: what this runtime may clone
repositories on the taskThe callerThe trigger: what this task does clone, and at what ref

The last two are the split to keep in mind. A grant clones nothing on its own: it names the set a runtime is allowed to reach and how far its credential reaches. A task then picks the subset it actually wants, and the ref to clone it at.

This guide assumes the organization has a GitHub connection, the recipe already has a runtime you can deploy, and the Introspection CLI is signed in.

1. Register the repository to the project

A grant names repositories that are already registered to the recipe’s project, never arbitrary URLs. Registration is what binds a repository to the organization’s GitHub integration, and it is the reason a grant cannot reach a repository the project does not own.

The repository holding your recipe is registered for you: creating a recipe from it, which introspection runtimes create and the dashboard’s new-runtime flow both do, registers it against the organization’s GitHub integration as a side effect. If the repository your agent needs to work on is also the one your recipe lives in — a common shape for an agent that maintains its own service — you have nothing to do here.

A repository that only ever appears as a workspace checkout has to be registered explicitly. Registration is authorized against the App installation, so a repository the installation cannot see is refused here rather than failing later at clone time.

introspection repositories add acme/api-service introspection repositories list

A full GitHub URL works too. The command is idempotent, so running it twice returns the existing registration. The dashboard and API provide the same operation; use the GitHub reference when you need those surfaces or the integration details.

Registering needs member authentication. repositories:write is a member-role scope, so a project API key cannot register a repository — keys top out at repositories:read. Use the dashboard, or the CLI signed in with introspection login. Reading the list is fine with an API key.

Registering grants nothing by itself. It makes a repository addressable: the token a sandbox mints is requested by repository id (POST /v1/repositories/{id}/access-token takes no slug), so an unregistered repository cannot be named in any request at all. What a runtime may reach is still the grant in the next step.

2. Grant the repository to the runtime

Declare the grant in the runtime manifest, under runtime.github:

# .introspection/coding-agent.yaml name: coding-agent description: Reviews and patches the API service path: apps/coding-agent runtime: github: repositories: - acme/api-service - acme/web

Each entry is an owner/name slug for a registered repository. The grant carries nothing else — no ref, no depth, no destination folder — because those are per-task decisions, and a checkout always lands at workspace/repos/<repository name>.

Validate before deploying. introspection check mirrors the same grammar the server enforces, so a typo surfaces locally instead of at deploy:

introspection check

The grant derives from the runtime. A deploy never widens an existing one: editing runtime.github in the manifest produces a new runtime version. A running task’s checkout list is fixed at launch, so what it has already cloned cannot change underneath it. Its token ceiling is read from the runtime on each mint, so an explicit PATCH /v1/runtimes/{id} that rewrites the grant does reach a task already in flight — treat that route as the privileged one it is. It replaces config_json wholesale rather than merging, so send the runtime’s current config with github edited into it.

A granted repository that is not registered to the project resolves to nothing: it is never cloned and never mintable. This degrades quietly by design, so that manifests and registration can be done in either order — but it does mean a repository missing from step 1 looks like a grant that silently does nothing. Case, at least, is not a way to trip on this: slugs match case-insensitively, the way GitHub itself treats them, so acme/API-Service and acme/api-service resolve to the same registration.

3. Choose the permission ceiling

By default the grant is read-only. permissions raises the ceiling on what a token minted for these repositories may do:

runtime: github: repositories: - acme/api-service permissions: contents: write pull-requests: write

The block mirrors GitHub Actions permissions:. Every supported read is implicit, so declare only write elevations. Unknown or privileged capabilities fail rather than silently widening access. The complete allow-list and the hyphenated/underscored key rules live in the GitHub permission reference.

Three ceilings nest, and the narrowest wins:

requested (one operation) ⊆ runtime.github.permissions ⊆ GitHub App installation

A request beyond the runtime’s map is refused, never silently narrowed, so a permission missing from the manifest surfaces as a clear denial instead of an unexplained GitHub error later in the run.

Deploy the new runtime version once the manifest is right. Runtime sync audits the declared permissions against the App installation and logs a warning for anything the installation has not been approved for — a warning rather than a failure, because it checks external state a GitHub admin controls.

4. Clone the repositories in a task

The grant says what may be cloned. The task says what is:

introspection tasks create \ --runtime coding-agent \ --environment production \ --repository acme/api-service@main \ --prompt "Fix the flaky checkout test and open a pull request"

--repository OWNER/NAME[@REF][:DEPTH] is repeatable, with no count limit. The JavaScript and Python SDKs expose the same repositories task field. Use their task-start references when the caller is an application rather than an operator at the CLI.

ref accepts a branch, tag, or full 40-character commit sha. Omit it and the clone takes the repository’s default branch, whatever it is named — nothing is stored to make that work, so it cannot go stale when a repository is renamed or its default branch changes. An abbreviated sha is not recognised as a pin: it is passed to git as a branch name, so the clone fails and the repository is dropped. depth defaults to a shallow clone; pass 0 for full history when the agent needs to read it, such as for git log analysis or a bisect.

A full commit sha ignores depth and always clones full history. Branches and tags are cloned directly at the ref, but a raw sha has to be reached by checking it out after the clone, which needs the history containing it. Pin to a sha when you want an exact tree; expect the slower boot that comes with it.

An entry outside the runtime’s grant is dropped by the server, not treated as a launch failure. So is one that fails to clone. A workspace repository is a convenience, not a launch precondition — a task with other work to do still starts. Malformed input is different: a bad slug, a ref with shell metacharacters, the same repository named twice, or two repositories that would land in the same folder are rejected with a 422 at task creation.

Clones run concurrently with the rest of boot and are joined before the first turn, so the agent never sees a half-populated workspace. While they run, the task reports a cloning_repos phase.

5. Work with the checkout

The checkout lands at workspace/repos/<repository name> — the repository name only, never the owner, and not configurable. Two granted repositories may not share a name for exactly this reason, and introspection check catches the collision at authoring time.

Inside the sandbox, ordinary Git and GitHub tooling works against the repositories this task cloned, without special handling:

cd workspace/repos/api-service git checkout -b fix/flaky-checkout-test # ... the agent edits files ... git commit -am "Fix flaky checkout test" git push -u origin fix/flaky-checkout-test gh pr create --fill

A credential helper is installed on the sandbox’s Git configuration, so git, gh, and anything built on them authenticate on their own — for the repositories this task requested, which is what the in-sandbox manifest lists. A granted repository the task did not ask for has no credential here, so add it to the task’s repositories rather than expecting the grant alone to reach it. For a tool that does not go through Git’s credential path — curl, an Octokit script, your own tooling — run it under the wrapper instead:

with-github-token -- ./scripts/sync-labels.sh with-github-token --repo acme/api-service --permissions contents:write -- ./scripts/triage.mjs

--repo is optional when the task requested exactly one repository, and required when it requested several — the in-sandbox manifest lists what was requested, including a repository whose clone failed, so a task that requested two and cloned one still needs --repo. --permissions asks for more than the operation would otherwise imply, still capped to the runtime’s ceiling; asking past it is refused, not narrowed.

The wrapper puts a real token in that one child process’s environment, which is why it is the escape hatch rather than the default route: the command and anything it spawns can read it. Credentials are minted per operation, cover a single repository, carry only that operation’s permissions, and expire within an hour. Nothing long-lived is written to disk, and each concurrent clone mints its own.

6. Ship the change through review

An agent with contents: write and pull-requests: write can push a branch and open a pull request. Treat that as the same capability you would grant a human contributor, and gate it the same way.

GitHub grants merge to any token holding both permissions, so branch protection is the boundary that stops an agent merging its own work. Require review on the branches that matter before enabling write on a runtime that handles untrusted input. Prompt injection reaching an agent with push access is a code-execution path into your repository, and the review requirement is what makes it a proposal rather than a deploy.

Where the agent’s pull request goes next is your existing process, unchanged: review it, and merge it through Git. If the change is to the recipe itself, the agent development lifecycle covers how a merged commit becomes a production runtime version.

An agent’s recipe is a repository like any other, so listing it in the grant and elevating contents gives the agent write access to its own instructions — the pattern behind agents that fix themselves. The capability, the monorepo case where you reach it without setting out to, and the two controls that keep a person in the path are covered in self-improving agents.

For registration errors, missing checkouts, credential failures, and the bounds on grants and clones — count limits, clone latency, baked-image exclusions, and why personal access tokens are not a supported substitute — see Troubleshooting.

Common failure pattern: granting the repository instead of the task

A runtime grant sets the maximum access a task may request; it does not place every granted repository into every sandbox. Request only the repositories the task needs, and keep the grant narrow enough that a prompt-injected agent cannot reach unrelated source. A missing checkout should lead you to inspect both the runtime grant and the task request, not to broaden permissions by default.

Done when

  • The repository is registered to the project and appears in GET /v1/repositories.
  • introspection check passes on the manifest carrying the grant.
  • A task requesting the repository shows it checked out at workspace/repos/<name>.
  • The agent’s credential reaches exactly as far as the work requires, and no further.
  • Branch protection requires review on any branch the agent can push to.

Next

  • GitHub: the App installation, recipe source, and lifecycle events behind the connection.
  • Runtime manifest: the manifest that carries the grant, and how versions pin it.
  • Security: sandbox isolation, the credential boundary, and self-improving agents.
  • CLI → Tasks: every option on tasks create, including --repository.
Last updated on