Implement agent activity tracking in work item timelines using SystemNoteService

Problem

We need to track and display GitLab Duo agent activity in work item (issues, MRs, etc.) timelines so users can understand what agents have done in relation to their work items. Currently, there's no visibility into agent sessions and activities within the context of specific work items.

Expected User Experience

When a GitLab Duo agent performs activities related to a work item, users should see that an Agent is working on the work-item in the work items timeline.

Examples of what users should see:

  • Session Started: "Duo Developer started session abc123 triggered by User"

These activities should:

  • Provide context about what triggered the agent activity (must have)
  • Include link to session for traceability (must have)
  • Follow existing GitLab timeline/activity feed patterns (must have)

Scope

Minimum

  • Setting up the services to provide a reusable way for sessions to add a SystemNote to a noteable when they start.
  • Including usage of this new method when a session is created in at least one specific case (e.g. Issue-To-MR is started from an issue or pipeline fixing is started on an MR)

Extended

Set up session creation in a way that an appropriate SystemNote is automatically created (e.g. if issue or MR is provided on session creation). This can also be moved into a separate issue if necessary.

Technical Proposal (Duo generated)

1. Extend SystemNoteService

Update ee/app/services/ee/system_note_service.rb to include agent-related methods:

# Methods for the AgentsService
def agent_session_started(noteable, project, author, session_id, trigger_source = 'User')
  duo_agents_service(noteable, project, author).agent_session_started(session_id, trigger_source)
end

def agent_session_completed(noteable, project, author, session_id, status = 'completed')
  duo_agents_service(noteable, project, author).agent_session_completed(session_id, status)
end

def agent_session_failed(noteable, project, author, session_id, reason = nil)
  duo_agents_service(noteable, project, author).agent_session_failed(session_id, reason)
end

private

def duo_agents_service(noteable, project, author)
  ::SystemNotes::AgentsService.new(noteable: noteable, container: project, author: author)
end

2. Create AgentsService

Create ee/app/services/system_notes/agents_service.rb:

# frozen_string_literal: true

module SystemNotes
  class AgentsService < ::SystemNotes::BaseService
    # Called when a new agent session is started
    def agent_session_started(session_id, trigger_source = 'User', agent_name = "Duo Developer")
      body = "#{agent_name} started session **#{session_id}** triggered by #{trigger_source}"

      create_note(NoteSummary.new(
        noteable,
        project,
        author,
        body,
        action: 'duo_agent_started'
      ))
    end

    # Called when a Duo agent session is completed
    def agent_session_completed(session_id, status = 'completed', agent_name = "Duo Developer")
      body = "#{agent_name} #{status} session **#{session_id}**"

      create_note(NoteSummary.new(
        noteable,
        project,
        author,
        body,
        action: 'duo_agent_completed'
      ))
    end

    # Called when a Duo agent session fails
    def agent_session_failed(session_id, reason = nil)
      body = "Duo Developer session **#{session_id}** failed"
      body += " (#{reason})" if reason.present?

      create_note(NoteSummary.new(
        noteable,
        project,
        author,
        body,
        action: 'duo_agent_failed'
      ))
    end
  end
end

3. Database Schema Changes

Add origin tracking to the workflow database:

# Migration to add origin tracking
add_column :workflows, :origin_type, :string
add_column :workflows, :origin_id, :integer
add_column :workflows, :origin_url, :string

# Or use polymorphic association
add_reference :workflows, :origin, polymorphic: true

4. Integration Points

Update workflow services to create system notes:

# In ee/app/services/ai/duo_workflows/start_workflow_service.rb
def create_workflow_started_system_note
  noteable = @workflow.origin # The associated work item
  return unless noteable

  session_id = @params[:workflow_id] || @workflow.id
  trigger_source = determine_trigger_source
  
  SystemNoteService.agent_session_started(
    noteable,
    noteable.project,
    @current_user,
    session_id,
    trigger_source
  )
end

Implementation Considerations

  • This is primarily backend work with minimal frontend changes needed, if any.
  • Leverages existing SystemNoteService patterns for consistency
  • System notes will automatically appear in existing timeline/activity feeds
  • Need to determine appropriate trigger sources and agent names
  • Consider rate limiting to avoid timeline spam from frequent agent activities

Acceptance Criteria

  • Agent session activities appear in work item timelines
  • Session IDs are included for traceability
  • Trigger sources are captured and displayed
  • Integration works with existing timeline/activity feed UI
  • Performance impact is minimal
  • Tests cover the new functionality

Related Issues

Design

See https://gitlab.com/gitlab-org/gitlab/-/issues/562383/designs/Agent_session_in_activity_line.png#note_2758347289

Edited by 🤖 GitLab Bot 🤖