feat(memory): add OM-managed working memory#18654
Conversation
🦋 Changeset detectedLatest commit: 298d8e0 The changes in this PR will be included in the next version bump. This PR includes changesets to release 25 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
PR triageLinked issue check skipped for core contributor @TylerBarnes. PR complexity score
Applied label: Changed test gateChanged tests failed against the base branch as expected. Label: |
Adds a WorkingMemoryExtractor that lets Observational Memory update working memory through the normal extractor pipeline. The extractor reads the active working memory template or schema, writes updates through the memory instance, and does not duplicate the value under OM extracted metadata. Also adds injectTools: boolean (default true) to BaseWorkingMemory config. Set to false when OM extractors or another path owns working memory updates, preventing the working memory tool from being injected into the main agent. Co-Authored-By: Mastra Code (crof/glm-5.2) <noreply@mastra.ai>
Co-Authored-By: Mastra Code (crof/glm-5.2) <noreply@mastra.ai>
331daf4 to
7fe1030
Compare
5d3d2b8 to
298e17e
Compare
| Adds a built-in `WorkingMemoryExtractor` for the Observational Memory extractor pipeline. When included in observation or reflection config, the observer/reflector can update working memory through the normal extractor pipeline instead of requiring the main agent to call the working memory tool. | ||
|
|
||
| Adds `workingMemory.agentManaged` to control whether the main agent receives working memory tool/instruction injection, and `observationalMemory.observation.manageWorkingMemory` to automatically add the working memory extractor, default `agentManaged` to false, and default `useStateSignals` to true when working memory is enabled. |
There was a problem hiding this comment.
add an example of configuring OM to manage working memory (just the sugar example)
| }) | ||
| ``` | ||
|
|
||
| This setting adds `WorkingMemoryExtractor`, defaults `workingMemory.agentManaged` to `false`, and defaults `workingMemory.useStateSignals` to `true`. Set `workingMemory.agentManaged: true` if the main agent should still receive working memory tool and instruction injection. |
There was a problem hiding this comment.
lets lead with the outcome: the agent no longer needs to manage its own working memory, it's managed automatically by the observer. This fixes issues with working memory:
- main agent is busy with other things and doesn't always remember to update working memory
- working memory updates invalidate the prompt cache because working memory is in the system prompt. since OM is all about maintaining prompt cache, turning on OM managed working memory also turns on state signals for WM, which makes them prompt cache friendly
|
|
||
| function buildWorkingMemoryInstructions(details: Awaited<ReturnType<typeof getWorkingMemoryDetails>>): string { | ||
| if (!details.memory) { | ||
| return 'Working memory is unavailable. Do not output this section.'; |
There was a problem hiding this comment.
this seems odd, when would this happen?
| if (!memory) { | ||
| throw new Error('Working memory extractor requires an active Memory instance.'); | ||
| } |
There was a problem hiding this comment.
how is this possible? we extract from within the memory system, memory must always exist here
| const existing = parseJsonObject(await memory.getWorkingMemory({ threadId, resourceId, memoryConfig })); | ||
| const update = parseJsonObject(current); | ||
| if (!update) { | ||
| throw new Error('Working memory extractor expected a JSON object update.'); |
There was a problem hiding this comment.
what if there was no update to make? it should be allowed to be omitted, and actually we may need to add that in to the working memory schema here somehow. The observer needs to be able to opt out of updating if there's no need to update
| if (!update) { | ||
| throw new Error('Working memory extractor expected a JSON object update.'); | ||
| } | ||
| workingMemory = JSON.stringify(deepMergeWorkingMemory(existing, update)); |
There was a problem hiding this comment.
is this how existing working memory works? I thought it just always replaced it
Move the unreleased working memory extraction controls to the final agentManaged/manageWorkingMemory API. This keeps the working memory extractor branch from introducing the discarded injectTools name and documents the managed working memory defaults. Co-Authored-By: Mastra Code (openai/gpt-5.5) <noreply@mastra.ai>
298e17e to
298d8e0
Compare
Summary
Adds a built-in WorkingMemoryExtractor and a simpler OM-managed working memory setup.
With
manageWorkingMemory, OM can extract working-memory updates from observations and apply them after the turn. The sugar defaults working memory to prompt-cache-friendly state signals and disables direct agent tool management unless the user opts back in.Users who still want both paths can opt in explicitly:
Test plan
pnpm --filter ./packages/memory test:unit -- --run src/processors/observational-memory/__tests__/extractor.test.ts src/processors/observational-memory/__tests__/observational-memory-api.test.ts --reporter=dot --bail 1pnpm --filter ./packages/memory checkStack