Skip to content

Revert "feat(agentex): Linear gateway — invoke agents from Linear" - #400

Merged
michael-chou359 merged 1 commit into
mainfrom
revert-399-mc/linear-gateway
Aug 10, 2026
Merged

Revert "feat(agentex): Linear gateway — invoke agents from Linear"#400
michael-chou359 merged 1 commit into
mainfrom
revert-399-mc/linear-gateway

Conversation

@michael-chou359

@michael-chou359 michael-chou359 commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Reverts #399

Greptile Summary

This PR reverts the Linear gateway by removing its webhook route, use case, tests, authentication exemption, and OpenAPI operation.

  • Removes the Linear gateway route and implementation.
  • Removes the corresponding unit-test suite and OpenAPI path.
  • Retains the Slack authentication exemption but accidentally registers the Slack router twice.

Confidence Score: 4/5

The PR appears safe to merge after the non-blocking duplicate Slack router registration is removed.

The Linear gateway is consistently removed across its route, implementation, tests, middleware exemption, and OpenAPI specification, but app initialization now registers both Slack endpoints twice.

Files Needing Attention: agentex/src/api/app.py

Important Files Changed

Filename Overview
agentex/src/api/app.py Removes the Linear router import but replaces its registration with a duplicate Slack router registration.
agentex/src/api/middleware_utils.py Removes the Linear authentication exemption while preserving and documenting Slack signature-based authentication.
agentex/src/api/routes/linear.py Deletes the Linear webhook ingress as intended by the revert.
agentex/src/domain/use_cases/linear_gateway_use_case.py Deletes the Linear gateway event-processing implementation as intended by the revert.
agentex/openapi.yaml Removes the POST /linear/events operation from the checked-in OpenAPI specification.
agentex/tests/unit/use_cases/test_linear_gateway_use_case.py Removes tests for the deleted Linear gateway behavior.

Fix All in Cursor Fix All in Claude Code Fix All in Codex

Prompt To Fix All With AI
### Issue 1
agentex/src/api/app.py:207
**Duplicate Slack router registration**

`slack.router` is already registered above, so this second call duplicates the `/slack/events` and `/slack/commands` route entries, producing duplicate operation identifiers during OpenAPI generation and leaving the second set of routes unreachable.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "Revert "feat(agentex): Linear gateway — ..." | Re-trigger Greptile

@michael-chou359
michael-chou359 requested a review from a team as a code owner August 10, 2026 16:43
@michael-chou359
michael-chou359 merged commit bcf5a79 into main Aug 10, 2026
10 of 11 checks passed
@michael-chou359
michael-chou359 deleted the revert-399-mc/linear-gateway branch August 10, 2026 16:44
@github-actions

github-actions Bot commented Aug 10, 2026

Copy link
Copy Markdown

✱ Stainless preview builds

This PR will update the agentex-sdk SDKs with the following commit messages.

openapi

feat: Revert "feat(agentex): Linear gateway — invoke agents from Linear"

python

feat: Revert "feat(agentex): Linear gateway — invoke agents from Linear"

typescript

feat: Revert "feat(agentex): Linear gateway — invoke agents from Linear"
agentex-sdk-openapi studio · code

Your SDK build had at least one "note" diagnostic.
generate ✅

⚠️ agentex-sdk-typescript studio · code

Your SDK build had at least one "warning" diagnostic.
generate ⚠️build ⏭️lint ⏭️test ✅

⚠️ agentex-sdk-python studio · code

Your SDK build had at least one "warning" diagnostic.
generate ⚠️build ⏭️lint ⏭️test ✅


This comment is auto-generated by GitHub Actions and is automatically kept up to date as you push.
If you push custom code to the preview branch, re-run this workflow to update the comment.
Last updated: 2026-08-10 16:47:03 UTC

michael-chou359 added a commit that referenced this pull request Aug 10, 2026
…401)

Re-lands the Linear gateway from #399, which was merged (`4718eee`) then
reverted by #400 (`bcf5a79`).

## Why it was reverted — and why that wasn't a code problem
#399's revert was triggered by the **"Stainless build"** check, which
failed in its *merge* step with:

> `404 One or both branches not found: main, preview/mc/linear-gateway`
— "This is a bug. Please report it at
https://github.com/stainless-api/upload-openapi-spec-action/issues"

That's a **Stainless SDK-generation / CI-infra failure** (the action
couldn't find a preview branch and flags it as its own bug), not a
defect in the gateway. **All 42 code checks on `4718eee` passed** — the
full unit + sync/async integration matrix. So no code change was needed
to re-land; this is the same commit (including the Greptile review
fixes).

If the Stainless build fails again the same way, it's an infra issue to
re-run / raise with the Stainless integration owners, not a blocker on
this code.

## What it is (unchanged from #399)
Platform-side ingress fronting a Linear agent app; `POST /linear/events`
verifies `Linear-Signature` + `webhookTimestamp`, dedups on
`Linear-Delivery`, normalizes `AgentSessionEvent` (created/prompted),
runs the Slack-gateway selector-cascade dispatch
(`task_metadata.channel="linear"`), and replies via
`agentActivityCreate` (thought → terminal response/error) using a
`client_credentials` app-actor token (re-minted on 401). Runs as a
dedicated bot service account. Includes the #399 review fixes:
fail-closed on empty signing secret, and no response-body in logs on
token failure.

## Testing
21 unit tests pass, ruff clean. Signed ingress + client_credentials
token mint validated against live Linear earlier.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- greptile_comment -->

<h3>Greptile Summary</h3>

The PR adds a signed Linear webhook gateway that deduplicates
deliveries, dispatches Linear agent-session turns through AgentEx, and
returns activities using an app-actor OAuth token.
- Registers and documents `POST /linear/events`.
- Adds signature freshness checks, delivery deduplication, target
selection, bot identity propagation, task dispatch, reply polling, and
Linear activity delivery.
- Adds unit coverage for authentication, normalization, dispatch,
identity handling, and token refresh.

<details><summary><h3>Confidence Score: 4/5</h3></summary>

The follow-up selector handling should be fixed before merging because
it can silently alter user prompts in existing Linear sessions.

Prompted events pass through the same selector-resolution path as
initial events, so a leading word matching an agent or configuration is
removed despite the session contract requiring follow-up content to
remain intact.

**Files Needing Attention:**
agentex/src/domain/use_cases/linear_gateway_use_case.py
</details>

<details><summary><h3>Important Files Changed</h3></summary>

| Filename | Overview |
|----------|----------|
| agentex/src/domain/use_cases/linear_gateway_use_case.py | Implements
the complete Linear ingress and dispatch lifecycle, but applies
first-turn selector stripping to prompted follow-ups. |
| agentex/src/api/routes/linear.py | Adds the Linear webhook route and
preserves the raw request body required for HMAC verification. |
| agentex/src/api/middleware_utils.py | Whitelists Linear ingress so the
gateway's webhook-signature authentication can run. |
| agentex/src/api/app.py | Registers the new Linear router while
removing a duplicate Slack router registration. |
| agentex/openapi.yaml | Documents the new Linear webhook endpoint and
its successful response. |
| agentex/tests/unit/use_cases/test_linear_gateway_use_case.py | Covers
core gateway behavior but does not exercise selector-like first words in
prompted follow-ups. |

</details>

<details><summary><h3>Sequence Diagram</h3></summary>

```mermaid
sequenceDiagram
    participant L as Linear
    participant API as POST /linear/events
    participant G as LinearGatewayUseCase
    participant R as Redis
    participant ACP as AgentEx ACP
    participant LA as Linear API
    L->>API: Signed AgentSessionEvent
    API->>G: Raw body, headers, payload
    G->>G: Verify signature and timestamp
    G->>R: SET delivery ID NX with TTL
    G-->>L: "200 {ok: true}"
    G->>LA: Emit thought activity
    G->>ACP: Resolve target and create/resume task
    ACP-->>G: Agent reply
    G->>LA: Emit terminal response or error
```
</details>

<a
href="https://app.greptile.com/api/ide/cursor?prompt=%23%23%23%20Issue%201%0Aagentex%2Fsrc%2Fdomain%2Fuse_cases%2Flinear_gateway_use_case.py%3A329%0A**Follow-up%20selector%20strips%20content**%0A%0AWhen%20a%20prompted%20follow-up%20starts%20with%20a%20registered%20agent%20or%20configuration%20name%2C%20%60_resolve_target%60%20treats%20that%20word%20as%20a%20selector%20and%20removes%20it%20before%20dispatching%20to%20the%20existing%20session%20task%2C%20causing%20the%20agent%20to%20receive%20a%20truncated%20user%20instruction%20even%20though%20selectors%20are%20intended%20to%20apply%20only%20on%20the%20first%20turn.%0A%0A---%0A%0AFor%20each%20issue%20above%2C%20determine%20whether%20it%20is%20valid%20and%20should%20be%20fixed.%20If%20so%2C%20fix%20it%20directly.&pr=401&platform=github"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCursorDark.svg?v=6"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCursor.svg?v=6"><img
alt="Fix All in Cursor"
src="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCursor.svg?v=6"></picture></a>
<a
href="https://app.greptile.com/ide/claude-code?prompt=%23%23%23%20Issue%201%0Aagentex%2Fsrc%2Fdomain%2Fuse_cases%2Flinear_gateway_use_case.py%3A329%0A**Follow-up%20selector%20strips%20content**%0A%0AWhen%20a%20prompted%20follow-up%20starts%20with%20a%20registered%20agent%20or%20configuration%20name%2C%20%60_resolve_target%60%20treats%20that%20word%20as%20a%20selector%20and%20removes%20it%20before%20dispatching%20to%20the%20existing%20session%20task%2C%20causing%20the%20agent%20to%20receive%20a%20truncated%20user%20instruction%20even%20though%20selectors%20are%20intended%20to%20apply%20only%20on%20the%20first%20turn.%0A%0A---%0A%0AFor%20each%20issue%20above%2C%20determine%20whether%20it%20is%20valid%20and%20should%20be%20fixed.%20If%20so%2C%20fix%20it%20directly.&repo=scaleapi%2Fscale-agentex&pr=401&platform=github"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInClaudeDark.svg?v=6"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInClaude.svg?v=6"><img
alt="Fix All in Claude Code"
src="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInClaude.svg?v=6"></picture></a>
<a
href="https://app.greptile.com/api/ide/codex?prompt=IMPORTANT%3A%20Work%20in%20the%20repository%20%22scaleapi%2Fscale-agentex%22%20on%20the%20existing%20branch%20%22mc%2Flinear-gateway-reland%22.%20Checkout%20that%20branch%20%E2%80%94%20do%20NOT%20create%20a%20new%20branch%20or%20open%20a%20new%20PR.%20Push%20your%20changes%20to%20%22mc%2Flinear-gateway-reland%22.%0A%0A%23%23%23%20Issue%201%0Aagentex%2Fsrc%2Fdomain%2Fuse_cases%2Flinear_gateway_use_case.py%3A329%0A**Follow-up%20selector%20strips%20content**%0A%0AWhen%20a%20prompted%20follow-up%20starts%20with%20a%20registered%20agent%20or%20configuration%20name%2C%20%60_resolve_target%60%20treats%20that%20word%20as%20a%20selector%20and%20removes%20it%20before%20dispatching%20to%20the%20existing%20session%20task%2C%20causing%20the%20agent%20to%20receive%20a%20truncated%20user%20instruction%20even%20though%20selectors%20are%20intended%20to%20apply%20only%20on%20the%20first%20turn.%0A%0A---%0A%0AFor%20each%20issue%20above%2C%20determine%20whether%20it%20is%20valid%20and%20should%20be%20fixed.%20If%20so%2C%20fix%20it%20directly.&repo=scaleapi%2Fscale-agentex&pr=401&platform=github"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodexDark.svg?v=6"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodex.svg?v=6"><img
alt="Fix All in Codex"
src="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodex.svg?v=6"></picture></a>

<details><summary>Prompt To Fix All With AI</summary>

`````markdown
### Issue 1
agentex/src/domain/use_cases/linear_gateway_use_case.py:329
**Follow-up selector strips content**

When a prompted follow-up starts with a registered agent or configuration name, `_resolve_target` treats that word as a selector and removes it before dispatching to the existing session task, causing the agent to receive a truncated user instruction even though selectors are intended to apply only on the first turn.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.
`````

</details>

<sub>Reviews (1): Last reviewed commit: ["feat(agentex): Linear gateway
— invoke
a..."](e0c6d4a)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=51876870)</sub>

> Greptile also left **1 inline comment** on this PR.

<!-- /greptile_comment -->

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant