Skip to main content

Connect to Linear

Connect your Linear organization to Squid to query and update issues

Creating a Linear personal API key

Requests to the Linear GraphQL API require an Authorization header. You can authorize your requests using OAuth2 access tokens or personal API keys. To learn more, view the Linear API documentation.

The following instructions use a personal API key. However, the same capabilities could be achieved by creating an OAuth2 access token. Using the personal API key enables you to use Squid's injection capability to automatically add the API key to all requests.

Adding the integration

  1. Navigate to the Integrations tab in the Squid Console.

  2. Click Available Integrations.

  3. Find the GraphQL integration, and select Add Integration.

  4. Provide the following details:

Integration ID: A string of your choice that uniquely identifies the integration in your code.

Base URL: https://api.linear.app/graphql

Inject Request Headers: Toggle on.

**Field name**: Authorization

**Location**: Header

**Secret** Toggle **on**. Create a new secret and put your Linear personal API key as the value. Secrets are stored securely in Squid. For more information on Squid Secrets, [view the Secrets documentation](/docs/development-tools/client-sdk/secrets).
  1. Save your newly created secret.

  2. Click Add field to save injection.

  3. Click Test Connection to test your connection to the API. If the connection fails, verify the value of your endpoint and try re-entering the value of your secret in the Secrets tab of the console.

  4. When the connection is successful, click Add Integration.

Using the integration

  1. Add the following imports to your application. If running the GraphQLClient from the Squid backend, you don't need to import Squid. Instead, you can access a provided Squid instance using this.squid.
import { Squid } from '@squidcloud/client';
import { GraphQLClient } from '@squidcloud/graphql';
  1. Create a GraphQL client, passing your Squid instance and the ID of your integration:
const graphQLClient = new GraphQLClient(squid, 'INTEGRATION_ID');
  1. To perform a query, use the GraphQLClient's query method, passing an object containing your query and any variables:
const graphQLClient = new GraphQLClient(squid, 'INTEGRATION_ID');
const query = `
query(id: String!) {
issue(id: $id) {
id
title
description
url
}
}
`;
const variables = {
id: 'some_id',
};

const result = await graphQLClient.query({
query: query,
variables: variables,
});
  1. To run a mutation, use the GraphQLClient's mutate method, passing your query and any variables:
const graphQLClient = new GraphQLClient(squid, 'INTEGRATION_ID');

const graphQlRequest = `
mutation ($title: String!, $description: String!, $teamId: String!, $stateId: String!) {
issueCreate(
input: {
title: $title,
description: $description,
teamId: $teamId,
stateId: $stateId
}
) {
success
issue {
id
title
description
}
}
}
`;
const variables = {
title: 'Example Title',
description: 'Example description.',
teamId: 'someTeamId',
stateId: 'someStateId',
};

const result = await graphQLClient.mutate({
query: graphQlRequest,
variables: variables,
});

Using your integration with an AI agent

There are two main ways you can use your Linear integration with an AI agent:

  1. Use an AI function to get the variables you need, and pass them to a specific query you want to perform.

  2. Provide your AI agent with Linear's GraphQL schema and allow the agent to create the queries for you.

Using Linear in an AI function

  1. In your Squid backend, implement an AI function that performs the desired action. AI functions allow an agent to run specified TypeScript functions based on its understanding of prompts.

When writing an AI function, attach the @aiFunction decorator to your function, and include a description of when the AI agent should call the function and what parameters it needs to pass. For more information on AI functions, view the AI functions documentation.

The following example showcases a function that queries Linear issues using a keyword filter:

Backend code
@aiFunction(
'Call this function when someone asks to find issues based on a keyword.',
[
{
name: 'filter',
description: 'The keyword or words to search for',
required: true,
type: 'string',
},
],
)
async searchForIssue(data: { filter: string }) {
const { filter } = data;
const query = `
query(searchTerm: String!) {
issues(filter: { description: { containsIgnoreCase: $searchTerm } }) {
nodes {
id
title
description
url
}
}
}
`;
const variables = {
searchTerm: filter,
}

const result = await graphQLClient.query({
query: query,
variables: variables,
});
return result;
}
  1. To use the function, create an AI agent and include the function as an option in calls to the agent.

The following example will call the searchForIssue function based on the provided prompt, and will search the descriptions of Linear issues for 'credit':

Backend code
const response = await this.squid
.ai()
.agent('AGENT_ID')
.ask('Which linear issues mention credit?', {
functions: ['searchForIssue'],
});

Performing queries on the fly

If you don't know what queries the client might need to run, you can allow an AI agent to run queries on your behalf. As a prompt, provide a description of the query to perform, and the AI agent can create the query that you then pass to the GraphQLClient.

  1. Provide your AI agent with the Linear GraphQL schema as context. In the Squid Console, navigate to your AI agent, and then upload the latest schema. You can download the schema from the Linear documentation.

  2. For instructions, inform the agent how it should interpret the client prompt.

The following example showcases one option for generating queries:

Using Linear's GraphQL API reference and the Squid GraphQLClient reference, generate the correct query to pass to the Squid GraphQLClient, and pass it to the callLinearAPI function. Always include `url` as a query parameter.

!! Important: Use Linear's GraphQL API reference as context.

!!Important: Do not pass issue IDs or other data points that aren't provided in the prompt.

When filtering with `contains`, always use `containsIgnoreCase`.

If querying for search terms in an issue, only search the description.

Example response format to pass to the function:

query {
issue(id: "DEV-184") {
id
title
description
url
}
}

Notice that these instructions include "!!Important" to highlight key points the agent needs to adhere to. It also specifies how the agent should produce the queries. For example, "If querying for search terms in an issue, only search the description." You can modify these instructions to suit your specific querying needs.

  1. In the Squid backend, create the AI function that will perform the query produced by the AI agent.

The following AI function takes the query from the AI agent as a parameter, and then performs the query using the GraphQLClient.

Backend code
@aiFunction(
'call this function when someone asks to query their Linear issues, including querying open issues, updates, cycles, etc.',
[
{
name: 'graphQLQuery',
description: 'The GraphQL query for the Linear GraphQL API',
required: true,
type: 'string',
},
],
)
async callLinearAPI(data: { graphQLQuery: string }) {
const { graphQLQuery } = data;
// Remove markdown
const query = graphQLQuery.replace(/```graphql|`/g, '');

const graphQLClient = new GraphQLClient(
this.squid,
'LINEAR_API_INTEGRATION_ID',
);

const result = await graphQLClient.query({
query: query,
});
}