4 min read

Project Management (Linear/Jira)

Stop manually creating tickets. Let the conversation become the ticket.

Dw

Dwizi Team

Editorial

Project Management (Linear/Jira)

Where does work actually happen?

Does it happen in Jira? Or does it happen in Slack/Discord/Teams?

For most teams, the work—the discussion, the debugging, the decision making—happens in chat. The record of the work lives in the Project Management tool (Linear, Jira, Asana).

The friction between these two worlds is where information is lost.

Engineer: "Hey, we should really fix that header alignment on mobile. It looks bad." PM: "Yeah, agreed." (3 days later) PM: "Did we fix the header?" Engineer: "Oh, I forgot to make a ticket. I'll do it now."

This is the Context Switch Tax. To make a ticket, you have to leave the conversation, open a new tab, wait for Jira to load, click "New Issue," type the title, type the description, assign it to a team... it's just enough friction that we often don't do it.

The Solution: Conversational Ticketing

What if the conversation was the ticket?

We can build a create_ticket tool. An Agent can listen to the chat (or be tagged in it). When it detects a commitment ("I'll fix that," "We should change this"), or when you explicitly ask it ("File a bug for this"), it handles the bureaucracy for you.

The Implementation

We will use the Linear API (GraphQL). Linear is perfect for this because it is fast and structured.

/**
 * Creates a new issue in Linear.
 * 
 * Description for LLM: "Create a ticket when a user reports a bug or requests a feature. Always infer the priority."
 */

type Input = {
  title: string;
  description: string;
  priority: "low" | "medium" | "high";
};

export default async function createLinearTicket(args: Input) {
  // 1. Auth
  // Stored in the Vault.
  const apiKey = Deno.env.get("LINEAR_API_KEY");
  if (!apiKey) throw new Error("Missing LINEAR_API_KEY");

  // 2. The GraphQL Mutation
  // We define the structure of the request.
  // Note that we hardcode the 'teamId'. 
  // In a more advanced version, the Agent could look up the Team ID based on the context.
  const query = `
    mutation IssueCreate($title: String!, $description: String!, $priority: Int) {
      issueCreate(input: {
        title: $title,
        description: $description,
        priority: $priority,
        teamId: "YOUR_TEAM_ID" 
      }) {
        success
        issue {
          identifier
          url
        }
      }
    }
  `;

  // 3. Logic Mapping
  // Linear uses integers for priority (0=No Priority, 1=Urgent).
  // The LLM thinks in words ("high", "medium").
  // We map the words to the numbers. This keeps the LLM interface clean.
  const priorityMap = { high: 1, medium: 2, low: 3 };

  const res = await fetch("https://api.linear.app/graphql", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "Authorization": apiKey
    },
    body: JSON.stringify({
      query,
      variables: {
        title: args.title,
        description: args.description,
        priority: priorityMap[args.priority]
      }
    })
  });

  const data = await res.json();
  const issue = data.data.issueCreate.issue;

  // 4. The Loop Close
  // We return the Identifier (ENG-123) and the URL.
  // This allows the Agent to post the link back into the chat.
  return { 
    success: true, 
    ticket: issue.identifier, // "ENG-123"
    url: issue.url 
  };
}

The Execution Story

User: "The login button is misaligned on mobile. It's blocking the signup flow. This is pretty urgent."

Agent Action:

  1. Extract: The Agent reads the message.
    • Title: "Login button misaligned on mobile"
    • Description: "It's blocking the signup flow."
    • Priority: The user said "urgent", so -> "high".
  2. Call: create_ticket({ title: "...", priority: "high" }).
  3. Execute: The tool hits Linear. Linear creates ENG-402.
  4. Reply: "I've filed ENG-402 [Link]. I marked it as High Priority because it blocks signup."

The Impact

The friction is gone. The "Copy-Paste Tax" was paid by the robot, not the human.

But more importantly, the mental load is gone. The engineer doesn't have to "remember to make a ticket." They just say it, and it exists. The conversation remains the single source of truth, but the system of record is automatically updated.

This is how we get back to coding.

Subscribe to Dwizi Blog

Get stories on the future of work, autonomous agents, and the infrastructure that powers them. No fluff.

We respect your inbox. Unsubscribe at any time.

Read Next

The Junior Dev (GitHub)

Automating the first 15 minutes of every bug report. How to build an agent that triages issues.

Read article