Agentic Workforce Challenge, Track 2 (security for agents acting for a user)
See what an agent did in Jira, then roll back only that
Every task an agent runs on a GurtOS box becomes a Jira issue with what it was asked, what it was allowed, its reasoning, every blocked attempt, its diff and its full action log. A Forge app adds a panel to the issue with Approve, Deny and Roll back, and Roll back removes only that task's changes on the box.
Proof BOX-2, a scripted agent that misread a rule, changed three configs instead of one and tried to send the repo to a paste site. It was blocked, approved from Jira, then rolled back from Jira: its configs came back and the README fix another task made a minute earlier stayed.
What Atlassian asked for
From Atlassian's Track 2 brief and the challenge rules, as copied into the project's track plan.
Audit and reversion: record every action with the inputs and reasoning behind it, so an admin can see exactly what happened the next morning and roll back only the changes that were wrong.
MetEach issue holds the prompt, the tools and hosts the task was allowed, the agent's reasoning in its own words, approvals and who gave them, blocked attempts, the diff and the last 40 log entries. Roll back this task takes out that task's layer of file changes on the box. Every other task keeps its own.
A Forge app for Jira or Confluence.
MetA Jira issue panel (UI Kit, native render) with a resolver in Atlassian's cloud, plus a
jira:entityPropertyindex so state, cost, blocked attempts and pending approvals are searchable in JQL. Installed on the demo site in production.Technical use of Forge.
MetThe resolver reads the issue property as the signed-in user, checks
EDIT_ISSUESbefore any action, and is the only place that holds the box's shared secret (a Forge encrypted variable). It calls one declared external host. Scopes are read-only: the app never writes to Jira; the box does.Usefulness to Atlassian users.
MetThe morning-after question is one JQL search:
project = BOX AND boxBlocked > 0. Agent work moves across a normal board (To Do, In Progress, In Review, Done), so a team reviews agents the way it reviews people.Demo video, 3 minutes at most.
PartlyShot list in the repo's
docs/videos.md; the video is embedded above once uploaded.Repo link.
MetThe track lives in
tracks/jira/(box side) andtracks/jira/forge/(the Forge app).
Screenshots






Open it yourself
- The track's code and READMEThe box side in
tracks/jira/, the Forge app intracks/jira/forge/. The Jira demo site itself is not public, so the screenshots above are from its BOX-1, BOX-2 and BOX-5 issues. - Docs: connect Jira
Evidence
The merge gate, ./demo, runs this track on every merge. With DEMO_LIVE=jira it runs against the real demo
site, then deletes the issues it made. This run passed on Oct 23 on the x86 test VM; BOX-8 and BOX-9 were real
issues on the site:
track jira
ok DEMO_LIVE=jira: the vault has the Jira site, email and API token
ok BOX-8: task A is an issue in Done, with its diff
ok BOX-9: task B waits for an OK, in In Review
ok BOX-9 holds B's prompt, steps and diff
ok BOX-9 has a comment for the blocked attempt on attacker.example
ok BOX-9 has a comment asking for the OK
ok without the shared secret the panel routes refuse to approve or roll back (401)
ok an approval can't be answered through another task's issue
ok approved from Jira, task B finished
ok rolled back from Jira: B's settings change is gone, A's fix stays
ok the panel's audit view shows the block, who approved and the roll back
ok BOX-9 says who rolled it back, in a comment and the description
ok no vault secret is in anything the box sent to Jira
The same 12 checks pass offline in every ./demo run, the latest on Oct 24 with all 22 sections of the gate
(175 checks, 0 failed).
How it works
- TaskAn agent worksIts own Linux user, its own copy of the files, no keys.
- GurtOS coreThe action logEvery step, tool call, approval and blocked host, in order.
- GurtOS coreJira track (log reader)Creates or updates one issue per task over Jira REST v3.
- OutsideJira issue and Forge panelThe resolver checks the user may edit the issue.
- YouApprove, Deny or Roll backThe resolver calls the box with the shared secret.
- GurtOS coreThe box actsSame undo and answer as the portal and phone, logged as jira:<name>.
- Task
- its own Linux user, its own copy of the files, no keys
- GurtOS core
- the GurtOS service on the box, root, the only part that reads the vault
- Outside
- a service outside the box
- You
- a person, on the portal, a phone, Jira or a chat
Into Jira. The box feeds the track every event in its append-only log, in order, and saves its place, so it survives restarts and power cuts. Agent output only ever goes into Atlassian Document Format text nodes, so a task cannot inject markup, links or mentions into Jira. Status follows the task: queued is To Do, running is In Progress, waiting for an OK is In Review, and done, failed or rolled back is Done. It is safe to repeat: a crash between creating an issue and saving its key finds the issue by label instead of making a second one.
Out of Jira. The panel's resolver runs in Atlassian's cloud. It reads the issue's box.task property as the
signed-in user (so the task id comes from Jira, never from the browser), asks Jira whether that user may edit the
issue, and only then calls the box with the shared secret, passing the user's name for the log. The box checks the
secret in constant time and checks that the approval belongs to that task. From the internet, the box forwards
only its Jira routes and one read-only status route; the rest of its API is a 404.
| Forge or Atlassian piece | Used for |
|---|---|
jira:issuePanel (UI Kit, native render) |
The Box agent task panel on BOX issues |
@forge/resolver |
load, answer, rollback |
jira:entityProperty |
JQL fields boxState, boxCost, boxBlocked, boxPending, boxSource |
api.asUser().requestJira |
Reads the property, the user's permissions and name, with the user's own access |
fetch with permissions.external.fetch.backend |
The one call out, to the box |
Encrypted variable BOX_SECRET |
The shared secret |
| Jira REST v3, from the box | issue, properties, transitions, comment, search/jql |
Try it
- Put
ATLASSIAN_SITE,ATLASSIAN_EMAIL,ATLASSIAN_API_TOKENandJIRA_BOX_SECRETin the box's vault,/etc/box/vault.env. - Turn syncing on:
echo '{"project":"BOX"}' > /var/lib/box/jira/config.json. - Give the box public HTTPS for
/t/jira/*only (the README has the Caddy block). - From
tracks/jira/forge/:forge variables set --encrypt BOX_SECRET <secret>,forge deploy,forge install. - Start any task on the box. Its issue appears in
BOX; open the panel and try Approve and Roll back.
The full steps are in the track README and the docs guide Connect Jira.
Live, test and simulated
| Part | State | Details |
|---|---|---|
| Jira issues, comments, status and JQL fields | Live | Written by the box to the demo site's BOX project. DEMO_LIVE=jira ./demo runs the whole flow against the real site. |
| Forge panel and resolver | Live | Installed in production on the demo site. |
| The agents behind the issues | Live | BOX-1 and BOX-5 are real Droid tasks running Claude. BOX-2 is a scripted agent, so the misread rule happens the same way every time. |
| Money | Test money | The coffee order uses the example track's example.spend, which moves no money. |
| Offline merge gate | Simulated | ./demo points the track at a stand-in for Jira Cloud on the test machine, so every merge runs it without touching the real site. |
Limits
- Roll back undoes the task's file changes. It cannot recall something a task already sent out through a tool, such as a payment. Those show in the issue so a person can follow up.
- One shared secret guards the box's three Jira routes. Forge Remote's signed invocation tokens would let the box check each call came from this app and this user; that is the next step.
- The box writes to Jira with one person's API token, so its comments show that person as the author.
- The panel polls the box every 4 seconds while it is open.
- Issue descriptions keep the last 40 log entries and the first 8,000 characters of the diff. The panel and the box's log have the rest.