Flows API
- Tier: Premium, Ultimate
- Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
Use this API to create and manage flows in the GitLab Duo Agent Platform. Flows are combinations of AI agents that work together to complete developer tasks, such as fixing bugs, writing code, or resolving vulnerabilities.
Trigger a flow
The requirement for a composite identity service account is controlled by a feature flag.
The availability of the callback_hook_id and client_reference attributes is controlled by a
separate feature flag. For more information, see the history.
Triggers and starts a new flow.
Prerequisites:
- If the
enforce_composite_identity_for_api_started_workflowsfeature flag is enabled andstart_workflowistrue, the flow must have a composite identity service account. The service account is either configured for the flow in the AI Catalog, or is the service account behind the request’s composite identity. Otherwise, GitLab returns403 Forbiddenand does not start the flow.
POST /ai/duo_workflows/workflowsSupported attributes:
If successful, returns 201 Created and the following response
attributes:
| Attribute | Type | Description |
|---|---|---|
agent_privileges | integer array | Privilege IDs assigned to the agent. |
agent_privileges_names | string array | Names corresponding to agent_privileges. |
ai_catalog_item_version_id | integer | ID of the AI Catalog item version. null if not set. |
allow_agent_to_request_user | boolean | When true, the agent may pause for user input. |
environment | string | Execution environment. null if not set. |
gitlab_url | string | Base URL of the GitLab instance. |
id | integer | ID of the flow. |
image | string | Container image for CI pipeline execution. null if not set. |
mcp_enabled | boolean | Whether MCP (Model Context Protocol) tools are enabled for this flow. |
namespace_id | integer | ID of the associated namespace. null if not set. |
pre_approved_agent_privileges | integer array | Privilege IDs the agent can use without asking for approval. |
pre_approved_agent_privileges_names | string array | Names corresponding to pre_approved_agent_privileges. |
project_id | integer | ID of the associated project. null if not set. |
status | string | Current flow status. One of created, running, paused, finished, failed, stopped, input_required, plan_approval_required, tool_call_approval_required, or idle. GitLab might add new values. |
summary | string | Short text summary of the workflow. |
title | string | Title of the session. |
web_url | string | URL of the session in the GitLab UI. null if the session is not for a project. |
workflow_definition | string | Flow type identifier. |
workload | object | Information about the workload. |
workload.id | integer | ID of the workload. null if no workload was created, for example when start_workflow is not true. |
workload.message | string | Status message for the workload. null if no workload was created. |
If the user must complete identity verification before they can use
GitLab Duo Agent Platform, GitLab returns 403 Forbidden with a
message:
{
"message": "403 Forbidden - Identity verification is required to use GitLab Duo Agent Platform"
}GitLab returns 400 Bad request when callback_hook_id
is set and either of the following is true:
- The
duo_flow_callback_hooksfeature flag is not enabled for the top-level group of the project or namespace the flow runs in. - The ID does not reference a webhook that has GitLab Duo flow callbacks turned on in the project or namespace the flow runs in, or in one of its ancestor groups.
Look up the consumer ID
Before you can use ai_catalog_item_consumer_id, you must use the GraphQL API to retrieve the ID from the AI Catalog.
The item must already be enabled for the project.
query {
aiCatalogConfiguredItems(projectId: "gid://gitlab/Project/<project_id>") {
nodes {
id
item { name }
}
}
}The id field is a Global ID in the format gid://gitlab/AiCatalogItemConsumer/<numeric_id>.
Use the numeric suffix as the ai_catalog_item_consumer_id value.
Example request using a built-in flow type:
curl --request POST \
--header "PRIVATE-TOKEN: <your_access_token>" \
--header "Content-Type: application/json" \
--data '{
"project_id": "5",
"goal": "Fix the failing pipeline by correcting the syntax error in .gitlab-ci.yml",
"workflow_definition": "developer/v1",
"start_workflow": true
}' \
--url "https://gitlab.example.com/api/v4/ai/duo_workflows/workflows"Example request using a catalog-configured flow:
curl --request POST \
--header "PRIVATE-TOKEN: <your_access_token>" \
--header "Content-Type: application/json" \
--data '{
"project_id": "5",
"goal": "Fix the failing pipeline by correcting the syntax error in .gitlab-ci.yml",
"ai_catalog_item_consumer_id": 12,
"start_workflow": true
}' \
--url "https://gitlab.example.com/api/v4/ai/duo_workflows/workflows"Example response:
{
"id": 1,
"web_url": "https://gitlab.example.com/group/project/-/automate/agent-sessions/1",
"project_id": 5,
"namespace_id": null,
"agent_privileges": [1, 2, 3, 4, 5, 6],
"agent_privileges_names": [
"read_write_files",
"read_only_gitlab",
"read_write_gitlab",
"run_commands",
"use_git",
"run_mcp_tools"
],
"pre_approved_agent_privileges": [],
"pre_approved_agent_privileges_names": [],
"workflow_definition": "developer/v1",
"status": "running",
"allow_agent_to_request_user": true,
"image": null,
"environment": null,
"ai_catalog_item_version_id": null,
"workload": {
"id": "abc-123",
"message": "Workflow started"
},
"mcp_enabled": false,
"gitlab_url": "https://gitlab.example.com"
}Restart a flow
- Status: Experiment
Restarts a failed or stopped flow by starting a new flow with the same flow parameters. The new flow runs
from the beginning. The original flow is not modified and keeps its failed or stopped status.
Only project-level flows with a failed or stopped status can be restarted. Restarting a
flow with any other status, or a group-level flow, returns 403 Forbidden. Restarting the same flow again while a restart is still
in progress returns 409 Conflict.
POST /ai/duo_workflows/workflows/:workflow_id/restartSupported attributes:
| Attribute | Type | Required | Description |
|---|---|---|---|
workflow_id | integer | Yes | ID of the flow to restart. |
If successful, returns 201 Created and the same response
attributes as Trigger a flow. The response describes the new flow, so id is
the ID of the new flow rather than the one you restarted.
Example request:
curl --request POST \
--header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/ai/duo_workflows/workflows/42/restart"Get workflow trace as JSONL
- Status: Experiment
Returns the ui_chat_log entries of a workflow session
as JSON Lines (JSONL).
Each line is a valid JSON object representing one entry from the ui_chat_log array.
Use this endpoint to parse or pipe the trace into tools like jq.
By default, the endpoint returns the complete conversation across all threads of the session,
including messages from before any context compaction.
Use the thread attribute to return a single thread instead.
GET /ai/duo_workflows/workflows/:workflow_id/trace.jsonlSupported attributes:
| Attribute | Type | Required | Description |
|---|---|---|---|
workflow_id | integer | Yes | ID of the workflow. |
thread | string | No | Which thread to return. Omit for the full trace across all threads. Use latest for the most recent thread only, or a thread ID for a specific thread. |
If successful, returns 200 OK with:
- Content-Type:
application/x-ndjson - Body: One JSON object per line, each representing a
ui_chat_logentry. Returns an empty body if the workflow has no checkpoints or noui_chat_logentries.
If the user must complete identity verification before they can use
GitLab Duo Agent Platform, GitLab returns 403 Forbidden with a
message:
{
"message": "403 Forbidden - Identity verification is required to use GitLab Duo Agent Platform"
}Example request:
curl --request GET \
--header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/ai/duo_workflows/workflows/1/trace.jsonl"Example response (each line is a separate JSON object):
{"status":"success","content":"Analyze the issue","message_type":"human"}
{"status":"success","content":"I'll start by reading the codebase.","message_type":"ai"}You can pipe the output into jq to filter entries by type:
curl --request GET \
--header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/ai/duo_workflows/workflows/1/trace.jsonl" \
| jq 'select(.message_type == "ai")'List all agent privileges
Lists all available agent privileges with their IDs, names, descriptions, and whether each is enabled by default.
GET /ai/duo_workflows/workflows/agent_privilegesThis endpoint has no supported attributes.
If successful, returns 200 OK and the following response
attributes:
Example request:
curl --request GET \
--header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/ai/duo_workflows/workflows/agent_privileges"Example response:
{
"all_privileges": [
{
"id": 1,
"name": "read_write_files",
"description": "Allow local filesystem read/write access",
"default_enabled": true
},
{
"id": 2,
"name": "read_only_gitlab",
"description": "Allow read only access to GitLab APIs",
"default_enabled": true
},
{
"id": 3,
"name": "read_write_gitlab",
"description": "Allow write access to GitLab APIs",
"default_enabled": true
},
{
"id": 4,
"name": "run_commands",
"description": "Allow running any commands",
"default_enabled": true
},
{
"id": 5,
"name": "use_git",
"description": "Allow git commits, push and other git commands",
"default_enabled": true
},
{
"id": 6,
"name": "run_mcp_tools",
"description": "Allow running MCP tools",
"default_enabled": true
}
]
}