---
ref: workflow:feature-requests-to-linear
title: Attach feature requests from support chats to Linear issues
author: thedogwiththedataonit
tools: [tool:intercom/search-conversations, tool:typesafe/answer-typed-questions, tool:linear/list-issues, tool:linear/create-issue, tool:linear/add-customer-request]
tags: [capability:classify-signals, capability:manage-tasks, capability:search-conversations, has:api, motion:retention]
updated: 2026-09-29
---

# Attach feature requests from support chats to Linear issues

Finds feature requests in recent Intercom conversations with Jev, matches each to an open Linear issue, and attaches the customer's ask.

Set up the tools below, then run the steps in order for the user, carrying each step's results into the next. The run is done when the user has the outcome below.

## Outcome

- A table of every feature request found, with its product area, the issue it matches and Jev's confidence.
- Each request attached to its Linear issue as a customer request from the customer's company, with the Intercom conversation ID.
- A new Linear issue for each request you approved that matched no open issue.

## Inputs

Ask the user for these before you start.

- `since`: when the last run ended, so only conversations created after it are read, e.g. 2026-09-22
- `product_areas`: the parts of your product a request can be about, each also a label in Linear, with one line on what it covers, e.g. reporting: dashboards and exports; integrations: connections to other tools; billing: plans and invoices
- `request_label`: the Linear label on feature-request issues, e.g. Feature request
- `team`: the Linear team that owns new requests, e.g. Product
- `min_confidence`: how sure Jev must be before its answer is used without you, e.g. 0.8; a yes-or-no answer counts as yes at or above it and as no at or below 1 minus it

## Set up

### Search conversations (Intercom, tool:intercom/search-conversations)

Use the first option your agent supports.

Note: Returns 20 conversations per page by default and at most 150, paged with `starting_after`. A `source.body` filter matches single words, not phrases.

#### MCP (official, remote)

Add this server to your agent's MCP settings, then sign in when asked.

```json
{ "mcpServers": { "intercom": { "url": "https://mcp.intercom.com/mcp" } } }
```

Call the MCP tool `search_conversations`.

#### API (official)

- Base URL: https://api.intercom.io
- Endpoint: `POST /conversations/search`
- Auth: send the header `Authorization: Bearer $INTERCOM_API_KEY`
- Get a key: https://app.intercom.io/a/apps/_/developer-hub/app-packages

### Answer typed questions (TypeSafe AI, tool:typesafe/answer-typed-questions)

Use the API.

- Base URL: https://api.typesafe.ai
- Endpoint: `POST /v1/systemone`
- Auth: send the header `Authorization: Bearer $TYPESAFE_API_KEY`
- Get a key: https://console.typesafe.ai

Note: Put every question about one record in one request. `GET /v1/models` lists the models and is the cheapest check of a key; a request over the rate limit gets a 429 with a Retry-After header.

Note: Send `state`, `model` (`jev-latest`) and named `questions`, each with `type`, `instructions` and `criteria`: a choice maps labels to descriptions, a score lists its levels in order, a noul's is optional. Read a score by its most likely level; send unsure answers to a person.

### Linear (tool:linear/list-issues, tool:linear/create-issue, tool:linear/add-customer-request)

Use the first option your agent supports.

Notes:

- List issues: Returns 50 issues at a time by default: pass `pageInfo.endCursor` as `after` for the next page.
- Create or update an issue: Needs a `teamId`. Without a `stateId`, an API-created issue lands in the team's first Backlog state, or in Triage when the team uses it.
- Add a customer request to an issue: Customer Requests must be enabled in the workspace settings. The customer must exist first: create it with `customerUpsert`, which matches an existing customer by domain instead of making a duplicate.

#### MCP (official, remote)

Add this server to your agent's MCP settings, then sign in when asked.

```json
{ "mcpServers": { "linear": { "url": "https://mcp.linear.app/mcp" } } }
```

- List issues: call the MCP tool `list_issues`
- Create or update an issue: call the MCP tool `save_issue`
- Add a customer request to an issue: call the MCP tool `save_customer_need`

#### API (official)

- Base URL: https://api.linear.app
- List issues: `POST /graphql`
- Create or update an issue: `POST /graphql`
- Add a customer request to an issue: `POST /graphql`
- Auth: send the header `Authorization: $LINEAR_API_KEY`
- Get a key: https://linear.app/settings/account/security

Before step 1, confirm access to each service with its cheapest read-only call, like a list or a search. Never send or change anything to test access.

## Steps

1. **Pull new conversations** with Search conversations (Intercom). Search conversations created after `since`. Keep each conversation's ID, its opening message and its author's email, and read the rest of a conversation when its opening message is only a greeting, a read-only call.
2. **Find the requests** with Answer typed questions (TypeSafe AI). Send each conversation's messages as the state, with a noul `feature_request` (asks for a new capability or a change, not help using an existing one) and a choice `area` over `product_areas`, each described by its line, plus other. Keep the conversations whose `feature_request` is yes, with their area, and the unsure ones for step 5.
3. **List the open requests** with List issues (Linear). List the open issues labeled `request_label`. Keep each issue's ID, title and labels; its area is the label that names one of `product_areas`.
4. **Match each request** with Answer typed questions (TypeSafe AI). Send each request's messages as the state, with a choice `issue` whose labels are the open issues in the request's area (for other, the issues with no area label), each described by its title, plus none. When an area has more than 254 open issues, send its requests to the user in step 5 instead. Keep the matched issue and its confidence.
5. **Check the unsure ones with the user** yourself. Show the user every unsure `feature_request`, every match below `min_confidence` and every request that matched none, and keep the issue the user picks or their approval to open a new one.
6. **Open new issues** with Create or update an issue (Linear). For each new request the user approved, create an issue in `team`, labeled `request_label` and its area, titled by what the customer asked for. Keep each new issue's ID.
7. **Attach the asks** with Add a customer request to an issue (Linear). For each request, upsert the Linear customer by the author's email domain, listing personal email domains for the user instead, then attach the customer's own words and the Intercom conversation ID to its matched or new issue.

## Notes

Matching a request is a choice over your own open issues, so it can only pick one that exists or none; a choice takes at most 255 labels, which is why step 4 narrows the issues to the request's area first. Customer requests carry the company, so each issue shows which customers asked.

Run it weekly with `since` set to the previous run.

## Rules

- Use only the services set up above. The read-only calls they need, like listing ids or polling for results, are fine.
- Ask the user before anything that sends messages, costs money, or changes data, and say how many records it touches. One approval covers a batch the user has seen.
- Never print API keys.
