Duo Agent Platform Service
- Service Overview
- Alerts: https://alerts.gitlab.net/#/alerts?filter=%7Btype%3D%22duo-agent-platform%22%2C%20tier%3D%22sv%22%7D
- Label: gitlab-com/gl-infra/production~“Service::DuoAgentPlatform”
Summary
Section titled “Summary”duo-agent-platform serves two purposes:
- Incident reporting umbrella. It is used in incident.io so that all incidents affecting Duo Agent Platform in any way are properly tagged and recorded, regardless of which underlying component failed.
- Monitored virtual service. It carries the SLIs for the GitLab monolith side of the Duo Agent Platform — signals emitted by Workhorse, and in future Rails and Sidekiq. It has no infrastructure of its own.
Note the asymmetry: the incident.io umbrella is broader than the error budget. An incident tagged
Service::DuoAgentPlatform may originate in gitlab-lsp or duo-workflow-svc, which are not
covered by this service’s SLIs.
Duo Agent Platform spans multiple components, each with its own observability surface:
- gitlab-lsp — Language Server Protocol client running in the IDE and in CI jobs
- GitLab (Rails) — handles API requests, authorization, orchestration, and checkpoint storage
- GitLab (Workhorse) — proxies WebSocket connections to the Duo Workflow Service
- Duo Workflow Service — the gRPC backend that executes workflows (https://gitlab.com/gitlab-org/modelops/applied-ml/code-suggestions/ai-assist), monitored separately as
duo-workflow-svc
Relationship to duo-workflow-svc
Section titled “Relationship to duo-workflow-svc”| Service | Covers | Emitted by | Mimir tenant |
|---|---|---|---|
duo-workflow-svc | The Duo Workflow Service itself (gRPC server, LLM calls, tool use, checkpoints) | Cloud Run / Runway | runway |
duo-agent-platform | The GitLab monolith side (Workhorse WebSocket handler; Rails/Sidekiq signals in future) | ai-assisted fleet, sidekiq, web | gitlab-gprd, gitlab-gstg |
The split is not cosmetic. The two halves are scraped into different, isolated Mimir tenants;
a recording rule evaluated in the runway tenant cannot read monolith series, and vice versa —
see mimir-rules-jsonnet/README.md.
Tenant selection is per-service (tenants: in the service definition), not per-SLI, so
monolith-emitted Duo Agent Platform SLIs need their own service definition.
Monitoring/Alerting
Section titled “Monitoring/Alerting”| SLI | Request rate | Error rate | Emitted by |
|---|---|---|---|
workhorse_dws_connections | gitlab_workhorse_duo_workflow_connections_total | gitlab_workhorse_duo_workflow_connection_errors_total | ai-assisted |
workhorse_dws_sessions | gitlab_workhorse_duo_workflow_sessions_total | gitlab_workhorse_duo_workflow_session_errors_total | ai-assisted |
Workhorse metrics
Section titled “Workhorse metrics”Workhorse exposes six Prometheus counters and one histogram for the duoworkflow package,
declared in
workhorse/internal/ai_assist/duoworkflow/metrics.go.
See the duoworkflow package README
for full documentation including example PromQL queries. The four connection/session counters back
the SLIs above; the three http_action metrics are not yet covered by an SLI.
They are emitted by the Workhorse process on the ai-assisted fleet. The Duo Agent Platform
WebSocket handler is registered on the /api/v4/ai/duo_workflows/ws route (duo_workflow_ws in
workhorse/internal/upstream/routes.go), which is an API-pattern route in Workhorse’s own routing
table — but HAProxy routes the request to ai-assisted, so that is the fleet whose counters move.
Hence the type="ai-assisted" selector and emittedBy: ['ai-assisted'] in the service definition.
On that fleet the scrape job is plain gitlab-workhorse, not a fleet-suffixed variant like
gitlab-workhorse-api.
Do not infer the fleet from the route table. These counters are package-level promauto
counters registered at process init, so every Workhorse fleet exports all four of them with a
permanent value of 0. Selecting the wrong type therefore produces a recorded series that reads
0 rather than returning no data, which is indistinguishable from a genuinely idle feature.
Confirm the fleet empirically:
sum by (type) (increase(gitlab_workhorse_duo_workflow_sessions_total{env="gprd"}[24h]))Alerts
Section titled “Alerts”| Alert | SLI | Type |
|---|---|---|
DuoAgentPlatformServiceWorkhorseDwsConnectionsErrorSLOViolation | workhorse_dws_connections | Error |
DuoAgentPlatformServiceWorkhorseDwsSessionsErrorSLOViolation | workhorse_dws_sessions | Error |
Traffic cessation and traffic absent alerts are intentionally disabled
(trafficCessationAlertConfig: false) on both SLIs. Duo Agent Platform WebSocket traffic can
legitimately fall to zero when the feature is idle, and these SLIs have no established baseline
ops rate yet — see Known gaps. Enable them once real volume is visible.
Troubleshooting
Section titled “Troubleshooting”Because this is a virtual service, triage usually means following the signal to the component that emits it:
- Check the service overview dashboard to see which SLI is degraded.
workhorse_dws_connectionserrors are Workhorse-local — WebSocket upgrade failures, runner initialisation failures, or runner execution failures. Theerror_typelabel distinguishesquota_exceededandlocked(both expected under load / contention) fromother(needs investigation). Follow the ai-assisted service runbook if the wholeai-assistedfleet is unhealthy.workhorse_dws_sessionserrors are failures on the gRPCExecuteWorkflowstream between Workhorse and the Duo Workflow Service. Thegrpc_codelabel points at the cause:ResourceExhaustedandDeadlineExceededusually indicate DWS-side pressure,Unavailablea connectivity or deployment issue. Cross-checkduo-workflow-svcbefore suspecting the monolith —duo-workflow-svcis a declared dependency, so its alerts may already explain the failure.
Known gaps
Section titled “Known gaps”- No observed baseline. These SLIs have never recorded real data. They first lived on
duo-workflow-svc, selectingtype="duo-workflow-svc"in therunwaytenant, where neither the tenant nor thetypelabel ever matched. Moving them here fixed the tenant but selectedtype="api", which recorded a flat zero. Only the correction totype="ai-assisted"produces real numbers, and recording rules do not backfill — expect an empty history before that change was deployed. TheerrorRatio: 0.95thresholds have been carried through all three revisions unchanged and have never been checked against observed data. gitlab_duo_workflow_stuck_workflows_cleaned_total(emitted byAi::DuoWorkflows::FailStuckWorkflowsWorkeron Sidekiq) belongs in this service but has no denominator metric today — there is no sessions-created counter. Tracked as a follow-up.- The broader Rails-side instrumentation gap is catalogued in
GitLab Duo Agent Platform observability (Rails),
which lists ~14 planned
gitlab_duo_agent_platform_*metrics. Those should land here as they ship.