Articles

Linear API: We Built a Triage Bot. Then We Stopped Maintaining It.

Ibby SyedIbby Syed, Founder, Cotera
8 min readMarch 8, 2026

Linear API: We Built a Triage Bot. Then We Stopped Maintaining It.

Linear API: We Built a Triage Bot. Then We Stopped Maintaining It.

Linear's GraphQL API is one of the best I've worked with. The schema is clean. The documentation is thorough. The webhook system is straightforward. Kenji, our lead backend engineer, called it "the API that makes you believe you can build anything on top of it." And he was right. We could build anything on top of it. The problem was keeping it alive.

This is the story of a triage bot that took three weeks to build, worked beautifully for two months, and then became the engineering equivalent of a houseplant nobody remembered to water.

Why We Built It

Our team had grown from eight to twenty-two engineers over about nine months. When we were eight, triage was simple. New issues came in. Kenji read them during his morning coffee. He set priority, assigned a team, added labels, and moved on. It took about fifteen minutes a day.

At twenty-two engineers, the issue volume tripled. Product managers filed bugs from customer calls. Support created tickets from Zendesk. QA logged issues from testing. Individual engineers filed improvement ideas. On an average day, we had between 15 and 25 new issues landing in the backlog. Kenji's fifteen-minute triage session turned into forty-five minutes, and things still fell through the cracks.

Priya suggested we build a triage bot. Linear had the API. We had the engineers. The rules seemed simple: read the title and description, guess the team, estimate priority based on keywords and reporter, apply labels, and drop the issue into the right team's triage queue.

Three Weeks of GraphQL

Kenji and Tomás paired on the bot. The first week was setup: authenticating with Linear's OAuth flow, subscribing to issue creation webhooks, and standing up a small service on our infrastructure. Linear's API made this easy. The webhook payload included the full issue object, so they didn't need to make follow-up queries for most use cases.

The second week was the triage logic. They wrote rules based on patterns we'd observed. If the issue title contained "crash," "500," or "timeout," it got high priority. If the reporter was from the support team, it went to the Platform team by default. If the description mentioned a specific product area (billing, onboarding, API), the bot assigned the corresponding team label. They built about forty rules covering the common cases.

The third week was edge cases and testing. What happens when an issue has no description? When the reporter is a new team member not in the routing table? When the title matches multiple team patterns? They added fallback logic, a default queue for ambiguous issues, and a Slack notification when the bot wasn't confident about its assignment.

The total effort was about 120 engineering hours across the two of them. The bot launched on a Monday. By Wednesday, Kenji said it was "handling maybe 70% of triage correctly." The remaining 30% hit the default queue, and he reviewed those manually. His triage time dropped from forty-five minutes to about fifteen. The project felt like a clear win.

The First Break

Six weeks after launch, Linear updated their webhook payload format. A field we depended on for team routing moved from a nested object to a flat reference. The bot started throwing null pointer errors at 2 AM. Tomás fixed it the next morning in about an hour.

Three weeks later, Linear added a new issue state that our bot didn't recognize. Issues in the new state weren't getting processed at all. They stacked up for two days before anyone noticed, because the bot didn't have monitoring for "issues it silently ignored."

A month after that, we reorganized our teams. Two teams merged, one split into three. The routing rules in the bot were hardcoded team IDs. Tomás spent a full afternoon updating them.

Each fix was small. An hour here, an afternoon there. But the fixes came on top of the feature work Tomás and Kenji were supposed to be doing. And the bot required someone who understood its internals to make changes. When Tomás went on vacation for two weeks, Kenji was the only person who could fix it. When they were both in a sprint crunch, the bot broke and stayed broken for four days. Nobody else on the team knew how to debug it.

The Maintenance Math

After six months, I sat down with Kenji and did the accounting. Building the bot: 120 hours. Maintenance over six months: roughly 40 hours. That's 160 hours of engineering time. At our internal cost rate, the bot was more expensive than hiring a part-time triage coordinator.

The time savings were real. Kenji's daily triage went from 45 minutes to 15 minutes. Over six months, that saved roughly 65 hours. But 160 hours invested to save 65 hours is not a good trade.

And those numbers didn't capture the worst cost: context switching. Every time the bot broke, it interrupted someone's sprint work. Tomás estimated that each fix cost him not just the fix time but about an hour of lost focus on whatever he'd been working on before the Slack alert pulled him away.

Kenji's summary was blunt: "We built a thing that's good enough to rely on and bad enough to break regularly. That's the worst possible combination."

What the API Is Actually Good For

I want to be clear: the Linear API is excellent. The problem wasn't the API. The problem was us deciding to build and maintain a custom integration on top of it.

The API is perfect for one-off scripts. Tomás wrote a script that bulk-closes stale issues older than 90 days. It runs manually when he wants to clean up. It's 40 lines of code, no webhook subscriptions, no state management, no maintenance. He's run it six times in the past year and it's worked every time.

Priya built a script that exports sprint data to a spreadsheet for quarterly planning. It queries completed issues by cycle, groups them by team, and calculates story point totals. She runs it at the end of each quarter. It took her two hours to write and has never needed updating because it reads data rather than reacting to events.

The pattern is clear. The API works well for pull-based operations: query data, process it, do something with the result. The maintenance burden shows up in push-based operations: listen for events, react in real time, keep the logic current as the team and the product evolve.

Replacing the Bot

We turned off the bot in month eight. Kenji wasn't sad about it.

What replaced it was an issue triage agent that reads new Linear issues and applies the same kind of logic our bot used, but without us maintaining the rules or the infrastructure. The agent understands team responsibilities from context rather than hardcoded routing tables. When we reorganized teams again, we didn't have to update anything. When Linear changes their data model, we don't get paged at 2 AM.

The agent handles about 80% of issues correctly on the first pass, which is better than our bot's 70%. More importantly, it's been running for four months with zero maintenance from our team. Tomás occasionally reviews the agent's triage decisions and provides feedback, but that takes about five minutes a week. Compare that to the 40 hours of maintenance over six months that the custom bot required.

When to Build, When Not To

If you're considering building on the Linear API, here's what I'd suggest based on our experience.

Build scripts, not services. A script that runs on demand, queries data, and produces output is low-maintenance. A service that subscribes to webhooks, maintains state, and reacts to events in real time is a maintenance commitment. Know which one you're signing up for.

Don't hardcode organizational knowledge. Our bot had team IDs, routing patterns, and priority rules baked into the code. Every organizational change required a code change. If your automation depends on knowing your team structure, that knowledge will go stale.

Monitor the silent failures. Our bot's worst failure mode wasn't crashing. It was silently skipping issues it didn't understand. If you build an integration, add monitoring for what it doesn't process, not just what it does.

Consider the total cost of ownership. The build cost is the fun part. The maintenance cost is the real price. Our 120-hour build turned into a 160-hour commitment, and it would have kept growing indefinitely.

The Linear API gives you the building blocks. Whether you should assemble them yourself depends on whether you want to maintain what you build. We learned that we didn't.


Try These Agents

For people who think busywork is boring

Build your first agent in minutes with no complex engineering, just typing out instructions.