-
Notifications
You must be signed in to change notification settings - Fork 30
feat: Upgrade to LangGraph 1.0 and Checkpoint 3.0 (#110) #120
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
dd7d686 to
c3b0acf
Compare
- Upgrade langgraph-checkpoint from >=2.0.21,<3.0.0 to >=3.0.0,<4.0.0 - Upgrade redisvl from >=0.5.1,<1.0.0 to >=0.11.0,<1.0.0 - Update Python requirement from >=3.9,<3.14 to >=3.10,<3.14 (Python 3.9 EOL) - Remove Python 3.9 from classifiers - Update Black target-version to remove py39 BREAKING CHANGE: Drops Python 3.9 support, now requires Python 3.10+ Addresses security vulnerability CVE-2025-64439 in langgraph-checkpoint
- Update dumps_typed signature to return tuple[str, bytes] (was tuple[str, str]) - Update loads_typed signature to accept tuple[str, bytes] - Remove dumps() and loads() methods (not in SerializerProtocol anymore) - Use orjson with custom _default_handler for LangChain object serialization - Leverage parent's _encode_constructor_args for LC format encoding - Use parent's _reviver for security-checked deserialization - Maintain Interrupt object handling from Issue #113 fix - Add msgpack backward compatibility for old checkpoints BREAKING CHANGE: dumps_typed/loads_typed signatures changed for checkpoint 3.0 The SerializerProtocol interface changed in checkpoint 3.0 to use only dumps_typed and loads_typed (dumps/loads removed), and the signatures now use bytes instead of strings. Addresses CVE-2025-64439 security fix in parent class.
- Replace serde.dumps()/serde.loads() with serde.dumps_typed()/serde.loads_typed() - Update _load_metadata and _dump_metadata to use new API - Fixes type errors in base.py
- Replace serializer.dumps()/loads() with dumps_typed()/loads_typed() - Add helper functions in test_jsonplus_serializer_default_handler.py - Update test_issue_113_interrupt_serialization.py - Update test_checkpoint_serialization.py - Update test_issue_85_message_coercion.py All test files now use the new SerializerProtocol API from checkpoint 3.0
- Add _encode_blob() calls in put_writes() and _dump_writes() - Blob data from dumps_typed() is now bytes (not string) - Must base64-encode before storing in Redis JSON - Fixes TypeError: Object of type bytes is not JSON serializable
- Add _encode_blob() in RedisSaver.put_writes() (__init__.py) - Add _encode_blob() in AsyncRedisSaver.aput_writes() (aio.py) - Both sync and async implementations now properly encode blob bytes - Completes blob encoding fix across all implementations
- Add _encode_blob() in ShallowRedisSaver.put_writes() - Add _encode_blob() in AsyncShallowRedisSaver.aput_writes() - Completes blob encoding fix across ALL implementations (regular and shallow)
…allback Call super()._load_pending_writes() instead of self._load_pending_writes() in the registry fallback path to avoid infinite recursion between _load_pending_writes and _load_pending_writes_with_registry_check.
Add static _decode_blob_static() method to handle base64 decoding of blob data retrieved from Redis before passing to serializer. This fixes orjson.JSONDecodeError when loading pending writes.
Update blob assertions to decode base64 data before comparing. Blobs are now base64-encoded in Redis with checkpoint 3.0.
Update dumps_helper/loads_helper to preserve full (type_str, bytes) tuple. Update test_dumps_typed_with_messages to expect bytes not str.
- Add bytes detection in _default_handler to trigger msgpack serialization - Update dumps_typed to fallback to parent's msgpack for bytes in dicts - Update _dump_checkpoint to handle both JSON and msgpack types - Add __bytes__ marker for bytes in channel_values stored via msgpack - Update _recursive_deserialize to decode __bytes__ markers - Fix test assertions to expect bytes instead of str from dumps_typed
Update tests to unpack (type_str, bytes) tuple from dumps_helper instead of expecting just bytes.
Auto-format code with black and isort for checkpoint 3.0 changes.
Convert all dumps/loads calls to dumps_typed/loads_typed. Update blob assertion to expect bytes instead of str.
BREAKING CHANGE: Minimum Python version is now 3.10 (was 3.9) - Upgrade langgraph from 0.4.9 to 1.0.3 - Upgrade langchain-core from 0.3.74 to 1.0.5 - Upgrade langgraph-checkpoint from 2.x to 3.x - Add redisvl >=0.11.0 dependency (security fix CVE-2025-64439)
BREAKING CHANGE: Interrupt object structure changed in LangGraph 1.0 LangGraph 1.0 simplified the Interrupt class from 4 fields to 2 fields: - Removed: resumable, ns, when - Retained: value, id Updated JsonPlusRedisSerializer._revive_if_needed() to detect and reconstruct Interrupt objects using the new 2-field structure. Changes: - Check for len(obj) == 2 instead of len(obj) == 4 - Check for "id" field instead of "resumable" - Construct Interrupt(value=..., id=...) instead of old signature
Update all Interrupt object creation and assertions to use the new LangGraph 1.0 API with only 'value' and 'id' fields. Changes: - Replace Interrupt(value=..., resumable=...) with Interrupt(value=..., id=...) - Remove assertions on removed fields (resumable, ns, when) - Add assertions for new 'id' field - Update test documentation to reflect LangGraph 1.0 changes Files updated: - tests/test_issue_113_interrupt_serialization.py (3 tests) - tests/test_jsonplus_redis_serializer_v3.py (3 tests)
- Update redisvl version from >=0.5.1 to >=0.11.0 in Dockerfile and README - Fix .gitignore comment: /docs -> /examples - Fix README reference to parent directory mount path - Fix create-react-agent-hitl.ipynb to use uuid for unique thread IDs - Update notebook markdown to reference RedisStore instead of InMemoryStore - Update notebook markdown to reference RedisSaver instead of MemorySaver These changes ensure: 1. Security fix (CVE-2025-64439) via redisvl >=0.11.0 2. Accurate documentation matching actual implementations 3. Notebooks work correctly with checkpoint state isolation
….9 from CI - Add MIGRATION_0.2.0.md with detailed migration instructions for: * LangGraph 1.0 Interrupt API changes (4 fields → 2 fields) * Checkpoint 3.0 serialization changes (str → bytes) * Python 3.10+ requirement * Data migration strategies and troubleshooting - Rename MIGRATION.md to MIGRATION_0.1.0.md for version clarity - Remove Python 3.9 from CI test matrix (EOL and no longer supported) The migration guide covers: - Breaking changes with before/after code examples - Step-by-step migration process - Data compatibility and migration options - Comprehensive troubleshooting section - Testing recommendations
…cking
- Add client_setinfo calls in RedisSaver.configure_client() to register library version with Redis
- Update all set_client_info/aset_client_info methods to use __full_lib_name__ instead of __redisvl_version__
- Ensure graceful error handling with fallback to echo() and silent failure
- Remove redundant test_jsonplus_redis_serializer.py from root directory
- Update all client info tests to expect full library name format
- Add client_setinfo/echo mock methods to BaseMockRedis for cluster mode tests
BREAKING CHANGE: Client info now sends complete version string format:
redis-py(redisvl_v{version};langgraph-checkpoint-redis_v{version})
This provides better visibility in Redis CLIENT LIST for monitoring and debugging,
showing redis-py client, RedisVL version, and checkpoint-redis library version.
177c1ae to
2e1c882
Compare
- Move base64 imports to top of test files for better style (test_sync.py, test_async.py)
- Make exception handling more specific in _default_handler (AttributeError, KeyError, ValueError, TypeError instead of bare Exception)
- Fix false positive Interrupt detection by adding __interrupt__ type marker to prevent user data with {value, id} structure from being incorrectly deserialized as Interrupt objects
- Add _preprocess_interrupts helper to recursively tag Interrupt objects before orjson serialization
- Support preprocessing of nested structures (dicts, lists, tuples)
This prevents critical bug where user data like {"value": "data", "id": "user-id"}
would be incorrectly deserialized as Interrupt(value="data", id="user-id").
ef70dc1 to
7c3b86e
Compare
Add pytest filterwarnings to ignore DeprecationWarning from testcontainers library's internal use of @wait_container_is_ready decorator. These warnings come from testcontainers v4.13.3 (latest) and are not our code to fix. The testcontainers maintainers haven't updated their own internal code yet despite deprecating the decorator. Warnings suppressed: - testcontainers.core.waiting_utils (line 215) - testcontainers.redis (line 46) This keeps test output clean while we wait for upstream fix.
- Add missing 'Not needed for LangGraph API users' info box - Change 'LangGraph Cloud' to 'LangGraph Platform' terminology - Clear all outputs for clean execution - Verified against source notebook in langgraph docs Ready for end-to-end execution with Redis checkpoint implementation.
- Change 'LangGraph Cloud' to 'LangGraph Platform' terminology - Clear all outputs for clean execution Ready for end-to-end execution with Redis store and checkpoint implementations.
- Change 'LangGraph Cloud' to 'LangGraph Platform' terminology - Clear all outputs for clean execution Ready for end-to-end execution with Redis store and checkpoint implementations.
- Clear all outputs for clean execution - Ready for end-to-end execution with Redis checkpoint
- Clear all outputs for clean execution on create-react-agent-memory.ipynb - Clear all outputs for clean execution on create-react-agent-hitl.ipynb - Ready for end-to-end execution with Redis checkpoint
- Clear all outputs for clean execution on subgraph-persistence.ipynb - Clear all outputs for clean execution on subgraphs-manage-state.ipynb - Ready for end-to-end execution with Redis checkpoint
- Clear all outputs for clean execution on all 11 notebooks - 7 human_in_the_loop notebooks: breakpoints, dynamic_breakpoints, edit-graph-state, review-tool-calls-openai, review-tool-calls, time-travel, wait-user-input - 4 memory notebooks: add-summary-conversation-history, delete-messages, manage-conversation-history, semantic-search - Ready for end-to-end execution with Redis checkpoint
…mem objects - Add support for serializing/deserializing dataclass objects (e.g., RunningSummary) - Add special handling for sets in nested structures - Prevent loss of type information when dataclasses are serialized - Fix AttributeError when langmem SummarizationNode stores context in state Changes: - Preprocess dataclass instances to LangChain constructor format before serialization - Add _reconstruct_from_constructor() to rebuild objects from constructor format - Handle sets with special __set_items__ marker to preserve contents - Update _revive_if_needed() to detect when parent reviver returns unchanged dict Tests: - Add comprehensive test suite in test_langmem_serialization.py - Test roundtrip serialization of RunningSummary objects - Test nested dataclasses in dicts and lists - All 382 tests passing Fixes the error in create-react-agent-manage-message-history.ipynb where RunningSummary objects were being deserialized as dicts instead of proper objects, causing AttributeError: 'dict' object has no attribute 'summarized_message_ids'
Add pytest filter to suppress LangGraphDeprecatedSinceV10 warning from trustcall library (a dependency of langmem). The warning is about trustcall using deprecated 'from langgraph.constants import Send' instead of 'from langgraph.types import Send'. This is an issue in their library, not ours.
Add Redis flush command at the start of notebooks to clear old checkpoints that were created with the buggy serializer (before dataclass support was added). This is necessary because: 1. Jupyter kernels cache Python modules 2. Old checkpoints in Redis were serialized without dataclass support 3. Deserializing old checkpoints causes AttributeError even with fixed code The flush ensures notebooks start fresh with the updated serializer.
Replace deprecated claude-3-5-sonnet-20240620 with claude-3-5-sonnet-20241022 to fix NotFoundError when running notebook. The old model version reached end-of-life and returns 404 errors.
b3ee2e3 to
3822ea5
Compare
Add Python version check to skip langmem serialization tests on Python < 3.11. The langmem library uses typing.NotRequired which was introduced in Python 3.11, causing import failures on Python 3.10 in CI. Tests will: - Skip on Python 3.10 (379 tests run) - Run on Python 3.11+ (382 tests run) Fixes CI test collection failures on Python 3.10.
3822ea5 to
587b768
Compare
abrookins
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! 👍
The only thing I wondered about was whether we'd want to try and support old Interrupt data -- it seems like we skip trying to load an Interrupt if the new fields aren't present. I could have misunderstood that (in _revive_if_needed), but even if we did restore an Interrupt saved by an older version, I'm not sure that would actually work from the LangGraph side.
Upgrade to LangGraph 1.0 and Checkpoint 3.0
This PR completes the migration from LangGraph 0.4.x/Checkpoint 2.x to LangGraph 1.0.3/Checkpoint 3.0, addressing breaking API changes and ensuring full compatibility with the latest versions. Also ensures proper library version passed to RedisPY
Breaking Changes
Python Version Requirement
LangGraph 1.0 API Changes
Checkpoint 3.0 API Changes
Dependency Updates
Implementation Changes
Serialization Layer
Blob Storage
Metadata Handling
Test Suite
Documentation & Examples
Migration Notes
Users upgrading to this version should be aware:
Related Issues