What Context Does Devin Actually Need to Fix a Customer-Reported Bug?
Beyond a ticket title, Devin needs four specific things before it can turn a customer bug report into a working fix. It needs the exact scope of what's broken, a reference to existing code that handles the same case correctly, links to any docs the fix depends on, and a measurable definition of done. That's not a guess about what a coding agent probably wants. It's what Cognition's own instructing guide tells you to put in the task.
The gap is that a customer bug report almost never arrives in that shape. It arrives as "the export button doesn't work anymore" in a support ticket, or a Slack message from someone on the customer success team relaying what a user said on a call. Someone has to turn that into the four things above before Devin can act on it, and that translation step is where most handoffs go wrong.
The four inputs, straight from Devin's docs
Cognition's guide to good vs. bad instructions makes the difference concrete with a paired example. The bad version is "Add a user stats endpoint." The good version is "Create a new endpoint /users/stats that returns a JSON object with user count and average signup age. Use our existing users table in PostgreSQL." Same request, and only one of them is executable.
Reading across both docs, the four inputs break down as:
- Domain and scope. Which repo, which service, which file. A bug report that says "the export is broken" could point at the frontend, the export worker, or the PDF library, and Devin will guess if you don't tell it.
- A pattern to follow. Point at code that already solves an adjacent version of the problem correctly, as in Cognition's own example, "Use
authTemplate.rsas a reference to maintain consistency in error handling." - Links to the docs it needs. If the fix touches a library's timezone handling or an API's request format, link the actual page. Devin reads it; you don't have to paraphrase it into the ticket.
- A measurable success criterion. Not "make sure it works," but something like the docs' own phrasing, "confirm the endpoint returns status 200 and includes all required fields." For a bug fix, that's usually a specific input that should now produce a specific output, plus the test that checks it.
None of these four live in a typical support ticket. They live in the codebase, in a docs site, and in whoever's head remembers that this exact class of bug got fixed correctly six months ago somewhere else in the app. Assembling them is a separate job from noticing the bug.
How Mateo Reyes rewrote a one-line ticket
A foreman at one of Coalfield's Growth-plan accounts filed a support ticket: shifts assigned to a job site in a different timezone than the crew's home base were showing the site's local time instead of converting to the viewer's. Coalfield builds workforce scheduling software for field service companies, and the ticket landed with Mateo Reyes, who leads the company's small platform team.
The first pass at a Devin task, written by whoever triaged the ticket, read:
Devin, timezones are messed up on the shift calendar. Can you take a look?
That's the bad example from Cognition's own docs, just with "timezone" swapped in for "user stats." Devin would have to guess which file owns the display logic, whether the bug is in storage or rendering, and what "fixed" even means, because the ticket doesn't say.
Mateo rewrote it after checking the support tool for prior tickets that sounded like the same issue, and the codebase for where shift times get formatted.
Fix the shift-time display bug reported by Coalfield (Growth plan, 40 seats). A shift assigned to a site in a different timezone than the crew's home site shows the site's local time instead of converting to the viewer's timezone. Two other Growth accounts described the same symptom in the last month (tickets #4471 and #4498), so this isn't isolated.
Scope:
apps/web/src/features/scheduling, specificallyShiftCard.tsxandshiftTimeFormatter.ts. Follow the conversion pattern already used intimesheetExport.ts, which handles the same cross-site case correctly. If you need the timezone reference,Intl.DateTimeFormat'stimeZoneoption is what the formatter should be using.Success: a shift in Phoenix assigned to a Denver-based viewer displays Denver local time on both the calendar view and the printed schedule PDF. Add a test in
shiftTimeFormatter.test.tscovering a cross-timezone case.
The rewrite adds scope, a pattern file, a docs link, and a testable definition of done on top of the same bug report. Devin opened a PR against the two files named, added the test, and the fix matched the pattern in timesheetExport.ts closely enough that review took Mateo ten minutes instead of a back-and-forth.
What Mateo's fifteen minutes doesn't survive
The rewrite above took Mateo about fifteen minutes, checking the support tool for duplicates, opening the repo, finding the comparable pattern, and writing the ticket. At Coalfield's current volume, that's fine. It stops being fine on two axes at once.
The first is volume. Once bug reports arrive daily across support tickets, Slack, and the occasional sales call, the fifteen-minute assembly step per bug turns into someone's whole afternoon, and it's exactly the kind of task that gets skipped when things are busy, which is when the thin tickets start reaching Devin again.
The second is memory. Mateo caught the two prior tickets because he happened to search for "timezone" in the support tool. That search only works if someone remembers to run it, and it only finds duplicates filed in the same tool. A bug mentioned on a sales call or in a different support channel doesn't show up in that search at all, so the "isolated report" framing in the ticket can be wrong without anyone noticing.
Devin's API supports feeding it accumulated context directly. A session created via POST /v3/organizations/{org_id}/sessions accepts knowledge_ids, letting a task pull in previously stored organizational knowledge instead of restating it every time. That's useful once the context exists. It doesn't solve where the context comes from in the first place, which is still the fifteen-minute search for duplicates and patterns above.
What an aggregation layer replaces
This is the point where an aggregation layer earns its keep. Modem reads Slack, support tickets, and sales call notes as they come in, clusters reports of the same bug into one topic with every account and plan that hit it attached, and keeps the thread of prior related reports so "two other Growth accounts described this" is something the system already knows, not something a human has to go find.
When a topic is ready to hand off, the Modem agent composes the brief from that context graph and delegates it to Devin directly. The scope still comes from someone pointing at the right files, the same craft Mateo used by hand. What Modem removes is the search itself. The affected accounts, the repro wording from each report, and the prior duplicate check are already assembled before the ticket gets written, so the fifteen-minute step per bug doesn't scale linearly with how many bugs show up. Modem is our product. Read that paragraph with this in mind, and see our guide to the best ways to hand customer-reported bugs to Devin for a more direct, side-by-side comparison.
The four inputs from Devin's own docs don't change either way. What changes is whether someone reconstructs them from scratch on every bug, or whether the reconstruction already happened by the time the ticket needs writing. The fuller pipeline, from first mention to merged PR, including the two gates worth keeping human, is covered in how to have your coding agent fix user-reported bugs.
Four questions before the next ticket goes out
Before the next customer bug goes to Devin, run through what Mateo did by hand:
- Which file or service actually owns this?
- What existing code already handles a similar case correctly?
- What doc does the fix depend on, and is it linked rather than paraphrased?
- What does "fixed" look like, stated so Devin can check it itself?
That's the whole difference between the two tickets Mateo wrote. It costs the same fifteen minutes either way, until something replaces the search.
