Skip to content

Adapters

Each adapter wires one MemoryRuntime into a framework and owns nothing else: identity derivation, turn capture, tool registration, result rendering, and the host-issued search in auto and hybrid. Both pass one shared contract suite. Install with --extra deepagents or --extra crewai.

retold.adapters.base

What every adapter shares: the protocol, principal derivation, policy text, context, and rendering.

An adapter owns three decisions only: who the principal is, when a turn happened, and when the session ended. Everything else, retrieval, admission, activation, and isolation, is the core's, and an adapter that starts making those decisions has stopped being an adapter.

Adapter

Bases: Protocol

The LLD 5 adapter contract, framework-neutral.

tools

tools() -> Sequence[Any]

The memory tools to register with the framework, already filtered by trigger mode.

principal_from_run

principal_from_run(run_context: Any) -> Principal

Derive the principal from trusted host configuration; never from model output.

end_session

end_session(run_context: Any) -> Thread | None

Close the session and return the extraction thread it started, when extraction is configured.

TurnContext dataclass

The last user turn and the last assistant turn, the context attached to every search.

turn_context

turn_context(
    store: Store,
    session_id: str | None,
    *,
    before_turn: int | None = None,
    steps_count: bool = False,
) -> TurnContext

Read the most recent user and assistant turns of a session from the store.

With steps_count the most recent tool turn also counts as the assistant side, which is the CrewAI shape: the task description plus the most recent step output.

args_model_from_schema

args_model_from_schema(
    name: str, schema: Mapping[str, Any]
) -> type[Any]

Build a pydantic model from one tool's JSON schema, for frameworks that validate through pydantic.

Nested objects become dictionaries and arrays of objects become lists of dictionaries; the handler validates the full structure against the JSON schema again, so nothing is lost by the flattening.

principal_from_mapping

principal_from_mapping(
    configurable: Mapping[str, Any],
    *,
    session_key: str = "thread_id",
) -> Principal

Build the principal from a host-supplied mapping; every identity comes from the host, none from the model.

policy_text

policy_text(
    trigger_mode: TriggerMode,
    base_prompt: str | None = None,
) -> str

LLD 13: the memory-use policy for the prompt prefix, varied by who triggers searches.

tool_names_for

tool_names_for(
    trigger_mode: TriggerMode,
) -> tuple[str, ...]

LLD 14.1: every tool in tool_only and hybrid; no memory_search in auto.

check_modes

check_modes(
    trigger_mode: TriggerMode, memory_mode: MemoryMode
) -> None

Refuse the one combination that would put memory in front of the model without a judge.

Host-issued search in auto and hybrid appends its results to the turn before the utility-aware path runs, so the model would see raw candidates whatever the admission policy went on to decide. The two mechanisms answer the same question and only one of them can own the answer, so the utility-aware path requires tool_only.

render_tool_result

render_tool_result(
    name: str,
    arguments: Mapping[str, Any],
    payload: Mapping[str, Any],
) -> str

Render one tool result for the model: search as the LLD 10.9 blocks, everything else as JSON.

recalled_memory_block

recalled_memory_block(
    queries: Sequence[str], payload: Mapping[str, Any]
) -> str | None

The block a host-issued search appends, or None when the search returned nothing.

retold.adapters.deepagents

The Deep Agents adapter: LangChain tools, a middleware for turns and host-issued memory, and session end.

The adapter reads identity from the run configuration the host passes to the graph, records every human, assistant, and tool message as a transcript turn through the session hooks, registers the five memory tools as LangChain tools, and, in the utility-aware modes, wraps each answer-producing model call in the orchestrator so memory reaches the model only when a judge says it would change the answer. Shadow mode runs the same path and never regenerates, so the served answer is the draft.

Requires the deepagents extra.

DeepAgentsMemoryAdapter

Wire one MemoryRuntime into a Deep Agents graph.

tools

tools() -> list[BaseTool]

The memory tools for this trigger mode, with the public schemas and no principal baked in.

principal_from_run

principal_from_run(run_context: Any) -> Principal

Identity from configurable; the session id is the thread id, or its idle-split continuation.

sync_messages

sync_messages(
    messages: Sequence[BaseMessage], run_context: Any
) -> Principal

Record every message not yet in the transcript, in order; return the principal to keep using.

host_search(
    principal: Principal, user_turn: str, message_id: str
) -> list[BaseMessage]

LLD 14.1: one relevance search per user turn, appended as a synthetic tool-call pair when non-empty.

RetoldMiddleware

Bases: AgentMiddleware[Any, Any, Any]

Turn capture, host-issued recall, and the utility-aware wrap around answer-producing model calls.

retold.adapters.crewai

The CrewAI adapter: tool wrappers, step callbacks, and an LLM proxy that carries the memory policy.

CrewAI drives a text-only model through a ReAct loop and hands the task to every model call, so the adapter has three parts. Tools wrap the handlers as BaseTool subclasses with pydantic argument models. Step callbacks record each tool result as a tool turn and each final answer as an assistant turn. The LLM proxy records the task description as the user turn on the first call of each task, adds the ambient profile to the system message in the utility-aware modes, appends the host-issued recalled block in auto and hybrid, and wraps an answer-producing first call in the orchestrator exactly as the Deep Agents middleware does. Shadow mode serves the draft by construction.

Identity is bound when the adapter is built, from the crew inputs and the agent role the host supplies; a CrewAI tool call carries no per-call configuration. Requires the crewai extra.

CrewAIMemoryAdapter

Wire one MemoryRuntime into a crew for one principal.

policy_text

policy_text(base_prompt: str | None = None) -> str

LLD 13 text for the agent's backstory; CrewAI has no separate system prompt slot.

step_callback

step_callback(step: Any) -> None

Record an action's tool result as a tool turn and a finish's output as an assistant turn.

CrewAI invokes the callback twice per tool use, first with the bare tool result and then with the action that carries the same result, so only steps that name a tool or carry a final output count.

task_callback

task_callback(output: Any) -> None

Record the task output when no step callback recorded it, so a host may use either hook.

begin_task

begin_task(description: str) -> Principal

The first model call of a task records its description as the user turn.

MemoryCrewTool

Bases: BaseTool

One memory tool for a crew; the principal is the adapter's, fixed by the host at construction.

MemoryLLM

Bases: BaseLLM

A proxy around the host's LLM. The host's model does the talking; the proxy applies the memory policy.