I Tried Atlassian's Teamwork Graph
A ticket landed this morning with three sentences of description: a financial ledger was writing one of its rows under the wrong account. No design doc, no linked context, just a hunch from whoever filed it. Most of my day, on tickets like this, isn’t spent writing the fix. It’s spent figuring out whether the hunch is right, and whether I’m the first person to notice.
This time I decided to run the whole investigation through
Atlassian’s Teamwork Graph, which is sold as an enterprise
context graph: it maps people, content and relationships across Jira, Confluence, code
hosting and the rest. I reached it two ways. One is twg, a command line interface built for
coding agents, which fronts semantic search, document search, and grep across every
repository my org owns. The other is the part I actually wanted to test, a literal
graph-traversal call: hand it one item, get back the things connected to it. I’d been
half-trusting all of it for weeks. I wanted an honest answer, on real work, to the question
the product’s own name asks. Is this actually a graph, or is that just what search tools call
themselves now?
What I understood going in
What I’d picked up from a few weeks of light use was that Teamwork Graph gives me two very different ways to ask the same question. What else connects to this ticket?
One is search: semantic search across tickets and wikis (rovo search), full-text search
across our internal docs (docs search), and grep across every repository in the org
(search-code). The other is the traversal call, getTeamworkGraphContext, which takes one
ticket, walks the relationships somebody actually declared (links, mentions, edits), and
hands back a small graph of what is connected to it.
Search finds things by meaning. Traversal finds things by citation. I’d been treating them as the same capability wearing different clothes. Today is when I stopped.
The ledger row filed under the wrong account
Before I touched the code, two things needed answering. Was this a real, agreed-on bug, or was I about to misread a system I only partly understood? And was anyone quietly depending on the current, wrong behavior?
I ran rovo search for the ticket’s own language, expecting a handful of loosely related
issues. What came back instead were two investigation pages, written for two other tickets,
that independently described this exact defect while scoping unrelated work. Neither page
linked back to my ticket. Nobody had connected them. The connection only existed in what the
pages said, in words, not in how anything was filed. I hadn’t found corroborating evidence.
I’d found two colleagues who’d already done half my investigation for me, months apart,
without knowing about each other.
rovo search call — five connected items, none linked from my ticketThen, mostly out of stubbornness, I asked the traversal call the same question about the same ticket. Not search this time. The feature the product is named for.
getTeamworkGraphContext — three people, no documentsThree edges, all people: who’d edited the ticket, who’d viewed it, who’d reported it. Nothing pointing at either document, because there was never a link to walk. The graph tool wasn’t wrong. It traversed exactly the graph that existed. That graph just wasn’t the one I needed.
How the ledger bug ended
The fix came to six lines: read the party’s own id when it’s there, and fall back to the id that was already being written when it isn’t, logging loudly when that happens so a missing upstream field can’t hide again. A fallback, not a migration.
The historical rows already filed under the wrong id I left alone, on purpose. Those two investigation pages were exactly what let me do that with a clear conscience. Whether to re-file history turned out to be an open question someone else already owned, not something to settle quietly inside a bugfix.
Not a clever change. A boring one, arrived at faster and with more confidence than usual.
The field that already had the wrong name
A second ticket, later the same day, asked for a currency conversion in a place it currently wasn’t happening. No design doc again. The risk with a ticket like that isn’t the code, it’s scoping it wrong before you’ve written a line.
A keyword search across our internal docs (docs search, not the graph) turned up a
finance-authored reference page nobody had linked from the ticket. It defined a field with a
name almost identical to the one I was about to introduce, computed differently, and the page
already carried a note from finance flagging that the two numbers disagreed. I hadn’t just
avoided a naming collision three weeks from now in review. I’d learned the collision already
had a paper trail I wasn’t looped into. Renaming around it became step one of my plan instead
of a surprise.
A search-code pass across every repo in the org, not just the one I was sitting in,
confirmed the field genuinely hadn’t landed anywhere yet, which is what let me say the
collision was still avoidable rather than something to untangle after the fact.
Whether that finance page counts as something “the graph” found is exactly the question this whole day kept asking me. Nothing pointed at it. No one had declared a relationship for anything to traverse. Meaning found it; citation never would have.
A third ticket the same day taught me something smaller. Our main issue-tracker integration
lost its authentication mid-session, through no fault of twg, and I’d have expected to sit
and wait. Instead twg turned out to also expose a thin authenticated REST client to the
same tracker, so I posted my update through that. Same payload, same destination, a different
pipe. Not a research win, but a useful thing to learn about a tool on the day its neighbour
goes down. It is an integration layer as much as a research one, and I hadn’t priced that in
going into today.
The habit I didn’t plan to form
By the third ticket I noticed I’d fallen into a rhythm without deciding to. Ask the search first, in plain language. Then ask the graph the exact same thing, about the exact same item, before moving on. Put the two answers next to each other. Believe whichever one told me something I didn’t already know.
Ask the search. Ask the graph the same thing. Believe whichever one surprised me.
I hadn’t set out to design a test. It just turned out to be the only honest way I could tell, on my own tickets, what the word “graph” in the product’s name was buying me. The one time I ran both against the same ticket, the gap was not close: search came back with five things I needed, and traversal came back with three names, correct and useless for the question I had. Everything else that helped me that day, the finance page included, was found by meaning too.
I’ll almost certainly do the same two-question thing to the next tool that arrives with a confident name. Today it was the difference between believing a product and knowing what it does.
Where it bit me
I lost a stretch of the afternoon guessing that confluence page get existed. It doesn’t.
The command is confluence content get, and only --help told me so. I lost more time to
search-code, which quietly parsed my query as a subcommand name because I’d left off the
verb, then failed with an “unknown command” that pointed at nothing. And I’m glad I ran the
traversal call once on a ticket I already understood, before I leaned on it for one I didn’t.
It is the only reason I knew what “connected” meant to
this tool before it mattered.
Small things, and every one of them a one-time cost.
Would I use it again
Yes. Teamwork Graph stays in my toolbox, routed through search first. The most graph-shaped result I got all day came out of a search box, and the feature actually named “graph” returned three names. That’s not a small caveat for a product with that name. But it’s also the most useful thing I learned today, and I only learned it by asking the same question twice.