# The GitHub connector

Connect GitHub and the issues and pull requests in the repositories you choose
reach your map as signals your agents read with `list_signals`. The same
connection lets Maplith's hosted agent answer an issue you label, under a
policy an admin sets: by default it observes and never acts.

GitHub connects through **Maplith Agents**, a GitHub app
([github.com/apps/maplith-agents](https://github.com/apps/maplith-agents)).
See every way Maplith connects on the [integrations page](/integrations).

## Two apps: read-only by default, Maplith Agents to act

Maplith is publishing a second GitHub app, **Maplith**, which can only read.
Once it is published it becomes the default: **Connect GitHub** installs it,
your repositories' events reach your signals, and nothing in GitHub can be
changed through it. Letting agents act stays a separate choice: an admin
chooses **Allow agents to act**, which installs Maplith Agents beside it. The
two connections sit side by side, each disconnected on its own, and the
hosted agent, its policy and every write go through Maplith Agents only.

What the read-only Maplith app asks for, all read:

| Permission | Access | Why |
|---|---|---|
| Metadata | read | Required by GitHub for every app: repository names, and whether a repository is private. |
| Issues | read | Receive issue and issue comment events, which become `external` signals. |
| Pull requests | read | Receive pull request events, which become `external` signals. |
| Actions | read | Receive workflow runs and read a workflow’s newest runs, for `ci_failed`. |
| Deployments | read | Receive deployment statuses and read an environment’s newest deployment, for `deploy_failed`. |
| Secret scanning alerts | read | Receive secret-scanning alerts, for `security_alert`. Never the secret itself. |
| Code scanning alerts | read | Receive code-scanning alerts, for `security_alert`. |
| Dependabot alerts | read | Receive Dependabot alerts, for `security_alert`. |
| Members (organisation) | read | Check, when you connect, that you own or administer the organisation you are connecting. |

It does not ask for your code (Contents): the map is built from what you
export, and nothing Maplith does with your GitHub reads it.

## Install

1. In your workspace, open Data sources › Systems and choose **Connect GitHub**. You
   need to be an admin or a builder of the workspace.
2. GitHub asks where to install Maplith Agents — your own account or an
   organisation — and which repositories: all of them, or a list you select.
   Select only the repositories you want your agents to follow. GitHub grants
   an app access per repository, never per folder.
3. GitHub asks you to authorise Maplith to check who you are. Before anything
   is connected, Maplith checks three things:
   - the request started in your workspace, in the last 15 minutes, and was
     not changed on the way;
   - you are an admin or a builder of that workspace;
   - your GitHub user can reach that installation, and owns the account or
     administers the organisation it is installed on. Being a member of the
     organisation is not enough.

   The sign-in GitHub hands Maplith for that check is used once and never
   stored.
4. Back on Data sources › Systems, the account shows as connected.

If an organisation owner must approve the installation first, GitHub says so.
Once it is approved, come back to Data sources › Systems and choose **Already installed
it? Re-link**.

One installation serves exactly one workspace, and a workspace has one
installation of each app. To connect a different account, an admin
disconnects the first.

## Permissions, and why

| Permission | Access | Why |
|---|---|---|
| Issues | write | Receive issue events, and post the hosted agent’s one analysis comment on an issue labelled `agent-fix`. |
| Pull requests | write | Open a proposal pull request when your policy allows it. In your repositories the app never merges. |
| Contents | write | Commit the proposal: one Markdown file under `docs/agent-proposals/` on a branch of its own, never on your default branch. |
| Metadata | read | Required by GitHub for every app: repository names, and whether a repository is private. The agent acts only in private ones. |
| Members (organisation) | read | Check, when you connect, that you own or administer the organisation you are connecting. |
| Secret scanning alerts | read | Today read only on Maplith’s own repositories, which run on the same app; Maplith does not read yours. It will feed the `security_alert` signal on the roadmap below. |

A GitHub app's permissions are one set: GitHub does not let you accept some of
them and not others. What limits the app is the repositories you choose and
the policy an admin sets in Maplith.

GitHub sends the app these events: **Issues**, **Issue comment**, **Pull request**.

## What Maplith reads and keeps

- **Deliveries.** For the repositories the installation covers, GitHub sends
  Maplith each issue, issue comment and pull request event, and the alert,
  workflow run and deployment events of the section on CI, deployments and
  security alerts below. Maplith keeps the delivery in your workspace — for an
  issue or pull request, its title and text, the label or comment, and the
  sender's login — for 12 months, so your agents can see what happened.
  Deliveries are not used to build the map.
- **The hosted agent**, only when your policy lets it act. To write its
  comment or proposal it reads the issue's text, treated as untrusted input,
  and a summary of your map (objects and open findings), and sends both to
  Maplith's model provider. It acts only in **private** repositories, and
  checks again that a repository is private before it opens a pull request.
- **Never.** Maplith does not build the map from your code. The app never
  merges, never commits to your default branch, and writes a proposal only as
  one Markdown file under `docs/agent-proposals/` on a branch of its own.

## The signals a delivery raises

A signal is work for an agent, so only a delivery an agent has to act on
becomes one: a label your policy acts on.

| GitHub event | Signal | State |
|---|---|---|
| An issue labelled `agent-fix` or `agent-pr` | `external`, severity `attention` | Open: work for an agent. One per issue and label |

Every other delivery — an issue labelled with any other label, a comment, a
pull request opened, closed, edited or updated — is news. It is kept as a
receipt with the delivery and raises no signal. (Until 2026-10-14 news was
raised as an `external` signal born done, with `notice: true`; those
signals stay in your history until the retention rule removes them.)

The payload holds `source: "github"`, `ref` (`owner/repository#number`),
`event`, `action`, the label and the title. With `list_signals`, read
the work with `states: ["open"]`. A GitHub signal concerns no object on your
map, so only members and agent keys whose access covers the whole map see it.

## If a delivery is missed

GitHub sends each delivery once and does not try again by itself. When
Maplith cannot record a delivery, it answers GitHub with an error, so the
delivery is marked failed in GitHub's delivery log, and Maplith's operators
are alerted with its delivery id, so it can be sent again from that log. A
delivery sent twice is recognised by its id and recorded once, and the signal
it raises is the same signal. Maplith does not poll your repositories: what
it knows about them is what GitHub delivers.

## CI, deployments and security alerts

Three more kinds are raised in your workspace from what GitHub sends. GitHub
sends these events only once your installation holds the read permissions
below: when the Maplith Agents app asks for them, an owner of your
installation accepts them at GitHub. Each delivery is kept in your workspace
like an issue or pull request event, for 12 months (see the [processing
description](https://maplith.com/processing), section 2.10).

| Signal | Raised when | Cleared when |
|---|---|---|
| `security_alert` | GitHub opens a secret-scanning, code-scanning or Dependabot alert on a connected repository: one per alert, with its number, the rule or package, the severity and a link, never the secret itself | GitHub reports the alert closed: fixed, resolved or dismissed |
| `ci_failed` | A GitHub Actions workflow fails on the repository's default branch: one per repository, branch and workflow | The next green run of that workflow |
| `deploy_failed` | The newest deployment of an environment fails: one per repository and environment | The newest deployment of that environment is live |

Each is raised the moment GitHub sends the event; Maplith does not poll your
repositories for them. For a workflow run or a
deployment, Maplith first reads that workflow's newest runs, or that
environment's newest deployment and all its statuses, from GitHub as your
installation, because runs finish out of order and one deployment can carry
several services. A failure anywhere on the newest deployment counts.

The permissions they need, all read-only: **Actions**, **Deployments**,
**Code scanning alerts** and **Dependabot alerts** (the app already holds
**Secret scanning alerts**), and the events **Workflow run**,
**Deployment status**, **Secret scanning alert**, **Code scanning alert**
and **Dependabot alert**.

## How your deliveries stay in your workspace

- **Signed.** Every delivery is checked against its signature, made with a
  secret only GitHub and Maplith hold, before anything else is read. A
  delivery without a valid signature is refused.
- **Bound by Maplith, not by the sender.** The workspace a delivery belongs to
  is looked up in Maplith's own record of which installation is connected to
  which workspace. Nothing in the delivery can choose the workspace. A
  delivery for an installation that is not connected is acknowledged and
  dropped.
- **Bound only after the three checks above.** An installation's number can be
  guessed, so knowing it is never enough to connect it.
- **Seen by those who manage integrations.** The connection is shown to the
  workspace's admins and builders; only an admin changes the policy or
  disconnects.

## The hosted agent

Connecting GitHub adds a policy to the connection, chosen by an admin under
Data sources › Systems: **Read-only** (the default: it never acts), **Autonomous** (one
analysis comment on an issue labelled `agent-fix`), or **Propose** (also a
proposal pull request on an issue labelled `agent-pr`, never merged). Each
step is an explicit choice, actions are capped per day and logged in Agents & access › Activity, and pausing your agents stops it too. See
[Agent keys & policies](/docs/agent-keys).

## When the app asks for new permissions

When Maplith Agents needs a new permission, GitHub asks an owner of each
installation to accept it, and the installation keeps its old permissions
until someone does. If the hosted agent needs one you have not accepted,
Data sources › Systems says so, with a link to the page at GitHub where you review
and accept it.

## Disconnect and uninstall

- **In Maplith:** a workspace admin chooses **Disconnect** under Data sources › Systems.
  Maplith uninstalls the app at GitHub, then removes the connection. If GitHub
  cannot be reached, nothing is removed and the page asks you to try again.
- **At GitHub:** uninstall Maplith Agents under your account's or your
  organisation's settings (**GitHub Apps**, then **Configure**). GitHub tells
  Maplith, which removes the connection. Under **Configure** you can also
  narrow the repositories instead.
- **What stays:** the deliveries and signals already recorded stay in your
  workspace for the rest of their 12 months, and what the hosted agent did
  stays in Agents & access › Activity, until the workspace is deleted.

## Messages when you connect

| Message | What to do |
|---|---|
| The app is not installed on your GitHub account yet | Choose **Connect GitHub** and install it |
| Your GitHub user is not an owner or admin of that account or organisation | Ask an organisation owner to connect it |
| Installation requested: an organisation owner needs to approve it | Once approved, choose **Already installed it? Re-link** |
| That GitHub account is already connected to another workspace | One installation serves one workspace; disconnect it there first |
| This workspace already has a GitHub account connected | An admin disconnects it first |
| Maplith Agents is on more than one of your GitHub accounts | Keep it on one account, then re-link |