Spike: Project Context Init Flow

Create a new flow for new projects to add context for use by Duo Agent Platform.

  • Creates a basic AGENTS.md and potential sub AGENTS.md (same as init command of CLIs) in a new MR
  • Subfolders created for skills, rules, etc. and adds README files
Screenshots
image
image
image
image

Implementation Plan

AI Gateway (ai-assist repo)

Related MR: gitlab-org/modelops/applied-ml/code-suggestions/ai-assist!4851 (closed)

  1. Add duo_workflow_service/agent_platform/v1/flows/configs/project_context_init/1.0.0.yml to the flow registry with two components:
    • context_analyzer (AgentComponent) — reads the repo tree, detects languages, existing agent context files (AGENTS.md, CLAUDE.md, CURSOR.md, .cursorrules, etc.), and tooling configs. Retrieves the current user ID via get_current_user for MR assignment. Toolset: list_dir, find_files, read_file, get_project, get_current_user
    • init_writer (AgentComponent) — generates a minimal, evidence-grounded AGENTS.md (no boilerplate; no skills//rules/ stubs), optional sub-AGENTS.md only for subdirs with distinct tooling, then opens a draft MR assigned to the initiating user. Toolset: create_file_with_contents, mkdir, create_branch, run_git_command, create_merge_request
  2. Add prompts for both components under ai_gateway/prompts/definitions/
  3. Add model selection entries for both components in ai_gateway/model_selection/unit_primitives.yml (unit_primitive: duo_agent_platform, default model: claude_sonnet_4_6)

GitLab Monolith (gitlab repo)

All monolith changes are gated behind the duo_project_context_init feature flag (type: beta, group: group::ai coding, default: disabled). The flag must be checked at every entry point: the controller, the service, the sidebar, and the frontend route.

Feature Flag Definition

Create ee/config/feature_flags/beta/duo_project_context_init.yml:

name: duo_project_context_init
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/226355
rollout_issue_url: # add rollout issue URL
milestone: '17.11'
group: group::ai coding
type: beta
default_enabled: false

Run bin/feature-flag duo_project_context_init --type beta to generate this file.

1. Backend: ExecuteWorkflowService validation enhancement

File: ee/app/services/ai/catalog/execute_workflow_service.rb

Modify validate to accept flow_name_reference? as a bypass for the json_config requirement:

def validate
  return error('You have insufficient permissions') unless allowed?
  return error('JSON config is required') unless json_config.present? || foundational_flow? || flow_name_reference?
  return error('Goal is required') unless goal.present?
  ServiceResponse.success
end

def flow_name_reference?
  @flow_definition.present? && !foundational_flow?
end

When json_config is nil, StartWorkflowService#serialized_duo_flow_config already returns nil, so DUO_WORKFLOW_FLOW_CONFIG is not set. The AI Gateway executor then resolves the flow YAML from the registry by name automatically via FlowConfig.from_yaml_config.

2. Backend: InitProjectContextService

File: ee/app/services/ai/duo_workflows/init_project_context_service.rb

New service that calls ExecuteWorkflowService with:

  • flow_definition: "project_context_init/v1"
  • container: project
  • goal: "Initialize project context for Duo Agent Platform"
  • No json_config needed

Guard the service with the feature flag:

def execute
  return ServiceResponse.error(message: 'Feature not available') unless Feature.enabled?(:duo_project_context_init, project)
  # ... call ExecuteWorkflowService
end

3. Backend: Controller

File: ee/app/controllers/projects/duo_agents_platform_controller.rb

  • Add 'onboarding' to DUO_AGENT_PLATFORM_ROUTES for correct feature_category
  • Add 'onboarding' to specific_vueroute? and authorized_for_route? (accessible to any user who can :duo_workflow on the project)
  • Add set_has_agents_md before_action scoped to the onboarding route only, gated by the feature flag:
before_action :set_has_agents_md, only: [:show]

def set_has_agents_md
  return unless params[:vueroute] == 'onboarding'
  return unless Feature.enabled?(:duo_project_context_init, @project)

  gon.push(has_agents_md: agents_md_exists?)
end

Where agents_md_exists? checks for AGENTS.md in both the project root and .ai/AGENTS.md.

4. Backend: Rails routes

File: ee/config/routes/project.rb

Add a named route helper for the sidebar:

scope :automate do
  get '/(*vueroute)' => 'duo_agents_platform#show', as: :automate, format: false
  get 'onboarding', to: 'duo_agents_platform#show', as: :automate_onboarding, format: false
end

5. Backend: Sidebar

File: ee/lib/sidebars/projects/super_sidebar_menus/duo_agents_menu.rb

Add an "Onboarding" menu item, rendered only when the feature flag is enabled:

override :configure_menu_items
def configure_menu_items
  add_item(duo_agents_runs_menu_item)
  add_item(duo_agents_onboarding_menu_item) if Feature.enabled?(:duo_project_context_init, context.project)
  true
end

def duo_agents_onboarding_menu_item
  ::Sidebars::MenuItem.new(
    title: s_('DuoAgentsPlatform|Onboarding'),
    link: project_automate_onboarding_path(context.project),
    active_routes: { controller: :duo_agents_platform },
    item_id: :agents_onboarding
  )
end

6. Frontend: Router constants

File: ee/app/assets/javascripts/ai/duo_agents_platform/router/constants.js

export const AGENTS_PLATFORM_ONBOARDING_ROUTE = 'onboarding_index';

7. Frontend: Router

File: ee/app/assets/javascripts/ai/duo_agents_platform/router/index.js

Add a new top-level route tree, conditionally included when glFeatures.duoProjectContextInit is enabled:

...(glFeatures.duoProjectContextInit ? [{
  component: NestedRouteApp,
  path: '/onboarding',
  meta: { text: s__('DuoAgentsPlatform|Onboarding') },
  children: [
    {
      name: AGENTS_PLATFORM_ONBOARDING_ROUTE,
      path: '',
      component: ProjectContextOnboardingPage,
    },
  ],
}] : []),

This gives the URL /automate/onboarding and the breadcrumb "Automate > Onboarding" automatically via the existing router-driven breadcrumb system.

8. Frontend: Onboarding page component

File: ee/app/assets/javascripts/ai/duo_agents_platform/pages/onboarding/project_context_onboarding_page.vue

A full page component with:

  • PageHeading with title "Set up your project for Duo Agent Platform"
  • Description explaining what the init flow does (creates AGENTS.md, sub-files, skill/rule stubs)
  • AGENTS.md absent state: primary "Initialize project context" GlButton that calls InitProjectContextService; button is disabled with a spinner while the flow session is in progress
  • AGENTS.md present state: a GlAlert (variant: success) informing the user that context has already been initialized, with a link to the resulting MR
  • Reads hasAgentsMd from window.gon?.has_agents_md (injected by the controller) to determine which state to render
  • On success, shows the success state in-page (no full redirect needed)

What is explicitly NOT needed

  • No new API endpoint
  • No AI Catalog registration or ItemConsumer
  • No foundational flow registration (avoids appearing in the group settings UI)
  • No full YAML bundled in the monolith
  • No new DB column to track init state (file presence is the guard)
  • No skills/ or rules/ directory stubs (removed from scope)
Edited by Allen Cook