Implementation:Langchain ai Langgraph SerializerProtocol
| Knowledge Sources | |
|---|---|
| Domains | Serialization, Protocol |
| Last Updated | 2026-02-11 16:00 GMT |
Overview
Defines the core protocol interfaces for serialization (`SerializerProtocol`) and encryption (`CipherProtocol`) used throughout LangGraph's checkpoint and cache subsystems.
Description
The SerializerProtocol module establishes the foundational contracts that all serializers and ciphers in LangGraph must satisfy. The `SerializerProtocol` is a `runtime_checkable` Protocol class requiring two methods: `dumps_typed` which serializes an object to a `(type_string, bytes)` tuple, and `loads_typed` which deserializes from that same tuple format. The typed approach preserves encoding metadata alongside the raw bytes, enabling heterogeneous storage backends to correctly reconstruct objects without out-of-band type information.
The module also provides `UntypedSerializerProtocol` for simpler serializers that only implement `dumps(obj) -> bytes` and `loads(data) -> Any`, along with `SerializerCompat`, an adapter class that wraps an untyped serializer to conform to the typed protocol. The `maybe_add_typed_methods` utility function automatically wraps legacy serializers when needed, ensuring backwards compatibility as the serialization API evolved.
The `CipherProtocol` defines the encryption contract with `encrypt(plaintext) -> (cipher_name, ciphertext)` and `decrypt(cipher_name, ciphertext) -> plaintext`. This protocol is used by `EncryptedSerializer` to layer encryption on top of any serializer. The cipher name is included in the output to support multiple encryption algorithms and key rotation scenarios.
Usage
Use these protocols when implementing custom serializers or ciphers for LangGraph checkpointers and caches. Any object satisfying `SerializerProtocol` can be passed to checkpoint savers and cache backends. Standard Python modules like `pickle`, `json`, and `orjson` can serve as valid implementations when wrapped appropriately.
Code Reference
Source Location
- Repository: Langchain_ai_Langgraph
- File: libs/checkpoint/langgraph/checkpoint/serde/base.py
Signature
class SerializerProtocol(Protocol):
def dumps_typed(self, obj: Any) -> tuple[str, bytes]: ...
def loads_typed(self, data: tuple[str, bytes]) -> Any: ...
class CipherProtocol(Protocol):
def encrypt(self, plaintext: bytes) -> tuple[str, bytes]: ...
def decrypt(self, ciphername: str, ciphertext: bytes) -> bytes: ...
class UntypedSerializerProtocol(Protocol):
def dumps(self, obj: Any) -> bytes: ...
def loads(self, data: bytes) -> Any: ...
class SerializerCompat(SerializerProtocol):
def __init__(self, serde: UntypedSerializerProtocol) -> None: ...
def maybe_add_typed_methods(
serde: SerializerProtocol | UntypedSerializerProtocol,
) -> SerializerProtocol: ...
Import
from langgraph.checkpoint.serde.base import SerializerProtocol, CipherProtocol
I/O Contract
SerializerProtocol
| Method | Input | Output | Description |
|---|---|---|---|
| `dumps_typed` | `obj: Any` | `tuple[str, bytes]` | Serializes an object to a `(type_name, raw_bytes)` tuple |
| `loads_typed` | `data: tuple[str, bytes]` | `Any` | Deserializes an object from a `(type_name, raw_bytes)` tuple |
CipherProtocol
| Method | Input | Output | Description |
|---|---|---|---|
| `encrypt` | `plaintext: bytes` | `tuple[str, bytes]` | Encrypts plaintext; returns `(cipher_name, ciphertext)` |
| `decrypt` | `ciphername: str, ciphertext: bytes` | `bytes` | Decrypts ciphertext using the named cipher; returns plaintext |
SerializerCompat
| Behavior | Description |
|---|---|
| `dumps_typed` | Returns `(type(obj).__name__, serde.dumps(obj))` |
| `loads_typed` | Calls `serde.loads(data[1])`, ignoring the type string |
Usage Examples
from langgraph.checkpoint.serde.base import (
SerializerProtocol,
CipherProtocol,
maybe_add_typed_methods,
)
# Check if an object implements the protocol
import json
class JsonSerializer:
def dumps_typed(self, obj):
return ("json", json.dumps(obj).encode())
def loads_typed(self, data):
return json.loads(data[1])
serde = JsonSerializer()
assert isinstance(serde, SerializerProtocol)
# Wrap a legacy untyped serializer
import pickle
class PickleSerde:
def dumps(self, obj):
return pickle.dumps(obj)
def loads(self, data):
return pickle.loads(data)
typed_serde = maybe_add_typed_methods(PickleSerde())
typ, raw = typed_serde.dumps_typed({"key": "value"})
print(typ) # "dict"
restored = typed_serde.loads_typed((typ, raw))
print(restored) # {"key": "value"}