Context Manager

In shortBaseContextManager and MessageContextManager — trim and bound the agent's message history before each LLM call.

  • 2 min read
  • 7 sections
  • Updated
  • v0.9.2
  • Markdown

When to use this

Use a context manager when your agents run long multi-turn conversations and you need to keep the message history within the LLM’s context window. The context manager is called on every Agent node invocation that has trim_context=True.

Import path

Python
from tenxgraph.core.state import BaseContextManager, MessageContextManager

MessageContextManager

The built-in implementation. Keeps the most recent N user messages plus all system messages.

Python
from tenxgraph.core.state import MessageContextManager

ctx_mgr = MessageContextManager(
    max_messages=10,
    remove_tool_msgs=False,
)

graph = StateGraph(context_manager=ctx_mgr)

Constructor parameters

Parameter Type Default Description
max_messages int 10 Maximum number of user-role messages to keep. Older messages are dropped.
remove_tool_msgs bool False If True, also remove AI messages containing tool calls and their corresponding tool result messages before counting.

Preservation guarantee

Messages with role == "system" are never trimmed regardless of max_messages. They are prepended to the front of every trimmed window.

Methods

Method Signature Description
trim_context (state: S) → S Synchronous trim. Returns the state with context replaced by the trimmed list, or the original state if no trimming was needed.
atrim_context async (state: S) → S Async version. Internally delegates to trim_context.

BaseContextManager

Abstract base class. Subclass this to implement custom trimming strategies.

Python
from tenxgraph.core.state import BaseContextManager, AgentState
from typing import TypeVar

S = TypeVar("S", bound=AgentState)

class MyContextManager(BaseContextManager[S]):

    def trim_context(self, state: S) -> S:
        # return state with state.context modified
        ...

    async def atrim_context(self, state: S) -> S:
        return self.trim_context(state)

Abstract methods

Method Signature Description
trim_context (state: S) → S Must implement. Trim state.context and return the updated state.
atrim_context async (state: S) → S Must implement. Async version.

Both methods receive the full AgentState (or custom subclass) and must return it after modifying state.context in place or replacing it.


Where it fits in the graph

plaintext
graph.compile()
  └── Agent node (trim_context=True)
        └── calls context_manager.atrim_context(state)
              before sending messages to the LLM provider

The context manager is called at the start of each Agent invocation, before the LLM API call. The trimmed state is used only for that invocation; the full state is still written to the checkpointer.


Dependency injection

The context manager is registered in the dependency container automatically when you pass it to StateGraph. Node functions can receive it via injection if needed:

Python
from injectq import Inject
from tenxgraph.core.state import BaseContextManager

async def my_node(
    state,
    config: dict,
    ctx_mgr: BaseContextManager | None = Inject[BaseContextManager],
) -> ...:
    if ctx_mgr:
        state = await ctx_mgr.atrim_context(state)
    return state

Common errors

Error Cause Fix
Context grows unbounded despite trim_context=True context_manager= not passed to StateGraph(...). Add context_manager=MessageContextManager() to StateGraph.
atrim_context not found Custom class only impl trim_context, not atrim_context. Both abstract methods must be implemented.
System prompt is being dropped System message role is not "system". Ensure role="system" — the check is exact string equality.
Last updated for v0.9.2Edit this page on GitHubReport an issue