-
-
The matching decision and the real blocker, on the issue, with no prompt
-
Every Jira and Confluence call runs as the signed-in user
-
One click on the citation opens the page with the same words
-
The Recall agent quotes the decision and its reason, and links to the page
-
When a page gives no reason, the agent says so
-
This issue blocks one ticket and is blocked by another. The agent names the right one.
Inspiration
This year's challenge describes context as knowing "what's already been decided". On many teams that knowledge exists but sits in the wrong place. A developer picks up a ticket without seeing the Confluence page that settled how it should be built, so they either build without it or make the decision again. Recall was built to close that gap: the decision should come to the work, without anyone having to search for it.
What it does
An issue panel in Jira. With no prompt, the panel shows:
- the recorded decision that matches the issue, with a link and its first sentence
- what is really blocking the issue
- other connected work
A Recall agent in Rovo. Ask in plain language:
- "Has the team already decided how webhook retries should work, and why?" The agent searches Confluence, reads the page, quotes its decision and reason, and links to it, so the answer can be checked in one click.
- "What is blocking this issue right now?" The agent reads the issue's links in the right direction. An issue this one blocks is not reported as a blocker.
- "Why did the team move invoice exports to a nightly batch?" That page records no reason, so the agent says so instead of offering one.
How it's built
Recall is a Forge app on the Node.js 24 runtime, with these modules:
- a
rovo:agentwith twoactionmodules,find-decisionsandissue-context - a
jira:issuePanelbuilt with UI Kit, using a resolver
find-decisions runs a CQL search, then reads up to three matching pages through the Confluence REST API. Search excerpts are only a few words, so the page text is what lets the agent state the real decision. issue-context reads the issue's status, assignee and links from the Jira REST API, and sorts its links by direction.
Every Jira and Confluence call uses api.asUser(), so requests run with the signed-in person's permissions. Recall stores no data and declares no outside services.
The pure logic (page text extraction, CQL building, link classification, choosing the decision line) lives in its own module, covered by 13 unit tests that run with node --test.
Challenges
- Keeping answers honest. In early testing the agent had only page titles and short excerpts, and one answer included a reason the page never gave. The fix had three parts: read the actual page text, instruct the agent to quote the page's sentences word for word, and test it with a page that has no reason on it.
- Permissions. A search made with the app's identity returned nothing, while the same search as the user found the page. Moving every call to
asUser()fixed that, and also means Recall works within each person's existing access. - Link direction. A first version matched the word "block" and so counted "blocks" as a blocker. Direction-aware classification and regression tests fixed it.
Accomplishments
- The panel surfaces a decision with no prompt, right beside the work.
- Answers quote the page and link to it, so a reader can check them.
- On a ticket that both blocks one issue and is blocked by another, the agent named only the real blocker in the recorded tests.
- Forge logs confirmed the actions ran during testing, rather than the model answering from memory.
What we learned
Trust in an agent comes from being able to check it. Instructions make a language model far more careful, but they aren't a guarantee, so the citation matters as much as the answer. A test page with nothing to find also reveals more than a page with a good answer on it.
What's next
- Better matching. The panel currently looks for pages with "decision" in the title that contain the issue's most distinctive words.
- Support for decisions recorded in Jira comments and other linked work.
- Testing the declared
rovo:mcpmodule, so the same tools can reach other agents.