Slack Assistant Linear Ticket Creation Integration
Context
The Linear integration enables users to create tickets directly from Slack. It is the simplest integration in the assistant — a single GraphQL mutation with no search, no caching, no formatting. It is also the only integration that writes data (rather than reading), which has implications for the approval flow.
Guidance
Simple GraphQL Mutation
const mutation = `
mutation CreateIssue($title: String!, $description: String!) {
issueCreate(input: { title: $title, description: $description }) {
success
issue { id url identifier }
}
}
`;
const resp = await fetch('https://api.linear.app/graphql', {
method: 'POST',
headers: {
Authorization: apiKey, // Raw API key, no "Bearer " prefix
'Content-Type': 'application/json',
},
body: JSON.stringify({ query: mutation, variables: { title, description } }),
});Auth note: Linear’s API accepts the raw API key in the Authorization header without a Bearer prefix. This is unusual — most APIs expect Bearer <token>. If you change this to use Bearer, it will silently fail with a 401.
Missing Team Assignment
The current mutation does not specify a teamId:
const teamQuery = teamId ? '' : ', teamId: team?.nodes?.[0]?.id';When no teamId is passed, the GraphQL query uses a fallback that doesn’t actually work (the team?.nodes?.[0]?.id syntax is invalid in GraphQL). This means the teamId parameter is effectively required but not always provided.
Fix pending: The mutation should include a team ID lookup or accept it as a required parameter.
Linear API Key Not Configured
LINEAR_API_KEY is not set in Railway production. The integration returns { ok: false, error: 'No Linear API key configured' } when called — it degrades gracefully without crashing.
No Approval Flow
Unlike the planned write-approval flow (ROADMAP Phase 1), this integration creates tickets immediately on request. There is no confirmation step. This is appropriate for a MVP but should be gated behind approval before wider rollout.
Why This Matters
Linear is the only write-path integration. This changes the security and UX model: every other integration reads data that already exists, while Linear creates new data. The current no-approval flow is acceptable for the pilot but would cause problems at scale (users accidentally creating duplicate tickets or tickets with poor titles).
When to Apply
- Any assistant that needs to create tickets from chat
- Slack → PM tool workflows
- Action-executing bots that need write capability
Examples
Creating a Ticket
const result = await createLinearTicket({
apiKey: config.linearApiKey,
title: "Login fails on mobile Safari",
description: "User reports that the login page doesn't render on iOS Safari 18. Steps to reproduce: ...",
});
// Returns: { ok: true, url: "https://linear.app/.../issue/LIN-123" }Graceful Failure (No API Key)
// When LINEAR_API_KEY is not set:
const result = await createLinearTicket({ apiKey: '', ... });
// Returns: { ok: false, error: 'No Linear API key configured' }Related
apps/slack-apps/brainforge-assistant/src/linear.tsapps/slack-apps/brainforge-assistant/src/assistant.ts(shouldTriggerSkill gate)apps/slack-apps/brainforge-assistant/TESTING.md(known issues)knowledge/engineering/brainforge-slack-assistant/ROADMAP.md(Phase 1 approval flow)docs/solutions/architecture-patterns/slack-assistant-v2-hybrid-ai-pipeline-2026-04-28.md