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.
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. Theapp:assignableandapp:mentionablescopes are what let members delegate issues to it and @mention it. Requested scopes areread,write,app:assignable,app:mentionable. - Answers agent sessions from memory. A mention or a delegation opens an agent session; Cognee runs a
HYBRID_COMPLETIONsearch 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
devcheckout — 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.
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 aggregateGET /api/v1/integrations/status reports the provider generically, but there is no Connect button yet. Drive the flow through the API:
/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.
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, namedlinear_<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.
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:
- Posts a
thoughtactivity immediately — “Searching cognee memory…” — before any search or LLM work. Linear requires an activity within 10 seconds of acreatedevent or it marks the session unresponsive, and aHYBRID_COMPLETIONsearch routinely takes longer than that. - Builds the query. Linear’s own
promptContext(its digest of the issue and prior comments) and workspace-levelguidanceare prepended to the user’s question, so retrieval is grounded in what the session is about. On apromptedevent the question is the new message; on acreatedevent it is the triggering comment, or — for a delegation, which has no comment — the issue’s title and description. - Searches memory with
HYBRID_COMPLETIONacross every dataset the connecting user can read, keeping the top three answers and discarding per-chunk completions that are really refusals (“no relevant information…”). - Posts a
responseactivity with the answer, which completes the turn.
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 toPOST /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 withLINEAR_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_SECRETtogether and restart the backend. Because the same secret also signs the OAuthstate, an install that is mid-flight during a rotation lands on?linear=error_invalid_state; just mint a fresh authorize URL.
thought activity satisfies.
Disconnect vs. Uninstall
Neither deletes indexed data:- Disconnect in Cognee —
DELETE /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
OAuthApprevokedwebhook, which revokes the credential server-side — the same end state, reached from the other side.
linear_<url_key> dataset stays exactly as it is in both cases. To remove the indexed data itself, use forget().
Troubleshooting
POST /authorizereturns 503 “linear integration is not configured on this server”:LINEAR_CLIENT_ID,LINEAR_REDIRECT_URI, orLINEAR_WEBHOOK_SECRET(it signs the state) is unset. The backend log names the exact variable. A missingLINEAR_FRONTEND_BASE_URLsurfaces later, as the same 503 from the callback instead.- Redirected to
?linear=error_invalid_state: the install didn’t start from a freshly minted/authorizeURL, more than 10 minutes passed before approving it, orLINEAR_WEBHOOK_SECRETchanged in between. Mint a new one. - 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: mismatchedLINEAR_CLIENT_ID/LINEAR_CLIENT_SECRET, aLINEAR_REDIRECT_URIthat doesn’t exactly match the app’s registered callback URL, a missingINTEGRATION_CREDENTIALS_KEY, or the identity query failing (Linear token response carries no organization id). - Redirected to
?linear=error_already_connected: this workspace is bound to another Cognee user. Disconnect it there first. - Redirected to
?linear=cancelled: the consent screen was cancelled, or Linear rejected the request. Nothing was stored. - 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>, orhas no issues to sync. It covers the 50 most recently updated issues only; everything older arrives when those issues are next touched. - Webhook deliveries return 401: either
LINEAR_WEBHOOK_SECRETdoesn’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 signatureversusStale Linear webhook timestamp. - 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. - 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. - 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.
Related
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.