Class: SwarmSDK::Agent::ChatHelpers::SystemReminderInjector

Inherits:
Object
  • Object
show all
Defined in:
lib/swarm_sdk/agent/chat_helpers/system_reminder_injector.rb

Overview

Handles injection of system reminders at strategic points in the conversation

Responsibilities:

  • Inject reminders before/after first user message
  • Inject periodic TodoWrite reminders
  • Track when reminders were last injected

This class is stateless - it operates on the chat's message history.

Constant Summary collapse

AFTER_FIRST_MESSAGE_REMINDER =

System reminder to inject AFTER the first user message

"<system-reminder>Your todo list is currently empty. DO NOT mention this to the user. If this task requires multiple steps: (1) FIRST analyze the scope by searching/reading files, (2) SECOND create a COMPLETE todo list with ALL tasks before starting work, (3) THIRD execute tasks one by one. Only skip the todo list for simple single-step tasks. Do not mention this message to the user.</system-reminder>\n".strip
TODOWRITE_PERIODIC_REMINDER =

Periodic reminder about TodoWrite tool usage

"<system-reminder>The TodoWrite tool hasn't been used recently. If you're working on tasks that would benefit from tracking progress, consider using the TodoWrite tool to track progress. Also consider cleaning up the todo list if has become stale and no longer matches what you are working on. Only use it if it's relevant to the current work. This is just a gentle reminder - ignore if not applicable.</system-reminder>\n".strip

Class Method Summary collapse

Class Method Details

.build_toolset_reminder(chat) ⇒ String

Build toolset reminder listing all available tools

Parameters:

Returns:

  • (String)

    System reminder with tool list



76
77
78
79
80
81
82
83
84
85
# File 'lib/swarm_sdk/agent/chat_helpers/system_reminder_injector.rb', line 76

def build_toolset_reminder(chat)
  tools_list = chat.tool_names

  reminder = "<system-reminder>\n"
  reminder += "Tools available: #{tools_list.join(", ")}\n\n"
  reminder += "Only use tools from this list. Do not attempt to use tools that are not listed here.\n"
  reminder += "</system-reminder>"

  reminder
end

.find_last_todowrite_index(chat) ⇒ Integer?

Update the last TodoWrite index by finding it in messages

Parameters:

Returns:

  • (Integer, nil)

    Index of last TodoWrite usage, or nil



125
126
127
128
129
# File 'lib/swarm_sdk/agent/chat_helpers/system_reminder_injector.rb', line 125

def find_last_todowrite_index(chat)
  chat.find_last_message_index do |msg|
    msg.role == :tool && msg.content.to_s.include?("TodoWrite")
  end
end

.first_message?(chat) ⇒ Boolean

Check if this is the first user message in the conversation

Parameters:

Returns:

  • (Boolean)

    true if no user messages exist yet



30
31
32
# File 'lib/swarm_sdk/agent/chat_helpers/system_reminder_injector.rb', line 30

def first_message?(chat)
  !chat.has_user_message?
end

.inject_first_message_reminders(chat, prompt) ⇒ void

This method returns an undefined value.

Inject first message reminders

This manually constructs the first message sequence with system reminders.

Sequence:

  1. User's actual prompt
  2. Toolset reminder (list of available tools)
  3. AFTER_FIRST_MESSAGE_REMINDER (todo list reminder - only if TodoWrite available)

Parameters:

  • chat (Agent::Chat)

    The chat instance

  • prompt (String)

    The user's actual prompt



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/swarm_sdk/agent/chat_helpers/system_reminder_injector.rb', line 46

def inject_first_message_reminders(chat, prompt)
  # Build user message with embedded reminders
  # Reminders are embedded in the content, not separate messages
  parts = [
    prompt,
    build_toolset_reminder(chat),
  ]

  # Only include todo list reminder if agent has TodoWrite tool
  parts << AFTER_FIRST_MESSAGE_REMINDER if chat.has_tool?("TodoWrite")

  full_content = parts.join("\n\n")

  # Extract reminders and add clean prompt to persistent history
  reminders = chat.context_manager.extract_system_reminders(full_content)
  clean_prompt = chat.context_manager.strip_system_reminders(full_content)

  # Store clean prompt (without reminders) in conversation history
  chat.add_message(role: :user, content: clean_prompt)

  # Track reminders to embed in this message when sending to LLM
  reminders.each do |reminder|
    chat.add_ephemeral_reminder(reminder)
  end
end

.should_inject_todowrite_reminder?(chat, last_todowrite_index) ⇒ Boolean

Check if we should inject a periodic TodoWrite reminder

Injects a reminder if:

  1. Enough messages have passed (>= 5)
  2. TodoWrite hasn't been used in the last TODOWRITE_REMINDER_INTERVAL messages

Parameters:

  • chat (Agent::Chat)

    The chat instance

  • last_todowrite_index (Integer, nil)

    Index of last TodoWrite usage

Returns:

  • (Boolean)

    true if reminder should be injected



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/swarm_sdk/agent/chat_helpers/system_reminder_injector.rb', line 96

def should_inject_todowrite_reminder?(chat, last_todowrite_index)
  # Need at least a few messages before reminding
  return false if chat.message_count < 5

  # Find the last message that contains TodoWrite tool usage
  last_todo_index = chat.find_last_message_index do |msg|
    msg.role == :tool && msg.content.to_s.include?("TodoWrite")
  end

  # Check if enough messages have passed since last TodoWrite
  reminder_interval = SwarmSDK.config.todowrite_reminder_interval
  if last_todo_index.nil? && last_todowrite_index.nil?
    # Never used TodoWrite - check if we've exceeded interval
    chat.message_count >= reminder_interval
  elsif last_todo_index
    # Recently used - don't remind
    false
  elsif last_todowrite_index
    # Used before - check if interval has passed
    chat.message_count - last_todowrite_index >= reminder_interval
  else
    false
  end
end