Agent Office v0.27.0 · POC Get started
Menu: Guides

Guides

Agents on GitHub

Let an agent work on chosen GitHub repositories through its own machine account: open pull requests, review, comment, file issues, and react when people ask it for a review, assign it or @mention it.

Your office lives on its own Gitea: the policy repo, vaults, mail and every agent identity stay there. GitHub is only where agents work on project repositories you choose, typically a public website or a repo with outside collaborators. Everything else stays on Gitea.

On GitHub each agent has its own machine account, created by a person: people @mention it, assign it issues and ask it for reviews, and it is the author of its commits and pull requests. Its token stays in the office; the agent gets tools, never the token. There is no office-wide GitHub App.

How it works#

  • Access is a grant on named repositories, reviewed as a policy PR. The agent's grant on the github connection lists each repository as owner/repo; the office refuses any other repository, and GitHub refuses it too, because the machine account is a collaborator only on the granted ones and its fine-grained token only covers them.
  • Agents open pull requests; people merge. Tools commit only to the agent's own branches, never to the default branch.
  • GitHub talks back. A review request, an assignment or an @mention of the machine account starts the agent's github.* event rule, or arrives as office mail. Comments and reviews on its own pull requests arrive as mail. Its open pull requests show on Needs you.

1. Add the GitHub connection#

Connections → Add connection → GitHub (built in). Merging the pull request adds:

# connections/github/connection.yaml
title: GitHub
transport: builtin
service: github
identity: agent          # always: each agent uses its own machine account
inbound:                 # optional
  poll_minutes: 5        # only if GitHub cannot reach your office (see step 5)

2. Grant an agent repositories#

In the agent's personnel.yaml (a policy PR, or the connection's Grants tab):

capabilities:
  - connections:
      github:
        tools: [gh_whoami, gh_list_prs, gh_get_pr, gh_open_pr, gh_commit_files, gh_get_file, gh_comment, gh_review,
                gh_list_issues, gh_get_issue, gh_create_issue]
        args: { repo: [acme/website, acme/docs] }    # required: the repositories, as owner/repo
        approve: [gh_review]                          # optional: reviews wait for a person

A GitHub grant must list its repositories (args: { repo: [...] }, or pin: { repo: owner/repo } for exactly one); a grant without them is a policy error. Names compare without case, as on GitHub. The grant is the whole story: no separate projects: file, and pins, limits and approvals work as for every connection.

Why a grant and not a new policy file. Repositories an agent may touch are exactly an argument limit on the GitHub tools, so the existing connections grant already expresses "Ada may open PRs on github.com/acme/website", is reviewed by PR, shows in the grants matrix and plain-English diffs, and is enforced by the gateway. The office reads the same list to know which repositories to check, poll and show.

3. Create the machine account and its token#

On the connection's Overview, each granted agent has a Link a machine account box with the exact steps, or run on the office host:

officectl github link ada

It walks you through:

  1. Create the account. In a private window, sign up on GitHub as, say, ada-acme, with the agent's office address (ada@agents.<office host>) and a display name like "Ada (AI agent at Acme)".
  2. Add it as a collaborator with the Write role on each granted repository, and accept the invitation as the machine account. On a paid organization plan an extra account may take a seat: check before adding it.
  3. Create a fine-grained token, signed in as the machine account, at Settings → Developer settings → Fine-grained tokens: resource owner = the repositories' owner, Only select repositories = the granted ones, permissions Contents, Pull requests and Issues: read and write (Metadata: read), and an expiry (90 days is a good default).
  4. Paste the token. The office checks it: who it is (GET /user), whether it can write to each granted repository, and when it expires (from GitHub's GitHub-Authentication-Token-Expiration header; --expires YYYY-MM-DD if GitHub doesn't say). A token GitHub refuses is not stored.

The token is stored as connection.github.agent.<slug>.token (with .token_expires and .login) in the encrypted secret store. The office warns a week before it expires, again the day before, and when it has: on the Connections page and as a notification to the people who manage connections (ledger connection.credential.expiring). To renew, create a new token and link again.

If the granted repositories have several owners, a fine-grained token can't cover them all: use a classic token with the repo scope instead. It still reaches only the repositories the machine account collaborates on.

4. What the agent can do#

ToolWhat it does
gh_whoamiIts login and profile URL.
gh_list_prsPull requests (state, author or me), with branches and reviewers asked.
gh_get_prOne pull request: description, files, reviews, and the diff (60,000 characters by default, up to 200,000).
gh_open_prOpen a pull request. With files, the office creates the branch from the base, commits the files as the agent, and opens the PR in one step.
gh_commit_filesAdd a commit to one of its branches, to address review comments. Refused on the default branch.
gh_get_fileRead a file (up to 200,000 characters) or list a directory, at any ref.
gh_commentComment on an issue or pull request.
gh_reviewReview a pull request: comment, request changes or approve, with line comments.
gh_list_issues, gh_get_issue, gh_create_issueIssues, with comments; open one with labels and assignees.

Tools appear to the agent as github__<tool>. Every call goes through the office gateway (grant, pins, limits, approvals) and is ledgered as connection.call; a pull request it opens is also ledgered as github.pr.opened and notifies the people who review its work.

Changing files: commits through the API, no git push#

Agents change files through gh_open_pr / gh_commit_files, which commit through GitHub's Git Data API with the agent's token (blobs → tree → commit → branch ref). Up to 50 files and 1 MB per commit; text or base64.

Pushing with git is deliberately not offered. A git push from the sandbox needs a credential in the sandbox (or an office-side push proxy), which is exactly what connections avoid: the agent never holds a long-lived credential, and GitHub's host is not on its network allowlist. API commits cover the changes agents make on project repositories (docs, copy, configuration, small fixes) with the same author, branch protection and review. Large refactors belong in Gitea repositories, where agents push with short-lived run tokens (see Agents that open pull requests).

5. Events from GitHub#

On the connection's Overview, Create webhook secret (shown once), then on each granted repository: Settings → Webhooks → Add webhook:

FieldValue
Payload URLhttps://<office>/api/github/webhook/github
Content typeapplication/json
Secretthe webhook secret
EventsIssues, Issue comments, Pull requests, Pull request reviews, Pull request review comments

(officectl github link creates the secret if there is none and prints it once.) Every delivery is checked against X-Hub-Signature-256; anything unsigned or wrongly signed gets a 401, and an unknown connection a 404.

On GitHubIn the office
Someone asks the machine account for a reviewgithub.pr.review_requested
An issue or pull request is assigned to itgithub.issue.assigned
@ada-acme in a new issue or PR, a comment, a review or a review commentgithub.mention
A comment or review on the agent's own pull requestMail ("Dana requested changes on your pull request acme/website#12")

With a matching rule the event starts an event run; without one it arrives as office mail, which starts a run if the agent takes mail:

run:
  on:
    - event: github.pr.review_requested
      repos: [acme/website]          # optional; owner/repo
      prompt: Review it against our style guide. Approve only copy changes.
    - event: github.mention

Only events on repositories granted to the agent count, and the agent's own doing never wakes it. Each delivery is ledgered as github.event.delivered, and is delivered once: GitHub's retries are dropped.

If GitHub cannot reach the office#

Set inbound: { poll_minutes: 5 } in the connection's policy file. The office then asks GitHub, with each agent's token, for review requests, assignments, new comments and new issues mentioning it, and reviews on its open pull requests. The first poll of a repository only records what is already there. Polling and webhooks use the same delivery keys, so turning both on never delivers twice.

6. Pull requests in Needs you#

Needs you lists every open pull request by an agent's machine account on its granted repositories, with the reviewers asked. People review and merge them on GitHub.

Security notes#

  • The token lives in the office secret store; the agent's sandbox never sees it and GitHub's host is not added to its network allowlist. The ledger records which account was linked and what each repository allows, never the token.
  • Two locks on every repository: the grant (checked by the office before each call) and GitHub itself (collaborator role and token scope).
  • Agents never commit to the default branch, and they can't merge: protect main on GitHub with required reviews so a person always does.
  • Text from GitHub (issue bodies, comments) is put in the agent's prompt as data from outside the office.