GraphQL. See the GraphQL limitation. All actions: codegen-report.md.
SDK relation calls are nested selections: issue.comments() sends issue(id) { comments }, so it is linear.query.issue, not linear.query.comments. Allowing linear.query.issue allows reading the issue's comments, attachments and history.
import { linear } from "@waterlock/gateway/providers/linear";
linear({ credentials: staticToken({ token: process.env.LINEAR_TOKEN! }) }); // auth: "apiKey" for a personal API key
// rule
{ when: (r) => r.action === "linear.mutation.issueCreate" && r.params.input.teamId === TEAM_ID }
// harness: stock SDK, gateway as apiUrl, session token as accessToken
new LinearClient({ accessToken: token, apiUrl: "http://127.0.0.1:8787/graphql" });Runnable example against a fake Linear with seed data: examples/ai-sdk-linear-triage.
Demo
An AI SDK agent on a real Linear workspace, through the gateway. Creating the issue and setting its priority are allowed. Moving it to another team is blocked by a TypeScript rule; filing a refund with a card number is blocked by a plain-language check. Linear is queried before and after the run.