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: ```ruby # 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`: ```ruby # 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: ```ruby # 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: ```ruby # 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 - Parent: https://gitlab.com/gitlab-org/gitlab/-/work_items/560161 - Related designs: https://gitlab.com/gitlab-org/gitlab/-/issues/560166 ## Design See https://gitlab.com/gitlab-org/gitlab/-/issues/562383/designs/Agent_session_in_activity_line.png#note_2758347289
issue