Skip to main content

flows

GitLab Duo Agent Platform - Flows

Overview

Flows are YAML-defined workflows that orchestrate AI agents to complete complex, multi-step tasks automatically. They represent the automation layer of the GitLab Duo Agent Platform, combining triggers, agents, and actions into cohesive workflows.

Introduced: GitLab 18.3 (Custom Flows) Execution: GitLab CI/CD (when triggered from UI) or inline (when triggered from IDE) Definition Format: YAML

What is a Flow?

A flow defines:

  1. Workflow Steps: Sequence of actions to perform
  2. Agent Orchestration: Which agents perform which steps
  3. Data Passing: How context flows between steps
  4. Conditional Logic: When to execute certain steps
  5. Error Handling: What to do when steps fail
  6. Output: What results are produced

Flow Lifecycle

TRIGGER  INITIALIZE  EXECUTE  COMPLETE

Detailed:
1. Trigger Event (mention, assign, schedule, etc.)
   
2. Flow Definition Loaded
   
3. Service Account Validated
   
4. Context Gathered (Knowledge Graph, MR data, etc.)
   
5. Step 1 Executed
   
6. Step 2 Executed (with context from Step 1)
   
7. ... (continue for all steps)
   
8. Results Aggregated
   
9. Session Logged
   
10. Notifications Sent (if configured)

Flow Types

1. Foundational Flows (Pre-built by GitLab)

Production-ready flows created by GitLab for common workflows.

Code Review Flow

Purpose: Automates code review with contextual analysis

Capabilities:

  • Analyzes code changes in merge requests
  • Reviews MR comments and linked issues
  • Understands repository structure via Knowledge Graph
  • Identifies cross-file dependencies
  • Provides actionable feedback with inline comments

Usage:

# In MR comment:
"@duo-developer please review this change"

# Or assign as reviewer in MR

What it does:

1. Loads MR diff and context
2. Queries Knowledge Graph for related code
3. Analyzes changes for:
   - Code quality issues
   - Potential bugs
   - Performance concerns
   - Security vulnerabilities
   - Style violations
4. Checks test coverage
5. Reviews documentation updates
6. Posts detailed review comments
7. Suggests improvements

Software Development Flow

Purpose: End-to-end development task automation

Capabilities:

  • Creates code from requirements
  • Writes tests automatically
  • Updates documentation
  • Creates merge requests
  • Manages full development lifecycle

Usage:

# In issue:
"@duo-developer implement this feature"

What it does:

1. Analyzes feature requirements from issue
2. Queries Knowledge Graph for existing patterns
3. Generates implementation code
4. Creates unit tests
5. Creates integration tests
6. Updates API documentation
7. Creates MR with all changes
8. Links MR back to issue

Security Triage Flow

Purpose: Automated vulnerability assessment and prioritization

Capabilities:

  • Scans security findings
  • Assesses exploitability
  • Evaluates business impact
  • Prioritizes remediation
  • Generates reports

Usage:

# Automatically triggered when security scan completes
# Or manually: @security-analyst in vulnerability issue

What it does:

1. Retrieves security scan results
2. Analyzes each vulnerability:
   - CVSS score
   - EPSS probability
   - Reachability analysis
   - Business context
3. Prioritizes by risk
4. Creates remediation tasks
5. Assigns to appropriate teams
6. Generates executive summary

2. Custom Flows (User-defined)

Teams create custom flows for specific processes.

Flow Definition Structure

Basic Flow

name: flow-name description: Human-readable description of what this flow does version: 1.0.0 trigger: event: mention | assign | assign_reviewer | schedule service_account: ai-<flow-name>-<group> flow: agents: - agent_name_1 - agent_name_2 steps: - name: step_1 agent: agent_name_1 action: action_name - name: step_2 agent: agent_name_2 action: action_name

Complete Flow Example

name: automated-dependency-update description: | Automatically detects outdated dependencies, checks for security vulnerabilities, updates packages, runs tests, and creates MR. version: 1.2.0 metadata: author: Platform Team category: automation tags: - dependencies - security - automation trigger: event: schedule service_account: ai-dependency-updater-platform schedule: cron: "0 2 * * 1" # 2 AM every Monday timezone: UTC conditions: - branch: main - not_already_running: true variables: UPDATE_STRATEGY: conservative # conservative | aggressive TEST_TIMEOUT: 30m MAX_UPDATES_PER_RUN: 10 flow: agents: - security_analyst_agent - code_generator_agent timeout: 1h steps: # Step 1: Scan for outdated dependencies - name: scan_dependencies agent: security_analyst_agent action: scan_dependencies timeout: 5m outputs: outdated_packages: result.packages total_count: result.count # Step 2: Check for security vulnerabilities - name: check_vulnerabilities agent: security_analyst_agent action: check_security timeout: 5m inputs: packages: steps.scan_dependencies.outputs.outdated_packages outputs: vulnerable_packages: result.vulnerable vulnerability_count: result.count # Step 3: Prioritize updates - name: prioritize_updates agent: security_analyst_agent action: prioritize timeout: 2m inputs: outdated: steps.scan_dependencies.outputs.outdated_packages vulnerable: steps.check_vulnerabilities.outputs.vulnerable_packages strategy: var.UPDATE_STRATEGY max_updates: var.MAX_UPDATES_PER_RUN outputs: update_list: result.priority_list # Step 4: Update packages - name: update_packages agent: code_generator_agent action: update_dependencies timeout: 10m condition: - steps.prioritize_updates.outputs.update_list.length > 0 inputs: packages: steps.prioritize_updates.outputs.update_list outputs: updated_files: result.files_changed update_summary: result.summary # Step 5: Run tests - name: run_tests agent: code_generator_agent action: run_test_suite timeout: var.TEST_TIMEOUT condition: - steps.update_packages.status == success inputs: test_scope: full outputs: test_results: result.test_summary passed: result.all_passed on_failure: - name: rollback_updates agent: code_generator_agent action: revert_changes - name: create_failure_issue agent: code_generator_agent action: create_issue params: title: "Dependency update failed tests" labels: ["dependencies", "failed-tests"] # Step 6: Create merge request - name: create_merge_request agent: code_generator_agent action: create_mr timeout: 2m condition: - steps.run_tests.outputs.passed == true inputs: files: steps.update_packages.outputs.updated_files title: "chore: update dependencies" description: | Automated dependency updates ## Summary ${steps.update_packages.outputs.update_summary} ## Tests ${steps.run_tests.outputs.test_results} ## Security Addresses ${steps.check_vulnerabilities.outputs.vulnerability_count} vulnerabilities labels: - dependencies - automation - security target_branch: main source_branch: automated-deps-${timestamp} assign_reviewers: - "@platform-team" outputs: mr_iid: result.merge_request_iid mr_url: result.merge_request_url # Step 7: Notify team - name: notify_success agent: code_generator_agent action: send_notification timeout: 1m condition: - steps.create_merge_request.status == success inputs: channel: "#dependency-updates" message: | Dependency update MR created: ${steps.create_merge_request.outputs.mr_url} Updated ${steps.prioritize_updates.outputs.update_list.length} packages Fixed ${steps.check_vulnerabilities.outputs.vulnerability_count} vulnerabilities # Flow-level error handling on_error: - name: notify_failure agent: code_generator_agent action: send_notification params: channel: "#dependency-updates" message: | Dependency update flow failed Error: ${error.message} Step: ${error.step} # Flow-level timeout on_timeout: - name: cleanup agent: code_generator_agent action: cleanup_resources - name: notify_timeout agent: code_generator_agent action: send_notification params: channel: "#dependency-updates" message: " Dependency update flow timed out after 1h" # Metadata for monitoring monitoring: track_metrics: true alert_on_failure: true alert_channels: - "#platform-alerts" slo: success_rate: 0.90 p95_duration: 30m

Step Configuration

Basic Step

- name: step_name agent: agent_name action: action_name

Step with Inputs/Outputs

- name: analyze_code agent: code_review_agent action: analyze inputs: files: context.merge_request.changed_files style_guide: project.config.style_guide outputs: issues: result.issues_found score: result.quality_score

Conditional Step

- name: security_scan agent: security_analyst_agent action: deep_scan condition: # Simple condition - context.merge_request.target_branch == "main" # Complex condition all: - steps.initial_scan.outputs.risk_level == "high" - context.merge_request.has_label("security") any: - steps.initial_scan.outputs.vulnerabilities > 0 - context.merge_request.files_match("**/auth/**")

Step with Timeout

- name: expensive_operation agent: analysis_agent action: deep_analysis timeout: 10m # Override default 5m timeout on_timeout: action: fallback_analysis params: mode: quick

Step with Retry Logic

- name: external_api_call agent: integration_agent action: call_external_service retry: max_attempts: 3 delay: 5s backoff: exponential # 5s, 10s, 20s retry_on: - error_type: network_timeout - error_type: rate_limited - status_code: 503 dont_retry_on: - error_type: authentication_failed - status_code: 401

Parallel Steps

steps: # These steps run in parallel - name: security_scan agent: security_analyst_agent action: security_scan parallel: group_1 - name: performance_analysis agent: code_review_agent action: performance_check parallel: group_1 - name: style_check agent: code_review_agent action: style_validation parallel: group_1 # This step waits for all parallel steps to complete - name: aggregate_results agent: code_review_agent action: combine_results depends_on: - security_scan - performance_analysis - style_check inputs: security: steps.security_scan.outputs performance: steps.performance_analysis.outputs style: steps.style_check.outputs

Context and Data Flow

Available Context

Every step has access to:

context: # Project context project: id: 12345 name: "my-project" namespace: "my-group/my-project" default_branch: "main" # Trigger context trigger: type: "mention" service_account: "ai-code-review" user: id: 67890 username: "john.doe" role: "developer" # Merge request context (if applicable) merge_request: iid: 42 title: "Add new feature" description: "..." source_branch: "feature/new-feature" target_branch: "main" state: "opened" draft: false labels: ["feature", "needs-review"] changed_files: - path: "src/feature.ts" additions: 150 deletions: 20 author: username: "jane.smith" # Issue context (if applicable) issue: iid: 123 title: "Implement feature X" description: "..." state: "opened" labels: ["feature", "priority::high"] assignees: ["john.doe"] milestone: "v1.2.0" # Knowledge Graph context knowledge_graph: snapshot_id: "kg-abc123" project_entities: 1523 relationships: 4567 # CI/CD context (when running in pipeline) ci: pipeline_id: 98765 job_id: 456789 runner_id: 12 commit_sha: "abc123..."

Passing Data Between Steps

steps: - name: step_1 agent: agent_1 action: action_1 outputs: result: result.data count: result.items.length - name: step_2 agent: agent_2 action: action_2 inputs: # Reference previous step output data: steps.step_1.outputs.result count: steps.step_1.outputs.count - name: step_3 agent: agent_3 action: action_3 inputs: # Reference multiple steps from_step_1: steps.step_1.outputs.result from_step_2: steps.step_2.outputs.processed # Reference context branch: context.merge_request.target_branch

Data Transformation

- name: transform_data agent: code_generator_agent action: transform inputs: raw_data: steps.collect_data.outputs.items transform: # Filter filtered: inputs.raw_data.filter(item => item.priority == "high") # Map mapped: inputs.filtered.map(item => ({ id: item.id, title: item.title, severity: item.severity })) # Reduce summary: { total: inputs.filtered.length, critical: inputs.filtered.filter(i => i.severity == "critical").length, high: inputs.filtered.filter(i => i.severity == "high").length } outputs: processed_items: transform.mapped summary: transform.summary

Flow Control

Conditional Execution

steps: - name: check_conditions agent: planning_agent action: evaluate outputs: should_deploy: result.ready_for_deployment environment: result.target_environment - name: deploy_to_staging agent: deployment_agent action: deploy condition: - steps.check_conditions.outputs.should_deploy == true - steps.check_conditions.outputs.environment == "staging" - name: deploy_to_production agent: deployment_agent action: deploy condition: - steps.check_conditions.outputs.should_deploy == true - steps.check_conditions.outputs.environment == "production" - context.merge_request.approvals >= 2

Loops and Iteration

- name: process_multiple_files agent: code_generator_agent action: process_file for_each: context.merge_request.changed_files as: file inputs: file_path: file.path file_content: file.content outputs: processed_files: result.all_results # Continue on individual failures continue_on_error: true

Early Termination

steps: - name: check_prerequisites agent: planning_agent action: validate - name: early_exit_if_invalid agent: planning_agent action: stop_flow condition: - steps.check_prerequisites.outputs.valid == false params: reason: "Prerequisites not met" status: "skipped" - name: continue_processing agent: code_generator_agent action: process # This only runs if early_exit_if_invalid didn't trigger

Error Handling

Step-Level Error Handling

- name: risky_operation agent: integration_agent action: call_external_api on_error: # Simple fallback action: fallback_action # Or multiple error handlers on_error: - name: log_error action: log params: message: "API call failed: ${error.message}" - name: notify_team action: send_notification params: channel: "#alerts" message: "External API error in flow ${flow.name}" - name: use_cached_data action: load_cache params: cache_key: "api_data_backup"

Flow-Level Error Handling

flow: steps: # ... steps ... on_error: - name: cleanup_resources agent: code_generator_agent action: cleanup - name: rollback_changes agent: code_generator_agent action: rollback condition: - error.step.name != "rollback_changes" # Prevent infinite loop - name: create_incident agent: planning_agent action: create_issue params: title: "Flow failure: ${flow.name}" labels: ["incident", "automation"] description: | Flow: ${flow.name} Failed Step: ${error.step.name} Error: ${error.message} Session: ${session.id} - name: notify_on_call agent: planning_agent action: send_notification params: channel: "#on-call" mention: "@on-call-engineer"

Error Recovery Strategies

- name: operation_with_recovery agent: code_generator_agent action: complex_operation retry: max_attempts: 3 strategy: exponential_backoff on_error: # Try alternative approach - name: alternative_approach action: alternative_operation condition: - error.attempt == error.max_attempts # If alternative fails too, degrade gracefully - name: degraded_mode action: minimal_operation condition: - steps.alternative_approach.status == failed

Flow Execution Modes

Immediate Execution

Runs synchronously, blocks until complete:

flow: execution_mode: immediate timeout: 5m steps: # Fast operations only

Queued Execution

Runs asynchronously via CI/CD pipeline:

flow: execution_mode: queued timeout: 30m priority: normal # or high, low steps: # Long-running operations

Scheduled Execution

Runs on a schedule:

trigger: event: schedule service_account: ai-nightly-checks schedule: cron: "0 2 * * *" timezone: UTC flow: execution_mode: scheduled # ...

Flow Versioning

name: code-review-flow version: 2.1.0 changelog: - version: 2.1.0 date: 2026-01-08 changes: - Added performance analysis step - Improved error handling - version: 2.0.0 date: 2025-12-15 changes: - Complete rewrite using new agent platform - Breaking: Changed output format - version: 1.5.0 date: 2025-11-01 changes: - Added security scanning integration deprecation: version: 2.0.0 sunset_date: 2026-06-01 migration_guide_url: https://docs.example.com/migrate-v2 flow: # ...

Flow Testing

Test Mode

flow: test_mode: true # Dry-run, no side effects steps: - name: test_step agent: code_generator_agent action: create_mr # In test mode, this logs what it would do but doesn't create MR

Flow Validation

# Validate flow syntax glab duo flow validate flow.yml # Test flow locally glab duo flow test flow.yml --context context.json # Dry-run in project glab duo flow run flow.yml --project :project_id --dry-run

Flow Management

Publishing Flows

# Publish to project glab duo flow publish flow.yml --project :project_id # Publish to group (available to all projects) glab duo flow publish flow.yml --group :group_id # Publish to instance (available globally - admin only) glab duo flow publish flow.yml --instance

Flow Lifecycle

Draft  Review  Published  Active  Deprecated  Archived

States:
- draft: Being developed, not executable
- review: Awaiting approval
- published: Available but not active
- active: Executable and running
- deprecated: Still works but use discouraged
- archived: No longer executable

Flow Discovery

# List available flows glab duo flow list --project :project_id # Search flows glab duo flow search "code review" --scope group # Get flow details glab duo flow show code-review-flow --project :project_id # View flow executions glab duo flow executions code-review-flow --limit 10

Best Practices

1. Keep Flows Focused

Too Complex:

name: do-everything-flow steps: # 50+ steps doing unrelated things

Focused:

name: security-scan-flow description: Security scanning and vulnerability assessment steps: # 5-10 related steps

2. Use Descriptive Names

steps: - name: scan_dependencies_for_vulnerabilities # Clear # vs - name: scan # Vague

3. Handle Errors Gracefully

- name: critical_operation agent: agent_name action: action_name on_error: - name: log_error - name: notify_team - name: attempt_recovery - name: graceful_degradation

4. Provide Helpful Outputs

- name: analysis agent: code_review_agent action: analyze outputs: summary: result.summary # Human-readable summary details: result.details # Detailed data metrics: result.metrics # Quantitative metrics recommendations: result.recommendations # Actionable items

5. Document Your Flows

name: my-flow description: | Detailed description of what this flow does, when to use it, and what outcomes to expect. ## Usage Mention @ai-my-flow in an MR comment ## Prerequisites - MR must be in 'opened' state - Tests must pass ## Outputs - Code review comments - Quality score - Approval/block decision metadata: author: Platform Team support_contact: "#platform-support" documentation_url: https://docs.example.com/flows/my-flow

Next Steps


Last Updated: January 2026 GitLab Version: 18.7 (Beta), 18.8 GA (Upcoming)