Skip to main content

Type-guided externalized state for LLM agent frameworks.

Project description

AgentRef

Agent checkpoints should not have to carry your entire data plane.

AgentRef externalizes large workflow state into content-addressed storage while keeping only compact references in LangGraph, LlamaIndex, AutoGen, and Deep Agents-style checkpoints. It gives state fields two explicit roles:

  • Inline[T]: small control state kept directly in checkpoints
  • Externalized[T]: large values stored externally; checkpoints keep only a ContentRef

The goal is to make checkpoint write amplification hard to represent in user code. Assigning an Externalized field stores the serialized payload in CAS and keeps only a content-addressed reference in state.

Memory Impact

Local RSS measurements show lower peak memory when large state values are stored outside framework checkpoints. The Deep Agents row is from a real Deep Agents-based complex workflow after obvious large-payload trimming was already in place; the other rows are deterministic complex workflow benchmarks that preserve final output hashes.

Workload Scenario Baseline peak RSS AgentRef peak RSS Peak RSS reduction
LangGraph Quality-preserving complex benchmark, 3-run median 703.6 MiB 191.6 MiB 72.8%
LlamaIndex Quality-preserving complex benchmark, 3-run median 902.5 MiB 229.8 MiB 74.5%
AutoGen Quality-preserving complex benchmark, 3-run median 659.1 MiB 243.3 MiB 63.1%
Deep Agents-based complex workflow Real workflow, 10 concurrent runs 1.056 GiB 803.4 MiB 25.7%

For the Deep Agents-based workflow, idle RSS for the application process was effectively unchanged (267.6 MiB baseline vs. 266.5 MiB with AgentRef). On an idle-adjusted basis, application RSS growth fell 34.0% (813.7 MiB -> 536.9 MiB). The companion Postgres process peak fell 35.6% (331.8 MiB -> 213.6 MiB), and its idle-adjusted RSS growth fell 41.0%. Both variants completed 10/10 runs.

These numbers are local benchmark results. They are intended to show memory behavior for comparable before/after workloads, not to claim universal absolute RSS values across machines.

Install

The PyPI distribution is agent-checkpoint-cas; the Python import package stays agentref.

With pip:

pip install agent-checkpoint-cas

Optional framework integrations are split by extra:

pip install "agent-checkpoint-cas[langgraph]"
pip install "agent-checkpoint-cas[llamaindex]"
pip install "agent-checkpoint-cas[autogen]"
pip install "agent-checkpoint-cas[postgres]"
pip install "agent-checkpoint-cas[all]"

With uv in a project:

uv add agent-checkpoint-cas
uv add "agent-checkpoint-cas[langgraph]"
uv add "agent-checkpoint-cas[llamaindex]"
uv add "agent-checkpoint-cas[autogen]"
uv add "agent-checkpoint-cas[postgres]"
uv add "agent-checkpoint-cas[all]"

With uv in the current environment:

uv pip install agent-checkpoint-cas

Usage

Declare State

from agentref import AgentRefState, Externalized, Inline


class ResearchState(AgentRefState):
    current_step: Inline[str]
    iteration: Inline[int]
    citations: Inline[list[str]]
    retrieved_docs: Externalized[list[dict]]
    raw_html: Externalized[str]

LangGraph

from langgraph.graph import StateGraph

from agentref import AgentRefState, Externalized, Inline
from agentref.adapters.langgraph import LangGraphAdapter
from agentref.storage import FilesystemCAS


class RAGState(AgentRefState):
    question: Inline[str]
    docs: Externalized[list[dict]]
    answer: Inline[str]


adapter = LangGraphAdapter(
    RAGState,
    backend=FilesystemCAS("./state_blobs"),
    inline_threshold_bytes=64 * 1024,
)


def retrieve(state):
    docs = [{"id": "doc-1", "text": "large retrieved text"}]
    return {"docs": docs}


def answer(state):
    return {"answer": f"Read {len(state['docs'])} document(s)."}


graph = StateGraph(adapter.schema())
graph.add_node("retrieve", adapter.wrap_node(retrieve))
graph.add_node("answer", adapter.wrap_node(answer))

LlamaIndex Workflow

from agentref import AgentRefState, Externalized, Inline
from agentref.adapters.llamaindex import LlamaIndexAdapter
from agentref.storage import FilesystemCAS


class WorkflowState(AgentRefState):
    current_step: Inline[str]
    docs: Externalized[list[dict]]


adapter = LlamaIndexAdapter(
    WorkflowState,
    backend=FilesystemCAS("./state_blobs"),
)


async def retrieve_step(ctx):
    store = adapter.context_store(ctx.store)
    await store.set("current_step", "retrieve")
    await store.set("docs", [{"id": "doc-1", "text": "large retrieved text"}])

await store.get("docs") hydrates on read, while await store.to_checkpoint_dict() keeps only ContentRef values for externalized fields.

AutoGen

AutoGen does not expose one stable state schema across versions. AgentRef therefore provides explicit helpers for state dictionaries and message-history payloads instead of monkeypatching Agent classes.

from agentref.adapters.autogen import AutoGenAdapter
from agentref.storage import FilesystemCAS

adapter = AutoGenAdapter(backend=FilesystemCAS("./state_blobs"))

history = adapter.externalize_message_history(
    [{"role": "worker", "tool_result": "large tool output"}],
    threshold_bytes=1024,
)

hydrated = adapter.hydrate_message_history(history)

See docs/autogen_limitations.md for the integration boundary.

Storage Backends

Use FilesystemCAS for local runs, benchmarks, and run-scoped temporary storage. Use PostgresCAS when checkpoints need persistent storage, TTL metadata, or operational cleanup.

Backend Best for Lifetime model Cleanup Notes
InMemoryCAS tests and ephemeral demos process lifetime process exit fastest option, not durable
FilesystemCAS local runs, benchmarks, run-scoped workflows directory lifetime delete the run directory or migrate/prune by hash simple durable storage, no built-in TTL
PostgresCAS production, persistent checkpoints, multi-worker apps database-managed lifetime expires_at plus prune_expired() TTL metadata, operational visibility, migration aliases

All backends are passed directly to adapters:

from agentref.adapters.langgraph import LangGraphAdapter
from agentref.storage import FilesystemCAS, InMemoryCAS, PostgresCAS

memory_adapter = LangGraphAdapter(RAGState, backend=InMemoryCAS())
local_adapter = LangGraphAdapter(RAGState, backend=FilesystemCAS("./state_blobs"))
postgres_adapter = LangGraphAdapter(
    RAGState,
    backend=PostgresCAS(
        dsn="postgresql://user:pass@localhost:5432/app",
        backend_id="postgres:agentref",
        default_ttl_seconds=7 * 24 * 3600,
    ),
)

PostgresCAS stores created_at, last_accessed_at, and expires_at metadata. Expired payloads are removed explicitly with backend.prune_expired(); AgentRef does not delete referenced objects automatically.

Existing filesystem payloads can be copied into Postgres without rewriting old checkpoints by configuring the Postgres backend with the old backend id as an alias:

from agentref.storage import FilesystemCAS, PostgresCAS, migrate_cas

old = FilesystemCAS("./state_blobs")
new = PostgresCAS(
    dsn="postgresql://user:pass@localhost:5432/app",
    backend_id="postgres:agentref",
    backend_aliases=[old.backend_id],
)

migrate_cas(old, new)

Invariants

The test suite covers these core invariants:

  • externalized payload bytes do not appear in checkpoint bytes
  • identical payloads produce identical content hashes
  • oversized inline values raise InlineSizeExceeded
  • checkpoint round trips preserve hydrated values
  • ambiguous framework auto-detection raises a clear error
  • older checkpoints can hydrate externalized values while CAS content exists

Examples

  • examples/langgraph_rag.py
  • examples/llamaindex_research_workflow.py
  • examples/autogen_multi_agent.py

Each example avoids importing optional framework packages at module import time, so the repository can be imported and tested without installing every framework.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

agent_checkpoint_cas-0.1.0.tar.gz (33.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

agent_checkpoint_cas-0.1.0-py3-none-any.whl (34.2 kB view details)

Uploaded Python 3

File details

Details for the file agent_checkpoint_cas-0.1.0.tar.gz.

File metadata

  • Download URL: agent_checkpoint_cas-0.1.0.tar.gz
  • Upload date:
  • Size: 33.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for agent_checkpoint_cas-0.1.0.tar.gz
Algorithm Hash digest
SHA256 6d2357cbc297920cde68ebd6407eec42f8fd266a13c5b3470b8cebf48c1143cc
MD5 3cafea17dde9b9664a8fdbebb411ac99
BLAKE2b-256 39ceea82c5c22287627d7f735de38b6999f8b007bbf0e8afdc859728281ade07

See more details on using hashes here.

Provenance

The following attestation bundles were made for agent_checkpoint_cas-0.1.0.tar.gz:

Publisher: publish.yml on myeolinmalchi/AgentRef

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file agent_checkpoint_cas-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for agent_checkpoint_cas-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 43780d3f5bee2103c743e4930f8c128f3a0b4a48d9d16a112900cf926db8af47
MD5 1dd9494febef3db4dff5282f738c987a
BLAKE2b-256 201c0abbac3fc8bf2d46ea5be7549af711a024dd5ebf4420c8aee49d2af6ecc1

See more details on using hashes here.

Provenance

The following attestation bundles were made for agent_checkpoint_cas-0.1.0-py3-none-any.whl:

Publisher: publish.yml on myeolinmalchi/AgentRef

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page