You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Python's memory-extraction API diverged from the TypeScript SDK in three ways that made the
Python happy path noticeably heavier than its TS counterpart. In TS a store opts into automatic
extraction with extraction: true and gets sensible defaults; in Python the caller had to
construct an ExtractionConfig, pick a trigger explicitly (it was required), and choose an
extractor by hand. The shared documentation ("the simplest form turns it on with defaults",
"defaults to an interval of 5") only held for TS — there was no Python equivalent.
This brings Python in line. A store can now enable extraction with extraction=True, the trigger is optional (defaulting to every 5 turns), and the extractor is selected automatically
from the store's write methods — matching TS's boolean | ExtractionConfig shape and its resolveExtractionConfig behavior.
The change is opt-in and pay-for-play: existing ExtractionConfig(trigger=...) call sites keep
working unchanged. Defaulting is now centralized in a single internal _resolve_extraction_config
(mirroring TS's resolve-extraction-config.ts), so the MemoryManager and ExtractionCoordinator
no longer re-interpret raw config or re-apply defaults — the manager resolves once and passes _ExtractionBindings downstream.
Public API Changes
A store's extraction field accepts a bool shorthand, and ExtractionConfig.trigger is now
optional:
# Before: extraction required an explicit ExtractionConfig with an explicit triggerclassMyStore:
extraction=ExtractionConfig(trigger=IntervalTrigger(turns=5))
# After: bool shorthand enables extraction with defaults (every 5 turns;# extractor chosen from the store's write methods)classMyStore:
extraction=True# After: trigger is optional — omit it to default to every 5 turnsclassMyStore:
extraction=ExtractionConfig() # interval trigger of 5, default extractor + filter
Default extractor is now resolved from the store's write methods, matching TS:
A store implementing only add → defaults to a ModelExtractor (client-side fact distillation,
written via add).
A store implementing add_messages → defaults to server-side extraction (raw messages handed to add_messages, no model call).
An explicit extractor or filter still overrides the default. An explicit empty trigger list is
still rejected at construction.
Related Issues
Documentation PR
N/A
Type of Change
New feature
Testing
How have you tested the change? Verify that the changes do not break functionality or introduce new warnings.
I ran hatch run prepare
Added a test_resolve_extraction_config suite (ported from the TS resolver tests) covering the
bool shorthand, trigger defaulting/normalization, capability-based extractor selection, and filter
defaulting. Existing coordinator and manager tests were updated to drive the resolved-config path;
the previously-raising "add-only store without an extractor" case now asserts the new ModelExtractor default behavior.
Checklist
I have read the CONTRIBUTING document
I have reviewed and understand every line of code in this PR, including any generated by AI tools, and I can explain why it works
My change is focused and reasonably small; I have split unrelated work into separate PRs
I have added any necessary tests that prove my fix is effective or my feature works
I have updated the documentation accordingly
I have added an appropriate example to the documentation to outline the feature, or no new docs are needed
My changes generate no new warnings
Any dependent changes have been merged and published
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.
Issue: This widens a public contract — MemoryStoreConfig.extraction becomes ExtractionConfig | bool | None and ExtractionConfig.trigger becomes optional. Per team/API_BAR_RAISING.md, public-API changes go through bar-raising tracked via the api/needs-review label, which isn't on this PR.
Suggestion: This is largely mitigated since the change deliberately mirrors the already-shipped TS boolean | ExtractionConfig shape and resolveExtractionConfig behavior — the design was effectively validated there. Worth a maintainer confirming whether "match an existing cross-SDK API" qualifies as a minimal change (PR review sufficient) or still wants the label for tracking. Not blocking from my side.
Clean, faithful port of TS's resolveExtractionConfig that genuinely simplifies the Python happy path. Centralizing defaulting in _resolve_extraction_config and threading _ExtractionBindings downstream is the right call — it removes the duplicated _normalize_triggers and stops the manager/coordinator from re-interpreting raw config. Verified locally: 114 tests pass, ruff and mypy ./src clean.
Review notes
Correctness: Resolver logic matches the TS reference line-for-line, including the capability-based extractor default and the "leave an explicit empty trigger list for the manager to reject" handoff. The config.filter or DEFAULT_... defaulting is safe — MemoryMessageFilter has no __bool__/__len__, so an explicit empty filter is preserved (confirmed).
Tests: Resolver suite is a 1:1 port of the TS test cases; the per-field trigger assertions are justified (no value equality on IntervalTrigger) and documented. Manager/coordinator tests correctly updated to drive the resolved-config path.
API: Public contract widens (extraction: bool | ExtractionConfig, optional trigger) — flagged separately re: api/needs-review, mitigated by mirroring the shipped TS API.
Docs: PR's "updated docs"/"added example" boxes are unchecked and there's no memory-extraction user guide in site/; docstrings are thorough, but one in init_agent still describes the pre-PR ExtractionConfig-only shape.
Nice, well-scoped change — the cross-SDK parity and the thorough docstrings made this easy to follow.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
area-communityRelated to community and contributor healthchoreMaintenance tasks, dependency updates, CI changes, refactoring with no user-facing impactsize/m
2 participants
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Python's memory-extraction API diverged from the TypeScript SDK in three ways that made the
Python happy path noticeably heavier than its TS counterpart. In TS a store opts into automatic
extraction with
extraction: trueand gets sensible defaults; in Python the caller had toconstruct an
ExtractionConfig, pick a trigger explicitly (it was required), and choose anextractor by hand. The shared documentation ("the simplest form turns it on with defaults",
"defaults to an interval of 5") only held for TS — there was no Python equivalent.
This brings Python in line. A store can now enable extraction with
extraction=True, thetriggeris optional (defaulting to every 5 turns), and the extractor is selected automaticallyfrom the store's write methods — matching TS's
boolean | ExtractionConfigshape and itsresolveExtractionConfigbehavior.The change is opt-in and pay-for-play: existing
ExtractionConfig(trigger=...)call sites keepworking unchanged. Defaulting is now centralized in a single internal
_resolve_extraction_config(mirroring TS's
resolve-extraction-config.ts), so theMemoryManagerandExtractionCoordinatorno longer re-interpret raw config or re-apply defaults — the manager resolves once and passes
_ExtractionBindings downstream.Public API Changes
A store's
extractionfield accepts aboolshorthand, andExtractionConfig.triggeris nowoptional:
Default extractor is now resolved from the store's write methods, matching TS:
add→ defaults to aModelExtractor(client-side fact distillation,written via
add).add_messages→ defaults to server-side extraction (raw messages handed toadd_messages, no model call).An explicit
extractororfilterstill overrides the default. An explicit empty trigger list isstill rejected at construction.
Related Issues
Documentation PR
N/A
Type of Change
New feature
Testing
How have you tested the change? Verify that the changes do not break functionality or introduce new warnings.
hatch run prepareAdded a
test_resolve_extraction_configsuite (ported from the TS resolver tests) covering thebool shorthand, trigger defaulting/normalization, capability-based extractor selection, and filter
defaulting. Existing coordinator and manager tests were updated to drive the resolved-config path;
the previously-raising "add-only store without an extractor" case now asserts the new
ModelExtractordefault behavior.Checklist
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.