Source code for zett_agent.extensions.memory

"""In-memory conversation accumulation exposed as an Agent extension."""

from ..agent import AgentRunContext
from ..messages import AnyMessage, SystemMessage
from .base import AgentExtension
from .events import CompactionEvent, ExtensionEvent, MessageAppendedEvent


[docs] class InMemoryMessageAccumulator(AgentExtension): """Retain replayable conversation messages for reuse by later requests. Messages with ``include_in_messages=False`` belong to the current request only. System instructions are rebuilt for every request and therefore do not accumulate stale prompts when an Agent or its tool guidance changes. """ def __init__(self) -> None: self._sessions: dict[str, list[AnyMessage]] = {}
[docs] async def on_state(self, context: AgentRunContext) -> None: """Combine current instructions with an independent copy of remembered dialogue.""" state = context.state instructions = [message for message in state.messages if isinstance(message, SystemMessage)] current_dialogue: list[AnyMessage] = [ message for message in state.messages if message.include_in_messages and not isinstance(message, SystemMessage) ] remembered = self._sessions.get(context.session_id) if remembered is None: remembered = list(current_dialogue) self._sessions[context.session_id] = remembered context.replace_messages([*instructions, *remembered], emit_new=False)
[docs] async def on_event(self, context: AgentRunContext, event: ExtensionEvent) -> None: """Accumulate raw messages and replace dialogue after successful compaction.""" session_id = context.session_id match event: case MessageAppendedEvent(message=message) if not message.include_in_messages: return case MessageAppendedEvent(message=message): self._sessions.setdefault(session_id, []).append(message) case CompactionEvent(): self._sessions[session_id] = [ message for message in context.state.messages if message.include_in_messages and not isinstance(message, SystemMessage) ]
[docs] def messages(self, session_id: str) -> tuple[AnyMessage, ...]: """Return remembered dialogue without request-specific system instructions.""" return tuple(self._sessions.get(session_id, ()))
[docs] def clear(self, session_id: str) -> None: """Forget one session without changing other accumulated sessions.""" self._sessions.pop(session_id, None)