Skip to main content
Connect a Linear workspace to Cognee by installing a Linear OAuth app into it as an agent. Workspace members can then @mention the agent or delegate an issue to it and get an answer drawn from your Cognee memory, while the workspace’s issues flow into a dataset of their own and stay fresh through webhooks.
This integration is for self-hosted Cognee deployments — you create and own the Linear OAuth app, so it lives in your own Linear workspace settings and talks only to your own Cognee backend.
Ships on dev. The connector landed after 1.5.3, so it is not in a tagged release yet — run a dev checkout (git checkout dev && uv sync) until the next release.

What It Does

  • Installs as an agent, not a bot user. The authorize URL carries actor=app, which puts an app user — the agent’s identity — into the workspace. The app:assignable and app:mentionable scopes are what let members delegate issues to it and @mention it. Requested scopes are read,write,app:assignable,app:mentionable.
  • Answers agent sessions from memory. A mention or a delegation opens an agent session; Cognee runs a HYBRID_COMPLETION search across every dataset the connecting user can read — not just the Linear one — and replies inside the session.
  • Indexes the workspace’s issues. Issue creates and updates are remembered as plain text in one dataset per workspace, plus a backfill of recent issues at install time.
  • One workspace, one Cognee user. The credential is owned by whoever completed the install, and answers come from that user’s memory.

Prerequisites

  • A Cognee dev checkout — see the version note above.
  • A running Cognee backend reachable over HTTPS from the public internet: Linear delivers webhooks and the OAuth redirect to it and will not call localhost. For local development use a tunnel (ngrok or similar) — see the Slack integration’s ngrok section, which applies verbatim; for production this is your deployment’s normal public domain.
  • Permission to create an OAuth application in the target Linear workspace.

Setup

1. Create the Linear OAuth app

Go to linear.app/settings/api/applications → create a new application and configure: Then collect the app’s Client ID and Client secret.
Create a separate app per environment (local dev, staging, production). One app has one webhook URL, so pointing a shared app at a laptop routes another environment’s deliveries there.

2. Configure Cognee

Copy the app’s values into your backend’s .env (the same block is in .env.template): Every one of these is checked at use time, not at boot: a deployment with Linear unconfigured still starts normally, and the first call that needs a missing value fails with LINEAR_<NAME> is not configured rather than a confusing downstream error. POST /authorize turns that into a 503 (linear integration is not configured on this server) instead of a 500. Restart the backend after any .env change.

3. Install and connect

The backend ships without frontend wiring for Linear in this release — the aggregate GET /api/v1/integrations/status reports the provider generically, but there is no Connect button yet. Drive the flow through the API:
Open that URL in a browser, pick the workspace, and approve. Linear redirects back to /api/v1/integrations/linear/callback, which binds the workspace to your Cognee account and then sends the browser to <LINEAR_FRONTEND_BASE_URL>/integrations?linear=connected.
Install from the minted URL. The signed state is what binds the install to a Cognee account, and it expires 10 minutes after /authorize returns. An install started without it (or after it expires) lands on ?linear=error_invalid_state and stores nothing.
The callback does one extra round trip before it redirects: Linear’s token response says nothing about which workspace authorized the app, but every webhook delivery routes by its organizationId, so the fresh token is immediately spent on a GraphQL query for viewer (the newly installed app user) and organization. The organization id becomes the credential’s account id; the organization name becomes its display label. The initial issue backfill is kicked off detached, after the redirect — the browser returns immediately.

What Gets Indexed

Issues land in one dataset per workspace, named linear_<url_key>: the workspace’s Linear URL key (the slug in linear.app/<url_key>) lowercased, with every run of characters outside A-Z a-z 0-9 _ collapsed to _. A workspace at linear.app/acme-corp becomes linear_acme_corp. One dataset per workspace rather than per team or per issue means backend access control isolates at the workspace boundary — per-issue datasets would mean one isolated database per issue. Each issue is stored as a deterministic plain-text rendering — identifier, title, URL, state, description, and nothing volatile — so re-syncing an unchanged issue produces byte-identical text instead of churning the graph.
At install time Cognee backfills the workspace’s 50 most recently updated issues in a single remember() call — webhooks only cover changes from then on, so this is what gives the agent something to recall from on day one. Because it is ordinary text ingestion, the content is reachable through the normal search types, and you can query the dataset directly:
Both the backfill and per-issue webhook syncs run with self_improvement=False, so they never trigger an improve() pass. Whole-graph enrichment carries LLM cost that is far too heavy to fire on every issue edit — it stays a human or scheduled decision.

Answering Agent Sessions

An agent session opens when a member @mentions the agent (AgentSessionEvent / created) or delegates an issue to it, and continues when they reply inside the session (prompted). For each turn Cognee:
  1. Posts a thought activity immediately — “Searching cognee memory…” — before any search or LLM work. Linear requires an activity within 10 seconds of a created event or it marks the session unresponsive, and a HYBRID_COMPLETION search routinely takes longer than that.
  2. Builds the query. Linear’s own promptContext (its digest of the issue and prior comments) and workspace-level guidance are prepended to the user’s question, so retrieval is grounded in what the session is about. On a prompted event the question is the new message; on a created event it is the triggering comment, or — for a delegation, which has no comment — the issue’s title and description.
  3. Searches memory with HYBRID_COMPLETION across every dataset the connecting user can read, keeping the top three answers and discarding per-chunk completions that are really refusals (“no relevant information…”).
  4. Posts a response activity with the answer, which completes the turn.
Every failure path ends in an error activity rather than silence, so a session never sits showing the agent as working forever. Two cases answer politely instead of erroring: no question could be found in the session, and nothing relevant in memory (“No relevant information found in cognee memory.”).

Keeping It in Sync

Webhook deliveries to POST /api/v1/integrations/linear/events drive everything after the install. Coverage is deliberately narrow in this first cut: Everything else — issue deletions included — is logged and dropped. Deleting indexed data on a webhook would be a silent, destructive surprise, so forget() stays a human decision. A delivery for a workspace Cognee doesn’t know (or has revoked) is logged and dropped rather than erroring — Linear gives no ordering guarantee, so a delivery racing ahead of the callback storing the credential is a normal, self-healing state.

Webhook Security

Every delivery is authenticated by a hex HMAC-SHA256 over the raw request body, keyed with LINEAR_WEBHOOK_SECRET and compared against the Linear-Signature header with a constant-time comparison. That signature is the entire auth model for the route — it is unauthenticated by design, since Linear cannot send a bearer token. A bad or missing signature is a 401. Linear also carries replay protection, which Cognee enforces: the payload’s webhookTimestamp (Unix milliseconds) must be within 60 seconds of the server’s clock, or the delivery is rejected as Stale Linear webhook timestamp — also a 401. A missing or malformed timestamp is rejected the same as a stale one, and the check runs only after the HMAC passes, since a timestamp read from unverified bytes proves nothing. Two consequences worth planning for:
  • Keep the Cognee host’s clock in sync (NTP). More than a minute of drift rejects every delivery even though its signature is perfect.
  • Rotating the signing secret is a two-sided change. Deliveries signed with the old secret fail the HMAC, so rotate on Linear and update LINEAR_WEBHOOK_SECRET together and restart the backend. Because the same secret also signs the OAuth state, an install that is mid-flight during a rotation lands on ?linear=error_invalid_state; just mint a fresh authorize URL.
Cognee acks the delivery as soon as both checks pass and handles it detached, so Linear’s delivery timeout is never in play no matter how long a search takes. The 10-second rule is separate — it is Linear’s clock on the session, which only the thought activity satisfies.

Disconnect vs. Uninstall

Neither deletes indexed data:
  • Disconnect in CogneeDELETE /api/v1/integrations/linear/connection — marks the stored credential revoked, so agent sessions and issue syncs stop. It also makes a best-effort remote revoke: Linear exposes a cheap token-revoke endpoint that kills only Cognee’s own token without touching the app install, so unlike the GitHub connector this is actually called. It is best effort by design — the local revoke is the real cut-off, and a network blip must never block a disconnect.
  • Removing the app in Linear fires the OAuthApp revoked webhook, which revokes the credential server-side — the same end state, reached from the other side.
The linear_<url_key> dataset stays exactly as it is in both cases. To remove the indexed data itself, use forget().

Troubleshooting

  1. POST /authorize returns 503 “linear integration is not configured on this server”: LINEAR_CLIENT_ID, LINEAR_REDIRECT_URI, or LINEAR_WEBHOOK_SECRET (it signs the state) is unset. The backend log names the exact variable. A missing LINEAR_FRONTEND_BASE_URL surfaces later, as the same 503 from the callback instead.
  2. Redirected to ?linear=error_invalid_state: the install didn’t start from a freshly minted /authorize URL, more than 10 minutes passed before approving it, or LINEAR_WEBHOOK_SECRET changed in between. Mint a new one.
  3. Redirected to ?linear=error_exchange_failed: the callback never 500s — it catches everything and redirects, and the traceback is in the backend log. Usual causes: mismatched LINEAR_CLIENT_ID/LINEAR_CLIENT_SECRET, a LINEAR_REDIRECT_URI that doesn’t exactly match the app’s registered callback URL, a missing INTEGRATION_CREDENTIALS_KEY, or the identity query failing (Linear token response carries no organization id).
  4. Redirected to ?linear=error_already_connected: this workspace is bound to another Cognee user. Disconnect it there first.
  5. Redirected to ?linear=cancelled: the consent screen was cancelled, or Linear rejected the request. Nothing was stored.
  6. Connect succeeds but no issues appear: the backfill runs detached — check the backend log for Syncing N Linear issues for organization <id> into dataset linear_<url_key>, or has no issues to sync. It covers the 50 most recently updated issues only; everything older arrives when those issues are next touched.
  7. Webhook deliveries return 401: either LINEAR_WEBHOOK_SECRET doesn’t match the app’s signing secret (easy to hit when juggling more than one app), or the host clock has drifted more than 60 seconds. The response detail distinguishes the two — Invalid Linear signature versus Stale Linear webhook timestamp.
  8. Webhook deliveries return 404: the provider name in the URL is wrong, or the backend is running a build without the Linear connector registered. The route is /api/v1/integrations/linear/events.
  9. The agent posts an error activity in the session: the search or the reply failed — the backend log carries the traceback under Linear agent session <id>: answering failed. If the answer instead says the connection “is not fully configured”, the Cognee user who installed the integration was deleted; disconnect and reconnect.
  10. The agent replies “No relevant information found in cognee memory.”: the search returned nothing usable for that question. Remember that it searches the installing user’s datasets — content ingested by a different Cognee user is not visible to it.

Slack

Ask and save memory from a conversation, sharing the same credential store and connect flow.

GitHub

The other first-party webhook connector — an org’s repositories into the code graph.