Full demo video: media/linear-agent-sessions-demo.mp4
An OpenClaw plugin that maps each Linear Agent Session to its own persistent OpenClaw conversation.
One Linear issue can contain many separate Agent Sessions, and each of those sessions maps to a separate OpenClaw session key. That means you can create as many independent agent threads as you want inside the same issue without mixing their context.
This repo is for the plugin runtime itself. It is not a full infrastructure guide for every possible ingress setup.
- Receives Linear Agent Session webhooks on
/plugins/linear/linear - Verifies webhook signatures and rejects stale payloads
- Maps one Linear
AgentSessionto one stable OpenClaw session key - Posts a fast visible
thoughtactivity as an acknowledgement - Runs one OpenClaw turn for each accepted Linear turn
- Publishes exactly one final visible
responseorerror - Uses
AgentSessionEventas the canonical trigger for native Linear session runs - Deduplicates known duplicate webhook combinations
- Supports OAuth callback and code exchange routes for app installation
- Optionally publishes post-run tool/file trace breadcrumbs when
linearDebugToolTrace=true
- It does not register
/plugins/linear/api - It does not expose
/hooks/linear - It does not run a plugin-side Linear tool API proxy
- It does not treat Linear as a second tool runtime
Linear is treated as a conversational surface. OpenClaw remains the runtime that actually executes the agent turn.
index.ts registers only these routes:
/plugins/linear/linear/plugins/linear/oauth/callback/plugins/linear/oauth/exchange
If your public ingress uses a proxy or tunnel, it still needs to forward into those plugin routes.
The active runtime lives in src/runtime/*.
High level flow:
- Linear sends a webhook to
/plugins/linear/linear. - The plugin validates the signature, normalizes the payload, and returns
202quickly. - The plugin resolves the Linear session identity and maps it to:
agent:<agentId>:linear:session:<linearSessionId> - The plugin posts an immediate visible
thoughtactivity. - The plugin runs one OpenClaw turn against that stable session key.
- The plugin publishes exactly one terminal
responseorerror.
For native Linear agent sessions, AgentSessionEvent is the canonical runtime trigger.
Comment webhooks may still be used for bootstrap/fallback lookup in edge cases, but normal comment events tied to an existing native agent session are ignored so one user turn cannot start a second run.
- One Linear
AgentSession= one isolated OpenClaw session. - One Linear issue can have many separate
AgentSessions. - If one Linear comment ends up spawning several
AgentSessions, each one still gets its own OpenClaw session. - Follow-up turns inside the same Linear
AgentSessioncontinue the same OpenClaw session instead of mixing with the others.
Why this is useful:
- you can run several independent agent conversations inside one issue
- context from one investigation does not bleed into another
- each thread keeps its own memory, tool history, and follow-ups
Minimal diagram:
Linear issue LUK-123
comment A
-> AgentSession S1
-> OpenClaw session OC1
comment B
-> AgentSession S2
-> OpenClaw session OC2
-> AgentSession S3
-> OpenClaw session OC3
follow-up inside S2
-> continues OC2
The plugin only requires a public HTTPS endpoint that ultimately reaches the registered plugin routes.
Direct setup:
Linear
-> public HTTPS
-> OpenClaw
-> /plugins/linear/linear
-> linear-agent-bridge
Common proxied setup:
Linear
-> public HTTPS
-> cloudflared
-> optional thin proxy
-> OpenClaw
-> /plugins/linear/linear
-> linear-agent-bridge
A proxy such as linear-proxy is optional. It can be useful for ingress logging, header preservation, or TLS/front-door separation, but the plugin itself does not depend on having a separate proxy layer.
The active config surface is defined in openclaw.plugin.json.
Core runtime settings:
agentId- OpenClaw agent id to run, defaultmaindevAgentId- legacy alias foragentIdlinearWebhookSecret- required for webhook verificationlinearApiKey- direct Linear token for GraphQL callslinearOauthClientIdlinearOauthClientSecretlinearOauthRedirectUrilinearTokenStorePath- persisted OAuth token storageopenclawProvider- provider override, defaultopenaiopenclawModel- model override, defaultgpt-5.4openclawThinking- thinking override, defaulthighdelegateOnCreate- optionally auto-delegate on session createstartOnCreate- optionally move issue to started on session createrepoByTeam- workspace hints by Linear teamrepoByProject- workspace hints by Linear projectdefaultDir- default workspace hint when no mapping matchesexternalUrlBase- optional external session link templateexternalUrlLabel- label for the external linklinearDebugToolTrace- when true, publish visible tool/file trace breadcrumbs after runs
openclaw.plugin.json still exposes some legacy compatibility fields so older installs do not fail validation. Those fields should not be treated as the active architecture. In particular, the current runtime does not register /plugins/linear/api, even if legacy config fields such as enableAgentApi, apiBaseUrl, apiCorsOrigins, apiCorsAllowCredentials, strictAddressing, or mentionHandle still appear in the schema.
When linearDebugToolTrace=true, the plugin fetches recent OpenClaw chat history after a run and publishes compact Linear thought activities summarizing tool usage for the current turn.
Examples:
read ~/repo/src/runtime/handler.tsedit ~/repo/src/runtime/handler.tsweb_search "linear duplicate follow-up bug" -> error: 429 rate limited
This is for debugging and operator visibility. It is intentionally opt-in because it adds noise to Linear activity history.
npm run build
npm testCompiled output goes to dist/.
Typical local extension path:
~/.openclaw/extensions/linear-agent-bridge/The plugin id remains linear-agent-bridge.
- Enable Linear Agent Session webhooks for your app.
- Point the public webhook endpoint so it ultimately reaches
/plugins/linear/linear. - Complete OAuth setup if you are using OAuth instead of a direct API token.
- Mention or delegate the app in a Linear issue.
- Confirm:
- a visible
thoughtappears quickly - only one OpenClaw run happens for the turn
- exactly one final visible
responseorerroris published - follow-up prompts continue the same conversation
- a visible
index.ts- registers the live webhook and OAuth routessrc/runtime/handler.ts- active native Linear runtime and dedupe logicsrc/runtime/payload.ts- webhook normalization and trigger extractionsrc/runtime/prompt.ts- chat-first prompt shapingsrc/runtime/gateway.ts- OpenClaw gateway invocation and history accesssrc/runtime/session-resolver.ts- session lookup and fallback recoverysrc/runtime/issue-policy.ts- issue start/delegate policy on session createsrc/runtime/skip-filter.ts- self-authored and system-echo filteringsrc/runtime/tool-trace.ts- post-run tool/file trace summarizationsrc/runtime/validation.ts- webhook signature validationsrc/linear-client.ts- Linear GraphQL clientsrc/oauth/*- OAuth callback, exchange, refresh, and token storage
