FrostAgent gives every user and every group chat its own isolated conversation history. A session holds the ordered list ofDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/GuaiZai233/FrostAgent/llms.txt
Use this file to discover all available pages before exploring further.
ChatMessage objects that the Engine sends to the LLM on each turn, so the model has the context it needs to give coherent, context-aware replies. Sessions live in memory, are automatically created on first use, and are evicted after 24 hours of inactivity.
SessionManager
SessionManager (defined in internal/llm/session.go) is the registry for all active sessions. The Engine holds a single *SessionManager instance for its entire lifetime.
Creating a manager
NewSessionManager returns a manager with sensible defaults and immediately starts a background cleanup goroutine:
| Field | Default | Purpose |
|---|---|---|
MaxHistory | 20 | Maximum non-system messages kept per session after each RunWithSession call. |
TTL | 24h | Sessions not updated within this window are removed by the cleanup routine. |
Methods
GetOrCreate(sessionID string) *SessionContext
Returns the existing session for sessionID, or creates and stores a new one if it does not exist yet. Uses a double-checked locking pattern — a read lock is tried first; only on a miss is a write lock acquired.
Count() int
Returns the current number of live sessions.
ListSessions(offset, limit int) []*SessionContext
Returns a paginated slice of session contexts. Ordering depends on map iteration order (non-deterministic). Pass limit <= 0 to retrieve all sessions from offset to the end.
Cleanup()
Iterates every session and deletes those whose UpdatedAt is older than TTL. Called automatically by the background goroutine every hour; can also be called manually for testing or forced eviction.
Delete(sessionID string)
Removes a specific session immediately, regardless of its age.
SessionContext
SessionContext is the per-session object. It holds the conversation history and exposes thread-safe methods for reading and writing it.
Locking
Lock() and Unlock() give external callers explicit control over the session mutex. The Engine’s RunWithSession uses them to guard the full read-modify-write cycle:
Snapshot() []ChatMessage
Returns a deep copy of History. ToolCalls slices inside each message are independently copied so mutations to the snapshot cannot corrupt the stored history.
ReplaceMessages(messages []ChatMessage)
Atomically replaces the entire history with a deep copy of the supplied slice and updates UpdatedAt. Used to write trimmed history back after a RunWithSession call.
AddMessage(msg core.ChatMessage)
Appends a single core.ChatMessage (converting it to the internal llm.ChatMessage representation) under the session lock and bumps UpdatedAt. Used by the OneBot adapter to record user and assistant messages independently of the Engine loop.
Messages() []core.ChatMessage
Returns the full history as a []core.ChatMessage slice, converting from the internal representation. Acquires the session lock internally.
Clear()
Resets History to nil and updates UpdatedAt. Useful for implementing user-facing “forget this conversation” commands.
Session IDs
Session identifiers are string keys assigned by the OneBot adapter inhistoryKey:
| Format | Used for |
|---|---|
group:<group_id> | Group chat — all members share one context window |
private:<user_id> | Direct message — one context window per user |
Context Trimming
Two utility functions ininternal/llm/context.go help manage message length independently of the Engine’s session-write trimmer.
TrimMessages(messages []ChatMessage, limit int) []ChatMessage
Keeps all system-role messages and trims non-system messages to the most recent limit entries. Unlike the Engine’s trimMessagesForSession, this function does not inspect tool-call chains, so use it only when you are certain the trim boundary will not split a tool call / tool result pair.
ApproxTokenCount(messages []ChatMessage) int
Provides a lightweight token estimate for a message slice. It adds 4 tokens of overhead per message (for role and structural tokens) and estimates content length at roughly 1 token per 4 Unicode runes. Tool call fields (ID, Type, function name, arguments) and ToolCallID are included in the estimate.
ApproxTokenCount is a heuristic, not an exact tokeniser. For English text the estimate is typically within 10–15 % of the actual BPE token count. For Chinese text the rune-based estimate can be less accurate; validate against your model’s context limit if you hit truncation errors.TTL Cleanup
startCleanupRoutine runs in a background goroutine started by NewSessionManager. It ticks every hour and calls Cleanup:
Cleanup acquires the manager write lock, then briefly locks each session to read its UpdatedAt field. Sessions older than TTL (24 h by default) are deleted from the map. The cleanup routine does not stop when sessions are empty — it runs for the lifetime of the process.
Example: Stateful Session with RunWithSession
RunWithSession appends the user message to the stored history, runs the loop, and writes back a trimmed snapshot — so the next call automatically picks up where the last one left off.