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:
- Workflow Steps: Sequence of actions to perform
- Agent Orchestration: Which agents perform which steps
- Data Passing: How context flows between steps
- Conditional Logic: When to execute certain steps
- Error Handling: What to do when steps fail
- 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
- Manage Agents: Read agents.md for agent lifecycle
- CI/CD Integration: Check integration.md for pipeline patterns
- Best Practices: Study best-practices.md for production
Last Updated: January 2026 GitLab Version: 18.7 (Beta), 18.8 GA (Upcoming)