Skip to main content

Purpose

Enable the agent to restore state across requests, process restarts, and multi-user scenarios. After each call() ends, two outputs are automatically persisted on parallel tracks:
  • StateModule snapshot (Memory, ToolExecutionContext, and other serializable state) — defaults to WorkspaceSession
  • Conversation JSONL (LLM context + full history) — goes through SessionTree, triggered by MemoryFlushManager.offloadMessages
The two are parallel, independent paths.

Trigger Points

Key Logic

Dual-Track Storage Layout

  • context/: WorkspaceSession extends JsonSession, base at agents/<agentId>/context/; each StateModule is stored per SessionKey → {key}.json in the sessionId subdirectory.
  • sessions/: SessionTree organizes a JSONL file as a id/parentId tree; the paired <sessionId>.log.jsonl is never compacted, used for auditing and session_search.

How RuntimeContext Aligns the Two Tracks

HarnessAgent.bindRuntimeContext does several things:
  1. Fill defaults: if session is null, use the defaultSession from build time (defaults to WorkspaceSession(workspace, agentId)); if sessionKey is null, try SimpleSessionKey.of(sessionId)SimpleSessionKey.of(agentName) in order.
  2. Distribute to hooks: workspaceContextHook, memoryFlushHook, sessionPersistenceHook, compactionHook all sync to this ctx — they can read sessionId during offload / saveTo.
  3. Link userIdRef: an AtomicReference<String> is updated to userId; the default NamespaceFactory → List.of(userId) uses this as a path prefix, enabling transparent multi-tenant isolation.
  4. Pre-load state: if both session and sessionKey are present, calls delegate.loadIfExists to overwrite current Memory. Does nothing if not found.

Default vs Custom Session

Multi-User Isolation at Two Levels

  • Session level: sessionId determines that context/<sessionId>/ and sessions/<sessionId>.jsonl are independent.
  • File level: userId + NamespaceFactory determines the file operation path prefix (the default LocalFilesystemWithShell reads userIdRef).

Session Index

After MemoryFlushManager.offloadMessages completes, WorkspaceManager.updateSessionIndex(agentId, sessionId, summary) merges a write into sessions/sessions.json. In another turn, the agent can use the session_list tool to see “what conversations this agent has had historically”.
  • Toolsession_search / session_list / session_history parameters
  • Memory — when offloadMessages is called, and how it feeds back into memory_search
  • FilesystemuserIdRef + NamespaceFactory multi-tenant path isolation
  • ArchitectureSessionPersistenceHook position in PostCallEvent / ErrorEvent