Skip to content

Commit 58da79a

Browse files
committed
docs(adr): ADR-017 — Linear agent-session as a future (flag-gated, post-GA) interaction channel (#56)
Design-only scoping of the actor=app / agent-session migration. Records: - VERIFIED LIVE (2026-06-17): both deployed workspace tokens carry 'read write app:assignable app:mentionable' → bgagent is already an app actor; the auth half of the migration is DONE, zero work. - Linear is an interaction layer, not compute — switching changes trigger + status display only; all compute stays on ABCA's AgentCore/ECS. - GO/NO-GO: adopt agent sessions as an ADDITIONAL flag-gated trigger/ack channel ONCE Linear GAs the Agents API (currently Developer Preview), reusing the channel-agnostic aws-samples#247 engine. Do NOT rip out the now-hardened comment path. The win is real but partial — it retires the brittle string-match-trigger + hand-rolled-ack seam, but the parent-epic panel / cascade / base-branch engine stays ours (no native cross-issue rollup). - Activity model (thought/action/response/elicitation/error + session states) maps cleanly onto the ack states aws-samples#247 already built. Includes the regenerated Starlight mirror (docs:sync). No code changes.
1 parent 7fdda3d commit 58da79a

2 files changed

Lines changed: 262 additions & 0 deletions

File tree

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# ADR-017: Linear agent-session as a future interaction channel
2+
3+
**Status:** proposed
4+
**Date:** 2026-06-17
5+
6+
## Context
7+
8+
ABCA's Linear integration today triggers and reports work through a
9+
**hand-rolled comment protocol** layered on Linear's generic Issue/Comment
10+
webhooks:
11+
12+
- **Trigger** — a string match on `@bgagent` in a `Comment` webhook body
13+
(`parseCommentTrigger`), plus a label-add on an issue to seed a #247
14+
orchestration.
15+
- **Acknowledgement** — emoji reactions managed by hand (👀 on receipt →
16+
✅/❌ on settle via `swapCommentReaction`/`swapIssueReaction`), threaded
17+
replies (`replyToComment`), and a single maturing "epic panel" comment
18+
edited in place (`upsertEpicPanel`).
19+
20+
This protocol works and is now well-tested (see the #247 UX.1–23 series),
21+
but the comment seam has been the single richest source of edge-case bugs:
22+
reply `issueId` vs `parentId` rules, "parent comment must be top-level"
23+
threading, webhook-redelivery reply spam, self-trigger loops from our own
24+
`@bgagent` example text, and reaction/state flapping. Each was a
25+
consequence of bolting an agent protocol onto a human-comment surface.
26+
27+
Linear now ships a first-class **Agents API** (agent-session model):
28+
delegate or @mention an installed agent app → a typed `AgentSessionEvent`
29+
webhook (`created`/`prompted`) → the agent emits typed **activities**
30+
(`thought` / `action` / `response` / `elicitation` / `error`) and Linear
31+
derives a native session **state** (`pending`/`active`/`awaitingInput`/
32+
`error`/`complete`/`stale`) with a built-in "thinking"/activity UI.
33+
34+
Two facts establish the starting point:
35+
36+
1. **The auth migration is already done.** ABCA's OAuth flow
37+
(`cli/src/linear-oauth.ts`) requests
38+
`read write app:assignable app:mentionable` with `actor=app`. Verified
39+
live on `backgroundagent-dev` (2026-06-17): both deployed workspace
40+
tokens (`bgagent-linear-oauth-maguireb`, `…-demo-abca`) carry exactly
41+
that scope. **bgagent is already installed as an app actor** — it is
42+
assignable, mentionable, and delegatable today. No auth work is needed
43+
to adopt agent sessions.
44+
2. **Linear is an interaction layer, not compute.** Adopting agent sessions
45+
changes *how we are triggered* and *how status is shown*. All compute
46+
(clone, run the coding agent, build/test, open the PR) still runs on
47+
ABCA's own AgentCore Runtime + ECS. The switch offloads nothing to
48+
Linear and does not change the AWS architecture or cost model.
49+
50+
## Decision
51+
52+
**Adopt the Linear agent-session model as an ADDITIONAL, flag-gated
53+
trigger/ack channel once Linear marks the Agents API GA — not now, and not
54+
as a replacement for the comment path.**
55+
56+
The orchestration **engine** is channel-agnostic by design (the #247
57+
trigger-agnostic seams): graph discovery, the reconciler, the epic
58+
panel/rollup, base-branch stacking, and the cascade do not care how a task
59+
was triggered. Agent sessions slot in as a new front end to that engine,
60+
mapping cleanly onto what we already built:
61+
62+
| ABCA today (hand-rolled) | Linear agent-session (native) |
63+
|-------------------------------------|-----------------------------------|
64+
| `@bgagent` string match in comment | `created` AgentSessionEvent (mention/delegate) |
65+
| 👀 reaction "on it" | `thought` activity |
66+
| 🤖 Starting / 🔗 PR opened | `action` activity (+ result) |
67+
| ✅ Updated / completion | `response` activity |
68+
| ❌ failure reply | `error` activity |
69+
| "reply with guidance" retry (UX.9) | `elicitation` + `prompted` webhook + conversation history |
70+
| panel header state (🔄/✅/⚠️) | session state (active/complete/error) |
71+
72+
### Why a channel, not a rewrite
73+
74+
- The win is **real but partial**: agent sessions retire the brittle
75+
*trigger + per-comment ack* seam (the bug class above), but Linear agent
76+
sessions are **per-issue delegations with no native cross-issue epic
77+
rollup**. The #247 parent-epic panel, fan-out integration node, dependency
78+
cascade, and base-branch stacking stay ABCA's responsibility either way —
79+
so roughly half of the recent bug classes (panel settle, cross-issue
80+
concurrency) are unaffected by the migration.
81+
- The Agents API is a **Developer Preview** (confirmed against
82+
`developers.linear.app`, 2026-06-17): "in active development… may change
83+
before GA." Ripping out a working, now-hardened comment path to depend on
84+
an unstable API is the wrong trade today.
85+
- Treating it as an additive channel behind a flag (per ADR-006) lets us
86+
reuse the channel-agnostic engine, run both paths side by side during
87+
evaluation, and revert via the flag if the Preview API shifts.
88+
89+
## Consequences
90+
91+
- **Positive:** removes the highest-friction seam (string-match trigger +
92+
hand-rolled threading/reactions); native progress UI; conversation-history
93+
retry replaces our bespoke loop; no auth work (already app-actor).
94+
- **Negative / risk:** Preview API churn; hard runtime constraints (webhook
95+
receiver must return within ~5s; an activity or external URL must be
96+
emitted within ~10s of `created` or the session is marked unresponsive) —
97+
ABCA's task spawn is async and slower than 10s, so the `created` handler
98+
must emit an immediate `thought` ack and hand off, exactly as the current
99+
processor 👀s then spawns.
100+
- **No-op surfaces:** the orchestration engine, panel/rollup renderer,
101+
reconciler, cascade, and base-branch logic are untouched by this decision.
102+
103+
## Phasing
104+
105+
1. **Now (this ADR):** record the decision; auth verified; do not build.
106+
Keep the hardened comment path as the sole Linear interaction channel.
107+
2. **When Linear GAs the Agents API:** spike a flag-gated `agent-session`
108+
trigger/ack adapter behind the existing channel-agnostic engine —
109+
`created`→seed/iterate, activities↔our ack states — running in parallel
110+
with the comment path on `backgroundagent-dev`.
111+
3. **After evaluation:** if the native path is strictly better, default the
112+
flag on and deprecate the `@bgagent` string-match trigger; keep the
113+
panel/rollup engine.
114+
115+
## Out of scope (this ADR)
116+
117+
- Any implementation. This is a direction + go/no-go record only.
118+
- Changes to the orchestration engine, OAuth/token storage (done, ADR-016
119+
governs pluggable identity), or the Slack/Jira channels.
120+
- The Mode B planner (#299) — orthogonal.
121+
122+
## References
123+
124+
- `cli/src/linear-oauth.ts``actor=app`, `app:assignable`/`app:mentionable`
125+
- `cdk/src/handlers/linear-webhook-processor.ts` — current comment trigger + acks
126+
- ADR-006 (feature flags), ADR-015 (Jira integration), ADR-016 (pluggable identity and auth)
127+
- Linear Agents API — `https://linear.app/developers/agents`,
128+
`https://linear.app/developers/agent-interaction` (Developer Preview, fetched 2026-06-17)
129+
- #247 UX.16–23 — the comment-path bug classes this would retire
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
---
2+
title: Adr 017 linear agent session interaction
3+
---
4+
5+
# ADR-017: Linear agent-session as a future interaction channel
6+
7+
**Status:** proposed
8+
**Date:** 2026-06-17
9+
10+
## Context
11+
12+
ABCA's Linear integration today triggers and reports work through a
13+
**hand-rolled comment protocol** layered on Linear's generic Issue/Comment
14+
webhooks:
15+
16+
- **Trigger** — a string match on `@bgagent` in a `Comment` webhook body
17+
(`parseCommentTrigger`), plus a label-add on an issue to seed a #247
18+
orchestration.
19+
- **Acknowledgement** — emoji reactions managed by hand (👀 on receipt →
20+
✅/❌ on settle via `swapCommentReaction`/`swapIssueReaction`), threaded
21+
replies (`replyToComment`), and a single maturing "epic panel" comment
22+
edited in place (`upsertEpicPanel`).
23+
24+
This protocol works and is now well-tested (see the #247 UX.1–23 series),
25+
but the comment seam has been the single richest source of edge-case bugs:
26+
reply `issueId` vs `parentId` rules, "parent comment must be top-level"
27+
threading, webhook-redelivery reply spam, self-trigger loops from our own
28+
`@bgagent` example text, and reaction/state flapping. Each was a
29+
consequence of bolting an agent protocol onto a human-comment surface.
30+
31+
Linear now ships a first-class **Agents API** (agent-session model):
32+
delegate or @mention an installed agent app → a typed `AgentSessionEvent`
33+
webhook (`created`/`prompted`) → the agent emits typed **activities**
34+
(`thought` / `action` / `response` / `elicitation` / `error`) and Linear
35+
derives a native session **state** (`pending`/`active`/`awaitingInput`/
36+
`error`/`complete`/`stale`) with a built-in "thinking"/activity UI.
37+
38+
Two facts establish the starting point:
39+
40+
1. **The auth migration is already done.** ABCA's OAuth flow
41+
(`cli/src/linear-oauth.ts`) requests
42+
`read write app:assignable app:mentionable` with `actor=app`. Verified
43+
live on `backgroundagent-dev` (2026-06-17): both deployed workspace
44+
tokens (`bgagent-linear-oauth-maguireb`, `…-demo-abca`) carry exactly
45+
that scope. **bgagent is already installed as an app actor** — it is
46+
assignable, mentionable, and delegatable today. No auth work is needed
47+
to adopt agent sessions.
48+
2. **Linear is an interaction layer, not compute.** Adopting agent sessions
49+
changes *how we are triggered* and *how status is shown*. All compute
50+
(clone, run the coding agent, build/test, open the PR) still runs on
51+
ABCA's own AgentCore Runtime + ECS. The switch offloads nothing to
52+
Linear and does not change the AWS architecture or cost model.
53+
54+
## Decision
55+
56+
**Adopt the Linear agent-session model as an ADDITIONAL, flag-gated
57+
trigger/ack channel once Linear marks the Agents API GA — not now, and not
58+
as a replacement for the comment path.**
59+
60+
The orchestration **engine** is channel-agnostic by design (the #247
61+
trigger-agnostic seams): graph discovery, the reconciler, the epic
62+
panel/rollup, base-branch stacking, and the cascade do not care how a task
63+
was triggered. Agent sessions slot in as a new front end to that engine,
64+
mapping cleanly onto what we already built:
65+
66+
| ABCA today (hand-rolled) | Linear agent-session (native) |
67+
|-------------------------------------|-----------------------------------|
68+
| `@bgagent` string match in comment | `created` AgentSessionEvent (mention/delegate) |
69+
| 👀 reaction "on it" | `thought` activity |
70+
| 🤖 Starting / 🔗 PR opened | `action` activity (+ result) |
71+
| ✅ Updated / completion | `response` activity |
72+
| ❌ failure reply | `error` activity |
73+
| "reply with guidance" retry (UX.9) | `elicitation` + `prompted` webhook + conversation history |
74+
| panel header state (🔄/✅/⚠️) | session state (active/complete/error) |
75+
76+
### Why a channel, not a rewrite
77+
78+
- The win is **real but partial**: agent sessions retire the brittle
79+
*trigger + per-comment ack* seam (the bug class above), but Linear agent
80+
sessions are **per-issue delegations with no native cross-issue epic
81+
rollup**. The #247 parent-epic panel, fan-out integration node, dependency
82+
cascade, and base-branch stacking stay ABCA's responsibility either way —
83+
so roughly half of the recent bug classes (panel settle, cross-issue
84+
concurrency) are unaffected by the migration.
85+
- The Agents API is a **Developer Preview** (confirmed against
86+
`developers.linear.app`, 2026-06-17): "in active development… may change
87+
before GA." Ripping out a working, now-hardened comment path to depend on
88+
an unstable API is the wrong trade today.
89+
- Treating it as an additive channel behind a flag (per ADR-006) lets us
90+
reuse the channel-agnostic engine, run both paths side by side during
91+
evaluation, and revert via the flag if the Preview API shifts.
92+
93+
## Consequences
94+
95+
- **Positive:** removes the highest-friction seam (string-match trigger +
96+
hand-rolled threading/reactions); native progress UI; conversation-history
97+
retry replaces our bespoke loop; no auth work (already app-actor).
98+
- **Negative / risk:** Preview API churn; hard runtime constraints (webhook
99+
receiver must return within ~5s; an activity or external URL must be
100+
emitted within ~10s of `created` or the session is marked unresponsive) —
101+
ABCA's task spawn is async and slower than 10s, so the `created` handler
102+
must emit an immediate `thought` ack and hand off, exactly as the current
103+
processor 👀s then spawns.
104+
- **No-op surfaces:** the orchestration engine, panel/rollup renderer,
105+
reconciler, cascade, and base-branch logic are untouched by this decision.
106+
107+
## Phasing
108+
109+
1. **Now (this ADR):** record the decision; auth verified; do not build.
110+
Keep the hardened comment path as the sole Linear interaction channel.
111+
2. **When Linear GAs the Agents API:** spike a flag-gated `agent-session`
112+
trigger/ack adapter behind the existing channel-agnostic engine —
113+
`created`→seed/iterate, activities↔our ack states — running in parallel
114+
with the comment path on `backgroundagent-dev`.
115+
3. **After evaluation:** if the native path is strictly better, default the
116+
flag on and deprecate the `@bgagent` string-match trigger; keep the
117+
panel/rollup engine.
118+
119+
## Out of scope (this ADR)
120+
121+
- Any implementation. This is a direction + go/no-go record only.
122+
- Changes to the orchestration engine, OAuth/token storage (done, ADR-016
123+
governs pluggable identity), or the Slack/Jira channels.
124+
- The Mode B planner (#299) — orthogonal.
125+
126+
## References
127+
128+
- `cli/src/linear-oauth.ts``actor=app`, `app:assignable`/`app:mentionable`
129+
- `cdk/src/handlers/linear-webhook-processor.ts` — current comment trigger + acks
130+
- ADR-006 (feature flags), ADR-015 (Jira integration), ADR-016 (pluggable identity and auth)
131+
- Linear Agents API — `https://linear.app/developers/agents`,
132+
`https://linear.app/developers/agent-interaction` (Developer Preview, fetched 2026-06-17)
133+
- #247 UX.16–23 — the comment-path bug classes this would retire

0 commit comments

Comments
 (0)