Documentation
¶
Overview ¶
Package agent implements the core agent loop.
Index ¶
- Constants
- type CapabilityTagStore
- type CapabilityWiring
- type ChannelDelegationWiring
- type ChannelLoopSource
- type ChannelOverviewConfig
- type ChannelOverviewProvider
- type ChannelProvider
- type Compactor
- type ContactContext
- type ContactLookup
- type ContactOriginPolicy
- type ContextRequest
- type CoreContextProvider
- type CoreContextProviderConfig
- type FailoverHandler
- type HintsFunc
- type IncompatibleModelError
- type InteractionRef
- type KBMenuHint
- type Loop
- func (l *Loop) ActiveTags(ctx context.Context) map[string]bool
- func (l *Loop) CheckpointSession(conversationID, label string) error
- func (l *Loop) CloseSession(conversationID, reason, carryForward string) error
- func (l *Loop) ConfigureCapabilityWiring(w CapabilityWiring)
- func (l *Loop) ConfigureChannelDelegation(w ChannelDelegationWiring)
- func (l *Loop) ConfigureSessionStores(w SessionStoreWiring)
- func (l *Loop) ConversationTranscript(conversationID string) string
- func (l *Loop) DropCapability(ctx context.Context, tag string) error
- func (l *Loop) GetContextWindow() int
- func (l *Loop) GetHistory(conversationID string) []memory.Message
- func (l *Loop) GetTokenCount(conversationID string) int
- func (l *Loop) HAInject() homeassistant.StateFetcher
- func (l *Loop) LastRunTags() map[string]bool
- func (l *Loop) MemoryStats() map[string]any
- func (l *Loop) Process(ctx context.Context, conversationID, message string) (string, error)
- func (l *Loop) RegisterAlwaysContextProvider(p TagContextProvider)
- func (l *Loop) RegisterTagContextProvider(tag string, p TagContextProvider)
- func (l *Loop) RequestCapability(ctx context.Context, tag string) error
- func (l *Loop) ResetCapabilities(ctx context.Context) ([]string, error)
- func (l *Loop) ResetConversation(conversationID string) error
- func (l *Loop) Router() *router.Router
- func (l *Loop) Run(ctx context.Context, req *Request, stream StreamCallback) (resp *Response, err error)
- func (l *Loop) SetCapabilityTagStore(store CapabilityTagStore)
- func (l *Loop) SetCapabilityTags(capTags map[string]config.CapabilityTagConfig, parsedTalents []talents.Talent)
- func (l *Loop) SetChannelTags(ct map[string][]string)
- func (l *Loop) SetEgoFile(path string)
- func (l *Loop) SetFailoverHandler(handler FailoverHandler)
- func (l *Loop) SetHAInject(fetcher homeassistant.StateFetcher)
- func (l *Loop) SetInjectFiles(paths []string)
- func (l *Loop) SetLensProvider(fn func() []string)
- func (l *Loop) SetOrchestratorTools(names []string)
- func (l *Loop) SetTagContextAssembler(a *TagContextAssembler)
- func (l *Loop) SetUsageRecorder(store *usage.Store, pricing map[string]config.PricingEntry, cat *fleet.Catalog)
- func (l *Loop) ShutdownArchive(conversationID string)
- func (l *Loop) SplitSession(conversationID string, atIndex int, atMessage string) error
- func (l *Loop) Tools() *tools.Registry
- func (l *Loop) ToolsJSON() string
- func (l *Loop) TriggerCompaction(ctx context.Context, conversationID string) error
- func (l *Loop) UseCapabilitySurface(surface []toolcatalog.CapabilitySurface)
- func (l *Loop) UseContactLookup(lookup ContactLookup)
- func (l *Loop) UseInjectFileVerifier(verifier func(context.Context, string, string) error)
- func (l *Loop) UseLiveRequestRecorder(recorder logging.RequestRecordFunc)
- func (l *Loop) UseModelRegistry(registry *fleet.Registry)
- func (l *Loop) UseModelRuntime(runtime *fleet.Runtime)
- type LoopOptions
- type LoopSnapshot
- type MemoryStore
- type Message
- type NoEligibleModelError
- type OpstateCapabilityTagStore
- type PhoneResolver
- type RelatedContact
- type Request
- type Response
- type SessionArchiver
- type SessionOrigin
- type SessionOriginAppliedRule
- type SessionOriginPolicyResult
- type SessionStoreWiring
- type StreamCallback
- type StreamEvent
- type TagContextAssembler
- func (a *TagContextAssembler) Build(ctx context.Context, req agentctx.ContextRequest) string
- func (a *TagContextAssembler) BuildRefs(ctx context.Context, refs []string) string
- func (a *TagContextAssembler) KBArticleTags() map[string]int
- func (a *TagContextAssembler) KBMenuHints() map[string]KBMenuHint
- func (a *TagContextAssembler) RegisterAlwaysProvider(p TagContextProvider)
- func (a *TagContextAssembler) RegisterTaggedProvider(tag string, p TagContextProvider)
- func (a *TagContextAssembler) TaggedProviders() map[string]TagContextProvider
- type TagContextAssemblerConfig
- type TagContextProvider
- type ToolCallRecorder
- type TrustPolicyView
Constants ¶
const ( KindToken = llm.KindToken KindToolCallStart = llm.KindToolCallStart KindToolCallDone = llm.KindToolCallDone KindDone = llm.KindDone KindLLMResponse = llm.KindLLMResponse KindLLMStart = llm.KindLLMStart )
Stream event kinds re-exported for consumers.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type CapabilityTagStore ¶
type CapabilityTagStore interface {
// LoadTags returns the previously activated tags for a conversation.
// Returns nil on missing/empty.
LoadTags(conversationID string) ([]string, error)
// SaveTags persists the active tags for a conversation. Pass nil
// or empty to clear.
SaveTags(conversationID string, tags []string) error
}
CapabilityTagStore persists activated capability tags per conversation. Tags activated via activate_capability are saved at the end of each Run and restored at the start of the next Run for the same conversation.
type CapabilityWiring ¶
type CapabilityWiring struct {
Tags map[string]config.CapabilityTagConfig
ParsedTalents []talents.Talent
Surface []toolcatalog.CapabilitySurface
Store CapabilityTagStore
ContextAssembler *TagContextAssembler
}
CapabilityWiring bundles the late-binding capability state resolved after the full tool registry is assembled. It groups the four post-construction setters that finalize_capability_tags previously invoked individually so the dependency surface is visible at the call site.
type ChannelDelegationWiring ¶
type ChannelDelegationWiring struct {
OrchestratorTools []string
ChannelTags map[string][]string
LensProvider func() []string
}
ChannelDelegationWiring bundles the late-binding routing and delegation policy that depend on the delegation init phase.
type ChannelLoopSource ¶
type ChannelLoopSource interface {
// ChannelLoops returns status snapshots for loops with
// category=channel metadata. The returned slice must be in a
// deterministic order (e.g., sorted by name) to ensure prompt
// stability across turns.
ChannelLoops() []LoopSnapshot
}
ChannelLoopSource provides snapshots of channel-category loops.
type ChannelOverviewConfig ¶
type ChannelOverviewConfig struct {
Loops ChannelLoopSource
Phones PhoneResolver // optional
Hints HintsFunc // optional; extracts routing hints from ctx
Logger *slog.Logger // optional; defaults to slog.Default
}
ChannelOverviewConfig holds dependencies for NewChannelOverviewProvider.
type ChannelOverviewProvider ¶
type ChannelOverviewProvider struct {
// contains filtered or unexported fields
}
ChannelOverviewProvider injects a compact JSON summary of active communication channels into the system prompt. The agent uses this to understand the current communication landscape — who's reachable, on which channel, and how recently they were active.
func NewChannelOverviewProvider ¶
func NewChannelOverviewProvider(cfg ChannelOverviewConfig) *ChannelOverviewProvider
NewChannelOverviewProvider creates a provider that aggregates channel state from the loop registry and contact store.
func (*ChannelOverviewProvider) TagContext ¶
func (p *ChannelOverviewProvider) TagContext(ctx context.Context, _ agentctx.ContextRequest) (string, error)
TagContext returns a compact JSON channel overview for injection into the system prompt. Returns empty string when no channel loops exist. Implements TagContextProvider; registered via Loop.RegisterAlwaysContextProvider.
type ChannelProvider ¶
type ChannelProvider struct {
// contains filtered or unexported fields
}
ChannelProvider is a ContextProvider that injects channel-specific context into the system prompt based on the "source" routing hint attached to the request context. When a ContactLookup is configured, it resolves sender names to contact records and injects a structured JSON contact profile alongside the channel notes.
func NewChannelProvider ¶
func NewChannelProvider(contacts ContactLookup) *ChannelProvider
NewChannelProvider creates a channel awareness context provider. The contacts parameter is optional — pass nil to disable contact resolution (the provider will still emit channel notes).
func (*ChannelProvider) TagContext ¶
func (p *ChannelProvider) TagContext(ctx context.Context, _ agentctx.ContextRequest) (string, error)
TagContext returns a channel context block if the request context carries a "source" hint that matches a known channel. When a contact lookup is available and the sender resolves to a known contact, the block includes a structured JSON contact profile with trust policy, communication channels, and interaction history. Returns an empty string for unrecognized sources or missing hints.
type Compactor ¶
type Compactor interface {
NeedsCompaction(conversationID string) bool
Compact(ctx context.Context, conversationID string) error
// CompactionThreshold returns the token count at which compaction
// triggers.
CompactionThreshold() int
}
Compactor handles conversation compaction.
type ContactContext ¶
type ContactContext struct {
ID string `json:"id,omitempty"`
Name string `json:"name"`
GivenName string `json:"given_name,omitempty"`
FamilyName string `json:"family_name,omitempty"`
TrustZone string `json:"trust_zone"`
TrustPolicy *TrustPolicyView `json:"trust_policy"`
Groups []string `json:"groups,omitempty"`
Org *string `json:"org,omitempty"`
Title *string `json:"title,omitempty"`
Role *string `json:"role,omitempty"`
Summary string `json:"summary,omitempty"`
Related []RelatedContact `json:"related,omitempty"`
Channels map[string]any `json:"channels,omitempty"`
LastInteraction *InteractionRef `json:"last_interaction,omitempty"`
ContactSince string `json:"contact_since,omitempty"`
}
ContactContext holds the rich contact profile injected into the system prompt as structured JSON. Fields are populated by the ContactLookup implementation and gated by the contact's trust zone — lower-trust zones receive fewer fields.
type ContactLookup ¶
type ContactLookup interface {
LookupContact(name string, source string) *ContactContext
LookupContactByID(id string, source string) *ContactContext
LookupContactOriginPolicy(id string, name string, source string) *ContactOriginPolicy
}
ContactLookup resolves contact identity into trust-gated profile and origin-policy context for system prompt injection. The source parameter identifies the channel (e.g., "signal", "email") so the implementation can gate fields and source-specific policy by trust zone. Returns nil when no matching contact is found.
type ContactOriginPolicy ¶
type ContactOriginPolicy struct {
Tags []string `json:"tags,omitempty"`
ContextRefs []string `json:"context_refs,omitempty"`
}
ContactOriginPolicy is contact-owned session shaping applied when a contact is the request origin.
type ContextRequest ¶
type ContextRequest = agentctx.ContextRequest
ContextRequest is re-exported from agentctx so callers within the agent package can use the bare type. The canonical definition lives in agentctx so context-producing packages can satisfy TagContextProvider without importing agent (which would cycle).
type CoreContextProvider ¶
type CoreContextProvider struct {
// contains filtered or unexported fields
}
CoreContextProvider publishes curated core identity and continuity documents through the normal context-provider pipeline.
func NewCoreContextProvider ¶
func NewCoreContextProvider(cfg CoreContextProviderConfig) *CoreContextProvider
NewCoreContextProvider creates a core context provider.
func (*CoreContextProvider) TagContext ¶
func (p *CoreContextProvider) TagContext(ctx context.Context, _ agentctx.ContextRequest) (string, error)
TagContext returns core continuity context for always-on injection.
type CoreContextProviderConfig ¶
type CoreContextProviderConfig struct {
Logger *slog.Logger
EgoFile string
ProvenanceStore *provenance.Store
InjectFiles []string
Now func() time.Time
}
CoreContextProviderConfig holds optional wiring for CoreContextProvider.
type FailoverHandler ¶
type FailoverHandler interface {
// OnFailover is called when switching from one model to another due to failure.
// Returns an error if failover should be aborted.
OnFailover(ctx context.Context, fromModel, toModel, reason string) error
}
FailoverHandler is called before model failover to allow checkpointing.
type HintsFunc ¶
HintsFunc extracts routing hints from a context. The caller provides this to bridge the awareness package to the tools context without a direct import dependency.
type IncompatibleModelError ¶
IncompatibleModelError reports that an explicit deployment cannot satisfy the request's required capabilities.
func (*IncompatibleModelError) Error ¶
func (e *IncompatibleModelError) Error() string
type InteractionRef ¶
type InteractionRef struct {
Ago string `json:"ago"`
Channel string `json:"channel,omitempty"`
SessionID string `json:"session_id,omitempty"`
Topics []string `json:"topics,omitempty"`
}
InteractionRef summarizes the contact's most recent interaction for temporal context. Ago is a signed-second delta such as "-3600s".
type KBMenuHint ¶
type KBMenuHint struct {
NextTags []string
}
KBMenuHint captures entry-point metadata that can be surfaced in the capability menu before a tag is activated.
type Loop ¶
type Loop struct {
// contains filtered or unexported fields
}
Loop is the core agent execution loop.
func NewLoop ¶
func NewLoop(opts LoopOptions) (*Loop, error)
NewLoop creates a new agent loop. Returns an error when a required LoopOptions field is missing. All optional wiring is applied during construction; late-binding wiring (capability tags, context providers, etc.) is supplied through the loop's grouped Configure* methods after dependent subsystems initialize.
func (*Loop) ActiveTags ¶
ActiveTags returns a snapshot of the currently active capability tags. ActiveTags returns the active tags from the context-scoped capability scope when available, falling back to the most recent Run()'s snapshot. This satisfies the tools.CapabilityManager interface.
func (*Loop) CheckpointSession ¶
CheckpointSession archives a snapshot of the current conversation state without ending the session. The active session continues uninterrupted.
func (*Loop) CloseSession ¶
CloseSession gracefully closes the current session, archives messages, injects a carry-forward handoff into the new session, and starts a fresh session. Unlike ResetConversation, the carry-forward summary provides continuity across the session boundary.
func (*Loop) ConfigureCapabilityWiring ¶
func (l *Loop) ConfigureCapabilityWiring(w CapabilityWiring)
ConfigureCapabilityWiring applies the resolved capability tag surface, store, talents, and context assembler. Empty fields are no-ops so callers can stage the wiring incrementally.
func (*Loop) ConfigureChannelDelegation ¶
func (l *Loop) ConfigureChannelDelegation(w ChannelDelegationWiring)
ConfigureChannelDelegation applies orchestrator tool gating, channel tag mappings, and the global lens provider. Each field is independently optional.
func (*Loop) ConfigureSessionStores ¶
func (l *Loop) ConfigureSessionStores(w SessionStoreWiring)
ConfigureSessionStores applies extractor and usage-recording wiring. Each field is independently optional.
func (*Loop) ConversationTranscript ¶
ConversationTranscript returns a formatted text transcript of the current in-memory conversation for the given ID. System and tool messages are excluded to focus on user/assistant dialogue. Returns an empty string if no user/assistant messages exist after filtering (for example, when there are no messages or only system/tool messages). The output is capped at [maxTranscriptBytes] to keep downstream LLM prompts within reasonable context limits.
func (*Loop) DropCapability ¶
DropCapability deactivates a capability tag for the current Run. Delegates to the context-scoped capabilityScope. Always-active and channel-pinned tags cannot be dropped.
func (*Loop) GetContextWindow ¶
GetContextWindow returns the context window size of the default model.
func (*Loop) GetHistory ¶
GetHistory returns the conversation messages for a given conversation.
func (*Loop) GetTokenCount ¶
func (*Loop) HAInject ¶
func (l *Loop) HAInject() homeassistant.StateFetcher
HAInject returns the HA entity state fetcher used for resolving ha-inject directives in context files. May be nil when HA is not configured.
func (*Loop) LastRunTags ¶
LastRunTags returns a snapshot of the most recent Run()'s active tags. Used by the dashboard callback which has no Run context.
func (*Loop) MemoryStats ¶
MemoryStats returns current memory statistics.
func (*Loop) RegisterAlwaysContextProvider ¶
func (l *Loop) RegisterAlwaysContextProvider(p TagContextProvider)
RegisterAlwaysContextProvider adds a provider to the always-on bucket. Always-on providers fire on every main-loop run but are suppressed for delegate runs where SuppressAlwaysContext is set. Same staging semantics as Loop.RegisterTagContextProvider.
func (*Loop) RegisterTagContextProvider ¶
func (l *Loop) RegisterTagContextProvider(tag string, p TagContextProvider)
RegisterTagContextProvider registers a live context provider for a capability tag. The provider fires when that tag is active during system-prompt assembly. Only one provider per tag is supported; a second registration for the same tag replaces the previous one.
If the tag context assembler has been wired (via Loop.SetTagContextAssembler) the registration forwards directly; otherwise it stages locally and is drained into the assembler when SetTagContextAssembler runs. This ordering accommodates init phases that register providers before the late-binding capability tag resolution completes.
func (*Loop) RequestCapability ¶
RequestCapability activates a capability tag for the current Run. Delegates to the context-scoped capabilityScope. Both configured tags and ad-hoc tags are accepted.
func (*Loop) ResetCapabilities ¶
ResetCapabilities returns the current Run to baseline capability state by dropping all user-activated tags while preserving always-active, protected, and pinned tags.
func (*Loop) ResetConversation ¶
ResetConversation archives and then clears the conversation history.
func (*Loop) Run ¶
func (l *Loop) Run(ctx context.Context, req *Request, stream StreamCallback) (resp *Response, err error)
Run executes one iteration of the agent loop. If stream is non-nil, tokens are pushed to it as they arrive.
func (*Loop) SetCapabilityTagStore ¶
func (l *Loop) SetCapabilityTagStore(store CapabilityTagStore)
SetCapabilityTagStore configures persistent storage for per-conversation capability tags. When set, tags activated via activate_capability are saved at the end of each Run and restored at the start of the next Run for the same conversation.
func (*Loop) SetCapabilityTags ¶
func (l *Loop) SetCapabilityTags(capTags map[string]config.CapabilityTagConfig, parsedTalents []talents.Talent)
SetCapabilityTags configures tag-driven tool and talent filtering. Tags marked always_active are activated immediately. The method also builds the tool registry's tag index and stores parsed talents for per-run filtering. When capTags is nil or empty, capability tagging is disabled and all tools/talents load unconditionally.
func (*Loop) SetChannelTags ¶
SetChannelTags configures channel-pinned tag activation. When a Run() request carries a "source" hint matching a key in channelTags, the listed capability tags are activated for that run in addition to any always-active or agent-requested tags. Channel-pinned tags are ref-counted per concurrent Run() call and cannot be dropped via DropCapability. They are removed on return to prevent cross-channel bleed.
func (*Loop) SetEgoFile ¶
SetEgoFile sets the path to ego.md. The file is published through the always-on context-provider pipeline and read fresh on each turn.
func (*Loop) SetFailoverHandler ¶
func (l *Loop) SetFailoverHandler(handler FailoverHandler)
SetFailoverHandler configures a handler to be called before model failover.
func (*Loop) SetHAInject ¶
func (l *Loop) SetHAInject(fetcher homeassistant.StateFetcher)
SetHAInject configures the HA entity state resolver for tag context documents.
func (*Loop) SetInjectFiles ¶
SetInjectFiles sets the core context files published through the always-on context-provider pipeline on each turn.
func (*Loop) SetLensProvider ¶
SetLensProvider configures a function that returns the currently active global lenses. These are merged into every Run's capability scope alongside always-active and channel-pinned tags.
func (*Loop) SetOrchestratorTools ¶
SetOrchestratorTools configures the restricted tool set for all iterations of the agent loop. When set, only the named tools are advertised on every LLM call, keeping the primary model in orchestrator mode and steering it toward delegation. If neither thane_now nor thane_assign is registered in the tool registry, gating is silently disabled to avoid leaving the agent without any way to delegate.
func (*Loop) SetTagContextAssembler ¶
func (l *Loop) SetTagContextAssembler(a *TagContextAssembler)
SetTagContextAssembler configures the shared assembler that builds the Capability Context section of the system prompt from tagged KB articles, tagged providers, and always-on providers. Drains any provider registrations staged before this call into the assembler.
func (*Loop) SetUsageRecorder ¶
func (l *Loop) SetUsageRecorder(store *usage.Store, pricing map[string]config.PricingEntry, cat *fleet.Catalog)
SetUsageRecorder configures persistent token usage recording. When set, every LLM completion in the agent loop is persisted for cost attribution and analysis.
func (*Loop) ShutdownArchive ¶
ShutdownArchive archives the current conversation state before shutdown.
func (*Loop) SplitSession ¶
SplitSession retroactively splits the current session at a past message boundary. Messages before the split point are archived as a completed session; messages at and after the split point are retained as the current session. Exactly one of atIndex (negative offset from end) or atMessage (substring match) must be non-zero.
func (*Loop) TriggerCompaction ¶
TriggerCompaction manually triggers conversation compaction.
func (*Loop) UseCapabilitySurface ¶
func (l *Loop) UseCapabilitySurface(surface []toolcatalog.CapabilitySurface)
UseCapabilitySurface stores the resolved capability surface used by shared model-facing renderers such as prompt summaries and capability manifest/help generation.
func (*Loop) UseContactLookup ¶
func (l *Loop) UseContactLookup(lookup ContactLookup)
UseContactLookup configures the contact-directory lookup used to include trust-gated contact profiles in session origin context.
func (*Loop) UseInjectFileVerifier ¶
UseInjectFileVerifier configures the verifier used before each core context file read during system-prompt assembly.
func (*Loop) UseLiveRequestRecorder ¶
func (l *Loop) UseLiveRequestRecorder(recorder logging.RequestRecordFunc)
UseLiveRequestRecorder configures live request detail recording for in-flight turns.
func (*Loop) UseModelRegistry ¶
UseModelRegistry configures the live model registry used for explicit model resolution and runtime usage attribution.
func (*Loop) UseModelRuntime ¶
UseModelRuntime configures the live model runtime used for explicit runner preparation flows such as LM Studio context expansion.
type LoopOptions ¶
type LoopOptions struct {
// Required at construction. Validated by NewLoop.
Logger *slog.Logger
Memory MemoryStore
LLM llm.Client
Model string
// Recommended for production use. Optional for minimal/test loops.
Compactor Compactor
Router *router.Router
HomeAssistant *homeassistant.Client
Scheduler *scheduler.Scheduler
ContextWindow int
// Optional, stable at construction.
Persona string
ParsedTalents []talents.Talent
Timezone string
RecoveryModel string
Archiver SessionArchiver
InjectFiles []string
EgoFile string
ProvenanceStore *provenance.Store
HAInject homeassistant.StateFetcher
ModelRegistry *fleet.Registry
ModelRuntime *fleet.Runtime
LiveRequestRecorder logging.RequestRecordFunc
RequestRecorder logging.RequestRecordFunc
}
LoopOptions declares everything required or optionally configurable at agent loop construction. NewLoop validates Logger, Memory, LLM, and Model — the minimum a runnable loop needs. The remaining fields are configuration-dependent: production runs through internal/app supply Compactor, Router, HomeAssistant, Scheduler, ContextWindow, and the rest, but the CLI ask path constructs a deliberately minimal loop with most fields zero-valued. Treat anything outside the four explicitly-validated fields as optional but recommended for full functionality.
Late-binding wiring that depends on subsystems initialized after the loop itself (capability tags, context providers, channel/extractor stores, failover handler) is configured through the loop's grouped Configure* methods rather than this struct.
type LoopSnapshot ¶
type LoopSnapshot struct {
ID string
Name string
State string
LastWakeAt time.Time
Metadata map[string]string
RecentConvIDs []string
}
LoopSnapshot is a subset of loop.Status relevant to channel overview. Defined here to avoid importing the loop package.
type MemoryStore ¶
type MemoryStore interface {
GetMessages(conversationID string) []memory.Message
AddMessage(conversationID, role, content string) error
GetTokenCount(conversationID string) int
Clear(conversationID string) error
Stats() map[string]any
}
MemoryStore is the conversation memory backend required by the agent loop. It manages per-conversation message history and token accounting so the loop can build prompts and enforce context-window limits.
type Message ¶
type Message struct {
Role string `json:"role"` // system, user, assistant
Content string `json:"content"`
Images []llm.ImageContent `json:"-"`
}
Message represents a chat message.
type NoEligibleModelError ¶
NoEligibleModelError reports that automatic routing could not find any deployment capable of satisfying the request.
func (*NoEligibleModelError) Error ¶
func (e *NoEligibleModelError) Error() string
type OpstateCapabilityTagStore ¶
type OpstateCapabilityTagStore struct {
// contains filtered or unexported fields
}
OpstateCapabilityTagStore implements CapabilityTagStore using opstate for persistence. Tags are stored as a JSON array per conversation ID.
func NewOpstateCapabilityTagStore ¶
func NewOpstateCapabilityTagStore(state *opstate.Store) *OpstateCapabilityTagStore
NewOpstateCapabilityTagStore creates a capability tag store backed by opstate.
type PhoneResolver ¶
type PhoneResolver interface {
ResolvePhone(phone string) (name string, trustZone string, ok bool)
}
PhoneResolver maps phone numbers to contact names and trust zones.
type RelatedContact ¶
RelatedContact represents a RELATED vCard entry on a contact.
type Request ¶
type Request struct {
Messages []Message `json:"messages"`
Model string `json:"model,omitempty"`
ConversationID string `json:"conversation_id,omitempty"`
ChannelBinding *memory.ChannelBinding `json:"channel_binding,omitempty"`
Hints map[string]string `json:"hints,omitempty"` // Routing hints (channel, mission, etc.)
SkipContext bool `json:"-"` // Skip memory, tools, and context injection (for lightweight completions)
AllowedTools []string `json:"-"` // Optional allowlist of tools visible for this run
ExcludeTools []string `json:"-"` // Tool names to exclude from this run (e.g., lifecycle tools for recurring wakes)
SkipTagFilter bool `json:"-"` // Bypass capability tag filtering (for self-scoping contexts like metacognitive)
InitialTags []string `json:"-"` // Tags to activate at Run start (carried forward from previous loop iterations)
RuntimeTags []string `json:"-"` // Trusted runtime-asserted tags pinned for this run only
RuntimeTools []*tools.Tool `json:"-"` // Request-scoped tools visible only to this run
MaxIterations int `json:"-"` // Optional per-request iteration cap (0 = default)
MaxOutputTokens int `json:"-"` // Optional output-token budget across all iterations (0 = unlimited)
ToolTimeout time.Duration `json:"-"` // Optional per-tool timeout (0 = no extra timeout)
UsageRole string `json:"-"` // Optional usage role override (e.g., "delegate")
UsageTaskName string `json:"-"` // Optional usage task name override
FallbackContent string `json:"-"` // Optional static fallback text when the run yields no content
PromptMode agentctx.PromptMode `json:"-"` // Optional system-prompt shape override.
// SystemPrompt, when non-empty, replaces the output of
// buildSystemPrompt(). Used by callers that assemble their own
// prompt context externally.
SystemPrompt string `json:"-"`
// SuppressAlwaysContext drops the always-on bucket from the
// system-prompt assembler's context output. Default false matches
// main-loop behavior (include presence, episodic memory, working
// memory, notification history, etc.). Delegates set true so the
// child agent sees only tag-scoped context appropriate to the
// bounded task.
SuppressAlwaysContext bool `json:"-"`
}
Request represents an incoming agent request.
type Response ¶
type Response struct {
Content string `json:"content"`
Model string `json:"model"`
FinishReason string `json:"finish_reason"`
InputTokens int `json:"input_tokens,omitempty"`
OutputTokens int `json:"output_tokens,omitempty"`
CacheCreationInputTokens int `json:"cache_creation_input_tokens,omitempty"`
CacheReadInputTokens int `json:"cache_read_input_tokens,omitempty"`
ToolsUsed map[string]int `json:"tools_used,omitempty"` // tool name → call count
EffectiveTools []string `json:"effective_tools,omitempty"`
LoadedCapabilities []toolcatalog.LoadedCapabilityEntry `json:"loaded_capabilities,omitempty"`
Iterations int `json:"iterations,omitempty"`
Exhausted bool `json:"exhausted,omitempty"`
// SessionID and RequestID are set by Run() so callers can
// correlate post-run log lines with the agent loop's context.
SessionID string `json:"session_id,omitempty"`
RequestID string `json:"request_id,omitempty"`
// ActiveTags is the set of capability tags active at the end of
// the Run. Used by loops to carry forward activations.
ActiveTags []string `json:"-"`
}
Response is the result of a single agent Run() call. It contains the model's final content, token usage counters, and metadata about which tools and capability tags were active during execution.
type SessionArchiver ¶
type SessionArchiver interface {
// ArchiveConversation archives all messages from a conversation before clearing.
ArchiveConversation(conversationID string, messages []memory.Message, reason string) error
// StartSession begins a new session for a conversation.
StartSession(conversationID string) (sessionID string, err error)
// EndSession ends the current session.
EndSession(sessionID string, reason string) error
// ActiveSessionID returns the current session ID, or empty if none.
ActiveSessionID(conversationID string) string
// EnsureSession starts a session if none is active, returns the session ID.
EnsureSession(conversationID string) string
// ArchiveIterations copies iteration records to the immutable archive.
ArchiveIterations(iterations []memory.ArchivedIteration) error
// LinkPendingIterationToolCalls links archived tool calls to their
// parent iterations using stored tool_call_ids.
LinkPendingIterationToolCalls(sessionID string) error
// OnMessage is called after each message to track session stats.
OnMessage(conversationID string)
// ActiveSessionStartedAt returns when the active session began,
// or the zero time if there is no active session.
ActiveSessionStartedAt(conversationID string) time.Time
}
SessionArchiver handles session lifecycle and message archiving.
type SessionOrigin ¶
type SessionOrigin struct {
Source string `json:"source,omitempty"`
Channel string `json:"channel,omitempty"`
ContactID string `json:"contact_id,omitempty"`
ContactName string `json:"contact_name,omitempty"`
TrustZone string `json:"trust_zone,omitempty"`
Address string `json:"address,omitempty"`
IsOwner bool `json:"is_owner,omitempty"`
HAUserID string `json:"ha_user_id,omitempty"`
Person string `json:"person,omitempty"`
PersonID string `json:"person_id,omitempty"`
DeviceID string `json:"device_id,omitempty"`
PipelineID string `json:"pipeline_id,omitempty"`
}
SessionOrigin is the normalized source identity for one agent run.
type SessionOriginAppliedRule ¶
type SessionOriginAppliedRule struct {
Name string `json:"name,omitempty"`
Source string `json:"source,omitempty"`
Tags []string `json:"tags,omitempty"`
ContextRefs []string `json:"context_refs,omitempty"`
}
SessionOriginAppliedRule is the model-facing summary of one matching origin policy rule.
type SessionOriginPolicyResult ¶
type SessionOriginPolicyResult struct {
Origin SessionOrigin `json:"origin"`
Applied []SessionOriginAppliedRule `json:"applied_rules,omitempty"`
Tags []string `json:"tags,omitempty"`
ContextRefs []string `json:"context_refs,omitempty"`
}
SessionOriginPolicyResult captures the origin-derived tags and context refs applied to a run.
type SessionStoreWiring ¶
type SessionStoreWiring struct {
Extractor *memory.Extractor
UsageStore *usage.Store
Pricing map[string]config.PricingEntry
UsageCatalog *fleet.Catalog
}
SessionStoreWiring bundles the late-binding storage handles initialized after the channel/storage subsystem comes online.
type StreamCallback ¶
type StreamCallback = llm.StreamCallback
StreamCallback receives streaming events. Alias to llm.StreamCallback for compatibility.
func BuildProgressStream ¶
func BuildProgressStream(progressFn func(string, map[string]any)) StreamCallback
BuildProgressStream converts a loop progress func into a StreamCallback that forwards in-flight LLM and tool events to the event bus for dashboard visibility. Returns nil if progressFn is nil.
This is the canonical bridge between the agent's streaming events and the loop infrastructure's progress reporting. Handlers that call Loop.Run inside a handler-only loop should use this to wire the loop's loop.ProgressFunc into the agent stream:
stream := agent.BuildProgressStream(loop.ProgressFunc(hCtx)) resp, err := runner.Run(hCtx, req, stream)
type StreamEvent ¶
type StreamEvent = llm.StreamEvent
StreamEvent is a single event in a streaming response. Alias to llm.StreamEvent for use by consumers.
type TagContextAssembler ¶
type TagContextAssembler struct {
// contains filtered or unexported fields
}
TagContextAssembler builds the Capability Context section from three sources, walked in one ordered pass per call:
- Tagged KB articles — markdown files in the knowledge base directory with `tags:` (any-of) and/or `tags_all:` (all-of) frontmatter, same pattern as talents. Filtered by ActiveTags.
- Tagged live providers — TagContextProvider implementations registered against a specific capability tag via Loop.RegisterTagContextProvider. Filtered by ActiveTags.
- Always-on providers — TagContextProvider implementations registered via Loop.RegisterAlwaysContextProvider. Gated by ContextRequest.IncludeAlways: main loop runs include them, delegate runs do not.
All three sources share one 64 KB aggregate cap, one truncation marker, and one unified [Build] method — there is no parallel always-bucket walker. Tagged vs always is encoded as where each source registered, not as a separate code path. KB articles and explicit context refs flow through the optional managed-root signature verifier. Providers that read disk-managed material are responsible for applying their own verification before returning model-facing content.
Both the main agent loop and delegate executor share a single assembler. The assembler is safe for concurrent use after construction.
func NewTagContextAssembler ¶
func NewTagContextAssembler(cfg TagContextAssemblerConfig) *TagContextAssembler
NewTagContextAssembler creates an assembler. The KB directory is scanned lazily — the article list (paths and tag affinity) is re-read from disk on every consumer call (Build, KBArticleTags, KBMenuHints), so frontmatter edits, additions, and deletions propagate without a process restart. Scans are cheap (a directory walk plus a frontmatter parse per .md file) and run once per consumer call, not once per article.
func (*TagContextAssembler) Build ¶
func (a *TagContextAssembler) Build(ctx context.Context, req agentctx.ContextRequest) string
Build assembles tag context for the request. The single internal pipeline walks three sources in order — KB articles, tagged providers, always-on providers — sharing one 64 KB aggregate cap and one truncation marker. Always-on providers are gated by req.IncludeAlways; main loop runs include them, delegate runs do not. Returns empty string when no source produces content.
func (*TagContextAssembler) BuildRefs ¶
func (a *TagContextAssembler) BuildRefs(ctx context.Context, refs []string) string
BuildRefs assembles exact managed document refs for origin-derived context. Refs are read fresh each turn, frontmatter is stripped, and each document is labeled by its semantic ref.
func (*TagContextAssembler) KBArticleTags ¶
func (a *TagContextAssembler) KBArticleTags() map[string]int
KBArticleTags returns the tag→article count index, useful for enriching the capability manifest with KB article counts. Both `tags:` (any-of) and `tags_all:` (all-of) memberships count — a `tags_all`-only article would otherwise be invisible to the menu surface despite gating real content. Tags appearing in both lists of the same article count once.
func (*TagContextAssembler) KBMenuHints ¶
func (a *TagContextAssembler) KBMenuHints() map[string]KBMenuHint
KBMenuHints returns one root-menu hint per tag, sourced from tagged KB entry-point documents. The first teaser encountered for a tag wins, with deterministic ordering provided by scanKBArticles.
func (*TagContextAssembler) RegisterAlwaysProvider ¶
func (a *TagContextAssembler) RegisterAlwaysProvider(p TagContextProvider)
RegisterAlwaysProvider adds a provider to the always-on bucket. Always-providers fire on every main-loop run but are suppressed for delegate runs that pass IncludeAlways=false. Order is preserved across registrations.
func (*TagContextAssembler) RegisterTaggedProvider ¶
func (a *TagContextAssembler) RegisterTaggedProvider(tag string, p TagContextProvider)
RegisterTaggedProvider associates a provider with one capability tag. The provider fires when that tag is active in a Build call. Idempotent on tag — last registration wins.
func (*TagContextAssembler) TaggedProviders ¶
func (a *TagContextAssembler) TaggedProviders() map[string]TagContextProvider
TaggedProviders returns a snapshot of the registered tag→provider map. Used by callers that need to inspect what's wired (e.g., the capability surface builder).
type TagContextAssemblerConfig ¶
type TagContextAssemblerConfig struct {
CapTags map[string]config.CapabilityTagConfig
KBDir string // resolved kb: directory; empty skips scanning
Resolver *paths.Resolver // managed document root resolver; nil falls back to KBDir for kb: refs
// Verifier is an optional managed-root verifier for context refs and
// tagged articles.
Verifier interface {
VerifyRef(ctx context.Context, ref string, consumer string) error
VerifyPath(ctx context.Context, path string, consumer string) error
}
HAInject homeassistant.StateFetcher // nil-safe
Logger *slog.Logger
}
TagContextAssemblerConfig holds the construction parameters for a TagContextAssembler.
type TagContextProvider ¶
type TagContextProvider interface {
// TagContext returns context to inject. The ctx carries any
// per-turn timeout (e.g., the shared 2-second HA deadline).
TagContext(ctx context.Context, req agentctx.ContextRequest) (string, error)
}
TagContextProvider supplies live-computed context for the system prompt. Implementations either register against a specific capability tag (via Loop.RegisterTagContextProvider) — in which case they fire only when that tag is active — or against the always-on bucket (via Loop.RegisterAlwaysContextProvider), where they fire on every main-loop run but are suppressed for delegate runs that pass agentctx.ContextRequest.IncludeAlways = false.
Output should follow #458 conventions: delta-annotated timestamps via promptfmt.FormatDelta, machine-first format, pre-computed relationships.
type ToolCallRecorder ¶
type ToolCallRecorder interface {
RecordToolCall(conversationID, messageID, toolCallID, toolName, arguments string) error
CompleteToolCall(toolCallID, result, errMsg string) error
}
ToolCallRecorder records tool call lifecycle events for observability. When the memory store also implements this interface, the agent loop calls RecordToolCall before execution and CompleteToolCall after, enabling auditing and debugging of tool interactions.
type TrustPolicyView ¶
type TrustPolicyView struct {
FrontierModel bool `json:"frontier_model"`
ProactiveOutreach string `json:"proactive_outreach"`
ToolAccess string `json:"tool_access"`
SendGating string `json:"send_gating"`
}
TrustPolicyView is the JSON-serializable view of a trust zone's capability matrix. It exposes the policy dimensions that the agent needs to adapt its behavior.