Linear Setup
Connect Linear comments or Agent Sessions with API-key or OAuth client-credentials authentication.
- Audience
- Operators running durable agent work
- Focus
- Bridges guidance shaped for scanability, day-two clarity, and operator context.
This guide connects a Linear workspace to AGH through either ordinary issue comments or Linear's Agent Session surface. Runtime mode and authentication mode are independent choices; configure both explicitly.
How the Linear bridge behaves
| Surface | AGH behavior |
|---|---|
comments mode | Ingests newly created Comment webhooks. Replies become Linear comments; existing bridge comments can be updated or deleted. |
agent_sessions mode | Ingests AgentSessionEvent actions created and prompted. Responses become append-only Agent Activities; edit and delete are unsupported. |
| Authentication | api_key sends the bound key as a bearer credential. oauth uses the client-credentials grant and caches the app token. |
| Workspace ownership | Every webhook and live identity result must match provider_config.organization_id. |
| Tool progress | Acknowledged without creating a Linear comment or Agent Activity. |
Choose the two modes
| Setting | Values | Conditional bindings |
|---|---|---|
provider_config.mode | comments, agent_sessions | Selects accepted webhook type and delivery behavior. |
provider_config.auth_mode | api_key, oauth | API key requires api_key; OAuth requires client_id and client_secret. |
The runtime accepts either auth mode with either provider mode. In practice, Linear Agent Sessions are configured on an OAuth application because its app identity is what users mention or assign.
Fastest supported path
Use comments + api_key for the first proof:
- Create a dedicated Linear API key and copy the organization ID returned for that identity.
- Create one Comment webhook with a unique signing secret.
- Create the AGH bridge disabled with explicit
mode: "comments"andauth_mode: "api_key". - Bind
webhook_secretandapi_key. - Verify configuration, enable, and inspect runtime health.
- Create one real issue comment and confirm the AGH route.
- Reply through
send-testand confirm the remote Linear comment ID.
Use agent_sessions + oauth when the app must be mentionable/assignable and produce append-only Agent
Activities.
Before you start
- Linear workspace admin access, or help from an admin who can create webhooks/apps.
- The workspace's organization ID.
- A public HTTPS callback and local provider listener.
- Either a personal API key or an OAuth application with client-credentials tokens enabled.
- An AGH workspace with a default agent.
Before configuring Linear, prove that the locally built provider is installed and visible in the daemon catalog:
PROVIDER=linear
agh extension status "$PROVIDER" -o json
curl -sS http://127.0.0.1:2123/api/bridges/providers | \
jq --arg provider "$PROVIDER" '.providers[] | select(.extension_name == $provider)'Continue only when the extension is enabled and the catalog row is not disabled or unhealthy. If either command has no provider, follow Install an in-tree provider first.
Find the organization ID in Linear's API explorer with the same identity the bridge will use:
query LinearProviderViewer {
viewer {
id
displayName
organization {
id
}
}
}Copy viewer.organization.id exactly. Runtime initialization compares the authenticated value with
provider_config.organization_id and degrades on a mismatch.
Step 1: Expose the provider endpoint
Linear → https://bridge.example.com/linear/product
→ reverse proxy or tunnel
→ http://127.0.0.1:18089/linear/productStore the listener in provider_config.webhook.listen_addr, or set
AGH_BRIDGE_LINEAR_LISTEN_ADDR=127.0.0.1:18089 in the daemon environment. One Linear provider
process uses one listener address. A shared path is allowed because the provider selects an instance
by organization and runtime mode before verifying that instance's secret.
Step 2A: Prepare API-key authentication
For the quickest comments setup:
- Open Linear Settings → API.
- Create a personal API key for the identity that should own AGH's comments.
- Copy it when Linear displays it.
The key inherits that user's team access. Use a dedicated integration identity if comments should not appear as a human operator.
Step 2B: Prepare OAuth client credentials
For app-owned comments or Agent Sessions:
- In Linear's API/application settings, create an OAuth application.
- Enable client credentials tokens for the application.
- Record the client ID and client secret.
- Configure the app's team access in the workspace.
- For
agent_sessions, enable the Agent session events webhook category and give the app a short, recognizable name and icon; that identity appears in mention and assignment menus.
AGH requests read, write, comments:create, and issues:create; Agent Session mode also requests
app:mentionable. Linear's OAuth client-credentials reference
documents the enablement toggle and token behavior. The Agents setup guide
covers app installation and Agent Session event registration.
Step 3: Create the bridge disabled
Linear has no guided agh bridge setup command. API-key comments example:
agh bridge create \
--scope workspace \
--workspace-id ws_8f33a913d23c4fd1 \
--platform linear \
--extension linear \
--display-name "Linear product comments" \
--enabled=false \
--include-group \
--include-thread \
--provider-config '{
"organization_id": "org_123",
"mode": "comments",
"auth_mode": "api_key",
"webhook": {
"public_url": "https://bridge.example.com/linear/product",
"listen_addr": "127.0.0.1:18089",
"path": "/linear/product"
}
}' \
-o jsonOAuth Agent Session example:
{
"organization_id": "org_123",
"mode": "agent_sessions",
"auth_mode": "oauth",
"webhook": {
"public_url": "https://bridge.example.com/linear/agent",
"listen_addr": "127.0.0.1:18089",
"path": "/linear/agent"
}
}Copy the returned bridge ID:
BRIDGE_ID=brg_123Step 4: Bind the webhook and auth secrets
Every mode requires the signing secret from the Linear webhook or OAuth application settings:
printf '%s' "$LINEAR_WEBHOOK_SECRET" | agh bridge secret-bindings put "$BRIDGE_ID" webhook_secret \
--secret-ref "vault:bridges/$BRIDGE_ID/webhook_secret" \
--kind secret \
--secret-value-stdinAPI-key authentication:
printf '%s' "$LINEAR_API_KEY" | agh bridge secret-bindings put "$BRIDGE_ID" api_key \
--secret-ref "vault:bridges/$BRIDGE_ID/api_key" \
--kind token \
--secret-value-stdinOAuth client credentials:
printf '%s' "$LINEAR_CLIENT_ID" | agh bridge secret-bindings put "$BRIDGE_ID" client_id \
--secret-ref "vault:bridges/$BRIDGE_ID/client_id" \
--kind credential \
--secret-value-stdin
printf '%s' "$LINEAR_CLIENT_SECRET" | agh bridge secret-bindings put "$BRIDGE_ID" client_secret \
--secret-ref "vault:bridges/$BRIDGE_ID/client_secret" \
--kind secret \
--secret-value-stdinStep 5A: Create a comments webhook
For comments mode:
- Open Linear Settings → API → Webhooks.
- Select New webhook.
- Set its URL to
provider_config.webhook.public_url. - Choose all public teams or the specific team scope AGH should receive.
- Select the Comment resource type.
- Save the webhook and copy its signing secret into the
webhook_secretbinding.
AGH ingests only type: "Comment" with action: "create"; update/remove webhooks are acknowledged
without starting another agent turn. Linear's webhook guide
documents the current settings page, public-HTTPS requirement, retries, and signature header.
Step 5B: Configure Agent Session events
For agent_sessions mode, use the OAuth application's webhook configuration rather than a separate
data-change webhook:
- Set the OAuth application's webhook URL to the AGH public callback.
- Enable Agent session events.
- Copy the app webhook signing secret into the AGH binding.
- Install/authorize the app in the intended workspace and grant its team access.
- Confirm the app is mentionable or assignable in a test issue according to the scopes you enabled.
AGH handles created and prompted Agent Session actions. Linear expects an agent to acknowledge a
new session quickly; keep the public endpoint and AGH daemon continuously available.
Step 6: Verify configuration, then runtime identity
agh bridge verify "$BRIDGE_ID" --jsonLinear currently reports provider.identity as skipped in the control command. While disabled,
webhook reachability is also skipped. The records still prove that the shared public URL is valid
and make the skipped checks explicit.
Enable the bridge so runtime initialization can perform the live GraphQL viewer query:
agh bridge enable "$BRIDGE_ID"
agh bridge verify "$BRIDGE_ID" --json
agh bridge get "$BRIDGE_ID" -o jsonRuntime health should reach ready. It fails authentication when the API key/client credentials are
invalid and degrades when the viewer's organization differs from organization_id.
Step 7: Establish a route and send
For comments mode, create a new comment on an issue. For Agent Sessions, mention or assign the app so
Linear sends a created event. Then inspect the route:
agh bridge routes "$BRIDGE_ID" -o jsonUse the route's issue group and encoded thread in a real delivery:
agh bridge send-test "$BRIDGE_ID" \
--message "AGH Linear connection check" \
--group-id "<group-id-from-route>" \
--thread-id "<thread-id-from-route>" \
--mode reply \
--jsonThe thread target is not valid by itself: Linear routes anchor it to the issue ID in group_id. In
comments mode, the response appears as a Linear comment. In Agent Session mode, it appears as an
Agent Activity and subsequent updates append rather than editing the earlier activity.
Configuration reference
| Field | Requirement / fallback | Purpose |
|---|---|---|
organization_id | yes | Linear organization that owns webhook routing and authenticated viewer. |
mode | yes | comments or agent_sessions. |
auth_mode | yes | api_key or oauth, independent of runtime mode. |
webhook.public_url | yes for setup/verification | Full public HTTPS webhook URL. |
webhook.listen_addr | AGH_BRIDGE_LINEAR_LISTEN_ADDR | Local provider listener. |
webhook.path | /linear | Local callback path; shared paths remain organization/mode scoped. |
The GraphQL and OAuth token destinations are official defaults or operator-owned process variables.
provider_config.api_base_url and oauth_token_url are rejected.
Known limits
- Comment mode only starts turns from newly created comments.
- Agent Session activities are append-only; edit and delete delivery operations are unsupported.
- Tool progress has no Linear side effect.
agh bridge verifydoes not run the viewer query; enabled runtime health does.- The provider validates a recent positive webhook timestamp, but the signing secret and organization/ mode selection remain the primary documented trust boundary.
Troubleshooting
| Symptom | What to check |
|---|---|
| Runtime reports organization mismatch | Run the viewer query with the same credential and copy viewer.organization.id exactly. |
| API-key auth is unauthorized | Recreate the API key, confirm its identity has access to the intended teams, and replace the binding. |
| OAuth token exchange fails | Enable client-credentials tokens, verify client ID/secret, and confirm the app's requested scopes are allowed. |
| Webhook signature fails | Copy the signing secret from the exact webhook/app configuration and ensure the proxy preserves the raw body. |
| Comments webhook returns success but starts no turn | Select the Comment resource and create a new comment; updates/removals are intentionally ignored. |
| Agent is missing from mention/assignment UI | Install the OAuth app, grant team access, enable Agent session events, and request the appropriate app scopes. |
| Agent Session starts but later output cannot edit | Agent Activities are append-only in this provider; do not use edit/delete expectations from comments mode. |
| Webhook becomes disabled in Linear | Restore a fast public 200 response, verify listener health, then re-enable the webhook in Linear settings. |
| Two bridge instances conflict | Give different organization/mode ownership or distinct paths; one ownership key cannot belong to two instances. |
Security notes
- Prefer an OAuth app identity or dedicated integration user over a personal admin key.
- Scope team access to the work the agent should see.
- Keep the public handler fast and preserve the raw request body for HMAC verification.
- Store
api_key,client_secret, andwebhook_secretonly through AGH secret bindings.
Rotate Linear credentials
For API-key mode, create the replacement key for the same integration identity and team-access
boundary. For OAuth, create/rotate the client secret on the same app. Disable the bridge, replace the
binding, enable it, and wait for the GraphQL viewer check to return ready before revoking the old
credential.
Rotate webhook_secret in the Linear webhook/app and AGH during the same disabled window. Prove a
new signed event after rotation; a successful GraphQL identity call does not validate webhook HMAC.
Completion checklist
- The Linear extension is installed, enabled, and healthy in the provider catalog.
organization_idmatches the authenticated viewer.- Provider mode and auth mode are explicit and have the required bindings.
- The webhook emits the event family selected by the provider mode.
- Runtime health performs the live identity proof omitted by the short-lived control check.
- Comment mode creates editable comments; Agent Session mode creates append-only activities.
- A real event establishes the expected issue/session route.
send-testreturns the remote Linear artifact ID.- The bridge returns to
readyafter one restart.