Skip to content

Integrations as knowledge

Integrations are connected once, app-wide, through OAuth. Tokens are sealed with AES-256-GCM using ENCRYPTION_KEY and stored in Postgres.

Provider OAuth provider id What agents get
GitHub github Repository catalog, cloning, PRs, issue/PR search
Jira atlassian (shared with Confluence) Issue search (JQL or text) and full issues with comments
Confluence atlassian Page search (CQL or text) and page content
Linear linear Issue search and full issues with comments
Slack slack A channel per project with run updates, stage summaries and approval requests
Railway railway Deployment targets and live deployment state (read-only to agents); releases after approval

Setup is self-serve under Organization → Integrations: press Set up app on a provider card, then Connect. Apps are organization-wide and required before a provider can be connected; nothing about integrations is read from .env. Railway is the exception to the app-first rule: it can be connected with an OAuth app or directly with a workspace/project token.

Deployment (Railway)

Railway is a first-class, organization-scoped deployment platform under the Deployment category. An owner or admin connects it once, either through Railway OAuth 2.0/OIDC (viewer scopes only) or with a token. The dialog prefers a workspace token scoped to the workspace that holds the organization's deployable projects; a project token is the narrowest (one environment) and an account token is the broadest and discouraged. All credentials are sealed in app_integrations like every other integration and never returned by the API.

A project links one Railway service + environment in the Deployment section of its Releasing tab (team admin, or the project's Release Manager or Owner). The project then shows the live state, service URL and last deployment time; a target that is removed or renamed in Railway is flagged invalid with re-link guidance rather than shown as stale-current. Unlink returns the project to merge-based delivery.

The existing human gate on the delivery step is the release approval — no separate prompt. Resolving it with approval makes deterministic Spaces code trigger exactly one serviceInstanceDeployV2 deployment (idempotent per run and target) and records the approver, time and target; rejection deploys nothing. Invalid credentials, an invalid or missing target, or an unauthorized approver fail closed. Agents receive a single read-only deployment_status tool and can never deploy, cancel, roll back or reconfigure Railway.

A linked project reaches Done only once delivery is merged and the deployment is confirmed successful; the delivery report carries the target, outcome, completion time and deployment link (or an explicit "no deployment performed" for an unlinked project). Unlinked projects keep today's merge-only behaviour.

GitHub App setup

Provider Setup
GitHub One click. Spaces posts a GitHub App manifest (name, callback URL, repository permissions: contents, pull requests and issues write; metadata, checks and actions read; no webhook). You confirm on GitHub, and Spaces exchanges the returned code for the app's client id, secret, private key and webhook secret, all stored encrypted. Install on GitHub picks the repositories; GitHub then returns to Spaces, which starts the ordinary authorize flow and stores the user token. The app can be created under a GitHub organization; a pre-existing OAuth App or GitHub App can be pasted in instead.
Slack Create Slack app opens Slack's create-from-manifest page prefilled with the redirect URL and bot scopes; the client id and secret are pasted from Basic Information.
Atlassian Guided through the developer console: create an OAuth 2.0 (3LO) app, add the callback URL and enable the listed scopes (copy buttons), paste the client id and secret.
Linear Guided through Linear's OAuth applications page: add the callback URL, paste the client id and secret.

Access tokens that expire (GitHub App user tokens after eight hours, Atlassian after one hour) are refreshed automatically before use through the provider's refresh token, and the new token is stored for every integration kind that shares it.

Reconnect needed

If the stored token can no longer be decrypted (for example the ENCRYPTION_KEY changed, or a process with a different key re-saved it), the panel shows ⚠ reconnect needed instead of connected, and token lookups fail with a message naming that cause.

Slack channels per project

With Slack connected, every project gets a public channel, #spaces-<code> (for example #spaces-defa-1). The channel is created when Slack is connected (for every existing project), when a project is created, or at its first post. An existing channel with that name is joined rather than duplicated. The project's team members are invited when Slack knows their email.

Runs post there:

When Message
A run starts The pipeline and its stages
A stage finishes Its summary (the compacted handoff the next stage receives)
Approval is needed @here, the summary of the stage to decide on, and an Open in Spaces button
The agent asks a question @here, the question, and the button
The run finishes or fails The outcome, and the error for a failure

Approving and answering happen in Spaces; the button links to the project (PUBLIC_URL/spaces/<code>). A channel deleted or archived in Slack is replaced at the next post. Slack errors never fail a run; a missing permission is logged once per organization.

The bot needs channels:manage, channels:read, channels:join, chat:write, users:read and users:read.email. The Create Slack app manifest includes them. A Slack app created before these were added needs the scopes added under OAuth & Permissions, then Slack reconnected under Organization → Integrations.

Agent tools

Connected sources are exposed to every agent session as two tools:

  • integration_search(source, query) — free text, an exact key (PROJ-123, ENG-45, owner/name#12), or a native query (JQL, CQL, GitHub search).
  • integration_get(source, id) — the full item: description, status, comments.

The shared context carries a Knowledge Sources note telling agents to fetch referenced tickets and docs rather than guess, to be efficient (one targeted search, then one to three items in full) and to cite ids in artifacts.

Per-project scope

In the project's Context tab you choose which connected sources the project may use and narrow them: Jira project keys, Linear teams and projects, Confluence spaces, GitHub repositories. Agents only see the selected sources, and their queries are filtered accordingly.

Importing tickets

The new-project wizard's Import from Jira / Linear searches a source, pulls a ticket in as the name, description and first feature, and attaches it to the project as a source snapshot that appears in every stage's context. POST /api/projects/:id/sources/import does the same for existing projects.

Organization knowledge base (RAG)

Beyond on-demand lookups, whole bodies of knowledge can be imported into a searchable knowledge base from Organization memory & knowledge in the user menu:

Import Picks from What is indexed
Confluence spaces every page of the space
Jira projects (or a JQL filter) issues with description and comments
Linear teams, projects, initiatives initiative and project descriptions, then their issues with comments
GitHub repositories documentation files (*.md, *.rst, *.txt, … or your own include patterns) on a branch, or issues and pull requests
Web pages URLs the page text
Notes — free text typed or pasted in

Each import is a source owned by the organization (visible to every team) or by one team. Importing runs inside the server; re-import is incremental (only pages, issues or files changed since the last import are re-read) and a full re-import re-enumerates the source and prunes items that disappeared.

Documents are split into heading-aware chunks and indexed twice: a Postgres full-text index, and a pgvector embedding (EMBEDDING_MODEL) when an embedding key is configured. Search fuses both rankings, so results degrade gracefully to keyword search without embeddings or without the vector extension.

Agents get the base in two ways: every stage's shared context starts with the excerpts most relevant to the project and current feature, and the org_knowledge_search(query) tool answers ad-hoc questions with cited excerpts. The panel has a search box to try queries yourself.

API: GET /api/org/knowledge/catalog?integration=… lists what can be imported, POST /api/org/knowledge/sources creates and imports a source, POST /api/org/knowledge/sources/:id/import re-imports ({"full": true} to re-enumerate), POST /api/org/knowledge/notes adds a note, and GET /api/org/knowledge/search?q=… searches.

Repository catalog

With GitHub connected, every visible repository is indexed with its README-derived use case into a catalog that the plan stage and onboarding use to name repositories. It refreshes on connect and every six hours (POST /api/github/catalog/sync forces it).

pi-knowledge

pi-knowledge adds local semantic search over files, PDFs and URLs and complements the integration tools; our tool names were chosen not to collide with it.