Documentation
¶
Overview ¶
Package session provides persistent conversation state management and conversation trimming strategies for bond agents.
Session Persistence ¶
The session package enables stateful conversations by persisting message history across requests. It defines the Store interface for storage backends and provides an InMemoryStore for development and testing.
Storage Backends ¶
The Store interface abstracts the persistence layer. Implementations include:
- InMemoryStore: Thread-safe, in-process store for development and testing.
- dynamostore.Store: DynamoDB-backed store for production (in sub-package).
Conversation Trimming ¶
Large language models have finite context windows. As conversations grow, the accumulated messages may exceed the model's capacity, causing errors or degraded responses. The agent.HistoryPolicy interface and concrete implementations select message subsets to fit within configured constraints while preserving conversation coherence.
Choose a trimming strategy and pass it to the TrimmingPlugin:
- SlidingWindowManager: retains the last N user/assistant pairs.
- TokenBudgetManager: trims to fit within a token budget.
Both strategies preserve system-level preamble messages and maintain the relative ordering of the original conversation.
Plugins ¶
The SessionPlugin registers hooks to automatically load and save conversation history, enabling stateful multi-turn conversations without modifying the agent loop:
store := session.NewInMemoryStore()
plugin := session.NewSessionPlugin(session.SessionPluginOptions{
Store: store,
ResolveID: func(ctx context.Context) (string, error) { return "user-123", nil },
})
The TrimmingPlugin integrates via bond's hook system, trimming messages before each model invocation. Optional auto-recovery detects bond.ErrContextOverflow from providers and retries with a trimmed history.
Deep Copy Semantics ¶
All store implementations must deep-copy messages on Save and Load to prevent aliasing between the caller's data and the stored data. The InMemoryStore implements this guarantee.
Index ¶
- type InMemoryStore
- type SessionIDResolver
- type SessionPlugin
- type SessionPluginOptions
- type SlidingWindowManager
- type SlidingWindowOptions
- type Store
- type SummarizationManager
- type SummarizationManagerOptions
- type Summarizer
- type TokenBudgetManager
- type TokenBudgetOptions
- type TokenCounter
- type TrimmingPlugin
- type TrimmingPluginOptions
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type InMemoryStore ¶
type InMemoryStore struct {
// contains filtered or unexported fields
}
InMemoryStore is a thread-safe, in-process SessionStore for development and testing. It stores sessions in a Go map protected by a sync.RWMutex. All Save and Load operations use deep copies to prevent aliasing with caller data.
func NewInMemoryStore ¶
func NewInMemoryStore() *InMemoryStore
NewInMemoryStore creates a new InMemoryStore ready for use.
type SessionIDResolver ¶
SessionIDResolver extracts a session ID from the context. This allows the caller to control session identification (e.g., from HTTP headers, A2A task IDs, or explicit configuration).
type SessionPlugin ¶
type SessionPlugin struct {
// contains filtered or unexported fields
}
SessionPlugin automatically loads session history before streaming and saves conversation turns as they are appended.
func NewSessionPlugin ¶
func NewSessionPlugin(opts SessionPluginOptions) *SessionPlugin
NewSessionPlugin creates a SessionPlugin with the given options.
func (*SessionPlugin) Init ¶
func (p *SessionPlugin) Init(registry *bond.HookRegistry)
Init registers hooks on the provided registry. Requirement: CONV-9.3, CONV-9.5 — load session history before stream Requirement: CONV-9.4, CONV-9.6 — save on message append
func (*SessionPlugin) Name ¶
func (p *SessionPlugin) Name() string
Name identifies the plugin (used for logging/debugging).
func (*SessionPlugin) Tools ¶
func (p *SessionPlugin) Tools() []bond.Tool
Tools returns nil — the session plugin contributes no tools.
type SessionPluginOptions ¶
type SessionPluginOptions struct {
// Store is the backing SessionStore.
Store Store
// ResolveID extracts the session ID from the context.
ResolveID SessionIDResolver
}
SessionPluginOptions configures the SessionPlugin.
type SlidingWindowManager ¶
type SlidingWindowManager struct {
// contains filtered or unexported fields
}
SlidingWindowManager keeps the last N user/assistant message pairs, always preserving the system preamble (messages before the first user message).
func NewSlidingWindowManager ¶
func NewSlidingWindowManager(opts SlidingWindowOptions) (*SlidingWindowManager, error)
NewSlidingWindowManager creates a SlidingWindowManager. Returns an error if opts.WindowSize <= 0.
func (*SlidingWindowManager) Select ¶ added in v0.10.0
func (m *SlidingWindowManager) Select(_ context.Context, messages []bond.Message) ([]bond.Message, error)
Select returns a subset of messages that retains at most the last N user/assistant pairs, prepended with the system preamble. A "pair" is defined as a user message followed by zero or more assistant messages until the next user message. If the total number of pairs is within the window size, the original slice is returned unchanged.
type SlidingWindowOptions ¶
type SlidingWindowOptions struct {
// WindowSize is the maximum number of user/assistant message pairs to retain.
// Must be positive.
WindowSize int
}
SlidingWindowOptions configures a SlidingWindowManager.
type Store ¶
type Store interface {
// Load retrieves the stored messages for the given session.
// Returns an empty slice (not nil) and nil error if no data exists.
Load(ctx context.Context, sessionID string) ([]bond.Message, error)
// Save persists the message slice for the given session, overwriting any previous data.
Save(ctx context.Context, sessionID string, messages []bond.Message) error
}
Store persists and retrieves conversation history keyed by session ID.
type SummarizationManager ¶ added in v0.10.0
type SummarizationManager struct {
// contains filtered or unexported fields
}
SummarizationManager wraps a fallback agent.HistoryPolicy, summarizing dropped messages via an LLM instead of discarding them. When the fallback policy trims messages from the conversation, this manager invokes the Summarizer to condense the dropped portion into a single message that is prepended to the retained history.
The dropped-message computation assumes the fallback policy retains a contiguous suffix of the input (as SlidingWindowManager and TokenBudgetManager do). Custom fallback policies that retain non-contiguous subsets may produce incorrect summaries.
func NewSummarizationManager ¶ added in v0.10.0
func NewSummarizationManager(opts SummarizationManagerOptions) (*SummarizationManager, error)
NewSummarizationManager creates a SummarizationManager. Returns an error if opts.Summarizer or opts.Fallback is nil.
func (*SummarizationManager) Select ¶ added in v0.10.0
func (m *SummarizationManager) Select(ctx context.Context, messages []bond.Message) ([]bond.Message, error)
Select implements agent.HistoryPolicy. It identifies messages dropped by the fallback policy, summarizes them via the configured Summarizer, and returns the system preamble followed by the summary message and the retained conversation messages. If the Summarizer returns an error, Select gracefully degrades by returning the fallback result without a summary.
type SummarizationManagerOptions ¶ added in v0.10.0
type SummarizationManagerOptions struct {
// Summarizer produces summaries of dropped messages.
Summarizer Summarizer
// Fallback is the underlying policy that determines what to drop.
Fallback agent.HistoryPolicy
}
SummarizationManagerOptions configures a SummarizationManager.
type Summarizer ¶ added in v0.10.0
type Summarizer interface {
// Summarize condenses the given messages into a single summary message.
Summarize(ctx context.Context, messages []bond.Message) (bond.Message, error)
}
Summarizer produces a summary message from a slice of messages using an LLM. Implementations typically delegate to an agent or model call to condense conversation history into a single representative message.
type TokenBudgetManager ¶
type TokenBudgetManager struct {
// contains filtered or unexported fields
}
TokenBudgetManager trims messages to fit within a token budget, always preserving the system preamble and the most recent user message.
func NewTokenBudgetManager ¶
func NewTokenBudgetManager(opts TokenBudgetOptions) (*TokenBudgetManager, error)
NewTokenBudgetManager creates a TokenBudgetManager. Returns an error if opts.MaxTokens <= 0 or opts.Counter is nil.
func (*TokenBudgetManager) Select ¶ added in v0.10.0
func (m *TokenBudgetManager) Select(_ context.Context, messages []bond.Message) ([]bond.Message, error)
Select returns a subset of messages that fits within the configured token budget. The system preamble (messages before the first user message) and the most recent user message are always preserved. If these anchors alone exceed the budget, an error is returned. Otherwise, messages between the preamble and the last user message are included from newest to oldest until the budget is exhausted.
type TokenBudgetOptions ¶
type TokenBudgetOptions struct {
// MaxTokens is the maximum token budget. Must be positive.
MaxTokens int
// Counter estimates token usage for a slice of messages.
Counter TokenCounter
}
TokenBudgetOptions configures a TokenBudgetManager.
type TokenCounter ¶
TokenCounter estimates the token count for a message slice.
type TrimmingPlugin ¶
type TrimmingPlugin struct {
// contains filtered or unexported fields
}
TrimmingPlugin registers a BeforeModelInvokeHook that trims conversation history before each model invocation. It also provides auto-recovery from context overflow errors when configured.
func NewTrimmingPlugin ¶
func NewTrimmingPlugin(opts TrimmingPluginOptions) *TrimmingPlugin
NewTrimmingPlugin creates a TrimmingPlugin with the given options. If AutoRecover is true and MaxRetries is 0, MaxRetries defaults to 1.
func (*TrimmingPlugin) Init ¶
func (p *TrimmingPlugin) Init(registry *bond.HookRegistry)
Init registers hooks on the provided registry. Requirement: CONV-4.2, CONV-4.3, CONV-4.4, CONV-4.5 — BeforeModelInvokeHook registration
func (*TrimmingPlugin) Name ¶
func (p *TrimmingPlugin) Name() string
Name identifies the plugin (used for logging/debugging).
func (*TrimmingPlugin) Recover ¶
func (p *TrimmingPlugin) Recover(ctx context.Context, err error, messages []bond.Message) ([]bond.Message, error)
Recover attempts to recover from a context overflow error by trimming messages and tracking retry attempts. It should be called by the agent loop or client code when a provider returns ErrContextOverflow.
Requirement: CONV-5.1, CONV-5.2, CONV-5.3, CONV-5.4, CONV-5.5
Returns the trimmed messages on success. Returns an error if:
- auto-recovery is not enabled
- the error is not a context overflow error
- max retries have been exhausted
- the select operation itself fails
func (*TrimmingPlugin) ResetRetries ¶
func (p *TrimmingPlugin) ResetRetries()
ResetRetries resets the retry counter, allowing auto-recovery attempts again. This should be called at the start of a new stream or conversation turn.
func (*TrimmingPlugin) Tools ¶
func (p *TrimmingPlugin) Tools() []bond.Tool
Tools returns nil — the trimming plugin contributes no tools.
type TrimmingPluginOptions ¶
type TrimmingPluginOptions struct {
// Policy is the history policy to invoke on each hook.
Policy agent.HistoryPolicy
// AutoRecover enables automatic retry on ErrContextOverflow.
AutoRecover bool
// MaxRetries is the maximum number of trim-and-retry attempts.
// Defaults to 1 if AutoRecover is true and MaxRetries is 0.
MaxRetries int
}
TrimmingPluginOptions configures the TrimmingPlugin.