langchain-ai/deepagents · error · ValueError

Offload operation must use the agent's composite backend

Error message

Offload operation must use the agent's composite backend

What it means

`attach_offload_operation` publishes an OffloadOperation onto the agent's CompositeBackend via a private attribute. Before doing so it checks that the summarization middleware bound inside the operation's compaction is wired to that same backend; if the operation references a different backend instance, it raises ValueError so archive writes never bypass the composite backend.

Source

Thrown at libs/code/deepagents_code/offload_middleware.py:737

    backend: CompositeBackend,
    operation: OffloadOperation,
) -> None:
    """Publish the operation on the backend shared with the server runtime.

    Args:
        backend: Composite backend owned by the agent server.
        operation: Offload implementation bound to that backend.

    Raises:
        ValueError: If compaction writes through a different backend.
    """
    # The SDK requires `backend` in its constructor, so a real summarization
    # middleware always has one; `None` here means a test double, which is
    # allowed through rather than asserted against.
    bound = getattr(operation._compaction._summarization, "_backend", None)
    if bound is not None and bound is not backend:
        msg = "Offload operation must use the agent's composite backend"
        raise ValueError(msg)
    setattr(backend, _OFFLOAD_OPERATION_ATTR, operation)


def offload_operation_from(backend: CompositeBackend) -> OffloadOperation | None:
    """Return the server operation published on `backend`, when available."""
    operation = getattr(backend, _OFFLOAD_OPERATION_ATTR, None)
    return operation if isinstance(operation, OffloadOperation) else None


def _event_cutoff(event: object) -> int:
    """Return the absolute cutoff index carried by a `_summarization_event`.

    Args:
        event: A `_summarization_event` mapping (as persisted in state), or
            `None`.

    Returns:
        The `cutoff_index`, or `0` when the event is missing or malformed.

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Create the OffloadOperation using the same CompositeBackend instance passed to the agent (via `create_cli_agent`).
  2. Rebuild the operation after any backend reconstruction, then re-attach.
  3. In tests, pass `None`-backed or matching test doubles — only mismatched real backends raise.

Example fix

// before
op = build_offload_operation(old_backend)
agent = create_cli_agent(backend=new_backend, offload_operation=op)
// after
backend = CompositeBackend(...)
op = build_offload_operation(backend)
agent = create_cli_agent(backend=backend, offload_operation=op)
Defensive patterns

Strategy: validation

Validate before calling

assert agent.backend is backend, "agent and attach target must share one CompositeBackend"
assert offload_operation_from(backend) is not None, "operation not attached"

Type guard

def operation_matches_backend(operation: OffloadOperation, backend: CompositeBackend) -> bool:
    bound = getattr(operation._compaction._summarization, "_backend", None)
    return bound is None or bound is backend

Try / catch

try:
    attach_offload_operation(backend, operation)
except ValueError as e:
    if "composite backend" in str(e):
        operation = rebuild_operation(backend)  # recreate against the live backend
        attach_offload_operation(backend, operation)

Prevention

When it happens

Trigger: Calling `attach_offload_operation(backend, operation)` where `operation._compaction._summarization._backend` is a different CompositeBackend instance — e.g. building the operation against one backend and the agent against another, or rebuilding the agent after the operation was created.

Common situations: Agent reconstruction on config reload while reusing a stale OffloadOperation; constructing separate CompositeBackend objects in tests/DI wiring; order-of-initialization mistakes where the backend is recreated after attach.

Related errors


AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29). Data as JSON: /api/errors/d5ee9fe8598840c7. Report an issue: GitHub.