Skip to content

[BUG] with_instructions(replace: true) causes duplicate system messages in memory #582

@trevorturk

Description

@trevorturk

Bug Description

with_instructions in ActiveRecord integration creates duplicate system messages in memory, triggering:

Anthropic's Claude implementation only supports a single system message. Multiple system messages will be combined into one.

Root Cause

In lib/ruby_llm/active_record/chat_methods.rb:93-99:

def with_instructions(instructions, replace: false)
  transaction do
    messages_association.where(role: :system).destroy_all if replace
    messages_association.create!(role: :system, content: instructions)
  end
  to_llm.with_instructions(instructions)  # BUG: adds duplicate
  self
end

The flow:

  1. Create system message in DB
  2. to_llm loads all messages from DB (including the new one)
  3. @chat.with_instructions(instructions) adds another copy

Result: DB has 1 system message, in-memory @chat has 2.

Reproduction

chat = Chat.create!(model: model)
chat.with_instructions("Be helpful", replace: true)

# DB - correct
chat.messages.where(role: :system).count  # => 1

# Memory - wrong
llm_chat = chat.instance_variable_get(:@chat)
llm_chat.messages.select { |m| m.role == :system }.count  # => 2 (should be 1)

Suggested Fix

The .with_instructions(instructions) call on line 98 is redundant - the message was already persisted and loaded by to_llm. Simply remove it:

def with_instructions(instructions, replace: false)
  transaction do
    messages_association.where(role: :system).destroy_all if replace
    messages_association.create!(role: :system, content: instructions)
  end
  to_llm  # Just sync in-memory state with DB
  self
end

The same fix is needed in acts_as_legacy.rb:110.

Environment

  • ruby_llm: 1.11.0
  • Ruby: 3.4.8
  • Rails: 8.1.2

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions