Linear Agent Session
Linear AgentSession lifecycle, 3 triggers, no-close-mutation.
Partial. The core Linear AgentSession lifecycle (3 trigger types, thought batching, forward suppression, and session close) is fully shipped. The following activity types are not yet emitted: action, elicitation, prompt. The platform currently emits thought, response, and error only.
Rensei integrates with Linear's Agent API to surface live agent activity inside Linear's UI - thoughts, responses, and errors appear in real time in the issue thread as your agent works. This page explains how the platform manages the AgentSession lifecycle, the three trigger types, and the mechanics of session close.
What is a Linear AgentSession?
When a user opens an @-mention for your Rensei agent in Linear or triggers an agent via the Linear UI, Linear creates an AgentSession object. This session is the container for all activity the agent reports back to Linear.
The platform maps one Rensei session to one Linear AgentSession. As the agent works, the platform forwards activities to the AgentSession via Linear's agentActivityCreate mutation.
Three Trigger Types
The Linear integration exposes three workflow trigger nodes. Each corresponds to a different event that Linear can generate for an AgentSession:
| Trigger node | Linear event | When it fires |
|---|---|---|
linear.agent_session.created | AgentSession created | A user creates a new agent session (e.g. first @mention or explicit agent trigger) |
linear.agent_session.prompted | signal: prompted | A user sends a follow-up @mention to an existing active session |
linear.agent_session.updated | AgentSession updated | Any other update to the AgentSession object |
The prompted Drop Behavior
linear.agent_session.prompted fires for @-mention events. If no workflow is subscribed to this trigger for the project, the event is silently dropped with an af.skip result. No error is surfaced to the user in Linear. If you expect @mentions to continue a session, ensure your workflow subscribes to linear.agent_session.prompted.
The prompted trigger is what powers Interactive Chat from the Linear side. When a user @mentions your agent in an existing issue thread, Linear fires signal: prompted, the platform routes it to linear.agent_session.prompted, and the workflow can re-queue work for the running session.
Session Lifecycle
A Linear AgentSession has no explicit active/complete state that the platform sets directly. Instead, Linear infers the session state from the activities emitted:
- A session is
activewhile the platform is emittingthought,action, orresponseactivities. - A session transitions to
completewhen the platform emits a finalresponseactivity.
Linear's Agent API has no close or terminate mutation. There is no agentSessionClose or updateAgentSession(state: closed) call. The only way to mark a session complete is to emit a response activity - Linear infers complete from that signal.
The platform's closeLinearAgentSession function wraps this contract. It emits a response activity with the session's terminal reason, then marks the session in the forward-suppression set so no further activities are forwarded.
// From linear-session-close.ts
await emitActivity(
client,
linearSessionId,
'response', // closes the AgentSession on Linear's side
reason ?? 'Session complete.',
false,
)The linear.agent_session.close Workflow Node
The SDLC default template ships a linear.agent_session.close action node at the terminal branch of every SDLC stage. This is the canonical place to emit the final response. If you build a custom workflow that creates its own Linear AgentSessions, you should wire this node at every terminal exit point.
A lifecycle hook also fires the close as a safety net when a session reaches any terminal status (completed, failed, stopped) - even if the workflow didn't include the close node explicitly.
Thought Batching (F2)
Agents at high cadence can emit more than 4 thought activities per second. Forwarding each one individually would exhaust Linear's 5,000 req/hr quota in minutes for active sessions.
The platform uses a 1.5-second debounce batcher per session:
enqueueThought(sessionId, body, emitFn)overwrites any pending thought and resets the timer.- When the timer fires, the last body wins and is forwarded exactly once.
- Intermediate thoughts are discarded - this matches Linear's own "rolling thought" UI pattern.
response and error activities bypass the batcher and are forwarded immediately. Before emitting either, the batcher flushes any pending thought to preserve chronological order in Linear's thread.
To disable batching for debugging:
LINEAR_THOUGHT_BATCHER_DISABLED=1Forward Suppression
Some Rensei sessions have a linearSessionId that is a synthetic UUID - generated by agent.dispatch_stage for self-dispatched stages where Linear never created a real AgentSession. Forwarding activities to a nonexistent AgentSession generates noisy 404 errors.
The platform handles this with a per-process suppression set:
- The first
agentActivityCreatecall that returns "Entity not found: AgentSession" marks the session as suppressed. - All subsequent activity forwards and close attempts for that session are no-ops.
- The suppression set is in-process memory and clears on process restart (benign: the first call after restart retries once, then suppresses again).
This means: if you see a session that has activities in the Rensei UI but nothing appearing in Linear, check whether the session's linearSessionId is a synthetic UUID by inspecting it via the Session Inspector.
Activity Types
Linear defines six activity types. Rensei currently emits three:
| Type | Platform emits | Notes |
|---|---|---|
thought | Yes | Debounced; 1.5s window |
response | Yes | Immediate; bypasses batcher; closes session |
error | Yes | Immediate; bypasses batcher |
action | No | Not yet implemented |
elicitation | No | Not yet implemented |
prompt | No | Not yet implemented |
And four signal types that can accompany activities:
| Signal | Used by platform |
|---|---|
auth | No |
continue | Via /prompt endpoint (re-queues work) |
select | No |
stop | Via /stop endpoint (terminates session) |
OAuth Scopes Required
Your Linear OAuth connection must include the app:assignable and app:mentionable scopes for agentActivityCreate to succeed. User-scope-only OAuth (read,write,issues:create,comments:create) silently 401s agent activity calls - the agent runs locally and Rensei shows activity, but Linear's UI stays empty.
If you reconnected Linear before June 2026, you may need to re-connect to pick up the updated scopes. Check the Integrations section of your project settings.
Webhook Path
Linear webhooks arrive at POST /api/webhooks/linear. The platform verifies the HMAC signature using the signing secret configured for your Linear App (one secret per application, not per org - see the Linear integration guide for setup).
Linear AgentSession webhooks have sub-second delivery budgets. Any synchronous work beyond signature verification and idempotency check must be deferred via Next.js after(). Synchronous processing after the budget kills the webhook chain silently.
Troubleshooting
Agent activities appear in Rensei but not in Linear:
- Check the Linear OAuth scopes -
app:assignableandapp:mentionableare required. - Inspect the session's
linearSessionId. If it looks like a synthetic UUID, the session was self-dispatched and suppression is working as intended. - Check Vercel runtime logs for
[linear-session-close]or[linear-dispatch-utils]warnings.
@mention in Linear does nothing:
- Verify a workflow is subscribed to
linear.agent_session.promptedfor the project. - Check the subscription status in the project's workflow settings - the UI badge ("Published") reads
project_template_subscriptions, but the router readstrigger_subscriptions. If a workflow was archived and re-published, the two may be out of sync.
Double response activity closing the session twice:
This is prevented by the forward-suppression set. After closeLinearAgentSession emits the final response, the session is added to the suppression set and any subsequent close attempt from the lifecycle hook safety net is a no-op.
Related Pages
- Interactive Chat - prompt or stop sessions via CLI (mirrors
agent_session.prompted) - Session Detail - view activity stream
- Context Derivation - how tool calls become context facets forwarded to Linear
- Linear Integration - OAuth setup, webhook configuration, required scopes
- SDLC Default Template - how the default SDLC closes AgentSessions at each stage