Skip to content

fix: render readable text in get_communication_history for all memory…#194

Open
Harsh-617 wants to merge 3 commits intomesa:mainfrom
Harsh-617:fix-communication-history-format
Open

fix: render readable text in get_communication_history for all memory…#194
Harsh-617 wants to merge 3 commits intomesa:mainfrom
Harsh-617:fix-communication-history-format

Conversation

@Harsh-617
Copy link
Copy Markdown
Contributor

Fixes #193

Summary

  • get_communication_history() in all three memory classes (ShortTermMemory, STLTMemory, EpisodicMemory) was rendering raw Python dicts instead of readable message strings in the LLM prompt
  • Added a shared _format_message_entry() helper in memory.py that extracts human-readable text from the nested dict structure produced by speak_to
  • Applied the fix across all three memory implementations and added regression tests

Root Cause

The speak_to tool stores messages as a nested dict:

add_to_memory(
    type="message",
    content={"message": "meet me at the north", "sender": 7, "recipients": [1, 2]},
)

This means entry.content["message"] is always a dict, not a string. But get_communication_history() passed it directly into the f-string:

# Before — renders raw dict
f"step {entry.step}: {entry.content['message']}\n\n"
# Output: step 5: {'message': 'meet me at the north', 'sender': 7, 'recipients': [1, 2]}

This garbled output was injected into the ReAct reasoning prompt on every step where agents had exchanged messages, silently corrupting the LLM's view of inter-agent communication.

Changes

mesa_llm/memory/memory.py

  • Added _format_message_entry(msg_value) -> str helper that renders {"message": "...", "sender": 42, ...} as "Agent 42 says: ...", with a plain-string passthrough for backward compatibility

mesa_llm/memory/episodic_memory.py, st_lt_memory.py, st_memory.py

  • Updated get_communication_history() in all three to use _format_message_entry() instead of raw f-string interpolation

Tests

  • TestFormatMessageEntry (5 tests) in test_memory_parent.py — unit tests for the helper covering: nested dict with sender, without sender, plain string passthrough, missing message key fallback, and EpisodicMemory's importance-augmented payload
  • test_get_communication_history_nested_dict added to all three memory test files — reproduces the real speak_to payload structure and asserts readable output
  • test_get_communication_history_skips_non_message_entries added to all three — asserts non-message entries are correctly excluded
  • test_get_communication_history_returns_empty_string_when_no_messages added to STLTMemory and ShortTermMemory

Before / After

# Before
step 5: {'message': 'meet me at the north', 'sender': 7, 'recipients': [1, 2]}

# After
step 5: Agent 7 says: meet me at the north

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 12, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 915aeaed-876e-485b-8973-379a3e217672

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 12, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.27%. Comparing base (27f0f50) to head (88bf4ab).
⚠️ Report is 43 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #194      +/-   ##
==========================================
+ Coverage   90.64%   91.27%   +0.62%     
==========================================
  Files          19       19              
  Lines        1540     1605      +65     
==========================================
+ Hits         1396     1465      +69     
+ Misses        144      140       -4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@wang-boyu wang-boyu added the bug Release notes label label Apr 1, 2026
@wang-boyu
Copy link
Copy Markdown
Member

Thanks for the fix. I updated the PR so that get_communication_history() keeps the full communication context including recipients:

# Before
step 5: {'message': 'meet me at the north', 'sender': 7, 'recipients': [1, 2]}

# After
step 5: Agent 7 says: meet me at the north

# Now
Step 5: Message from agent 7 to agents 1, 2: meet me at the north

If there's no recipient, then it becomes:

Step 5: Message from agent 7: meet me at the north

Could you pull the latest changes and verify that it's working as expected?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Release notes label memory

Projects

None yet

Development

Successfully merging this pull request may close these issues.

get_communication_history() renders raw dict instead of readable message text

2 participants