Describe the bug
speak_to call crashes with AttributeError when an
LLM agent calls it and any of the named recipients is a plain (non-LLM) Mesa agent.
The tool looks up recipients by scanning agent.model.agents which includes all
agents and not just LLMAgents, then unconditionally calls
recipient.memory.add_to_memory(). Plain Mesa agents have no memory attribute,
so this raises:
AttributeError: 'RuleBasedAgent' object has no attribute 'memory'
Expected behavior
When a recipient has no memory attribute, speak_to should skip that recipient silently (not crash the simulation) and emit a logger.warning so the developer can see which agent was skipped
LLM recipients in the same call should still receive the message normally.
To Reproduce
import os
os.environ["GEMINI_API_KEY"] = "just_testing"
from mesa.model import Model
from mesa.agent import Agent
from mesa.space import MultiGrid
from unittest.mock import MagicMock
from mesa_llm.llm_agent import LLMAgent
from mesa_llm.reasoning.cot import CoTReasoning
from mesa_llm.tools.inbuilt_tools import speak_to
class RuleBasedAgent(Agent):
def step(self): pass
class MixedModel(Model):
def __init__(self):
super().__init__(seed=42)
self.grid = MultiGrid(5, 5, torus=False)
model = MixedModel()
llm_agent = LLMAgent(model=model, reasoning=CoTReasoning)
rule_agent = RuleBasedAgent(model=model)
model.grid.place_agent(llm_agent, (1, 1))
model.grid.place_agent(rule_agent, (2, 2))
llm_agent.memory.add_to_memory = MagicMock()
speak_to(llm_agent, [rule_agent.unique_id], "Hello!") #will crash here
Additional context
- The existing test
test_speak_to_records_on_recipients manually attaches a mock .memory to every test recipient, which is why it passes even on the broken code
- Mixed-agent models (LLM agents + rule-based agents) are a standard Mesa pattern; this bug makes cross-type communication difficult
Describe the bug
speak_tocall crashes withAttributeErrorwhen anLLM agent calls it and any of the named recipients is a plain (non-LLM) Mesa agent.
The tool looks up recipients by scanning
agent.model.agentswhich includes allagents and not just LLMAgents, then unconditionally calls
recipient.memory.add_to_memory(). Plain Mesa agents have nomemoryattribute,so this raises:
Expected behavior
When a recipient has no
memoryattribute,speak_toshould skip that recipient silently (not crash the simulation) and emit alogger.warningso the developer can see which agent was skippedLLM recipients in the same call should still receive the message normally.
To Reproduce
Additional context
test_speak_to_records_on_recipientsmanually attaches a mock.memoryto every test recipient, which is why it passes even on the broken code