Hand server-side Duo turns off to Workhorse detached
What does this MR do and why?
A server-side Duo Agent Platform turn (Slack, note replies) runs in ServerSideTurnWorker. The job holds a Sidekiq thread for the whole turn, only to read the stream from POST /api/v4/ai/duo_workflows/workflows/:id/execute. !264218 (merged) lets Workhorse run the turn detached: it answers 202 once the run has started and keeps it going on its own. This MR is the Rails side, behind the new wip flag duo_workflow_detached_server_side_execution (actor: the workflow's user).
- Pre-authorization.
executetakes a newdetachedparameter. It returnsDetached: trueonly when the caller sentdetached=trueand the flag is on for the user. Workhorse reads only that field, so the flag decides, not the caller. - Worker. With the flag on, the worker sends
detached=true. On a202it returns without delivering. If pre-authorization didn't grant the detached run, Workhorse streams the turn and the worker runs the existing blocking path, so a flag change between the two checks is harmless. Errors before the202are reported as today. - Delivery. Finished, failed and stopped turns are already delivered by
CallbackWorkerfrom their events. A turn that pauses for the user (input_required) was only delivered inline by the worker:CallbackWorkercallson_input_required, which no adapter implements. It now delivers the answer for detached turns. The worker sets adetached_turnmarker in the callback context before the request (the turn can pause before Workhorse answers), andper_turn_resetclears it. It is also a session-state key, so a restarted or child session doesn't inherit it.CallbackWorkerdelivers only while the workflow is stillinput_required, so a late event can't post this turn's answer over the next one.
Why keep the job at all? Some callers of ExecuteRunService run in web requests: the Slack approval buttons (Slack expects an answer within 3 seconds), the MCP agent-session start and tool-approval resolution. Calling Workhorse from there would make Puma call itself through Workhorse and wait up to 10 seconds, with pre-authorization needing a second Puma thread meanwhile. The job now finishes in seconds instead.
With the flag off, nothing changes. The marker is never set, so CallbackWorker doesn't deliver on input_required.
Known limitations, tracked on the work item
- A
409or503before the202is reported to the user as a failure, as in the blocking mode. A Sidekiq job re-pushed while its first run is going would also see a409; retrying or ignoring it is a follow-up. - A detached run that ends while the workflow is still
running(deploy, stream error, the 55-minute limit) is caught by the stuck-workflow cleanup after about 30 minutes, which delivers a failure. The segment-end callback is the follow-up that fixes this. - The flag must stay off until the Workhorse MR is deployed and the Duo Workflow Service lists
WORKHORSE_RUN_LIMITas an infrastructure stop reason. All Sidekiq nodes must also run this code, since an olderCallbackWorkerdoesn't deliver detached answers.
References
- Work item: #634394
- Workhorse MR: !264218 (merged)
Screenshots or screen recordings
Not applicable: no UI change.
How to set up and validate locally
Needs Workhorse built from !264218 (merged).
- In the Rails console, enable the flag for your user:
Feature.enable(:duo_workflow_detached_server_side_execution, User.find_by_username('root')) - Start a server-side turn, for example by mentioning
@GitLabDuoin a note on a project with Duo Agent Platform enabled, or by messaging Duo in Slack. - In the Workhorse log, look for
duo workflow: detached run accepted. TheAi::Messaging::ServerSideTurnWorkerjob in the Sidekiq log finishes within seconds. - The answer is still posted, now by
Ai::Messaging::CallbackWorker. Reply to it to check that the next turn is answered too. - Disable the flag and repeat: the worker job now lasts for the whole turn, as before.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.