Skip to main content
The GitHub connector pulls repository content into your organization’s knowledge graph and keeps it current. It is the only provider Exo manages in v1.

Before you start

  • A key with the write scope. See Scopes.
  • Permission to install a GitHub App on the account or organization that owns the repositories.
  • A browser, for the install step. The connect flow returns a URL you have to send a human to.

The flow

Connecting is three calls with a browser redirect in the middle.

Connect

1

Begin the connect flow

The state parameter is a signed, short-lived token that binds the resulting installation back to the authenticated caller. Do not strip it, do not cache the URL, and do not hand the same URL to two different people.
2

Send the user to that URL

They pick which repositories the app can see. GitHub then calls Exo back and the installation is finalized.This step needs a real browser and a real human with install rights. There is no headless path.
3

Confirm and see the repositories

id is the GitHub installation id rendered as a string. Keep it: every other connector call takes it in the path.
Before you have ever connected GitHub, GET /v1/connectors returns a provider stub: one entry with provider: "github", status: "not_connected" and a null id. It exists so a client can discover the provider and offer a connect button without special-casing an empty list.Code that reads data[0].id unconditionally breaks on a fresh organization. Check status first.

Keep it synced

Repositories sync on their own. POST /v1/connectors/{id}/sync forces a pass now, which is what you want after adding repositories to the installation or after a long gap.
One backfill job per repository in the installation. Track them like any other job with GET /v1/jobs/{id}.
This call is safe to repeat. The worker dedups content at ingest, and a backfill already in flight for a repository is absorbed by the queue’s own dedup, so a nervous retry does not double-sync anything. jobsEnqueued reports only the jobs that were newly created, so a repeat call can legitimately return 0.

Disconnect

Disconnecting marks the installation disconnected and stops repositories syncing. It is a tombstone status, not a physical delete, and it is idempotent: a second disconnect of a connector you own still succeeds.
Disconnecting stops future syncing. It does not remove content already in your graph. To remove that too, forget the nodes individually with DELETE /v1/graph/nodes/{id}, or run a scoped purge. See Forgetting and portability.
Reconnect by beginning the connect flow again. You get a new installation id.

When it goes wrong

The provider is not supported. v1 manages github and nothing else. The problem body names the supported providers. See validation_error.
No connector with that id exists in this organization. Two usual causes: you passed the provider name where the id belongs, or you used an id from a different organization. Read the id from GET /v1/connectors. See connector_not_found.Do not confuse this with the connector status not_connected, which is what the provider stub reports before you have ever connected. That is a normal state, not an error.
The connector is not in a syncable state, which normally means it has been disconnected. Reconnect first. A suspended installation, usually a GitHub-side billing or permission problem, also lands here. See connector_not_syncable.
The install granted access to no repositories, or the first backfill has not run. Check the App’s repository access on GitHub, then trigger POST /v1/connectors/{id}/sync and watch the returned job ids.

Next

Reacting to change

Subscribe to job.completed instead of polling every sync.

The knowledge graph

What a synced repository becomes once it is in the graph.