Skip to content

fix(memory)!: wire contextTokenBudget and autoExtractEntities, remove autoRecordMessages and consolidationEnabled (closes #1579) - #1827

Merged
kannupriyakalra merged 5 commits into
mainfrom
fix/memory-manager-config-1579
Oct 12, 2026
Merged

kannupriyakalra merged 5 commits into
mainfrom
fix/memory-manager-config-1579

Conversation

@kannupriyakalra

Copy link
Copy Markdown
Collaborator

Summary

Closes #1579

MemoryManagerConfig had six options, and only defaultImportance (plus consolidationConfig) was read by a manager. This PR decides each of the four dead options: two are wired and tested, two are removed with a migration note. Every option left on MemoryManagerConfig now changes what SimpleMemoryManager / LLMMemoryManager do.

Decisions, per option

Option Decision Why
contextTokenBudget Implemented getRelevantContext already takes a maxTokens; letting a manager carry its budget means code that only has a MemoryManager (an agent loop, a prompt builder) gets the operator's budget without threading an int through. The trait's maxTokens default is now contextTokenBudget, a new concrete member on MemoryManager (default MemoryManager.DefaultContextTokenBudget = 2000, so existing third-party implementations compile and behave as before); the shared managers override it from their config. An explicit maxTokens still wins. Default stays 2000, so nobody's output changes unless they set it.
autoExtractEntities Implemented It has a clear, cheap meaning and a ready implementation: recordMessage (and so recordConversation) calls extractEntities(content, Some(conversationId)) on each user and assistant message after recording it. System prompts and tool output are not analysed (instructions and raw JSON are not facts about the world, and tool output can be large). Extraction is best-effort: the message is already recorded, so a failed LLM call is logged as a warning and the manager holding the message is returned, rather than reporting a failure for a record that succeeded (and, for SQLite, is already persisted). It stays opt-in (false); on LLMMemoryManager it costs one LLM call per message, on SimpleMemoryManager it does nothing because that manager's extractEntities extracts nothing (documented).
autoRecordMessages Removed A manager only sees the messages passed to recordMessage/recordConversation; there is no message stream for it to record automatically, and llm4s-memory does not depend on llm4s-agent (nor should it). Its default was true, which told readers recording was automatic when it never was.
consolidationEnabled Removed Automatic consolidation needs a trigger policy (age, count, schedule) and would hide an LLM call inside record*; none of that exists, and designing it is a feature of its own. consolidateMemories already runs when called and reads consolidationConfig, which stays.

llm4s-memory is Beta and has no MiMa baseline, so removal now is cheaper than freezing two no-op fields into 0.5.0. With the two fields gone, the "binary-compatible 5-parameter" constructor / apply / copy overloads (which took them) are removed as well.

What changed

  • MemoryManager.scala: MemoryManagerConfig(autoExtractEntities, defaultImportance, contextTokenBudget, consolidationConfig); Scaladoc states what each option does; MemoryManager.contextTokenBudget + MemoryManager.DefaultContextTokenBudget; getRelevantContext(query, maxTokens = contextTokenBudget, ...); ConsolidationConfig Scaladoc no longer refers to consolidationEnabled; fullFeatured = autoExtractEntities = true.
  • BaseMemoryManagerOps.scala: contextTokenBudget from config; best-effort extraction after recording user/assistant messages.
  • Tests: new MemoryManagerConfigBehaviourSpec; MemoryManagerConfigBinaryCompatSpec replaced by MemoryManagerConfigSpec (value semantics of the new shape); the pendingUntilFixed test in MemoryGuideSpec is promoted to a normal test (with a positive control), plus a test for the new guide snippet.
  • Docs: docs/guide/agents/memory.md (options table, recording / consolidation / extraction / budget paragraphs), modules/memory/README.md, docs/migrations/0-4-1-to-0-5-0.md, CHANGELOG (Added + Removed with migration).

Acceptance criteria → tests

Criterion Test(s)
contextTokenBudget changes behaviour MemoryManagerConfigBehaviourSpec: "contextTokenBudget should bound getRelevantContext when the call passes no maxTokens", "let the memory in when the configured budget has room for it", "default to 2000 tokens", "give way to an explicit maxTokens, in either direction", "be kept by the manager returned from a record call", "be honoured by LLMMemoryManager"; "MemoryManager.contextTokenBudget should default to 2000 for an implementation that does not override it"
autoExtractEntities changes behaviour MemoryManagerConfigBehaviourSpec: "extract entities from a recorded user message when true", "make no LLM call and store no entity when false", "analyse user and assistant messages of a recorded conversation, but not system or tool messages", "keep the recorded message when extraction fails", "have no effect on SimpleMemoryManager"
autoRecordMessages, consolidationEnabled removed with a CHANGELOG migration note CHANGELOG ### Removed entry + migration guide; MemoryManagerConfigSpec pins the remaining options (defaults, apply, copy, equals/hashCode over every option, toString)
The pendingUntilFixed test from #1577 promoted or deleted MemoryGuideSpec "keep the context within contextTokenBudget when the call passes no maxTokens" (now a normal test)
Guide and README match MemoryGuideSpec "build the configuration of the Configuration Options block"; guide/README text updated

Evidence the tests fail without the fix

With the wiring disabled in BaseMemoryManagerOps (extraction guarded by false, contextTokenBudget returning the constant 2000) and the tests unchanged:

- should bound getRelevantContext when the call passes no maxTokens *** FAILED ***
- should be kept by the manager returned from a record call *** FAILED ***
- should be honoured by LLMMemoryManager *** FAILED ***
- should extract entities from a recorded user message when true *** FAILED ***
- should analyse user and assistant messages of a recorded conversation, but not system or tool messages *** FAILED ***
- should build the configuration of the Configuration Options block *** FAILED ***
- should keep the context within contextTokenBudget when the call passes no maxTokens *** FAILED ***
Tests: succeeded 38, failed 7

(On main itself the new tests do not compile: there is no MemoryManager.contextTokenBudget, and the promoted guide test was pendingUntilFixed because it failed.)

Checks run locally

  • memory/test — 1645 passed, 0 failed
  • memoryPostgres/Test/compile, samples/Test/compile, samples/testOnly *ComparisonGuideSpec *UpgradeGuideSpec — pass
  • memory/scalafmtCheckAll, scalafmtSbtCheck, memory/scalafixAll --check, coveragePolicyCheck, memory/doc — pass
  • coverage memory/test memory/coverageReport — 91.38% statements (floor 80)
  • scripts/check-doc-links.sh, check-doc-nav-order.sh, check-doc-support.sh, check-doc-versions.sh, check-docs-site-links.sh — pass

Behaviour change / migration

  • Removed: MemoryManagerConfig.autoRecordMessages, consolidationEnabled, and the 5-parameter constructor/apply/copy overloads. Drop the arguments; record turns with recordMessage/recordConversation and call consolidateMemories yourself. Positional calls shift to (autoExtractEntities, defaultImportance, contextTokenBudget, consolidationConfig).
  • Changed: getRelevantContext without maxTokens now uses the configured contextTokenBudget (default unchanged at 2000). autoExtractEntities = true (and MemoryManagerConfig.fullFeatured) now makes LLMMemoryManager call the LLM once per recorded user/assistant message.

…autoRecordMessages and consolidationEnabled (closes #1579)

MemoryManagerConfig had four options no manager read.

- contextTokenBudget is now the budget getRelevantContext uses when a
  call passes no maxTokens, through MemoryManager.contextTokenBudget
  (2000 by default; an explicit maxTokens still wins).
- autoExtractEntities makes recordMessage and recordConversation run
  extractEntities over each user and assistant message, best-effort.
- autoRecordMessages and consolidationEnabled are removed with the
  5-parameter overloads: a manager cannot record messages it is not
  given, and automatic consolidation has no trigger.

The pendingUntilFixed contextTokenBudget test in MemoryGuideSpec is
promoted; the guide, README, CHANGELOG and migration guide match.

Signed-off-by: kannupriyakalra <kannupriyakalra@gmail.com>
…nfig-1579

Signed-off-by: kannupriyakalra <kannupriyakalra@gmail.com>

# Conflicts:
#	CHANGELOG.md
@codecov

codecov Bot commented Oct 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Signed-off-by: kannupriyakalra <kannupriyakalra@gmail.com>
Signed-off-by: kannupriyakalra <kannupriyakalra@gmail.com>
Signed-off-by: kannupriyakalra <kannupriyakalra@gmail.com>
@kannupriyakalra
kannupriyakalra merged commit ecf1d8d into main Oct 12, 2026
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MemoryManagerConfig: four of six options are never read

1 participant