This guide walks through setting up the ABCA Linear integration. Once configured, applying the bgagent label to an issue in a mapped Linear project triggers an autonomous task. The agent posts progress comments back on the Linear issue as it works.
Phase 2.0b — ABCA now authenticates to Linear via OAuth (
actor=app) instead of a personal API key. One OAuth app per ABCA deployment, one credential provider per Linear workspace. Personal API keys are no longer supported (see Migration from 2.0a (PAK) to 2.0b (OAuth) below).
- ABCA CDK stack deployed (see Developer guide)
- A Cognito user account configured (see User guide)
- A Linear workspace where you have admin access (you'll create an OAuth app and install it on the workspace)
- AWS CLI configured with credentials for your ABCA account, with
bedrock-agentcore-control:*permissions on the deployment region - The
bgagentCLI installed and logged in (bgagent configure+bgagent login)
- A Linear-workspace admin creates a Linear OAuth app, registers it as an AgentCore Identity credential provider, and authorizes it on the workspace via
bgagent linear setup. The workspace's OAuth token lives in the AgentCore Identity vault, keyed onuserId=linear-workspace-<organizationId>. One install per workspace, used by all teammates — this matches the v1 personal-API-key semantics. - A user adds the
bgagentlabel (configurable per project) to a Linear issue. - Linear fires a webhook to
POST /v1/linear/webhook. ABCA verifies the HMAC signature and dedups retries. - A processor Lambda looks up the Linear
organizationIdinLinearWorkspaceRegistryTableto find the credential provider name, retrieves the workspace's OAuth token via AgentCore Identity, then resolves the project → repo mapping and creates a task withchannel_source: 'linear'. - The agent clones the repo, writes
.mcp.jsonwith Linear's hosted MCP server, and runs. It usesmcp__linear-server__save_comment/mcp__linear-server__update_issueto post updates asbgagent[bot](the OAuth app's identity). - The agent opens a PR on GitHub and adds a final comment to the Linear issue with the PR link.
Trigger: only Linear issues with the configured label in a mapped project create tasks. Issues without the label, or in unmapped projects, are ignored. Label removal does not cancel a running task.
Multi-workspace: a single ABCA deployment can serve multiple Linear workspaces. Each workspace gets its own AgentCore credential provider via bgagent linear add-workspace.
The credential provider is an AWS-side OAuth2 client registration. It generates the AWS-hosted callback URL that Linear will redirect the browser to during consent — without this URL, you can't complete Step 2.
bgagent linear oauth-register-workspace <workspace-slug>Where <workspace-slug> is the Linear urlKey of the workspace (e.g. acme from https://linear.app/acme/...). The command prompts for the Linear OAuth app's clientId and clientSecret — you don't have these yet, so first create the Linear OAuth app in Step 2 below, then come back and finish this step. Either order works; just pair them.
The command:
- Calls
aws bedrock-agentcore-control create-oauth2-credential-providerwithcredentialProviderVendor='CustomOauth2'(Linear is not a built-in vendor, so the command supplies an explicitauthorizationServerMetadatablock — Linear has no.well-known/openid-configuration). - Prints the AWS-hosted callback URL you'll paste into Linear's app form.
- Records the provider name (
linear-oauth-<workspace-slug>) forbgagent linear setupto use later.
Why AWS hosts the callback. Earlier ABCA designs (and most third-party docs at the time of writing) assumed the integrator hosted their own callback service. AgentCore Identity actually proxies the callback itself; the URL it surfaces in
create-oauth2-credential-providerresponse (callbackUrl) is what Linear redirects to, not an URL you control. TheresourceOauth2ReturnUrlyou pass toget_resource_oauth2_tokenis just where AWS sends the browser after AWS finishes the code-exchange — typically a localhost URL thatbgagent linear setuplistens on for that one redirect.
Run:
bgagent linear app-templateThis prints the exact field values to paste into Linear's OAuth app form. Open Linear Settings → API → New application and fill in the fields the template lists. Critical fields (each gates the actor=app agent flow — without them Linear surfaces a misleading "Invalid redirect_uri" error):
- GitHub username: must end with the literal
[bot]suffix (e.g.,bgagent[bot]) - Webhooks: toggle ON (the URL value can be a placeholder; we don't subscribe to events for the OAuth flow itself)
- Callback URLs: paste the AWS-hosted URL from Step 1 on a single line. Wildcards are not accepted; if you have multiple environments, register each URL fully.
If you ran Step 1 first, pass the AWS callback URL to the template so it's filled in:
bgagent linear app-template --aws-callback-url "<paste from Step 1 output>"Click Save, then copy the Client ID and Client Secret from the app's detail page.
Return to the terminal where Step 1 is paused at the Client ID: prompt and paste the values you copied from Linear. The credential provider is now wired up.
bgagent linear setupThe wizard:
- Looks up the credential provider you registered in Step 1.
- Starts an ephemeral HTTPS server on
localhost:8443with a self-signed cert. Your browser will warn about the cert — click through, it's local-only. - Calls
get_resource_oauth2_tokenwithcustomParameters={'actor': 'app'}and opens the returnedauthorizationUrlin your default browser. - You authorize the OAuth app on the Linear consent screen.
- AWS handles the code-exchange with Linear behind the scenes, then redirects your browser to
https://localhost:8443/oauth/callback?session_id=.... - The wizard captures the
session_id, polls for the access token (5s/600s timeout), then queries Linear'sviewer { id, organization { id, urlKey } }to record workspace metadata inLinearWorkspaceRegistryTable.
The OAuth token is stored in the AWS-managed token vault under userId=linear-workspace-<organizationId>. All teammates' Linear-triggered tasks share this single token — that's by design (matches the v1 PAK semantics, just with a revocable / scoped credential and audit trail).
In Linear Settings → API → Webhooks → +:
- URL: paste the URL
bgagent linear setupprinted at the end of Step 4 (looks likehttps://<your-api-id>.execute-api.<region>.amazonaws.com/v1/linear/webhook) - Resource types: check Issues only
- Team: whichever team owns the projects you'll map to ABCA (or all teams)
Save, then open the webhook's detail page and copy the signing secret. Run:
bgagent linear setup --webhook-secret <paste>This stores the secret in LinearWebhookSecret. (Webhook signing is independent of OAuth — it's how Linear authenticates inbound calls to your API Gateway, separate from how the agent authenticates outbound calls to Linear.)
Map a Linear project UUID to the GitHub repo you want tasks routed to:
bgagent linear onboard-project <linear-project-id> --repo owner/repoOptional flags:
| Flag | Purpose | Default |
|---|---|---|
--label <label> |
Linear label that triggers a task | bgagent |
--team-id <id> |
Linear team UUID (stored for debug only) | — |
--region <region> |
AWS region | from bgagent configure |
--stack-name <name> |
CloudFormation stack name | backgroundagent-dev |
Finding the Linear project UUID. Linear's project URL (https://linear.app/<workspace>/project/<slug>-<short>) contains a truncated UUID at the end — that's not the full UUID the webhook sends. List the full UUIDs for all projects visible to the OAuth token:
bgagent linear list-projectsCopy the id of the project you want to onboard. onboard-project validates the UUID format and will reject the truncated slug version with a pointer back to this command.
ABCA needs to know which platform user a Linear actor maps to so triggered tasks are attributed correctly (concurrency caps, billing, bgagent list).
The admin who ran bgagent linear setup is auto-linked. Setup queries Linear's viewer { id } with the new OAuth token and writes a row in LinearUserMappingTable for the Cognito user running the CLI. Look for ✓ Linked Linear user … in the setup output.
For other teammates: Linear-triggered tasks they apply the label on will be dropped by the processor with "Linear actor has no linked platform user — skipping task creation" until their identity is mapped. Two paths:
-
Manual (today): the admin inserts a row into
LinearUserMappingTable:aws dynamodb put-item \ --table-name <stack>-LinearIntegrationUserMappingTable... \ --item '{ "linear_identity": {"S": "<workspaceId>#<viewerId>"}, "platform_user_id": {"S": "<their Cognito sub>"}, "status": {"S": "active"}, "linked_at": {"S": "2026-05-19T00:00:00Z"} }'
Find the
viewerIdvia Linear's API (viewer { id }while logged in as that teammate) and the Cognito sub viabgagent admin invite-user(printed when you create their user) or by decoding their cached id_token. -
Self-service (planned, v2.x): a comment-driven
@bgagent linkflow that exchanges a code for a row write —bgagent linear link <code>exists in v1 but is non-functional until the Linear-side code generator ships.
Add the bgagent label to a Linear issue in a mapped project. Within a few seconds:
- The Linear webhook Lambda logs an
INFOentry and invokes the processor. - The processor looks up
LinearWorkspaceRegistryTableby the webhook'sorganizationId, retrieves the workspace's OAuth token via AgentCore Identity, and creates a task inTaskTablewithchannel_source: 'linear'. - The agent container starts, clones the repo, and posts a
🤖 Starting on this issue…comment asbgagent[bot]. - When the agent opens a PR, another comment appears with the PR link and the issue transitions to
In Review(if that state exists). - On completion or failure, a final status comment is posted.
A single ABCA deployment can serve multiple Linear workspaces. Each workspace gets its own credential provider and OAuth install:
bgagent linear add-workspace <workspace-slug>This re-runs Steps 1, 2, and 4 of the setup (asks for a new clientId/secret pair, creates a linear-oauth-<workspace-slug> provider, runs the OAuth dance against the new workspace). You'll need to create a separate Linear OAuth app for each workspace — Linear apps are workspace-scoped at install time even though the same OAuth credentials could technically install in multiple workspaces. Per-workspace apps give cleaner revocation and per-workspace branding.
The 50-credential-provider-per-account quota in AgentCore is the practical ceiling for multi-tenant deployments.
Add the bgagent label (or whatever you configured) to an issue in a mapped Linear project. The issue title + description becomes the task description.
- From Linear: the issue itself — progress comments are posted as the agent works.
- From the CLI:
bgagent list/bgagent status <task-id>.
Use bgagent cancel <task-id>. Removing the Linear label does not cancel a running task.
- Is the project mapped? Run
aws dynamodb scan --table-name <LinearProjectMappingTableName>(look up the table name viaaws cloudformation describe-stacks). - Is the workspace registered? Scan
LinearWorkspaceRegistryTablefor the LinearorganizationIdfrom the webhook payload. - Is the label spelled exactly as configured? Match is case-insensitive but must be the same word.
- Check CloudWatch logs for
WebhookFnandWebhookProcessorFnforInvalid Linear webhook signature,Linear workspace is not onboarded,Linear project is not onboarded, orLinear actor has no linked platform user.
The Linear user who applied the label hasn't been mapped to a Cognito user. See Step 7.
This is Linear's misleading error for actor=app flows where the OAuth app config is incomplete. Check, in your Linear app settings:
- GitHub username field is set to a value ending in
[bot](e.g.bgagent[bot]) - Webhooks toggle is ON
- The AWS-hosted callback URL is on a single line in the Callback URLs textarea (line-wrapped URLs become two malformed entries that Linear silently rejects)
Re-run bgagent linear setup after fixing.
- Verify the OAuth credential provider exists:
aws bedrock-agentcore-control list-oauth2-credential-providers --region <region>— look forlinear-oauth-<workspace-slug>. - Verify the workspace is registered: scan
LinearWorkspaceRegistryTable. - Check the agent container logs for
Linear MCP configured at …— absence meanschannel_sourcewasn't set on the task or the workspace lookup failed. - Check for
WARN linear_reactions: HTTP 401 from Linearin CloudWatch — usually means the OAuth token in the vault has been revoked from the Linear side. Re-runbgagent linear setupto re-authorize.
The signing secret in Secrets Manager doesn't match the webhook. Re-run bgagent linear setup --webhook-secret <new-secret> and paste the secret from the webhook's detail page (not the OAuth app page).
If your deployment is on Phase 2.0a (personal API key), 2.0b is a hard cutover — there is no --use-pak fallback flag. Plan for a short maintenance window (typically <30 min for a single workspace).
What changes under the hood. 2.0a stored a single
LinearApiTokenSecret(one PAK shared by all teammates) and granted the agent runtimesecretsmanager:GetSecretValueon that one ARN. 2.0b stores a per-workspacebgagent-linear-oauth-<slug>secret containing{access_token, refresh_token, expires_at, client_id, client_secret, …}, and replaces the single-ARN grant with abgagent-linear-oauth-*prefix grant. The CDK stack drops theLinearApiTokenSecretresource entirely, so there's no automated rollback once 2.0b is deployed.
Run these BEFORE deploying 2.0b so you have everything ready when the maintenance window starts:
- List your in-flight tasks.
bgagent list --status RUNNING --status PENDING— the migration will not corrupt these, but their final Linear comment may fail because the OAuth token isn't yet authorized when the agent runs. - Pick one Linear workspace to migrate first. Multi-workspace orgs should rehearse on the lowest-traffic workspace before doing the rest.
- Note the workspace's
urlKey(the<slug>inlinear.app/<slug>/...). You'll need it forbgagent linear setup <slug>. - Confirm CLI admin access. You need an AWS principal with
secretsmanager:CreateSecretonbgagent-linear-oauth-*ANDdynamodb:PutItemonLinearWorkspaceRegistryTable. Without these,bgagent linear setupaborts mid-way (the OAuth dance succeeds, the secret write fails — your Linear OAuth app gets stuck with no usable token).
- Drain the queue. Wait for in-flight tasks to finish. In-flight tasks at deploy time will fail their final Linear comment because their token resolver short-circuits when neither
LinearApiTokenSecret(gone) norbgagent-linear-oauth-<slug>(not yet created) is present. - Deploy 2.0b.
mise //cdk:deploy. This addsLinearWorkspaceRegistryTable, removes theLinearApiTokenSecretresource and IAM grants, and adds thebgagent-linear-oauth-*prefix grant on the agent runtime + webhook processor + orchestrator. - For each Linear workspace, run Steps 1–4 above. Each workspace needs:
- A new Linear OAuth app (Settings → API → Applications → Create new app, scopes
read,write,app:assignable,app:mentionable) bgagent linear setup <slug>to run the OAuth dance and write the per-workspace secret- The webhook signing secret pasted into the Secrets Manager
LinearWebhookSecretresource
- A new Linear OAuth app (Settings → API → Applications → Create new app, scopes
- Re-onboard projects. If 2.0a had
LinearProjectMappingTablerows, they survive — but verify withbgagent linear list-projectsthat the listed projects still match what's mapped. The mapping rows are keyed onlinear_project_idUUID which is stable across the migration. - Verify with a test issue. Apply the trigger label in each onboarded workspace and confirm the agent posts as
bgagent[bot](not as the previous PAK owner's Linear identity). The author byline change is the cleanest signal that OAuth — not the PAK — is on the wire. - Decommission the PAK. Once 2.0b is verified working, revoke the personal API key in Linear settings (Linear Settings → Security → Personal API keys → revoke). The PAK is no longer used by any code path; revoking is a clean break with no rollback.
If 2.0b fails verification and you need to revert before doing the OAuth setup:
- The
LinearApiTokenSecretCFN resource has been deleted, so acdk deployof the previous commit will recreate it but the secret value will be empty. You'd need to re-paste the PAK value manually. - Recommend instead: fix-forward. The 2.0b OAuth dance is a 5-minute step per workspace; rolling back is rarely worth the time.
LinearUserMappingTable— keyed on Linear identity (organization + user UUID), which is unchanged across PAK→OAuth.LinearProjectMappingTable— keyed onlinear_project_idUUID, also stable.LinearWebhookDedupTable— TTL-bounded; rows from the maintenance window will TTL out within 8h.- GitHub PR comments and Linear-issue mappings in any in-flight task records.
LinearApiTokenSecretSecrets Manager value — gone with the CDK resource.- The 2.0a
linear-api-keyAgentCore credential provider (if 2.0a-with-Identity was deployed mid-Phase) — clean it up after with:aws bedrock-agentcore-control delete-api-key-credential-provider --name linear-api-key. Phase 2.0b-O2 does not use AgentCore Identity at all, so there's nothing to clean up if you skipped the parked 2.0a-Identity branch.
Linear's API rate limits per OAuth-installed app, per workspace:
| Metric | Limit / hour |
|---|---|
| Requests | 5,000 |
| Complexity points | 3,000,000 |
A typical task makes ~10 Linear API calls (one starting comment, one PR comment, one state transition, one final comment), nowhere near the ceiling. Heavy users should monitor the X-RateLimit-Requests-Remaining header in agent logs.
AgentCore Identity quotas worth knowing:
| Metric | Limit |
|---|---|
| OAuth2 credential providers per account-region | 50 |
| Workload identities per account-region | (check Service Quotas console) |
Token refresh: Linear access tokens expire in 24h (since April 2026). AgentCore Identity auto-refreshes via the stored refresh token; the agent's get_resource_oauth2_token call returns a fresh token transparently.
- Comment-driven task triggers: only labels trigger tasks. Comment commands (e.g.
@bgagent fix this) are v2+. - Self-service user linking: see Step 7 — admins must insert mapping rows manually until v2.x ships the
@bgagent linkcomment flow. - Attachments: tickets are text-only. Linear attachments (mockups, screenshots) are planned via S3 pre-fetch.
- Per-issue status polling: use
bgagent statusor watch the Linear issue comments.
Deactivate a project mapping:
aws dynamodb update-item \
--table-name <LinearProjectMappingTableName> \
--key '{"linear_project_id":{"S":"<uuid>"}}' \
--update-expression 'SET #s = :removed' \
--expression-attribute-names '{"#s":"status"}' \
--expression-attribute-values '{":removed":{"S":"removed"}}'Revoke a workspace install:
aws bedrock-agentcore-control delete-oauth2-credential-provider \
--name linear-oauth-<workspace-slug> \
--region <region>
aws dynamodb update-item \
--table-name <LinearWorkspaceRegistryTableName> \
--key '{"linear_workspace_id":{"S":"<linear-org-uuid>"}}' \
--update-expression 'SET #s = :revoked' \
--expression-attribute-names '{"#s":"status"}' \
--expression-attribute-values '{":revoked":{"S":"revoked"}}'Delete the Linear webhook from Linear Settings → API and uninstall the OAuth app from Workspace Settings → Integrations on the Linear side.
To remove the Linear integration from your ABCA deployment entirely, delete the webhook in Linear, uninstall the OAuth app, run the delete-oauth2-credential-provider for each workspace, then delete the LinearIntegration construct from the stack and redeploy.