agent

package
v1.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 12, 2026 License: Apache-2.0 Imports: 62 Imported by: 0

Documentation

Overview

Copyright 2026 Teradata

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Package agent provides dynamic tool discovery for MCP servers.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Package agent provides MCP integration for the Loom agent framework.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Index

Constants

View Source
const (
	StagePatternSelection = types.StagePatternSelection
	StageSchemaDiscovery  = types.StageSchemaDiscovery
	StageLLMGeneration    = types.StageLLMGeneration
	StageToolExecution    = types.StageToolExecution
	StageSynthesis        = types.StageSynthesis
	StageHumanInTheLoop   = types.StageHumanInTheLoop
	StageGuardrailCheck   = types.StageGuardrailCheck
	StageSelfCorrection   = types.StageSelfCorrection
	StageCompleted        = types.StageCompleted
	StageFailed           = types.StageFailed
)

Re-export ExecutionStage constants for backward compatibility

View Source
const CreatedBySessionMetadataKey = task.CreatedBySessionMetadataKey

CreatedBySessionMetadataKey records, in task metadata, the conversation session that created a task via this tool (create/decompose). Claims are a separate lifecycle event (see executeClaim); this key lets callers scope "tasks created in this conversation" without pre-claiming, which would break the ready → claim workflow (ClaimTask requires an unclaimed task).

View Source
const (
	// EncoderPoolSizeEnvVar lets operators override the tiktoken encoder pool
	// size without a recompile. When set to a positive integer, the singleton
	// TokenCounter uses that value; anything else (unset, non-numeric, <=0)
	// falls back to the GOMAXPROCS-driven default.
	//
	// The value is parsed with strconv.Atoi and NOT whitespace-trimmed, so
	// shell-quoting accidents like LOOM_TOKEN_ENCODER_POOL_SIZE="16 " (trailing
	// space) will silently fall through to the default. If an override you set
	// does not appear to take effect, re-export without surrounding whitespace.
	EncoderPoolSizeEnvVar = "LOOM_TOKEN_ENCODER_POOL_SIZE"
)

Variables

View Source
var ErrNotThisTurn = errors.New("not a current-turn in-memory payload")

ErrNotThisTurn is the typed miss for in-turn payload lookups: the id does not resolve to a current-turn in-memory tool result. Callers convert it to their own loud error and never guess — there is no cross-turn data door except re-run (HLD §7.1, §7.2).

View Source
var ProfileDefaults = map[loomv1.WorkloadProfile]CompressionProfile{
	loomv1.WorkloadProfile_WORKLOAD_PROFILE_BALANCED: {
		Name:                     "balanced",
		MaxL1Tokens:              6400,
		MinL1Messages:            4,
		WarningThresholdPercent:  60,
		CriticalThresholdPercent: 90,
		NormalBatchSize:          3,
		WarningBatchSize:         5,
		CriticalBatchSize:        7,
	},
	loomv1.WorkloadProfile_WORKLOAD_PROFILE_DATA_INTENSIVE: {
		Name:                     "data_intensive",
		MaxL1Tokens:              4000,
		MinL1Messages:            3,
		WarningThresholdPercent:  60,
		CriticalThresholdPercent: 90,
		NormalBatchSize:          2,
		WarningBatchSize:         4,
		CriticalBatchSize:        6,
	},
	loomv1.WorkloadProfile_WORKLOAD_PROFILE_CONVERSATIONAL: {
		Name:                     "conversational",
		MaxL1Tokens:              9600,
		MinL1Messages:            6,
		WarningThresholdPercent:  60,
		CriticalThresholdPercent: 90,
		NormalBatchSize:          4,
		WarningBatchSize:         6,
		CriticalBatchSize:        8,
	},
}

ProfileDefaults provides preset profiles for common workload types. These are static fallback values - use NewSegmentedMemoryWithDynamicAllocation for adaptive sizing.

Functions

func ContextWithProgressCallback

func ContextWithProgressCallback(ctx context.Context, callback ProgressCallback) context.Context

ContextWithProgressCallback stores a progress callback in the context so that nested operations (like tool executions) can emit progress events.

func DefaultGraphMemoryConfig added in v1.3.0

func DefaultGraphMemoryConfig() *loomv1.GraphMemoryConfig

DefaultGraphMemoryConfig returns a GraphMemoryConfig with sane defaults. Used when graph memory is enabled but no explicit config is provided (e.g., pre-existing agents).

func EffectiveOutputReservation added in v1.4.0

func EffectiveOutputReservation(provider, model string, configuredMaxTokens, configuredReserved, maxContextTokens int) int

EffectiveOutputReservation returns the token count the relief water marks must subtract from the window (HLD §5.1 "usable"). The provider accepts exactly when prompt + max_tokens ≤ window, so the reservation has to cover the request's REAL max_tokens — otherwise usable is over-stated and the marks sit above the provider's refusal line, where proactive relief can never fire.

loom resolves the wire max_tokens in two places with different rules (registry builds clients from llm.max_tokens; the factory falls back to the catalog), so the reservation takes the largest value any build path could send:

  1. the configured reserve (llm.reserved_output_tokens), or 10% of the window when unset — the historical default;
  2. llm.max_tokens, when explicitly configured — sent verbatim by every build path;
  3. the model's catalog MaxOutputTokens — what the factory sends when llm.max_tokens is unset.

Taking the maximum only ever grows the reservation, so it never changes what loom asks the provider for; it can make relief fire earlier than strictly necessary, which is the safe direction. Returns 0 when nothing is known, so callers keep their existing defaults.

func EncoderPoolSize added in v1.3.0

func EncoderPoolSize() int

EncoderPoolSize returns the resolved size of the singleton TokenCounter's encoder pool. Exposed for tests and startup diagnostics; not a reconfiguration hook — the channel is built once in GetTokenCounter.

func ExtractSkillsConfig added in v1.2.0

func ExtractSkillsConfig(metadata map[string]string) *skills.SkillsConfig

ExtractSkillsConfig extracts a SkillsConfig from proto metadata. Returns nil if no skills config is present in metadata.

func GetAvailableROMs

func GetAvailableROMs() []string

GetAvailableROMs returns a list of available ROM identifiers. Useful for documentation and validation.

func GetBaseROM

func GetBaseROM() []byte

GetBaseROM returns the raw base ROM content (START_HERE.md). This is the single source of truth for the base ROM, used by both: - Agent ROM loading (via LoadROMContent) - Deployment to $LOOM_DATA_DIR/START_HERE.md (via embedded package)

func GetBaseROMSize

func GetBaseROMSize() int

GetBaseROMSize returns the size of the base ROM (START_HERE.md).

func GetDomainROMSize

func GetDomainROMSize(romID string) int

GetDomainROMSize returns the size of a specific domain ROM. Returns 0 if ROM doesn't exist.

func GetROMSize

func GetROMSize(romID string) int

GetROMSize returns the total size of composed ROM in bytes. Includes base ROM + domain ROM if applicable.

func LoadAgentConfig

func LoadAgentConfig(path string) (*loomv1.AgentConfig, error)

LoadAgentConfig loads agent configuration from a YAML file and converts it to proto.

func LoadConfigFromString

func LoadConfigFromString(yamlContent string) (*loomv1.AgentConfig, error)

LoadConfigFromString loads agent configuration from a YAML string and converts it to proto. This is used by the meta-agent factory to spawn agents from generated YAML configs. Supports both legacy format (agent:) and k8s-style format (apiVersion/kind/metadata/spec).

func LoadROMContent

func LoadROMContent(romID string, backendPath string) string

LoadROMContent loads ROM (Read-Only Memory) content based on configuration. ROM provides operational guidance and optional domain-specific knowledge.

Architecture:

  • Base ROM (START_HERE.md): Always included for all agents (5KB) Provides: tool discovery, communication patterns, artifacts, memory usage
  • Domain ROMs: Optional specialized knowledge (e.g., TD.rom for Teradata SQL) Automatically composed with base ROM using clear separators

Parameters:

  • romID: ROM identifier from agent config ("TD", "teradata", "auto", "none", or "")
  • backendPath: Backend path from agent metadata (for auto-detection)

Returns composed ROM content (markdown format).

ROM Composition Rules:

  1. Base ROM is ALWAYS included (operational guidance)
  2. Domain ROM is added if specified (with separator)
  3. Use romID="none" to opt-out of ALL ROMs (rare)
  4. Empty romID="" = base ROM only (no domain knowledge)

Examples:

romID=""         → Base ROM only (5KB)
romID="TD"       → Base + Teradata ROM (5KB + 11KB = 16KB)
romID="auto"     → Base + auto-detected domain ROM
romID="none"     → No ROM at all (explicit opt-out)

func LoadWorkflowAgents

func LoadWorkflowAgents(path string, llmProvider LLMProvider) ([]*loomv1.AgentConfig, error)

LoadWorkflowAgents loads a workflow file and extracts ALL agent configs (coordinator + sub-agents). Returns a slice of AgentConfigs with proper namespacing:

  • Coordinator: registered as {workflow-name}
  • Sub-agents: registered as {workflow-name}:{agent-id}

Supports two formats: 1. Orchestration format (apiVersion/kind/spec) - used by looms workflow run 2. Weaver format (agent config with embedded workflow section)

This allows connecting to individual agents while ensuring the workflow uses the same registered instances.

func LoadWorkflowCoordinator

func LoadWorkflowCoordinator(path string, llmProvider LLMProvider) (*loomv1.AgentConfig, error)

LoadWorkflowCoordinator loads a workflow file and extracts only the coordinator agent. This is a convenience wrapper around LoadWorkflowAgents for backward compatibility. Deprecated: Use LoadWorkflowAgents to register all agents in the workflow.

func NewProgressNotifier added in v1.4.0

func NewProgressNotifier() shuttle.Notifier

NewProgressNotifier returns the bridge that converts a pending HumanRequest into a StageHumanInTheLoop ProgressEvent delivered on the run's installed ProgressCallback.

func OpenDB

func OpenDB(config DBConfig) (*sql.DB, error)

OpenDB opens a SQLite database with optional encryption support. Returns a *sql.DB connection or an error.

Uses SQLCipher driver for all connections (handles both encrypted and unencrypted). When encryption is disabled (default), no key is set. When encryption is enabled, uses SQLCipher with the provided key.

Example without encryption (default):

db, err := OpenDB(DBConfig{Path: "sessions.db"})

Example with encryption:

db, err := OpenDB(DBConfig{
    Path: "sessions.db",
    EncryptDatabase: true,
    EncryptionKey: os.Getenv("LOOM_DB_KEY"),
})

func SaveAgentConfig

func SaveAgentConfig(config *loomv1.AgentConfig, path string) error

SaveAgentConfig saves an agent configuration to a YAML file

func ValidateAgentConfig

func ValidateAgentConfig(config *loomv1.AgentConfig) error

ValidateAgentConfig validates an agent configuration

func ValidatePatternConfig

func ValidatePatternConfig(cfg *PatternConfig) error

ValidatePatternConfig validates pattern configuration

func WithOccurredAt added in v1.4.0

func WithOccurredAt(ctx context.Context, t time.Time) context.Context

WithOccurredAt returns a context that overrides the arrival timestamp of every message persisted during the conversation call — the user turn, the assistant reply, and tool rows. It exists for replayed or imported conversations (WeaveRequest.occurred_at), where the wall clock at ingestion is not when the conversation happened: temporal grounding (compiled-view arrival stamps, graph-memory extraction anchoring) reads Message.Timestamp, so the override keeps all of those signals anchored to the conversation's real time. Live conversations must not use this.

Types

type AdminSession added in v1.2.0

type AdminSession struct {
	*Session
	UserID string
}

AdminSession represents a session with its owner for admin queries. Uses a pointer to Session to avoid copying the embedded sync.RWMutex.

type AdminStorage added in v1.2.0

type AdminStorage interface {
	// ListAllSessions returns sessions across all users (bypasses RLS).
	ListAllSessions(ctx context.Context, limit, offset int) ([]AdminSession, int32, error)

	// CountSessionsByUser returns session counts grouped by user_id.
	CountSessionsByUser(ctx context.Context) ([]UserSessionCount, error)

	// GetSystemStats returns aggregate statistics across all users.
	GetSystemStats(ctx context.Context) (*SystemStats, error)
}

AdminStorage defines operations that bypass RLS for platform administration. Implementations must execute queries without setting app.current_user_id, giving cross-tenant visibility to authorized operators.

type Agent

type Agent struct {
	// contains filtered or unexported fields
}

Agent is the core conversation agent that orchestrates LLM calls, tool execution, and backend interactions. It's designed to be backend-agnostic and work with any ExecutionBackend implementation (SQL databases, REST APIs, documents, etc.).

func NewAgent

func NewAgent(backend fabric.ExecutionBackend, llmProvider LLMProvider, opts ...Option) *Agent

NewAgent creates a new Agent instance.

For comprehensive observability, pass instrumented LLM and executor:

llmProvider = llm.NewInstrumentedProvider(baseProvider, tracer)
// Then create agent with WithTracer(tracer)

The agent will automatically use instrumented versions if provided, enabling end-to-end tracing of conversations, LLM calls, and tool executions.

func (*Agent) AdoptApprovedSet added in v1.4.0

func (a *Agent) AdoptApprovedSet(s shuttle.ApprovedSetAccessor)

AdoptApprovedSet hands this agent an existing approved-set accessor. The hot-reload path carries the outgoing agent's set onto its replacement so live sessions' recorded approvals survive the swap — an agent rebuild is an operator action on the agent, not on its sessions, and must not falsify an approval a human already gave. A nil accessor is ignored.

func (*Agent) ApprovedSet added in v1.4.0

func (a *Agent) ApprovedSet() shuttle.ApprovedSetAccessor

ApprovedSet returns the executor's approved-set accessor; nil until one is wired.

func (*Agent) Chat

func (a *Agent) Chat(ctx context.Context, sessionID string, userMessage string) (*Response, error)

Chat processes a user message and returns a response. This is the main entry point for conversational interaction.

func (*Agent) ChatWithContentBlocks added in v1.4.0

func (a *Agent) ChatWithContentBlocks(ctx context.Context, sessionID string, userMessage string, contentBlocks []ContentBlock, progressCallback ProgressCallback) (*Response, error)

ChatWithContentBlocks is like ChatWithProgress but the user turn carries multimodal content blocks (text and/or images) alongside the plain-text content. userMessage remains the canonical text (used for persistence, graph-memory extraction, and providers without multimodal support).

When contentBlocks is non-empty, providers build the request from the blocks only — Content is not sent. To keep userMessage canonical, if contentBlocks contains no text block, userMessage is automatically prepended as one, so an image-only call still delivers the question text to the model. Callers that include their own text block are unaffected.

progressCallback may be nil, in which case no progress events are emitted (equivalent to Chat).

func (*Agent) ChatWithProgress

func (a *Agent) ChatWithProgress(ctx context.Context, sessionID string, userMessage string, progressCallback ProgressCallback) (*Response, error)

ChatWithProgress is like Chat but supports streaming progress updates. The progressCallback will be called at key execution stages to report progress. This is used by StreamWeave to provide real-time feedback to clients.

func (*Agent) CleanupMCPClients

func (a *Agent) CleanupMCPClients() error

CleanupMCPClients closes all MCP clients that were registered with AutoClose=true. This should be called when the agent is done to properly cleanup resources.

Example:

defer agent.CleanupMCPClients()

func (*Agent) ClearAllSessions added in v1.3.0

func (a *Agent) ClearAllSessions()

ClearAllSessions removes all sessions from memory. Used by the benchmark server to free memory between scenarios.

func (*Agent) CreateSession

func (a *Agent) CreateSession(ctx context.Context, sessionID, name string) *Session

CreateSession creates a new session without sending a message to the LLM. Use this for session initialization; use Chat() for actual conversations. ctx carries user identity for RLS-scoped storage access. name is an optional human-readable session name.

func (*Agent) DeleteSession

func (a *Agent) DeleteSession(sessionID string)

DeleteSession removes a session.

func (*Agent) EnableDynamicDiscovery

func (a *Agent) EnableDynamicDiscovery(mcpMgr *manager.Manager)

EnableDynamicDiscovery enables dynamic tool discovery on the agent.

When enabled, if a tool is not found in the registered tools, the agent will attempt to discover it from MCP servers at runtime.

Example:

agent := NewAgent(config)
agent.EnableDynamicDiscovery(mcpMgr)

// Don't register tools upfront
// Tools discovered on-demand during conversations

func (*Agent) FlushGraphMemoryExtraction added in v1.3.0

func (a *Agent) FlushGraphMemoryExtraction()

FlushGraphMemoryExtraction blocks until all in-flight async graph memory extractions have completed. Call this before querying graph memory to ensure recently ingested content has been fully extracted.

func (*Agent) GetActiveProviderName added in v1.2.0

func (a *Agent) GetActiveProviderName() string

GetActiveProviderName returns the currently active provider name.

func (*Agent) GetAllRoleLLMs added in v1.2.0

func (a *Agent) GetAllRoleLLMs() map[loomv1.LLMRole]LLMProvider

GetAllRoleLLMs returns all configured role-specific LLM providers (non-nil only). Always includes the main agent LLM. Used for health checks and diagnostics.

func (*Agent) GetCircuitBreakers

func (a *Agent) GetCircuitBreakers() *fabric.CircuitBreakerManager

GetCircuitBreakers returns the circuit breaker manager for failure isolation (may be nil if not enabled).

func (*Agent) GetConfig

func (a *Agent) GetConfig() *Config

GetConfig returns a copy of the agent configuration.

func (*Agent) GetContextState added in v1.2.0

func (a *Agent) GetContextState(sessionID string) *ContextState

GetContextState returns a snapshot of the agent's memory and context window state for the given session. Returns nil if the session has no SegmentedMemory.

func (*Agent) GetDescription

func (a *Agent) GetDescription() string

GetDescription returns the agent description from configuration.

func (*Agent) GetGuardrails

func (a *Agent) GetGuardrails() *fabric.GuardrailEngine

GetGuardrails returns the guardrail engine for pre-flight validation (may be nil if not enabled).

func (*Agent) GetID added in v1.1.0

func (a *Agent) GetID() string

GetID returns the agent's unique identifier. Every agent instance has a UUID assigned by NewAgent(). Registry-managed agents have stable GUIDs persisted to database.

func (*Agent) GetLLMForRole added in v1.2.0

func (a *Agent) GetLLMForRole(role loomv1.LLMRole) LLMProvider

GetLLMForRole returns the LLM provider for a specific role. Fallback chain: role-specific LLM -> main agent LLM.

func (*Agent) GetLLMModel

func (a *Agent) GetLLMModel() string

GetLLMModel returns the model identifier (e.g., "claude-3-5-sonnet-20241022").

func (*Agent) GetLLMModelForRole added in v1.2.0

func (a *Agent) GetLLMModelForRole(role loomv1.LLMRole) string

GetLLMModelForRole returns the model identifier for a specific role's LLM.

func (*Agent) GetLLMProviderName

func (a *Agent) GetLLMProviderName() string

GetLLMProviderName returns the name of the LLM provider (e.g., "anthropic", "bedrock", "ollama").

func (*Agent) GetLLMProviderNameForRole added in v1.2.0

func (a *Agent) GetLLMProviderNameForRole(role loomv1.LLMRole) string

GetLLMProviderNameForRole returns the provider name for a specific role's LLM.

func (*Agent) GetName

func (a *Agent) GetName() string

GetName returns the agent name from configuration.

func (*Agent) GetOrchestrator

func (a *Agent) GetOrchestrator() *patterns.Orchestrator

GetOrchestrator returns the pattern orchestrator for intent classification.

func (*Agent) GetProviderPool added in v1.2.0

func (a *Agent) GetProviderPool() map[string]LLMProvider

GetProviderPool returns the named provider pool (nil if not configured).

func (*Agent) GetSession

func (a *Agent) GetSession(sessionID string) (*Session, bool)

GetSession retrieves a session by ID.

func (*Agent) InTurnPayload added in v1.4.0

func (a *Agent) InTurnPayload(sessionID string, messageID int64) (string, error)

InTurnPayload returns the full in-memory content of message id iff the message belongs to the current turn (m.Turn == T) and holds a tool result. Any other case returns ErrNotThisTurn — a typed miss carrying the id. One reader path, no store, no copy: it resolves against L1 in memory.

func (*Agent) ListSessions

func (a *Agent) ListSessions() []*Session

ListSessions returns all active sessions.

func (*Agent) ListTools

func (a *Agent) ListTools() []string

ListTools returns a list of all registered tool names.

func (*Agent) Receive

func (a *Agent) Receive(ctx context.Context, msg *loomv1.CommunicationMessage) (interface{}, error)

Receive receives and resolves a message from another agent. If the message uses reference semantics, the reference is resolved to actual data.

func (*Agent) ReceiveWithTimeout

func (a *Agent) ReceiveWithTimeout(ctx context.Context, timeout time.Duration) (*loomv1.CommunicationMessage, error)

ReceiveWithTimeout receives a message with a timeout. Returns nil if no message is available within the timeout period.

func (*Agent) RegisterLazyTools added in v1.2.0

func (a *Agent) RegisterLazyTools(tools []shuttle.Tool, trigger func(string) bool)

RegisterLazyTools registers tools that will only be added to the active tool set when trigger(userMessage) returns true. Safe to call concurrently.

func (*Agent) RegisterMCPServer

func (a *Agent) RegisterMCPServer(ctx context.Context, mcpMgr *manager.Manager, serverName string) error

RegisterMCPServer registers all tools from ONE specific server in the manager.

This provides selective registration at the server level instead of registering all servers at once. Useful for controlling context window usage.

Example:

err := agent.RegisterMCPServer(ctx, mcpMgr, "filesystem")
// Only filesystem tools registered, not github, postgres, etc.

func (*Agent) RegisterMCPServers

func (a *Agent) RegisterMCPServers(ctx context.Context, configs ...MCPServerConfig) error

RegisterMCPServers is a convenience method to register multiple MCP servers at once.

Example:

err := agent.RegisterMCPServers(ctx,
    MCPServerConfig{Name: "filesystem", Client: fsClient},
    MCPServerConfig{Name: "github", Client: ghClient},
    MCPServerConfig{Name: "postgres", Client: pgClient},
)

func (*Agent) RegisterMCPTool

func (a *Agent) RegisterMCPTool(ctx context.Context, mcpMgr *manager.Manager, serverName, toolName string) error

RegisterMCPTool registers ONE specific tool from a server.

This provides the finest-grained control over tool registration. Useful when you need just 1-2 specific tools from a server.

Example:

err := agent.RegisterMCPTool(ctx, mcpMgr, "filesystem", "read_file")
// Only filesystem:read_file registered

func (*Agent) RegisterMCPTools

func (a *Agent) RegisterMCPTools(ctx context.Context, config MCPServerConfig) error

RegisterMCPTools connects to an MCP server and registers all its tools with the agent.

This is a convenience method that: 1. Lists all tools from the MCP server 2. Converts them to shuttle.Tool instances 3. Registers them with the agent

Example usage:

// Create MCP client
trans := transport.NewStdioTransport(config)
mcpClient := client.NewClient(client.Config{Transport: trans})
mcpClient.Initialize(ctx, clientInfo)

// Register all MCP tools with agent
err := agent.RegisterMCPTools(ctx, MCPServerConfig{
    Name:   "filesystem",
    Client: mcpClient,
})

Tools will be namespaced by server name (e.g., "filesystem:read_file")

func (*Agent) RegisterMCPToolsFromManager

func (a *Agent) RegisterMCPToolsFromManager(ctx context.Context, mcpMgr *manager.Manager) error

RegisterMCPToolsFromManager registers tools from a manager using config-based filtering.

This is the recommended method for production use. It respects the tool filters defined in the manager's configuration.

Example config:

mcp:
  servers:
    filesystem:
      enabled: true
      tools:
        include: [read_file, write_file]
    github:
      enabled: true
      tools:
        all: true
        exclude: [delete_repository]

Example usage:

err := agent.RegisterMCPToolsFromManager(ctx, mcpMgr)
// Only tools matching config filters are registered

func (*Agent) RegisterTool

func (a *Agent) RegisterTool(tool shuttle.Tool)

RegisterTool registers a tool with the agent. Honours the WithoutBuiltinTool suppression set: if the tool's name has been suppressed via that option, the registration is silently skipped so the LLM never sees the tool. Subsystems that drive the tool keep running — only the surface is hidden.

func (*Agent) RegisterTools

func (a *Agent) RegisterTools(tools ...shuttle.Tool)

RegisterTools registers multiple tools, honouring per-name suppression.

func (*Agent) RegisteredTools

func (a *Agent) RegisteredTools() []shuttle.Tool

RegisteredTools returns all registered tools.

func (*Agent) RegisteredToolsByBackend

func (a *Agent) RegisteredToolsByBackend(backend string) []shuttle.Tool

RegisteredToolsByBackend returns all tools registered for a specific backend. Pass empty string to get backend-agnostic tools.

func (*Agent) ResetSessionContext added in v1.2.0

func (a *Agent) ResetSessionContext(sessionID string) bool

ResetSessionContext clears the context window for a session, preserving ROM and registered tools. Returns true if the session was found and reset, false otherwise.

func (*Agent) Send

func (a *Agent) Send(ctx context.Context, toAgent string, messageType string, data interface{}) (*loomv1.CommunicationMessage, error)

Send sends a message to another agent using value or reference semantics. The communication policy determines whether to use direct value or reference.

func (*Agent) SendAndReceive

func (a *Agent) SendAndReceive(ctx context.Context, toAgent string, messageType string, data interface{}, timeout time.Duration) (interface{}, error)

SendAndReceive sends a message and waits for a response (RPC-style). Blocks until response is received or timeout occurs.

func (*Agent) SendAsync

func (a *Agent) SendAsync(ctx context.Context, toAgent string, messageType string, data interface{}) (string, error)

SendAsync sends a message asynchronously (fire-and-forget). If the destination agent is offline, the message is queued for later delivery. Returns immediately without waiting for the message to be delivered.

func (*Agent) SendWithAck

func (a *Agent) SendWithAck(ctx context.Context, toAgent string, messageType string, data interface{}, timeout time.Duration) error

SendWithAck sends a message and waits for acknowledgment. Returns nil if message was successfully delivered and acknowledged.

func (*Agent) SetActiveProvider added in v1.2.0

func (a *Agent) SetActiveProvider(name string) error

SetActiveProvider switches to a named provider from the pool. Returns an error if the name is not in the pool or not in the allowed list.

func (*Agent) SetCommunicationPolicy

func (a *Agent) SetCommunicationPolicy(policy *communication.PolicyManager)

SetCommunicationPolicy configures the communication policy manager. This determines when to use references vs values in inter-agent communication.

func (*Agent) SetID added in v1.1.0

func (a *Agent) SetID(id string)

SetID sets the agent's ID (used by Registry for stable GUID assignment). This method allows external systems to set a stable GUID for the agent. IMPORTANT: This should only be called during agent initialization or hot-reload.

func (*Agent) SetLLMProvider

func (a *Agent) SetLLMProvider(llm LLMProvider)

SetLLMProvider switches the main LLM provider for this agent. This allows mid-session model switching while preserving conversation context. The new provider will be used for all future LLM calls in all sessions. Only updates memory's LLM provider if no dedicated compressor LLM is set.

func (*Agent) SetLLMProviderForRole added in v1.2.0

func (a *Agent) SetLLMProviderForRole(role loomv1.LLMRole, llm LLMProvider)

SetLLMProviderForRole sets the LLM provider for a specific role. For COMPRESSOR role, also updates memory's LLM provider. For AGENT/UNSPECIFIED role, delegates to SetLLMProvider.

func (*Agent) SetOffloadExemptTools added in v1.4.0

func (a *Agent) SetOffloadExemptTools(names []string)

SetOffloadExemptTools replaces the set of tool names whose current-turn results always render whole regardless of the offload threshold (§5.2 step 6 carve-out), for existing and future sessions. Use it for tools whose full output is the product of the call — content the model must read inline in the producing turn — where an offload stub would defeat the call. Prior-turn and evicted rows still render stubs, so relief and turn-end truncation behave identically for every tool.

func (*Agent) SetPatternTracker added in v1.2.0

func (a *Agent) SetPatternTracker(tracker *learning.PatternEffectivenessTracker)

SetPatternTracker wires a PatternEffectivenessTracker into this agent's orchestrator so that every pattern-guided turn records metrics to the pattern_effectiveness table. Safe to call with nil (no-op).

func (*Agent) SetProviderPool added in v1.2.0

func (a *Agent) SetProviderPool(pool map[string]LLMProvider, active string, allowed []string) error

SetProviderPool configures the named provider pool and optional active provider.

func (*Agent) SetReferenceStore

func (a *Agent) SetReferenceStore(store communication.ReferenceStore)

SetReferenceStore configures the reference store for inter-agent communication. This enables Send/Receive methods for agent-to-agent messaging.

func (*Agent) SetSharedMemory

func (a *Agent) SetSharedMemory(sharedMemory *storage.SharedMemoryStore)

SetSharedMemory configures shared memory for this agent. This injects the shared memory store into: - The agent itself (for formatToolResult to store large results) - All existing sessions' segmented memory - The tool executor for automatic large result handling - Future sessions created by this agent - Re-registers GetToolResultTool with the new store

func (*Agent) SetSharedMemoryThreshold added in v1.2.0

func (a *Agent) SetSharedMemoryThreshold(threshold int64)

SetSharedMemoryThreshold configures the byte threshold for storing large tool results in shared memory. -1 = use storage.DefaultSharedMemoryThreshold, 0 = always reference, >0 = reference only if result exceeds N bytes.

func (*Agent) SetToolRegistryForDynamicDiscovery

func (a *Agent) SetToolRegistryForDynamicDiscovery(toolRegistry shuttle.ToolRegistry, mcpManager shuttle.MCPManager)

SetToolRegistryForDynamicDiscovery configures the tool registry for dynamic tool discovery. When enabled, agents can use tools discovered via tool_search without explicit registration. MCP tools and builtin tools found in the registry will be dynamically registered when first used.

func (*Agent) SetWorkflowCommunicationContext added in v1.1.0

func (a *Agent) SetWorkflowCommunicationContext(ctx *WorkflowCommunicationContext)

SetWorkflowCommunicationContext sets the workflow communication context for this agent. This context is used to inject dynamic communication instructions into the system prompt.

func (*Agent) ToolCount

func (a *Agent) ToolCount() int

ToolCount returns the number of registered tools.

func (*Agent) UnregisterTool

func (a *Agent) UnregisterTool(name string)

UnregisterTool unregisters a tool by name.

type AgentConfigYAML

type AgentConfigYAML struct {
	Agent struct {
		Name             string                 `yaml:"name"`
		Description      string                 `yaml:"description"`
		BackendPath      string                 `yaml:"backend_path"`
		LLM              LLMConfigYAML          `yaml:"llm"`
		JudgeLLM         *LLMConfigYAML         `yaml:"judge_llm"`
		OrchestratorLLM  *LLMConfigYAML         `yaml:"orchestrator_llm"`
		ClassifierLLM    *LLMConfigYAML         `yaml:"classifier_llm"`
		CompressorLLM    *LLMConfigYAML         `yaml:"compressor_llm"`
		ActiveProvider   string                 `yaml:"active_provider"`
		AllowedProviders []string               `yaml:"allowed_providers"`
		SystemPrompt     string                 `yaml:"system_prompt"`
		ROM              string                 `yaml:"rom"` // ROM identifier: "TD", "teradata", "auto", or ""
		Tools            ToolsConfigYAML        `yaml:"tools"`
		Memory           MemoryConfigYAML       `yaml:"memory"`
		Behavior         BehaviorConfigYAML     `yaml:"behavior"`
		Metadata         map[string]interface{} `yaml:"metadata"`
	} `yaml:"agent"`
}

AgentConfigYAML represents the YAML structure for agent configuration. This struct mirrors the proto AgentConfig but uses YAML-friendly types. Legacy format with "agent:" as root key.

type AgentInstanceInfo

type AgentInstanceInfo struct {
	ID             string
	Name           string
	Status         string // "running", "stopped", "error", "initializing"
	CreatedAt      time.Time
	UpdatedAt      time.Time
	ActiveSessions int
	TotalMessages  int64
	Error          string
}

AgentInstanceInfo tracks runtime information about an agent instance

type AnthropicCompressor

type AnthropicCompressor struct {
	// contains filtered or unexported fields
}

AnthropicCompressor is a production-ready LLM caller for Anthropic's Claude. Implements LLMCaller interface using the official Anthropic SDK.

Example usage:

import "github.com/anthropics/anthropic-sdk-go"

client := anthropic.NewClient(option.WithAPIKey("your-key"))
compressor := NewAnthropicCompressor(client, "claude-3-haiku-20240307")
memCompressor := NewLLMCompressor(compressor)

Note: This is a reference implementation. Users should adapt based on their LLM provider and SDK. The key is implementing the LLMCaller interface.

func NewAnthropicCompressor

func NewAnthropicCompressor(client interface{}, modelName string) *AnthropicCompressor

NewAnthropicCompressor creates an Anthropic-based compressor. This is a reference implementation - adapt for your LLM provider.

func (*AnthropicCompressor) CompressConversation

func (a *AnthropicCompressor) CompressConversation(ctx context.Context, conversationText string) (string, error)

CompressConversation implements LLMCaller for Anthropic's Claude. Note: This is a skeleton implementation. Full implementation requires the anthropic-sdk-go and proper error handling.

type BehaviorConfigYAML

type BehaviorConfigYAML struct {
	MaxIterations          int                `yaml:"max_iterations"`
	TimeoutSeconds         int                `yaml:"timeout_seconds"`
	AllowCodeExecution     bool               `yaml:"allow_code_execution"`
	AllowedDomains         []string           `yaml:"allowed_domains"`
	MaxTurns               int                `yaml:"max_turns"`
	MaxToolExecutions      int                `yaml:"max_tool_executions"`
	Patterns               *PatternConfigYAML `yaml:"patterns"`
	Skills                 SkillsConfigYAML   `yaml:"skills"`
	OutputTokenCBThreshold int                `yaml:"output_token_cb_threshold"`
	EnableSelfHealing      *bool              `yaml:"enable_self_healing"`
}

BehaviorConfigYAML represents behavior configuration in YAML

type CachedToolResult

type CachedToolResult struct {
	ToolName      string
	Args          map[string]interface{}
	Result        string // Brief summary of result (for small results)
	Timestamp     time.Time
	DataReference *loomv1.DataReference // For large results stored in shared memory
}

CachedToolResult represents a recent tool execution stored in memory.

type CompressionProfile

type CompressionProfile struct {
	// Profile name (for logging and debugging)
	Name string

	// Maximum tokens in L1 cache before compression triggers
	// This is the primary trigger - when L1 token count exceeds this, compression occurs
	MaxL1Tokens int

	// Minimum messages to keep in L1 after compression (for recency)
	// Ensures at least last few exchanges are preserved even if small
	MinL1Messages int

	// Warning threshold as percentage of usable context (0-100).
	// The relief release mark (LWM, HLD §5.1): relief sheds down to this.
	WarningThresholdPercent int

	// Critical threshold as percentage of usable context (0-100).
	// The relief start mark (HWM, HLD §5.1): relief begins when the
	// estimate reaches this.
	CriticalThresholdPercent int

	// Number of messages to compress in normal conditions
	NormalBatchSize int

	// Number of messages to compress under warning threshold
	WarningBatchSize int

	// Number of messages to compress under critical threshold
	CriticalBatchSize int
}

CompressionProfile defines memory compression behavior for a specific workload type. Profiles provide preset values for thresholds, batch sizes, and L1 cache limits.

func ResolveCompressionProfile

func ResolveCompressionProfile(config *loomv1.MemoryCompressionConfig) (CompressionProfile, error)

ResolveCompressionProfile resolves a compression configuration into a final profile. Precedence: Explicit config values > Profile defaults > Balanced profile defaults

func (CompressionProfile) Validate

func (p CompressionProfile) Validate() error

Validate checks if the profile has valid values.

type Config

type Config struct {
	// Name is the agent name (used for identification and logging)
	Name string

	// Description is a human-readable description of the agent's purpose
	Description string

	// MaxTurns is the maximum number of conversation turns before forcing completion
	MaxTurns int

	// MaxToolExecutions is the maximum number of tool executions per conversation
	MaxToolExecutions int

	// MaxIterations caps tool calls executed per single LLM response (per-turn).
	// When the LLM emits more tool calls than this limit in one response, only
	// MaxIterations are executed; the rest receive "turn_limit_exceeded" errors.
	// 0 = use default (10).
	MaxIterations int

	// SystemPrompt is the direct system prompt text (takes precedence over SystemPromptKey)
	SystemPrompt string

	// SystemPromptKey is the key for loading the system prompt from promptio
	SystemPromptKey string

	// ROM identifier for domain-specific knowledge ("TD", "teradata", "auto", or "")
	Rom string

	// Metadata for agent configuration (includes backend_path for ROM auto-detection)
	Metadata map[string]string

	// EnableTracing enables observability tracing
	EnableTracing bool

	// PatternsDir is the directory containing pattern YAML files (optional)
	PatternsDir string

	// Backend configuration
	BackendConfig map[string]interface{}

	// Retry configuration for LLM calls
	Retry RetryConfig

	// MaxContextTokens is the model's context window size (0 = use defaults/auto-detect)
	MaxContextTokens int

	// ReservedOutputTokens is the number of tokens reserved for model output (0 = use defaults, typically 10%)
	ReservedOutputTokens int

	// ProtectedRecentTurns is K (HLD §5.1): the top rung of relief's halving
	// ladder — the newest turns relief tries hardest to keep, though the ladder
	// walks toward T−1 when shedding at K is not enough. 0 = default (16).
	ProtectedRecentTurns int

	// PatternConfig controls pattern injection (nil = use defaults)
	PatternConfig *PatternConfig

	// SkillsConfig controls skill activation and injection (nil = use defaults)
	SkillsConfig *skills.SkillsConfig

	// Automatic finding extraction configuration
	EnableFindingExtraction bool // Whether to enable automatic finding extraction (default: true)
	ExtractionCadence       int  // Number of tool executions between extractions (default: 3)
	MaxFindings             int  // Maximum findings to keep in cache (default: 50)

	// OutputTokenCBThreshold is the number of consecutive turns where the LLM
	// hits the output token limit AND returns truncated tool calls before the
	// circuit breaker fires. 0 uses the default (8). -1 disables the CB entirely.
	OutputTokenCBThreshold int

	// EnableSelfHealing enables Tier 1 automatic recovery (context trimming,
	// tool disabling) before errors propagate to the caller. Default: true.
	EnableSelfHealing bool

	// RecoveryConfig holds tunables for the self-healing orchestrator.
	// Nil uses DefaultRecoveryConfig().
	RecoveryConfig *RecoveryConfig

	// Debug holds opt-in diagnostic switches, all off by default.
	Debug DebugConfig
}

Config holds agent configuration.

func DefaultConfig

func DefaultConfig() *Config

DefaultConfig returns a Config with sensible defaults.

type ContentBlock added in v1.4.0

type ContentBlock = types.ContentBlock

type Context

type Context = types.Context

type ContextState added in v1.2.0

type ContextState struct {
	ActivePattern     string
	ContextTokensUsed int64
	ContextTokensMax  int64
	Rom               string
	ToolsLoaded       []string
}

ContextState holds a snapshot of the agent's memory and context window state. Used to populate the proto ContextState message in WeaveResponse.

type CustomToolConfigYAML

type CustomToolConfigYAML struct {
	Name           string `yaml:"name"`
	Implementation string `yaml:"implementation"`
}

CustomToolConfigYAML represents custom tool configuration in YAML

type DBConfig

type DBConfig struct {
	// Path to the SQLite database file
	Path string

	// EncryptDatabase enables SQLCipher encryption at rest.
	// When true, requires EncryptionKey to be set.
	// Default: false (opt-in for enterprise deployments)
	EncryptDatabase bool

	// EncryptionKey is the encryption key for SQLCipher.
	// Can be provided directly or via LOOM_DB_KEY environment variable.
	// Required when EncryptDatabase is true.
	EncryptionKey string
}

DBConfig holds database configuration including optional encryption.

type DebugConfig added in v1.4.0

type DebugConfig struct {
	// ContextDump enables one un-redacted dump record per provider call,
	// capturing the compiled (messages, tools) about to be dispatched. Written
	// only to a local per-run sink, never to zap/Hawk. Off by default; also
	// enabled via the LOOM_DEBUG_CONTEXT_DUMP environment variable.
	ContextDump bool
}

DebugConfig holds opt-in diagnostic switches. Every field defaults to its zero value (off) so the production path stays untouched unless a switch is explicitly set.

type DynamicToolDiscovery

type DynamicToolDiscovery struct {
	// contains filtered or unexported fields
}

DynamicToolDiscovery enables runtime tool discovery using simple text search.

Instead of registering all tools upfront, tools are discovered on-demand based on user intent. This prevents context window bloat while maintaining access to all available tools.

Search Strategy:

  • Simple text matching (case-insensitive) on tool name and description
  • No complex NLP or embedding required
  • Results cached for future use

Example:

discovery := NewDynamicToolDiscovery(mcpMgr, logger)
tool, err := discovery.Search(ctx, "read file")
// Finds "filesystem:read_file" by matching "read" and "file"

func NewDynamicToolDiscovery

func NewDynamicToolDiscovery(mcpMgr *manager.Manager, logger *zap.Logger) *DynamicToolDiscovery

NewDynamicToolDiscovery creates a new dynamic tool discovery system.

func (*DynamicToolDiscovery) CacheSize

func (d *DynamicToolDiscovery) CacheSize() int

CacheSize returns the current cache size.

func (*DynamicToolDiscovery) ClearCache

func (d *DynamicToolDiscovery) ClearCache()

ClearCache clears the discovery cache.

func (*DynamicToolDiscovery) Search

func (d *DynamicToolDiscovery) Search(ctx context.Context, intent string) (shuttle.Tool, error)

Search finds a tool matching the user intent using simple text search.

Search process:

  1. Check cache for previously discovered tools
  2. Search all MCP servers for matching tools
  3. Use simple text matching on tool name and description
  4. Cache the result for future use
  5. Return the first matching tool

Returns an error if no matching tool is found.

func (*DynamicToolDiscovery) SearchMultiple

func (d *DynamicToolDiscovery) SearchMultiple(ctx context.Context, intent string) ([]shuttle.Tool, error)

SearchMultiple finds multiple tools matching the intent.

Unlike Search which returns the first match, this returns all matching tools. Useful when you want to give the LLM multiple options.

type ExecutionStage

type ExecutionStage = types.ExecutionStage

type ExtractedEntity added in v1.3.0

type ExtractedEntity struct {
	Name       string `json:"name"`
	EntityType string `json:"entity_type"`
	Properties string `json:"properties"`
	IsUser     bool   `json:"is_user"` // true if this person entity IS the human speaking
}

ExtractedEntity represents an entity extracted from conversation context.

type ExtractedEntityRole added in v1.3.0

type ExtractedEntityRole struct {
	Name string `json:"name"`
	Role string `json:"role"` // "about" = primary subject, "mentions" = referenced
}

ExtractedEntityRole pairs an entity name with its role in a memory.

type ExtractedGraphData added in v1.3.0

type ExtractedGraphData struct {
	Entities      []ExtractedEntity       `json:"entities"`
	Relationships []ExtractedRelationship `json:"relationships"`
	Memories      []ExtractedMemory       `json:"memories"`
}

ExtractedGraphData is the top-level JSON response from the LLM extraction.

type ExtractedMemory added in v1.3.0

type ExtractedMemory struct {
	Content    string                `json:"content"`
	Summary    string                `json:"summary"`
	MemoryType string                `json:"memory_type"`
	Tags       []string              `json:"tags"`
	Salience   float64               `json:"salience"`
	Entities   []ExtractedEntityRole `json:"entities"`
	// EventDate is the absolute ISO date (YYYY-MM-DD) for when the fact
	// described by this memory occurred. Produced by anchoring any relative
	// time phrase in the conversation against the current_date the extractor
	// was given. Empty when no temporal cue is present or when the cue cannot
	// be resolved to a specific date.
	EventDate string `json:"event_date,omitempty"`
	// EventDateConfidence is "exact" | "approximate" | "ambiguous" | "".
	// "ambiguous" is reserved for cases where the extractor saw a time cue
	// like "a while back" and declined to fabricate a date.
	EventDateConfidence string `json:"event_date_confidence,omitempty"`
}

ExtractedMemory represents a memory worth remembering.

type ExtractedRelationship added in v1.3.0

type ExtractedRelationship struct {
	Source   string `json:"source"`
	Target   string `json:"target"`
	Relation string `json:"relation"`
}

ExtractedRelationship represents a relationship between two entities.

type FailureEscalationConfig

type FailureEscalationConfig struct {
	MaxConsecutiveFailures int  // Threshold for escalation (default: 2)
	TrackFailureSignature  bool // Whether to track failure signatures (default: true)
}

FailureEscalationConfig holds configuration for failure escalation.

func DefaultFailureEscalationConfig

func DefaultFailureEscalationConfig() FailureEscalationConfig

DefaultFailureEscalationConfig returns default failure escalation configuration.

type GraphMemoryConfigYAML added in v1.3.0

type GraphMemoryConfigYAML struct {
	Enabled                       *bool   `yaml:"enabled"`
	ContextBudgetPercent          int     `yaml:"context_budget_percent"`
	MaxContextTokens              int     `yaml:"max_context_tokens"`
	DecayRate                     float64 `yaml:"decay_rate"`
	BoostAmount                   float64 `yaml:"boost_amount"`
	MinSalienceThreshold          float64 `yaml:"min_salience_threshold"`
	MaxRecallCandidates           int     `yaml:"max_recall_candidates"`
	DefaultSalience               float64 `yaml:"default_salience"`
	EnableExtraction              *bool   `yaml:"enable_extraction"`
	ExtractionCadence             int     `yaml:"extraction_cadence"`
	MaxEntitiesPerExtraction      int     `yaml:"max_entities_per_extraction"`
	ConversationExtractionCadence int     `yaml:"conversation_extraction_cadence"`
	ExtractionTimeoutSeconds      int     `yaml:"extraction_timeout_seconds"`
}

GraphMemoryConfigYAML represents graph memory configuration in YAML. Enabled is a *bool so we can distinguish "not set" (nil → defaults to true, opt-out) from "explicitly set to false" (opt-out by the user).

type GraphMemoryTool added in v1.3.0

type GraphMemoryTool struct {
	// contains filtered or unexported fields
}

GraphMemoryTool provides agent-facing graph memory operations. Actions: remember, recall, forget, supersede, consolidate, context_for, entities, relate.

func NewGraphMemoryTool added in v1.3.0

func NewGraphMemoryTool(store memory.GraphMemoryStore, agentID string) *GraphMemoryTool

NewGraphMemoryTool creates a new graph memory tool.

func (*GraphMemoryTool) Backend added in v1.3.0

func (t *GraphMemoryTool) Backend() string

func (*GraphMemoryTool) Description added in v1.3.0

func (t *GraphMemoryTool) Description() string

func (*GraphMemoryTool) Execute added in v1.3.0

func (t *GraphMemoryTool) Execute(ctx context.Context, input map[string]interface{}) (*shuttle.Result, error)

func (*GraphMemoryTool) InputSchema added in v1.3.0

func (t *GraphMemoryTool) InputSchema() *shuttle.JSONSchema

func (*GraphMemoryTool) Name added in v1.3.0

func (t *GraphMemoryTool) Name() string

type HITLRequestInfo

type HITLRequestInfo = types.HITLRequestInfo

type K8sStyleAgentConfig

type K8sStyleAgentConfig struct {
	APIVersion string `yaml:"apiVersion"`
	Kind       string `yaml:"kind"`
	Metadata   struct {
		Name        string                 `yaml:"name"`
		Version     string                 `yaml:"version"`
		Description string                 `yaml:"description"`
		Role        string                 `yaml:"role"`
		Workflow    string                 `yaml:"workflow"`
		Labels      map[string]interface{} `yaml:"labels"`
	} `yaml:"metadata"`
	Spec struct {
		Backend struct {
			Name   string                 `yaml:"name"`
			Type   string                 `yaml:"type"`
			Config map[string]interface{} `yaml:"config"`
		} `yaml:"backend"`
		BackendPath      string                 `yaml:"backend_path"` // Path to backend YAML config file
		LLM              LLMConfigYAML          `yaml:"llm"`
		JudgeLLM         *LLMConfigYAML         `yaml:"judge_llm"`
		OrchestratorLLM  *LLMConfigYAML         `yaml:"orchestrator_llm"`
		ClassifierLLM    *LLMConfigYAML         `yaml:"classifier_llm"`
		CompressorLLM    *LLMConfigYAML         `yaml:"compressor_llm"`
		ActiveProvider   string                 `yaml:"active_provider"`
		AllowedProviders []string               `yaml:"allowed_providers"`
		Tools            interface{}            `yaml:"tools"` // Can be ToolsConfigYAML or []interface{}
		SystemPrompt     string                 `yaml:"system_prompt"`
		ROM              string                 `yaml:"rom"` // ROM identifier: "TD", "teradata", "auto", or ""
		Config           BehaviorConfigYAML     `yaml:"config"`
		Memory           MemoryConfigYAML       `yaml:"memory"`
		Observability    map[string]interface{} `yaml:"observability"`
	} `yaml:"spec"`
}

K8sStyleAgentConfig represents the new k8s-style YAML format with apiVersion, kind, metadata, spec.

type LLMCaller

type LLMCaller interface {
	// CompressConversation takes conversation text and returns a concise summary.
	// Should limit output to 512 tokens for cost efficiency.
	CompressConversation(ctx context.Context, conversationText string) (string, error)
}

LLMCaller defines the interface for calling an LLM to compress messages. Implementations should provide cheap, fast compression calls.

type LLMCompressor

type LLMCompressor struct {
	// contains filtered or unexported fields
}

LLMCompressor is a concrete implementation of MemoryCompressor that uses an LLM to create intelligent summaries of conversation history.

Provides 50-80% token reduction through LLM-powered summarization.

func NewLLMCompressor

func NewLLMCompressor(llmCaller LLMCaller) *LLMCompressor

NewLLMCompressor creates a new LLM-powered memory compressor. If llmCaller is nil, falls back to simple text extraction.

func (*LLMCompressor) CompressMessages

func (c *LLMCompressor) CompressMessages(ctx context.Context, messages []Message) (string, error)

CompressMessages compresses a slice of messages into a concise summary. Uses LLM if available, otherwise falls back to simple extraction.

LLM compression typically achieves: - 50-80% token reduction - 2-3 sentence summaries - Preservation of key context (tables, queries, findings)

func (*LLMCompressor) IsEnabled

func (c *LLMCompressor) IsEnabled() bool

IsEnabled returns whether LLM-powered compression is enabled.

func (*LLMCompressor) SetLLMCaller

func (c *LLMCompressor) SetLLMCaller(llmCaller LLMCaller)

SetLLMCaller updates the LLM caller for the compressor. Useful for lazy initialization after agent is fully set up.

type LLMConfigYAML

type LLMConfigYAML struct {
	Provider             string   `yaml:"provider"`
	Model                string   `yaml:"model"`
	Temperature          float64  `yaml:"temperature"`
	MaxTokens            int      `yaml:"max_tokens"`
	StopSequences        []string `yaml:"stop_sequences"`
	TopP                 float64  `yaml:"top_p"`
	TopK                 int      `yaml:"top_k"`
	MaxContextTokens     int      `yaml:"max_context_tokens"`
	ReservedOutputTokens int      `yaml:"reserved_output_tokens"`
}

LLMConfigYAML represents LLM configuration in YAML

type LLMProvider

type LLMProvider = types.LLMProvider

type LLMResponse

type LLMResponse = types.LLMResponse

type LoadPatternTool added in v1.4.0

type LoadPatternTool struct {
	// contains filtered or unexported fields
}

LoadPatternTool retrieves a pattern's content on demand and returns it as an ordinary tool-result. The content lands in L1 as tool-result data, so it is subject to the same size-threshold and compaction rules as any other data — it is never a system-slot injection. The reference the model passes here is the one surfaced from a skill's PatternRefs by manage_skills(load).

func NewLoadPatternTool added in v1.4.0

func NewLoadPatternTool(orchestrator *patterns.Orchestrator) *LoadPatternTool

NewLoadPatternTool creates a load_pattern tool backed by the pattern orchestrator.

func (*LoadPatternTool) Backend added in v1.4.0

func (t *LoadPatternTool) Backend() string

func (*LoadPatternTool) Description added in v1.4.0

func (t *LoadPatternTool) Description() string

func (*LoadPatternTool) Execute added in v1.4.0

func (t *LoadPatternTool) Execute(ctx context.Context, params map[string]interface{}) (*shuttle.Result, error)

Execute loads the referenced pattern and returns its LLM rendering as string tool-result data. An unknown reference yields an error result so no pattern content enters the conversation.

func (*LoadPatternTool) InputSchema added in v1.4.0

func (t *LoadPatternTool) InputSchema() *shuttle.JSONSchema

func (*LoadPatternTool) Name added in v1.4.0

func (t *LoadPatternTool) Name() string

type MCPClientRef

type MCPClientRef struct {
	Client     interface{ Close() error } // MCP client with Close method
	ServerName string
}

MCPClientRef holds a reference to an MCP client for cleanup

type MCPServerConfig

type MCPServerConfig struct {
	// Name is the unique identifier for this MCP server
	// Used for tool namespacing (e.g., "filesystem" -> "filesystem:read_file")
	Name string

	// Client is the initialized MCP client
	Client *client.Client

	// AutoClose determines if the client should be closed when agent is done
	// Default: false (client lifecycle managed externally)
	AutoClose bool
}

MCPServerConfig configures an MCP server connection

type MCPToolConfigYAML

type MCPToolConfigYAML struct {
	Server string   `yaml:"server"`
	Tools  []string `yaml:"tools"`
}

MCPToolConfigYAML represents MCP tool configuration in YAML

type ManageSkillsTool added in v1.4.0

type ManageSkillsTool struct {
	// contains filtered or unexported fields
}

ManageSkillsTool is the model-facing pull interface for skills: it loads a skill body into the conversation and lists the library annotated with the skills active for the calling session. Both the load's tool-wiring and the list's active annotation read the orchestrator's per-session active set, so "which skills are loaded" has a single source and is never re-derived from the conversation.

There is no unload action: a load appends to the active set and required-tool wiring stays until the session ends.

func NewManageSkillsTool added in v1.4.0

func NewManageSkillsTool(
	orch *skills.Orchestrator,
	library *skills.Library,
	permissionChecker *shuttle.PermissionChecker,
	enforceTools func(sessionID string),
) *ManageSkillsTool

NewManageSkillsTool constructs the manage_skills builtin. enforceTools is the agent's required-tool enforcement bound to this agent; it may be nil, in which case a load activates the skill but does not wire its required tools.

func (*ManageSkillsTool) Backend added in v1.4.0

func (t *ManageSkillsTool) Backend() string

Backend returns the backend type this tool requires. Empty means the tool is backend-agnostic.

func (*ManageSkillsTool) Description added in v1.4.0

func (t *ManageSkillsTool) Description() string

Description returns the tool description for the LLM.

func (*ManageSkillsTool) Execute added in v1.4.0

func (t *ManageSkillsTool) Execute(ctx context.Context, params map[string]interface{}) (*shuttle.Result, error)

Execute dispatches on the action.

func (*ManageSkillsTool) InputSchema added in v1.4.0

func (t *ManageSkillsTool) InputSchema() *shuttle.JSONSchema

InputSchema returns the JSON schema for the tool input.

func (*ManageSkillsTool) Name added in v1.4.0

func (t *ManageSkillsTool) Name() string

Name returns the tool name.

type Memory

type Memory struct {
	// contains filtered or unexported fields
}

Memory manages conversation sessions and history. Supports optional persistent storage via SessionStorage interface.

func NewMemory

func NewMemory() *Memory

NewMemory creates a new in-memory session manager. Uses zap.L() (the global logger) by default, so storage errors are visible if a global logger has been configured (e.g., via zap.ReplaceGlobals). If no global logger is configured, zap.L() returns a no-op logger. Call SetLogger() to inject an explicit logger instance.

func NewMemoryWithStore

func NewMemoryWithStore(store SessionStorage) *Memory

NewMemoryWithStore creates a memory manager with persistent storage. Uses zap.L() (the global logger) by default, so storage errors are visible if a global logger has been configured (e.g., via zap.ReplaceGlobals). If no global logger is configured, zap.L() returns a no-op logger. Call SetLogger() to inject an explicit logger instance.

func (*Memory) AddMessage

func (m *Memory) AddMessage(ctx context.Context, sessionID string, msg Message)

AddMessage adds a message to a session and notifies observers. This is the preferred way to add messages when real-time updates are needed. Falls back to session.AddMessage if session not found in Memory. ctx is threaded through to enable RLS-aware storage operations.

func (*Memory) ClearAll

func (m *Memory) ClearAll()

ClearAll removes all sessions from memory (does not affect persistent store).

func (*Memory) CountSessions

func (m *Memory) CountSessions() int

CountSessions returns the number of active sessions.

func (*Memory) DeleteSession

func (m *Memory) DeleteSession(sessionID string)

DeleteSession removes a session.

func (*Memory) GetOrCreateSession

func (m *Memory) GetOrCreateSession(ctx context.Context, sessionID string) *Session

GetOrCreateSession gets an existing session or creates a new one. If persistent storage is configured, attempts to load from database first. ctx is threaded through to storage operations to enable RLS user isolation.

func (*Memory) GetOrCreateSessionWithAgent

func (m *Memory) GetOrCreateSessionWithAgent(ctx context.Context, sessionID, agentID, parentSessionID string) *Session

GetOrCreateSessionWithAgent gets an existing session or creates a new one with agent metadata. This is used for multi-agent workflows where sub-agents need to access parent sessions. ctx is threaded through to storage operations to enable RLS user isolation. Parameters:

  • ctx: Context with user identity for RLS-scoped storage access
  • sessionID: Unique session identifier
  • agentID: Agent identity (e.g., "coordinator", "analyzer-sub-agent")
  • parentSessionID: Parent session ID (for sub-agents to access coordinator session)

func (*Memory) GetSession

func (m *Memory) GetSession(sessionID string) (*Session, bool)

GetSession retrieves a session by ID.

func (*Memory) GetStore

func (m *Memory) GetStore() SessionStorage

GetStore returns the SessionStorage if persistence is enabled, nil otherwise. Used for registering cleanup hooks and accessing persistence layer.

func (*Memory) ListSessions

func (m *Memory) ListSessions() []*Session

ListSessions returns all active sessions.

func (*Memory) PersistMessage

func (m *Memory) PersistMessage(ctx context.Context, sessionID string, msg *Message, turnStart bool) error

PersistMessage saves a message's durable row, once, applying the fixed write rules of HLD §4 to the stored copy — the in-memory message stays whole. The store derives the row's seq and turn at insert and stamps both back onto msg; turnStart is passed only by the Chat()-entry persist site — the only turn-incrementing event.

Write rules applied here (loom's single persist seam):

  • §4.1 truncation: every tool result row is bounded at the threshold, tail included (core cut backward to a rune boundary + normative tail).
  • §4.3 retrieval pairs are not persisted: query_tool_result entries are filtered from an assistant row's calls; tool rows whose tool_use_id matches a filtered entry are not persisted; an assistant message left with no text and no calls is not persisted. Both sides always — an orphaned pair breaks replay at the API.

func (*Memory) PersistSession

func (m *Memory) PersistSession(ctx context.Context, session *Session) error

PersistSession saves a session to persistent storage if configured.

func (*Memory) PersistToolExecution

func (m *Memory) PersistToolExecution(ctx context.Context, sessionID string, exec ToolExecution) error

PersistToolExecution saves a tool execution to persistent storage if configured.

func (*Memory) RegisterObserver

func (m *Memory) RegisterObserver(agentID string, observer MemoryObserver)

RegisterObserver registers an observer for a specific agent's memory updates. The observer will be notified when messages are added to any session for this agent. This enables real-time cross-session updates.

func (*Memory) SetCompressionProfile

func (m *Memory) SetCompressionProfile(profile *CompressionProfile)

SetCompressionProfile sets the compression profile for new sessions. This controls compression behavior (thresholds, batch sizes) for memory management. If profile is nil, balanced profile defaults will be used.

func (*Memory) SetCompressor added in v1.4.0

func (m *Memory) SetCompressor(compressor MemoryCompressor)

SetCompressor sets the LLM-powered compressor for L2 compaction across all sessions (existing and future). With a compressor present, compaction routes through it; sessions without one fall back to the heuristic summariser.

func (*Memory) SetContextDebug added in v1.4.0

func (m *Memory) SetContextDebug(cd *contextDebug)

SetContextDebug injects the per-mutation debug carrier. It is forwarded to every SegmentedMemory this manager builds and read by the restore re-fire pass, so compaction and re-fire logs share the agent's context-dump switch.

func (*Memory) SetContextLimits

func (m *Memory) SetContextLimits(maxContextTokens, reservedOutputTokens int)

SetContextLimits sets the context window size and output reservation for new sessions. If maxContextTokens is 0, defaults will be used (200K for backwards compatibility). If reservedOutputTokens is 0, it will be calculated as 10% of maxContextTokens.

func (*Memory) SetLLMProvider

func (m *Memory) SetLLMProvider(llm LLMProvider)

SetLLMProvider sets the LLM provider for semantic search reranking (existing and future sessions). This enables LLM-based relevance scoring to improve search quality beyond BM25 keyword matching.

func (*Memory) SetLogger added in v1.2.0

func (m *Memory) SetLogger(logger *zap.Logger)

SetLogger sets the structured logger for storage error reporting.

func (*Memory) SetOffloadExemptTools added in v1.4.0

func (m *Memory) SetOffloadExemptTools(names []string)

SetOffloadExemptTools replaces the set of tool names whose current-turn results always render whole regardless of the threshold (§5.2 step 6 carve-out), for existing and future sessions. An empty slice clears the set.

func (*Memory) SetProtectedRecentTurns added in v1.4.0

func (m *Memory) SetProtectedRecentTurns(k int)

SetProtectedRecentTurns configures K — protected newest user turns (HLD §5.1; config ProtectedRecentTurns) — for existing and future sessions.

func (*Memory) SetRestoreReFireHooks added in v1.4.0

func (m *Memory) SetRestoreReFireHooks(activateSkill func(sessionID, skillName string))

SetRestoreReFireHooks wires the callback the restore replay uses to rebuild a session's runtime state from its durable messages: activateSkill re-fires a load marker (no-evict activation + required-tool wiring). The agent layer supplies it because it touches the skill orchestrator and the per-session tool ledger. Disclosure re-fire is deleted (HLD §8): refs never survive a turn, so there is nothing to re-advertise on restore, and the error store is gone.

func (*Memory) SetSharedMemory

func (m *Memory) SetSharedMemory(sharedMemory *storage.SharedMemoryStore)

SetSharedMemory configures shared memory for all sessions. This will inject the shared memory into all existing sessions and ensure future sessions also get it.

func (*Memory) SetSkillDeactivationHook added in v1.4.0

func (m *Memory) SetSkillDeactivationHook(fn func(sessionID, skillName string))

SetSkillDeactivationHook wires the skills orchestrator's deactivation path into every session's memory (existing and future): fold deactivates skills whose manage_skills load pair lies inside the folded region (HLD §4.5).

func (*Memory) SetSystemPromptFunc

func (m *Memory) SetSystemPromptFunc(fn SystemPromptFunc)

SetSystemPromptFunc sets a function to generate system prompts for new sessions. This allows dynamic prompt loading from PromptRegistry or other sources.

func (*Memory) SetThresholdBytes added in v1.4.0

func (m *Memory) SetThresholdBytes(bytes int64)

SetThresholdBytes sets the one threshold value (HLD §5.1: compile-time offload bound, persist-time row bound, retrieval page bound) for existing and future sessions.

func (*Memory) SetTracer

func (m *Memory) SetTracer(tracer observability.Tracer)

SetTracer sets the observability tracer for all sessions (existing and future). This enables error logging and metrics collection for memory operations.

func (*Memory) UnregisterObserver

func (m *Memory) UnregisterObserver(agentID string, observer MemoryObserver)

UnregisterObserver removes an observer for a specific agent. Note: This does a simple identity comparison, so the same observer instance must be passed.

type MemoryCompressionBatchSizesYAML

type MemoryCompressionBatchSizesYAML struct {
	Normal   int `yaml:"normal"`
	Warning  int `yaml:"warning"`
	Critical int `yaml:"critical"`
}

MemoryCompressionBatchSizesYAML represents compression batch sizes in YAML

type MemoryCompressionConfigYAML

type MemoryCompressionConfigYAML struct {
	WorkloadProfile          string                           `yaml:"workload_profile"`
	MaxL1Messages            int                              `yaml:"max_l1_messages"`
	MinL1Messages            int                              `yaml:"min_l1_messages"`
	WarningThresholdPercent  int                              `yaml:"warning_threshold_percent"`
	CriticalThresholdPercent int                              `yaml:"critical_threshold_percent"`
	BatchSizes               *MemoryCompressionBatchSizesYAML `yaml:"batch_sizes"`
}

MemoryCompressionConfigYAML represents memory compression configuration in YAML

type MemoryCompressor

type MemoryCompressor interface {
	CompressMessages(ctx context.Context, messages []Message) (string, error)
	IsEnabled() bool
}

MemoryCompressor defines the interface for LLM-powered memory compression. Implementations should compress message history into brief summaries.

type MemoryConfigYAML

type MemoryConfigYAML struct {
	Type                       string                       `yaml:"type"`
	Path                       string                       `yaml:"path"`
	DSN                        string                       `yaml:"dsn"`
	MaxHistory                 int                          `yaml:"max_history"`
	SharedMemoryThresholdBytes int64                        `yaml:"shared_memory_threshold_bytes"`
	MaxToolResults             int                          `yaml:"max_tool_results"`
	MemoryCompression          *MemoryCompressionConfigYAML `yaml:"memory_compression"`
	GraphMemory                *GraphMemoryConfigYAML       `yaml:"graph_memory"`
	TaskBoard                  *TaskBoardConfigYAML         `yaml:"task_board"`
}

MemoryConfigYAML represents memory configuration in YAML

type MemoryLayer

type MemoryLayer string

MemoryLayer represents different tiers of context memory

const (
	LayerROM    MemoryLayer = "rom"    // Read-only: Documentation, system prompt (never changes)
	LayerKernel MemoryLayer = "kernel" // Advertised tool schemas (ride the provider tools parameter)
	LayerL1     MemoryLayer = "l1"     // The message list, in order
	LayerL2     MemoryLayer = "l2"     // The session summary: one cumulative text
)

type MemoryObserver

type MemoryObserver interface {
	// OnMessageAdded is called when a message is added to any session for this agent
	OnMessageAdded(agentID string, sessionID string, msg Message)
}

MemoryObserver is called when messages are added to sessions. This enables real-time updates across multiple sessions viewing the same agent's memory.

type MemoryObserverFunc

type MemoryObserverFunc func(agentID string, sessionID string, msg Message)

MemoryObserverFunc is a function adapter for MemoryObserver.

func (MemoryObserverFunc) OnMessageAdded

func (f MemoryObserverFunc) OnMessageAdded(agentID string, sessionID string, msg Message)

OnMessageAdded implements MemoryObserver.

type MemorySnapshot

type MemorySnapshot struct {
	ID           int
	SessionID    string
	SnapshotType string
	Content      string
	TokenCount   int
	CreatedAt    time.Time
}

MemorySnapshot represents a saved memory snapshot (e.g., L2 summary).

type Message

type Message = types.Message

Type aliases for backward compatibility with code that imports pkg/agent. These types are now defined in pkg/types to break import cycles.

type ModelContextLimits

type ModelContextLimits struct {
	MaxContextTokens     int // Total context window size
	ReservedOutputTokens int // Tokens reserved for model output (typically 10%)
}

ModelContextLimits defines the context window and output reservation for a model

func GetModelContextLimits

func GetModelContextLimits(modelName string) *ModelContextLimits

GetModelContextLimits returns the context limits for a given model name. Returns the limits if found, or nil if the model is not in the lookup table.

func GetProviderDefaultLimits

func GetProviderDefaultLimits(provider string) ModelContextLimits

GetProviderDefaultLimits returns sensible defaults for a provider. Used when model-specific limits are not available.

func ResolveContextLimits

func ResolveContextLimits(provider, model string, configuredMax, configuredReserved int32) ModelContextLimits

ResolveContextLimits determines the context limits to use, with fallback precedence:

  1. Explicit configuration (if configuredMax > 0)
  2. Built-in catalog entry for provider+model (authoritative ContextWindow / MaxOutputTokens from pkg/llm/catalog)
  3. Legacy prefix-matched lookup table (covers Ollama tags and pre-catalog model name variants)
  4. Provider defaults
  5. System-wide conservative fallback

type Option

type Option func(*Agent)

Option is a functional option for configuring an Agent.

func BuildSkillsOptions added in v1.3.0

func BuildSkillsOptions(deps SkillsWiringDeps) []Option

BuildSkillsOptions assembles the agent.Options that wire the skills subsystem (orchestrator + Discovery + hierarchical router) onto an Agent.

This is the single source of truth for skills wiring across the loom ecosystem (loom, loom-cloud, avmo-tera-cloud). Callers in those repos should append the returned options to their existing agent.Option slice when constructing an Agent.

Side effect: when the router is enabled and a routerLLM is resolvable, this kicks off a background goroutine that builds and persists the hierarchical skill index. The goroutine outlives the caller's context; a SetTree on the router upgrades Discovery from FTS5-only to router-first.

Returns nil when skills are not configured or disabled.

func WithAdmissionHooks added in v1.4.0

func WithAdmissionHooks(chain *shuttle.Chain) Option

WithAdmissionHooks sets the admission hook chain consulted before every tool body runs. The chain carries the name-level permission check as its first hook; a nil chain leaves tool execution as a pure pass-through.

func WithCircuitBreakers

func WithCircuitBreakers(breakers *fabric.CircuitBreakerManager) Option

WithCircuitBreakers enables failure isolation for tools.

func WithClassifierLLM added in v1.2.0

func WithClassifierLLM(llm LLMProvider) Option

WithClassifierLLM sets the LLM provider for intent classification.

func WithCommunicationPolicy

func WithCommunicationPolicy(policy *communication.PolicyManager) Option

WithCommunicationPolicy sets the policy for determining reference vs value communication.

func WithCompressionProfile

func WithCompressionProfile(profile *CompressionProfile) Option

WithCompressionProfile sets the compression profile for memory management. This controls compression thresholds and batch sizes for conversation history.

func WithCompressorLLM added in v1.2.0

func WithCompressorLLM(llm LLMProvider) Option

WithCompressorLLM sets the LLM provider for memory compression.

func WithConfig

func WithConfig(config *Config) Option

WithConfig sets the agent configuration.

func WithDescription

func WithDescription(description string) Option

WithDescription sets the agent description.

func WithEmbedder added in v1.3.0

func WithEmbedder(embedder memory.Embedder) Option

WithEmbedder sets the vector embedding provider for semantic memory search.

func WithGraphMemoryStore added in v1.3.0

func WithGraphMemoryStore(store memory.GraphMemoryStore, config *loomv1.GraphMemoryConfig) Option

WithGraphMemoryStore sets the graph-backed episodic memory store.

func WithGuardrails

func WithGuardrails(guardrails *fabric.GuardrailEngine) Option

WithGuardrails enables pre-flight validation and error tracking.

func WithIdentityResolver added in v1.4.0

func WithIdentityResolver(resolver func(context.Context) string) Option

WithIdentityResolver sets the resolver that reads the caller identity (AdmissionRequest.UserID) from the call context. The value lookup is injected by the composition root because pkg/agent cannot import the storage layer that owns the user-id context key without an import cycle.

func WithJudgeLLM added in v1.2.0

func WithJudgeLLM(llm LLMProvider) Option

WithJudgeLLM sets the LLM provider for evaluation operations.

func WithMemory

func WithMemory(memory *Memory) Option

WithMemory sets a custom memory manager.

func WithMessageQueue

func WithMessageQueue(queue *communication.MessageQueue) Option

WithMessageQueue enables async agent-to-agent messaging. When set, agents can send/receive messages via the queue, enabling fire-and-forget, request-response, and acknowledgment-based communication.

func WithName

func WithName(name string) Option

WithName sets the agent name in the configuration.

func WithOrchestratorLLM added in v1.2.0

func WithOrchestratorLLM(llm LLMProvider) Option

WithOrchestratorLLM sets the LLM provider for fork-join merge/synthesis.

func WithPatternConfig

func WithPatternConfig(cfg *PatternConfig) Option

WithPatternConfig sets pattern configuration.

func WithPatternInjection

func WithPatternInjection(enabled bool) Option

WithPatternInjection enables/disables pattern injection.

func WithPermissionChecker

func WithPermissionChecker(checker *shuttle.PermissionChecker) Option

WithPermissionChecker sets the permission checker for tool execution.

func WithPrompts

func WithPrompts(registry prompts.PromptRegistry) Option

WithPrompts sets the prompt registry.

func WithReferenceStore

func WithReferenceStore(store communication.ReferenceStore) Option

WithReferenceStore enables inter-agent communication via reference store. When set, agents can send/receive messages using value or reference semantics.

func WithSharedMemory

func WithSharedMemory(sharedMemory interface{}) Option

WithSharedMemory sets the SharedMemoryStore for large tool result storage. This enables agents to store and reference large tool outputs efficiently.

func WithSkillDiscovery added in v1.3.0

func WithSkillDiscovery(d *discovery.Discovery) Option

WithSkillDiscovery wires the top-level Discovery. Skills are pulled by the model through manage_skills, so the conversation loop performs no discovery, matching or activation of its own; the wired Discovery is available to callers that drive it directly.

func WithSkillOrchestrator added in v1.2.0

func WithSkillOrchestrator(orch *skills.Orchestrator) Option

WithSkillOrchestrator sets the skill orchestrator for skill activation and injection.

func WithSkillTaskEmitter added in v1.3.0

func WithSkillTaskEmitter(e *skilltasks.Emitter) Option

WithSkillTaskEmitter wires the skill task emitter. When set and the skill's EffectiveEmitTasks() returns true, freshly-activated skills materialize tasks onto the agent's task board. Requires that the agent's task manager is also configured.

func WithSystemPrompt

func WithSystemPrompt(prompt string) Option

WithSystemPrompt sets the direct system prompt text.

func WithTaskBoard added in v1.3.0

func WithTaskBoard(manager *task.Manager, decomposer *task.Decomposer, config *loomv1.TaskBoardConfig) Option

WithTaskBoard sets the task manager, decomposer, and config for task decomposition and kanban.

func WithTracer

func WithTracer(tracer observability.Tracer) Option

WithTracer sets the observability tracer.

func WithoutBuiltinTool added in v1.3.0

func WithoutBuiltinTool(name string) Option

WithoutBuiltinTool suppresses the named builtin tool from surfacing to the LLM. The corresponding subsystem (e.g. the graph memory extractor, task manager, error store) keeps running — only the tool definition is hidden from the agent's tool list.

Used by the server to enforce tools.minimal / tools.none policy without disabling subsystem wiring. Pass one name per call; call repeatedly to suppress multiple tools.

Currently honoured for: graph_memory, task_board, query_tool_result, recall, manage_skills, load_pattern. Other tools either are registered eagerly by the caller (cmd_serve) and can be omitted there, or are not subject to suppression.

func WithoutSelfCorrection

func WithoutSelfCorrection() Option

WithoutSelfCorrection explicitly disables self-correction (guardrails + circuit breakers). By default, agents have self-correction enabled. Use this option to disable it. Note: This creates a marker guardrails/breakers that prevents default initialization.

type PatternConfig

type PatternConfig struct {
	// Enabled controls whether pattern injection is active
	Enabled bool

	// MinConfidence is the minimum confidence threshold (0.0-1.0)
	MinConfidence float64

	// MaxPatternsPerTurn limits patterns injected per conversation turn
	MaxPatternsPerTurn int

	// EnableTracking enables pattern effectiveness metrics
	EnableTracking bool

	// UseLLMClassifier enables LLM-based intent classification (default: false, uses keyword-based)
	UseLLMClassifier bool
}

PatternConfig holds pattern injection configuration

func DefaultPatternConfig

func DefaultPatternConfig() *PatternConfig

DefaultPatternConfig returns defaults for pattern injection (enabled by default)

type PatternConfigYAML

type PatternConfigYAML struct {
	Enabled            *bool    `yaml:"enabled"`
	MinConfidence      *float64 `yaml:"min_confidence"`
	MaxPatternsPerTurn *int     `yaml:"max_patterns_per_turn"`
	EnableTracking     *bool    `yaml:"enable_tracking"`
	UseLLMClassifier   *bool    `yaml:"use_llm_classifier"`
}

PatternConfigYAML represents pattern configuration in YAML

type ProgressCallback

type ProgressCallback = types.ProgressCallback

func ProgressCallbackFromContext

func ProgressCallbackFromContext(ctx context.Context) ProgressCallback

ProgressCallbackFromContext retrieves the progress callback from context. Returns nil if no callback is stored in the context.

type ProgressEvent

type ProgressEvent = types.ProgressEvent

type QueryToolResultTool

type QueryToolResultTool struct {
	// contains filtered or unexported fields
}

QueryToolResultTool serves this turn's memory, nothing else (HLD §7.1): pages (offset, limit) or SQL over one L1 message's full in-memory payload, addressed by message_id — the id printed on the offload stub. Every return is bounded at the threshold — pages and SQL alike. Valid only within the producing turn: memory is per turn, large data is not persisted, and there is no cross-turn data door except re-run.

func NewQueryToolResultTool

func NewQueryToolResultTool(a *Agent) *QueryToolResultTool

NewQueryToolResultTool creates the message_id-addressed query tool (HLD §7.1).

func (*QueryToolResultTool) Backend

func (t *QueryToolResultTool) Backend() string

Backend returns the backend type this tool requires. Empty string means backend-agnostic (works with any agent).

func (*QueryToolResultTool) Description

func (t *QueryToolResultTool) Description() string

Description returns the normative §7.1 tool description.

func (*QueryToolResultTool) Execute

func (t *QueryToolResultTool) Execute(ctx context.Context, input map[string]interface{}) (*shuttle.Result, error)

Execute serves pages or SQL over the addressed message's in-memory payload.

func (*QueryToolResultTool) InputSchema

func (t *QueryToolResultTool) InputSchema() *shuttle.JSONSchema

InputSchema returns the JSON schema for the tool input.

func (*QueryToolResultTool) Name

func (t *QueryToolResultTool) Name() string

Name returns the tool name.

type RecallTool added in v1.4.0

type RecallTool struct {
	// contains filtered or unexported fields
}

RecallTool retrieves conversation that is no longer shown, by an address cited in the session summary (HLD §6). It returns the span's user and assistant rows as stored — call signatures included, since they live inside the assistant row and are what makes "re-run" literal — and omits role='tool' rows entirely; a result's only door is re-running its call.

func NewRecallTool added in v1.4.0

func NewRecallTool(a *Agent) *RecallTool

NewRecallTool creates the recall tool (HLD §6). Registered always.

func (*RecallTool) Backend added in v1.4.0

func (t *RecallTool) Backend() string

Backend returns the backend type this tool requires. Empty string means backend-agnostic (works with any agent).

func (*RecallTool) Description added in v1.4.0

func (t *RecallTool) Description() string

Description returns the normative §6 tool description.

func (*RecallTool) Execute added in v1.4.0

func (t *RecallTool) Execute(ctx context.Context, input map[string]interface{}) (*shuttle.Result, error)

Execute reads the span's user and assistant rows as stored (session-filtered) and returns them bounded at the threshold, cut at a row boundary with the normative continuation line.

func (*RecallTool) InputSchema added in v1.4.0

func (t *RecallTool) InputSchema() *shuttle.JSONSchema

InputSchema returns the JSON schema for the tool input.

func (*RecallTool) Name added in v1.4.0

func (t *RecallTool) Name() string

Name returns the tool name.

type RecoverableError added in v1.3.0

type RecoverableError struct {
	ErrorType       string
	Message         string
	RecoveryAction  string
	RecoveryPayload map[string]any
	Retryable       bool
	Cause           error
}

RecoverableError is returned when self-healing fails but the error carries enough context for an upper layer (cloud, TUI) to offer recovery to the user.

func (*RecoverableError) Error added in v1.3.0

func (e *RecoverableError) Error() string

func (*RecoverableError) Unwrap added in v1.3.0

func (e *RecoverableError) Unwrap() error

type RecoveryConfig added in v1.3.0

type RecoveryConfig struct{}

RecoveryConfig holds tunables for the self-healing orchestrator. The destructive trim knobs are gone with the second relief ladder (blueprint A5): no code path outside releasePressure can remove or shrink a message.

func DefaultRecoveryConfig added in v1.3.0

func DefaultRecoveryConfig() *RecoveryConfig

DefaultRecoveryConfig returns sensible defaults.

type Registry

type Registry struct {
	// contains filtered or unexported fields
}

Registry manages agent configurations and instances. It provides centralized agent lifecycle management, hot-reloading, and persistence.

func NewRegistry

func NewRegistry(config RegistryConfig) (*Registry, error)

NewRegistry creates a new agent registry

func (*Registry) BuildSkillsOptions added in v1.3.0

func (r *Registry) BuildSkillsOptions(
	skillsConfig *skills.SkillsConfig,
	classifierLLM LLMProvider,
	primaryLLM LLMProvider,
	agentName string,
) []Option

BuildSkillsOptions is a Registry-bound convenience wrapper around the free-function BuildSkillsOptions; it forwards r.tracer, r.logger, r.providerPool, and r.db so in-tree callers (buildAgent, cmd/looms/cmd_serve.go) don't have to plumb those manually. Also wires OnWired so the registry tracks every router subsystem for ReloadAllSkillRouters.

External callers that don't hold a *Registry (loom-cloud, avmo-tera-cloud) should call the free-function form directly with their own SkillsWiringDeps.

func (*Registry) Close

func (r *Registry) Close() error

Close closes the registry and cleans up resources

func (*Registry) CreateAgent

func (r *Registry) CreateAgent(ctx context.Context, name string) (*Agent, error)

CreateAgent instantiates an agent from its configuration

func (*Registry) CreateEphemeralAgent

func (r *Registry) CreateEphemeralAgent(ctx context.Context, role string) (*Agent, error)

CreateEphemeralAgent creates a temporary agent based on a role. This implements the collaboration.AgentFactory interface. The agent is NOT registered and caller must manage its lifecycle.

Ephemeral agents receive stable GUIDs for tracking and observability, but are NOT persisted to the database since they're temporary.

func (*Registry) DB added in v1.3.0

func (r *Registry) DB() *sql.DB

DB returns the registry's underlying SQLite handle. Exported so peer services (e.g., the SkillsImportService) can construct their own index.Store without re-opening the file. Read-only intent: callers should not Close it; lifecycle is owned by Registry.

func (*Registry) DeleteAgent

func (r *Registry) DeleteAgent(ctx context.Context, nameOrID string, force bool) error

DeleteAgent removes an agent by name or GUID

func (*Registry) ForceReload

func (r *Registry) ForceReload(ctx context.Context, name string) error

ForceReload manually triggers a reload for the specified agent. This bypasses the file watcher and directly calls the reload callback. Useful for programmatic reloads (e.g., after metaagent creates an agent) or when file watchers are unreliable (e.g., macOS fsnotify issues).

func (*Registry) GetAgent

func (r *Registry) GetAgent(ctx context.Context, nameOrID string) (*Agent, error)

GetAgent returns a running agent instance by name or GUID

func (*Registry) GetAgentByID added in v1.1.0

func (r *Registry) GetAgentByID(id string) (*AgentInstanceInfo, error)

GetAgentByID returns information about an agent by GUID only. Use this when you specifically need GUID-based lookup without name fallback.

func (*Registry) GetAgentInfo

func (r *Registry) GetAgentInfo(nameOrID string) (*AgentInstanceInfo, error)

GetAgentInfo returns information about an agent by name or GUID. Supports both stable GUID lookups and legacy name-based lookups.

func (*Registry) GetConfig

func (r *Registry) GetConfig(name string) *loomv1.AgentConfig

GetConfig returns the config for a specific agent by name

func (*Registry) ListAgents

func (r *Registry) ListAgents() []*AgentInstanceInfo

ListAgents returns all registered agents

func (*Registry) ListConfigs

func (r *Registry) ListConfigs() []*loomv1.AgentConfig

ListConfigs returns all loaded agent configurations (including non-instantiated agents)

func (*Registry) LoadAgents

func (r *Registry) LoadAgents(ctx context.Context) error

LoadAgents loads all agent configurations from the agents directory and workflows

func (*Registry) LoadWorkflows

func (r *Registry) LoadWorkflows(ctx context.Context) error

LoadWorkflows loads workflow files and registers their coordinator agents

func (*Registry) RegisterConfig

func (r *Registry) RegisterConfig(config *loomv1.AgentConfig)

RegisterConfig registers an agent configuration in the registry This is used by the meta-agent factory to add dynamically generated configs

func (*Registry) RegisterWiredSkillSubsystem added in v1.3.0

func (r *Registry) RegisterWiredSkillSubsystem(w WiredSkillSubsystem)

RegisterWiredSkillSubsystem records a router subsystem the registry owns for the lifetime of the process. Called via the OnWired callback in SkillsWiringDeps. Safe for concurrent use.

External callers (loom-cloud, avmo-tera-cloud) that hold their own *Registry can wire this method into SkillsWiringDeps.OnWired to gain the same hot-reload semantics that the loom server has.

func (*Registry) ReloadAgent

func (r *Registry) ReloadAgent(ctx context.Context, nameOrID string) error

ReloadAgent hot-reloads an agent's configuration by name or GUID

func (*Registry) ReloadAllSkillRouters added in v1.3.0

func (r *Registry) ReloadAllSkillRouters(ctx context.Context) (reloaded, failed int)

ReloadAllSkillRouters rebuilds the persisted index from each wired library and SetTrees the result onto each wired router. Used by the SkillsImportService after AddSkill / ClassifySkill / BulkImportSkills writes new YAMLs so running agents see the new tree without a server restart.

Behavior per wired subsystem:

  1. InvalidateCache on the library so it re-reads YAMLs from disk.
  2. Build a fresh index using the wired Builder against the now-fresh library catalog.
  3. Persist the new index to the wired Store (when non-nil).
  4. SetTree the new tree onto the wired Router.

Errors from individual subsystems are logged and the iteration continues — a transient build failure on one agent doesn't block reloads on others. Returns the count of successfully reloaded subsystems and the count of failed ones.

Safe for concurrent use; takes a read lock on r.mu so concurrent agent registrations don't race the iteration.

func (*Registry) RemoveAgentRuntime added in v1.2.0

func (r *Registry) RemoveAgentRuntime(name string)

RemoveAgentRuntime removes the in-memory agent instance from the registry without deleting database records or config files. This is used during agent reload to clear the "already running" check before recreating.

func (*Registry) SetGraphMemoryStore added in v1.3.0

func (r *Registry) SetGraphMemoryStore(store memory.GraphMemoryStore, embedder memory.Embedder)

SetGraphMemoryStore injects the server-level graph memory subsystem into the registry. Every agent built through buildAgent will receive WithGraphMemoryStore so the extractor and recall paths run. The per-agent memory.graph_memory.enabled flag in YAML can opt out for a specific agent.

tools.minimal / tools.none on the server control only TOOL surfacing via SetSuppressedBuiltinTools — they do NOT disable the subsystem here.

Safe to call concurrently with other registry operations. Must be called before agents are loaded or created to take effect for those agents.

func (*Registry) SetProviderPool added in v1.2.0

func (r *Registry) SetProviderPool(pool map[string]LLMProvider)

SetProviderPool injects a server-level named provider pool into the registry. Agents whose LLM config names a pool entry (e.g., provider: "fast") will receive the corresponding pre-built LLMProvider instead of constructing a new one. This must be called before agents are loaded or created to take effect. It is safe to call concurrently with other registry operations.

func (*Registry) SetReloadCallback

func (r *Registry) SetReloadCallback(cb ReloadCallback)

SetReloadCallback sets the callback function to be called when an agent config changes. The callback receives the agent name and new configuration, and should update the running agent.

func (*Registry) SetSharedMemory

func (r *Registry) SetSharedMemory(sharedMemory interface{})

SetSharedMemory sets the SharedMemoryStore for agents created by this registry. This must be called after registry creation if agents need access to shared memory for large tool result storage.

func (*Registry) SetSuppressedBuiltinTools added in v1.3.0

func (r *Registry) SetSuppressedBuiltinTools(names []string)

SetSuppressedBuiltinTools configures the server-level tool-surface policy. Every agent built through buildAgent receives WithoutBuiltinTool(name) for each name in the slice. Subsystems are unaffected.

Safe to call concurrently with other registry operations. Must be called before agents are loaded or created to take effect for those agents.

func (*Registry) SetTaskManager added in v1.3.0

func (r *Registry) SetTaskManager(manager *task.Manager, decomposer *task.Decomposer)

SetTaskManager injects the server-level task subsystem into the registry. Every agent subsequently built through buildAgent will receive WithTaskBoard so the skills-overhaul task emitter is reachable. The per-agent memory.task_board.enabled flag continues to gate tool/context surfacing (task_board builtin, kanban prompt supplement, in-context task summary), but task emission itself becomes always-on whenever a manager is wired — matching the overhaul-doc invariant that skill activations always produce trackable work.

Safe to call concurrently with other registry operations. Must be called before agents are loaded or created to take effect for those agents.

func (*Registry) StartAgent

func (r *Registry) StartAgent(ctx context.Context, nameOrID string) error

StartAgent starts a stopped agent by name or GUID

func (*Registry) StopAgent

func (r *Registry) StopAgent(ctx context.Context, nameOrID string) error

StopAgent stops a running agent by name or GUID

func (*Registry) WatchConfigs

func (r *Registry) WatchConfigs(ctx context.Context) error

WatchConfigs watches for config file changes and auto-reloads agents.

Note: fsnotify behavior varies by platform. On Darwin (macOS), the underlying FSEvents/kqueue implementation may not reliably detect file modifications in all cases. The callback mechanism is solid, but file change detection may require investigation or alternative approaches (e.g., polling, explicit reload triggers) on macOS.

func (*Registry) WorkflowsDir added in v1.4.0

func (r *Registry) WorkflowsDir() string

WorkflowsDir returns the directory holding saved workflow YAML definitions ($LOOM_DATA_DIR/workflows). Used by the server to resolve workflow_ref (run a saved workflow by name) and to list runnable workflows.

type RegistryConfig

type RegistryConfig struct {
	ConfigDir    string
	DBPath       string
	MCPManager   *manager.Manager
	LLMProvider  LLMProvider
	Logger       *zap.Logger
	Tracer       observability.Tracer
	SessionStore SessionStorage         // For persistent agent session traces
	ToolRegistry *toolregistry.Registry // Tool search registry for dynamic tool discovery

	// Agent dependencies (injected by server)
	PermissionChecker *shuttle.PermissionChecker   // For permission validation
	AdmissionChain    *shuttle.Chain               // Admission hook chain for tool-call admission
	IdentityResolver  func(context.Context) string // Resolves AdmissionRequest.UserID from the call context
	ArtifactStore     interface{}                  // artifacts.Store for workspace tool

	// Database encryption (opt-in for enterprise deployments)
	EncryptDatabase bool   // Enable SQLCipher encryption
	EncryptionKey   string // Encryption key (or use LOOM_DB_KEY env var)
}

RegistryConfig configures the agent registry

type ReloadCallback

type ReloadCallback func(name string, guid string, config *loomv1.AgentConfig) error

ReloadCallback is called when an agent config changes. It receives the agent name, agent GUID, and new configuration. The GUID is the stable identifier that should be used for agent registration.

type Response

type Response struct {
	// Content is the text response
	Content string

	// Usage tracks token usage and cost
	Usage Usage

	// ToolExecutions contains tools that were executed
	ToolExecutions []ToolExecution

	// Metadata contains additional response information
	Metadata map[string]interface{}

	// Thinking contains the agent's internal reasoning process
	// (for models that support extended thinking)
	Thinking string
}

Response represents the agent's response to a user message.

type RetryConfig

type RetryConfig struct {
	// MaxRetries is the maximum number of retry attempts (0 = no retries)
	MaxRetries int

	// InitialDelay is the initial delay before the first retry
	InitialDelay time.Duration

	// MaxDelay is the maximum delay between retries
	MaxDelay time.Duration

	// Multiplier is the exponential backoff multiplier (e.g., 2.0 for doubling)
	Multiplier float64

	// Enabled enables retry logic
	Enabled bool
}

RetryConfig configures exponential backoff retry logic for LLM calls

type SegmentedMemory

type SegmentedMemory struct {
	// contains filtered or unexported fields
}

SegmentedMemory holds the context segments (HLD §2 — data, no logic):

  • KERNEL — the advertised tool schemas ride the provider tools parameter; only their serialized byte count is tracked here (blueprint A6).
  • ROM — the system prompt. Byte-stable for the life of the session.
  • L2 — the session summary: ONE cumulative text, empty until the first fold; persisted as version rows, the newest version is the summary.
  • L1 — the message list, in order. In memory during a turn (full natural forms); rebuilt from rows on the next turn or on reload.

All logic lives in ContextCompilation (context_compilation.go): compile renders, releasePressure is the only mutator of context state. Arrival appends; nothing here examines, sizes, flags, or transforms at arrival.

func NewSegmentedMemory

func NewSegmentedMemory(romContent string, maxContextTokens, reservedOutputTokens int) *SegmentedMemory

NewSegmentedMemory creates a new segmented memory instance with ROM content. If maxContextTokens or reservedOutputTokens are 0, defaults to Claude Sonnet 4.5 values (200K/20K)

func NewSegmentedMemoryWithCompression

func NewSegmentedMemoryWithCompression(romContent string, maxContextTokens, reservedOutputTokens int, profile CompressionProfile) *SegmentedMemory

NewSegmentedMemoryWithCompression creates a new segmented memory instance with a custom profile. The profile's CriticalThresholdPercent / WarningThresholdPercent are the relief water marks (HWM/LWM, HLD §5.1), percentages of usable context; a missing or inverted pair falls back to 90/60.

func (*SegmentedMemory) AddMessage

func (sm *SegmentedMemory) AddMessage(ctx context.Context, msg Message)

AddMessage appends a message to L1 (HLD §1: arrival appends — nothing is examined, sized, flagged, or transformed at arrival). The incremental token caches are updated for reporting only; no mechanism here acts on them.

func (*SegmentedMemory) CurrentTurn added in v1.4.0

func (sm *SegmentedMemory) CurrentTurn() int64

CurrentTurn returns T — the session's current turn number: max(Turn) over L1 (HLD §5.1). Derived, never counted.

func (*SegmentedMemory) DropTurnPayloads added in v1.4.0

func (sm *SegmentedMemory) DropTurnPayloads()

DropTurnPayloads is the TURN END drop (HLD §1, §7.3; blueprint A1), run when a new turn starts: every prior-turn tool message's in-memory content is replaced by its persisted-row form (truncated core + tail), so a long-lived loom agent does not grow by one payload set per turn. Cloud gets this for free by being stateless.

func (*SegmentedMemory) GetActivePattern added in v1.2.0

func (sm *SegmentedMemory) GetActivePattern() string

GetActivePattern returns the name of the active pattern (empty if none).

func (*SegmentedMemory) GetContextWindow

func (sm *SegmentedMemory) GetContextWindow() string

GetContextWindow renders the compiled context as a formatted string, via the same compile.

func (*SegmentedMemory) GetL1MessageCount

func (sm *SegmentedMemory) GetL1MessageCount() int

GetL1MessageCount returns number of messages in L1 cache.

func (*SegmentedMemory) GetL2Summary

func (sm *SegmentedMemory) GetL2Summary() string

GetL2Summary returns the session summary's newest version text. Returns empty string if no fold has occurred yet.

func (*SegmentedMemory) GetMemoryStats

func (sm *SegmentedMemory) GetMemoryStats() map[string]interface{}

GetMemoryStats returns comprehensive memory statistics (reporting only — no UsagePercentage read gates any action anywhere).

func (*SegmentedMemory) GetMessages

func (sm *SegmentedMemory) GetMessages() []Message

GetMessages returns all L1 messages for building conversation context.

func (*SegmentedMemory) GetMessagesForLLM

func (sm *SegmentedMemory) GetMessagesForLLM() []Message

GetMessagesForLLM builds the compiled context for the LLM call (ContextCompilation, HLD §5.2 steps 1–7).

func (*SegmentedMemory) GetRecentConversationTurns added in v1.3.0

func (sm *SegmentedMemory) GetRecentConversationTurns(n int) []types.Message

GetRecentConversationTurns retrieves the last N messages from L1 cache, including all roles (user, assistant, tool). Used by graph memory extraction to get richer context than tool-only results.

func (*SegmentedMemory) GetTokenBudgetMax added in v1.2.0

func (sm *SegmentedMemory) GetTokenBudgetMax() int

GetTokenBudgetMax returns the total token budget (context window size).

func (*SegmentedMemory) GetTokenBudgetUsage

func (sm *SegmentedMemory) GetTokenBudgetUsage() (int, int, int)

GetTokenBudgetUsage returns current token budget usage information. Returns: (used, available, total)

func (*SegmentedMemory) GetTokenCount

func (sm *SegmentedMemory) GetTokenCount() int

GetTokenCount returns current token count across all memory layers (reporting).

func (*SegmentedMemory) HasL2Content

func (sm *SegmentedMemory) HasL2Content() bool

HasL2Content returns true if the session summary has content (a fold occurred).

func (*SegmentedMemory) ReleasePressure added in v1.4.0

func (sm *SegmentedMemory) ReleasePressure(ctx context.Context, penalty int) (shed bool, estimate, target int)

ReleasePressure is the relief pass, called at compile before every send. It SELF-GATES on loom's own accounting: if the estimate is under the start mark (HWM, §5.1) there is no pressure and it is a no-op. Otherwise it sheds to the release mark (LWM) via the escalating evict-then-fold ladder below — recompiling and re-estimating after each op, returning the instant the estimate reaches the mark. Returns whether it shed and the post-pass {estimate, target}.

penalty (percentage points) lowers both marks. It is 0 for the normal compile pass; on the one recovery pass after a provider refusal it is pressureRecoveryPenalty, so a shed the normal gate would skip is forced — the only place the provider's refusal touches relief.

func (*SegmentedMemory) ReplayMessages added in v1.3.0

func (sm *SegmentedMemory) ReplayMessages(ctx context.Context, messages []Message)

ReplayMessages bulk-loads rows into L1 (reload, HLD §8): a pure append of rows already filtered folded=false by the store read. T = max(Turn) over the read rows — nothing else to restore; live and restored are the same read of the same rows.

func (*SegmentedMemory) ResetContext added in v1.2.0

func (sm *SegmentedMemory) ResetContext()

ResetContext clears the conversational state: L1, the summary, and the active pattern name. ROM and kernel are preserved — they are structural.

func (*SegmentedMemory) SearchMessages

func (sm *SegmentedMemory) SearchMessages(
	ctx context.Context,
	query string,
	limit int,
) ([]Message, error)

SearchMessages performs semantic search over conversation history using BM25 + LLM reranking.

Algorithm: 1. BM25 full-text search via FTS5 (top-50 candidates) 2. LLM-based reranking for semantic relevance (top-N results)

Returns top-N most relevant messages ordered by relevance.

func (*SegmentedMemory) SetAdvertisedToolsBytes added in v1.4.0

func (sm *SegmentedMemory) SetAdvertisedToolsBytes(bytes int)

SetAdvertisedToolsBytes records the serialized bytes of the advertised tool schemas — the provider tools parameter as built (HLD §2, blueprint A6). The schemas' bytes are part of the compiled artifact and therefore of the estimate; nothing acts on the derived token count.

func (*SegmentedMemory) SetCompressor

func (sm *SegmentedMemory) SetCompressor(compressor MemoryCompressor)

SetCompressor sets the memory compressor for fold (HLD §5.4). Should be called after agent initialization to avoid dependency cycles.

func (*SegmentedMemory) SetContextDebug added in v1.4.0

func (sm *SegmentedMemory) SetContextDebug(cd *contextDebug)

SetContextDebug injects the per-mutation debug carrier.

func (*SegmentedMemory) SetLLMProvider

func (sm *SegmentedMemory) SetLLMProvider(llm LLMProvider)

SetLLMProvider injects an LLM provider for semantic search reranking. If not set, semantic search will fall back to BM25-only ranking.

func (*SegmentedMemory) SetOffloadExemptTools added in v1.4.0

func (sm *SegmentedMemory) SetOffloadExemptTools(names []string)

SetOffloadExemptTools replaces the set of tool names whose current-turn results always render whole regardless of the threshold (§5.2 step 6 carve-out). Empty names are ignored; an empty slice clears the set. Exemption affects only the producing turn's render: prior-turn and evicted rows still render stubs, and the persist-time row bound (§4.1) is unchanged.

func (*SegmentedMemory) SetProtectedRecentTurns added in v1.4.0

func (sm *SegmentedMemory) SetProtectedRecentTurns(k int)

SetProtectedRecentTurns configures K (config ProtectedRecentTurns, §9).

func (*SegmentedMemory) SetSessionStore

func (sm *SegmentedMemory) SetSessionStore(store SessionStorage, sessionID string)

SetSessionStore binds the durable store: relief transactions (flags, summary versions) and reload read through it.

func (*SegmentedMemory) SetSharedMemory

func (sm *SegmentedMemory) SetSharedMemory(sharedMemory *storage.SharedMemoryStore)

SetSharedMemory sets the shared memory store (backs explicit shared_memory tools).

func (*SegmentedMemory) SetSkillDeactivationHook added in v1.4.0

func (sm *SegmentedMemory) SetSkillDeactivationHook(fn func(sessionID, skillName string))

SetSkillDeactivationHook wires the skills orchestrator's deactivation path, used when fold flags a region containing a manage_skills load pair.

func (*SegmentedMemory) SetThreshold added in v1.4.0

func (sm *SegmentedMemory) SetThreshold(bytes int64)

SetThreshold sets the one threshold value in bytes (HLD §5.1: one value, three roles — compile-time offload bound, persist-time row bound, retrieval page bound). Non-positive values keep the current threshold; positive values below minThreshold clamp to it — the truncation tail alone runs ~150 bytes, so a tinier bound could not hold stored = core + tail ≤ threshold.

func (*SegmentedMemory) SetTracer

func (sm *SegmentedMemory) SetTracer(tracer observability.Tracer)

SetTracer sets the observability tracer for error logging and metrics.

func (*SegmentedMemory) Threshold added in v1.4.0

func (sm *SegmentedMemory) Threshold() int

Threshold returns the configured threshold in bytes.

type Session

type Session = types.Session

type SessionCleanupHook

type SessionCleanupHook func(ctx context.Context, sessionID string)

SessionCleanupHook is called when a session is deleted. Used for cleanup tasks like releasing shared memory references. The hook receives the session ID being deleted.

type SessionStorage added in v1.2.0

type SessionStorage interface {
	// Sessions
	SaveSession(ctx context.Context, session *Session) error
	LoadSession(ctx context.Context, sessionID string) (*Session, error)
	ListSessions(ctx context.Context) ([]string, error)
	DeleteSession(ctx context.Context, sessionID string) error
	LoadAgentSessions(ctx context.Context, agentID string) ([]string, error)

	// Messages
	//
	// SaveMessage derives the row's turn at insert (HLD §4.5): the turnStart
	// site — the Chat()-entry user message, the only turn-incrementing event —
	// computes turn = COALESCE(MAX(turn),0)+1 for the session; every other site
	// uses the same subquery without the +1. The store stamps the derived seq
	// and turn back onto msg.
	SaveMessage(ctx context.Context, sessionID string, msg *Message, turnStart bool) error
	LoadMessages(ctx context.Context, sessionID string) ([]Message, error)

	// ListMessagesBySeqRange is the by-seq span read backing recall (HLD §6):
	// rows lo..hi inclusive, session-filtered, seq ascending, folded included
	// (a summary-cited span is exactly what recall retrieves).
	ListMessagesBySeqRange(ctx context.Context, sessionID string, lo, hi int64) ([]Message, error)
	LoadMessagesForAgent(ctx context.Context, agentID string) ([]Message, error)
	LoadMessagesFromParentSession(ctx context.Context, sessionID string) ([]Message, error)

	// Search (backend-agnostic: FTS5 for SQLite, tsvector for PostgreSQL)
	SearchMessages(ctx context.Context, sessionID, query string, limit int) ([]Message, error)
	SearchMessagesByAgent(ctx context.Context, agentID, query string, limit int) ([]Message, error)

	// Tool executions
	SaveToolExecution(ctx context.Context, sessionID string, exec ToolExecution) error

	// Relief transactions (HLD §5.2 — write-once flags, one transaction per
	// operation, set only inside releasePressure):
	//
	// MarkEvicted sets evicted=true on the given rows in one transaction.
	MarkEvicted(ctx context.Context, sessionID string, seqs []int64) error
	// FoldMessages writes summary version n (snapshot_type='fold', content =
	// JSON {"n","text"}) and sets the region's folded flags in ONE transaction
	// (HLD §5.4.6) — a fold never stands in memory without its row.
	FoldMessages(ctx context.Context, sessionID string, seqs []int64, n int, text string) error

	// Memory snapshots
	SaveMemorySnapshot(ctx context.Context, sessionID, snapshotType, content string, tokenCount int) error
	LoadMemorySnapshots(ctx context.Context, sessionID string, snapshotType string, limit int) ([]MemorySnapshot, error)

	// Lifecycle
	RegisterCleanupHook(hook SessionCleanupHook)
	GetStats(ctx context.Context) (*Stats, error)
	Close() error
}

SessionStorage defines the backend-agnostic interface for session persistence. Implementations include SQLite (SessionStore) and PostgreSQL (postgres.SessionStore). All operations must be safe for concurrent use.

type SessionStore

type SessionStore struct {
	// contains filtered or unexported fields
}

SessionStore provides persistent storage for sessions, messages, and tool executions. All database operations are traced to hawk for observability.

func NewSessionStore

func NewSessionStore(dbPath string, tracer observability.Tracer) (*SessionStore, error)

NewSessionStore creates a new SessionStore with SQLite persistence. For backward compatibility, encryption is disabled by default. Use NewSessionStoreWithConfig for encryption support.

func NewSessionStoreWithConfig

func NewSessionStoreWithConfig(config DBConfig, tracer observability.Tracer) (*SessionStore, error)

NewSessionStoreWithConfig creates a new SessionStore with optional encryption.

func (*SessionStore) Close

func (s *SessionStore) Close() error

Close closes the database connection.

func (*SessionStore) DeleteSession

func (s *SessionStore) DeleteSession(ctx context.Context, sessionID string) error

DeleteSession removes a session and all its associated data.

func (*SessionStore) FoldMessages added in v1.4.0

func (s *SessionStore) FoldMessages(ctx context.Context, sessionID string, seqs []int64, n int, text string) error

FoldMessages writes summary version n (snapshot_type='fold', content = JSON {"n","text"}) and sets the region's folded flags in ONE transaction (HLD §5.4.6) — never a fold that evaporates on reload.

func (*SessionStore) GetStats

func (s *SessionStore) GetStats(ctx context.Context) (*Stats, error)

GetStats returns database statistics for monitoring.

func (*SessionStore) ListMessagesBySeqRange added in v1.4.0

func (s *SessionStore) ListMessagesBySeqRange(ctx context.Context, sessionID string, lo, hi int64) ([]Message, error)

ListMessagesBySeqRange is the by-seq span read backing recall (HLD §6): rows lo..hi inclusive for one session, seq (messages.id) ascending. Folded rows are included — a summary-cited span is exactly what recall retrieves.

func (*SessionStore) ListSessions

func (s *SessionStore) ListSessions(ctx context.Context) ([]string, error)

ListSessions returns all session IDs.

func (*SessionStore) LoadAgentSessions

func (s *SessionStore) LoadAgentSessions(ctx context.Context, agentID string) ([]string, error)

LoadAgentSessions loads all sessions for a given agent. Returns sessions where agent_id matches the provided agentID.

func (*SessionStore) LoadMemorySnapshots

func (s *SessionStore) LoadMemorySnapshots(ctx context.Context, sessionID string, snapshotType string, limit int) ([]MemorySnapshot, error)

LoadMemorySnapshots retrieves memory snapshots for a session. Returns snapshots in chronological order (oldest first). Limit controls the maximum number of snapshots to return (0 = all).

func (*SessionStore) LoadMessages

func (s *SessionStore) LoadMessages(ctx context.Context, sessionID string) ([]Message, error)

LoadMessages loads all messages for a session.

func (*SessionStore) LoadMessagesForAgent

func (s *SessionStore) LoadMessagesForAgent(ctx context.Context, agentID string) ([]Message, error)

LoadMessagesForAgent loads all messages for an agent across all its sessions. This includes messages from: - All sessions owned by this agent (agent_id = agentID) - Parent sessions (if agent has coordinator parent) Filters by session_context to include only relevant messages (coordinator, shared).

func (*SessionStore) LoadMessagesFromParentSession

func (s *SessionStore) LoadMessagesFromParentSession(ctx context.Context, sessionID string) ([]Message, error)

LoadMessagesFromParentSession loads messages from the parent session of a given session. This is used by sub-agents to see coordinator instructions. Returns empty slice if session has no parent.

func (*SessionStore) LoadSession

func (s *SessionStore) LoadSession(ctx context.Context, sessionID string) (*Session, error)

LoadSession loads a session from the database.

func (*SessionStore) MarkEvicted added in v1.4.0

func (s *SessionStore) MarkEvicted(ctx context.Context, sessionID string, seqs []int64) error

MarkEvicted sets evicted=1 on the given rows in one transaction (relief operation; HLD §5.2). Flags are write-once — no code path clears them.

func (*SessionStore) RegisterCleanupHook

func (s *SessionStore) RegisterCleanupHook(hook SessionCleanupHook)

RegisterCleanupHook registers a callback to be invoked when sessions are deleted. This enables decoupled cleanup operations (e.g., releasing shared memory references) without tight coupling between SessionStore and other components. Thread-safe: Can be called from multiple goroutines.

func (*SessionStore) SaveMemorySnapshot

func (s *SessionStore) SaveMemorySnapshot(ctx context.Context, sessionID, snapshotType, content string, tokenCount int) error

SaveMemorySnapshot persists a memory snapshot (L2 summary) to the database. This is used by the swap layer to archive L2 summaries when they exceed the token limit.

func (*SessionStore) SaveMessage

func (s *SessionStore) SaveMessage(ctx context.Context, sessionID string, msg *Message, turnStart bool) error

SaveMessage persists a message to the database. The row's turn is derived at insert (HLD §4.5): turnStart — passed only by the Chat()-entry persist site, the only turn-incrementing event — adds 1 to the session's MAX(turn); every other site stamps MAX(turn) unchanged. The derived seq (messages.id) and turn are stamped back onto msg.

func (*SessionStore) SaveSession

func (s *SessionStore) SaveSession(ctx context.Context, session *Session) error

SaveSession persists a session to the database.

func (*SessionStore) SaveToolExecution

func (s *SessionStore) SaveToolExecution(ctx context.Context, sessionID string, exec ToolExecution) error

SaveToolExecution persists a tool execution to the database.

func (*SessionStore) SearchMessages added in v1.2.0

func (s *SessionStore) SearchMessages(ctx context.Context, sessionID, query string, limit int) ([]Message, error)

SearchMessages searches message content using full-text search with BM25 ranking. For SQLite, this uses FTS5. For PostgreSQL, this uses tsvector/tsquery. Returns messages sorted by relevance (highest score first).

Parameters:

  • sessionID: Filter results to specific session (empty = all sessions)
  • query: Natural language search query
  • limit: Maximum number of results to return

Returns messages ordered by relevance score.

func (*SessionStore) SearchMessagesByAgent added in v1.2.0

func (s *SessionStore) SearchMessagesByAgent(ctx context.Context, agentID, query string, limit int) ([]Message, error)

SearchMessagesByAgent searches messages across all sessions for a given agent using full-text search. For SQLite, this uses FTS5. For PostgreSQL, this uses tsvector/tsquery. Uses BM25/rank scoring to return most relevant results first.

type SimpleCompressor

type SimpleCompressor struct{}

SimpleCompressor is a basic compressor that doesn't use LLM. Useful for testing or when LLM integration isn't available.

func NewSimpleCompressor

func NewSimpleCompressor() *SimpleCompressor

NewSimpleCompressor creates a compressor that only does keyword extraction.

func (*SimpleCompressor) CompressMessages

func (c *SimpleCompressor) CompressMessages(ctx context.Context, messages []Message) (string, error)

CompressMessages performs simple keyword extraction.

func (*SimpleCompressor) IsEnabled

func (c *SimpleCompressor) IsEnabled() bool

IsEnabled always returns false for simple compressor.

type SkillBindingYAML added in v1.3.0

type SkillBindingYAML struct {
	Name       string            `yaml:"name"`
	Mode       string            `yaml:"mode"`
	Priority   int32             `yaml:"priority"`
	LabelMatch map[string]string `yaml:"label_match"`
	MinVersion string            `yaml:"min_version"`
}

SkillBindingYAML represents a single skill binding entry in agent YAML.

type SkillsConfigYAML added in v1.2.0

type SkillsConfigYAML struct {
	Enabled              *bool    `yaml:"enabled"`
	EnabledSkills        []string `yaml:"enabled_skills"`
	DisabledSkills       []string `yaml:"disabled_skills"`
	MinAutoConfidence    *float64 `yaml:"min_auto_confidence"`
	MaxConcurrentSkills  *int     `yaml:"max_concurrent_skills"`
	SkillsDir            string   `yaml:"skills_dir"`
	ContextBudgetPercent *int     `yaml:"context_budget_percent"`

	// Declarative skill attachment for this agent. Empty falls back to the
	// legacy enabled_skills/disabled_skills filter via the resolver shim.
	Bindings []SkillBindingYAML `yaml:"bindings"`

	// Hierarchical (PageIndex-style) router controls.
	RouterEnabled         *bool  `yaml:"router_enabled"`
	RouterMaxCandidates   *int   `yaml:"router_max_candidates"`
	RouterCacheTTLSeconds *int   `yaml:"router_cache_ttl_seconds"`
	RouterModelOverride   string `yaml:"router_model_override"`

	// Skill -> task integration controls.
	SkillTaskBoardID string `yaml:"skill_task_board_id"`
	TasksEnabled     *bool  `yaml:"tasks_enabled"`
}

SkillsConfigYAML represents skills configuration in YAML

type SkillsWiringDeps added in v1.3.0

type SkillsWiringDeps struct {
	SkillsConfig   *skills.SkillsConfig
	ClassifierLLM  LLMProvider
	PrimaryLLM     LLMProvider
	AgentName      string
	Tracer         observability.Tracer
	Logger         *zap.Logger
	ProviderPool   map[string]LLMProvider
	IndexStoreDB   *sql.DB
	WarmIndexAsync func(lib *skills.Library, builder *skillindex.Builder, store skillindex.Store, router *skillindex.Router)
	OnWired        func(WiredSkillSubsystem)
}

SkillsWiringDeps is the explicit dependency bundle for skills wiring. External repos (loom-cloud, avmo-tera-cloud) call BuildSkillsOptions with this struct directly so they can stay decoupled from the Registry type.

Required fields:

  • SkillsConfig: per-agent skills config; helper returns nil when SkillsConfig == nil || !SkillsConfig.Enabled.
  • PrimaryLLM: the agent's main LLM, used as the router's final fallback.

Optional fields:

  • ClassifierLLM: pre-built classifier provider, second router preference.
  • AgentName: log attribution; defaults to "" if unset.
  • Tracer: observability tracer; defaults to no-op via the underlying skills library when nil.
  • Logger: zap logger; defaults to a no-op zap logger when nil.
  • ProviderPool: named-provider pool consulted only when SkillsConfig.RouterModelOverride is set.
  • IndexStoreDB: SQLite DB for index persistence; when nil, the router still works but loses cold-start warm-up across restarts.
  • WarmIndexAsync: optional override for the background warm-up function; primarily used by the Registry to reuse its existing warmSkillIndex method. When nil, the helper defaults to a built-in warm-up.
  • OnWired: optional callback fired synchronously after the router subsystem is constructed (router + library + builder + store all non-nil). Used by the Registry to track every wired router so ReloadAllSkillRouters can iterate them on AddSkill / ClassifySkill. Not fired when the router subsystem is disabled (router LLM unresolvable, EffectiveRouterEnabled false). Free-function callers who don't care about post-import refresh leave this nil.

type SoftDeleteStorage added in v1.2.0

type SoftDeleteStorage interface {
	// SoftDeleteSession marks a session as deleted without removing data.
	// The session can be restored with RestoreSession.
	SoftDeleteSession(ctx context.Context, sessionID string) error

	// RestoreSession restores a soft-deleted session.
	RestoreSession(ctx context.Context, sessionID string) error

	// PurgeDeleted permanently removes all soft-deleted data older than the grace period.
	PurgeDeleted(ctx context.Context, graceInterval string) error
}

SoftDeleteStorage defines optional soft-delete operations. Not all backends support soft-delete (SQLite does hard delete). Use type assertion to check if a SessionStorage supports soft-delete:

if sds, ok := store.(SoftDeleteStorage); ok {
    sds.RestoreSession(ctx, sessionID)
}

type SoftReminderConfig

type SoftReminderConfig struct {
	ToolExecutionThreshold int  // Threshold to start reminders (default: 10)
	StopThreshold          int  // Threshold to stop reminders (default: 20)
	Enabled                bool // Whether soft reminders are enabled (default: true)
}

SoftReminderConfig holds configuration for soft reminders.

func DefaultSoftReminderConfig

func DefaultSoftReminderConfig() SoftReminderConfig

DefaultSoftReminderConfig returns default soft reminder configuration.

type Stats

type Stats struct {
	SessionCount       int
	MessageCount       int
	ToolExecutionCount int
	TotalCostUSD       float64
	TotalTokens        int
}

Stats holds database statistics.

type SystemPromptFunc

type SystemPromptFunc func(ctx context.Context) string

SystemPromptFunc is a function that returns the system prompt for a new session. It can be used to dynamically load prompts from a PromptRegistry or other source. Accepts context.Context to enable proper context propagation (e.g., for RLS user_id in PostgreSQL).

type SystemStats added in v1.2.0

type SystemStats struct {
	TotalSessions       int32
	TotalMessages       int64
	TotalToolExecutions int64
	TotalUsers          int32
	TotalCostUSD        float64
	TotalTokens         int64
}

SystemStats holds aggregate system-wide statistics across all users.

type TaskBoardConfigYAML added in v1.3.0

type TaskBoardConfigYAML struct {
	Enabled             *bool  `yaml:"enabled"`
	AutoDecompose       bool   `yaml:"auto_decompose"`
	MaxDepth            int    `yaml:"max_depth"`
	DefaultBoardID      string `yaml:"default_board_id"`
	DefaultStrategy     int    `yaml:"default_strategy"`
	ContextBudgetTokens int    `yaml:"context_budget_tokens"`
}

TaskBoardConfigYAML represents task board configuration in YAML.

type TaskBoardTool added in v1.3.0

type TaskBoardTool struct {
	// contains filtered or unexported fields
}

TaskBoardTool provides agent-facing task decomposition and kanban operations. Actions: decompose, ready, claim, update, close, create, list, show, add_dep, board.

func NewTaskBoardTool added in v1.3.0

func NewTaskBoardTool(manager *task.Manager, decomposer *task.Decomposer, agentID string, llm LLMProvider, config *loomv1.TaskBoardConfig) *TaskBoardTool

NewTaskBoardTool creates a new task board tool.

func (*TaskBoardTool) Backend added in v1.3.0

func (t *TaskBoardTool) Backend() string

func (*TaskBoardTool) Description added in v1.3.0

func (t *TaskBoardTool) Description() string

func (*TaskBoardTool) Execute added in v1.3.0

func (t *TaskBoardTool) Execute(ctx context.Context, input map[string]interface{}) (*shuttle.Result, error)

func (*TaskBoardTool) InputSchema added in v1.3.0

func (t *TaskBoardTool) InputSchema() *shuttle.JSONSchema

func (*TaskBoardTool) Name added in v1.3.0

func (t *TaskBoardTool) Name() string

type TokenBudget

type TokenBudget struct {
	MaxTokens      int
	UsedTokens     int
	ReservedTokens int // Reserved for output (e.g., 20000)
	// contains filtered or unexported fields
}

TokenBudget represents a token budget with usage tracking.

func NewTokenBudget

func NewTokenBudget(maxTokens, reservedForOutput int) *TokenBudget

NewTokenBudget creates a new token budget. For Claude Sonnet 4.5: 200K total, reserve 20K for output = 180K available for input.

func (*TokenBudget) AvailableTokens

func (tb *TokenBudget) AvailableTokens() int

AvailableTokens returns the number of tokens available for new content.

func (*TokenBudget) CanFit

func (tb *TokenBudget) CanFit(tokens int) bool

CanFit checks if a given number of tokens can fit in the budget.

func (*TokenBudget) Free

func (tb *TokenBudget) Free(tokens int)

Free returns tokens to the budget.

func (*TokenBudget) GetUsage

func (tb *TokenBudget) GetUsage() (used, available, total int)

GetUsage returns current usage statistics.

func (*TokenBudget) IsCritical

func (tb *TokenBudget) IsCritical() bool

IsCritical checks if usage is at critical levels (>85%).

func (*TokenBudget) IsNearLimit

func (tb *TokenBudget) IsNearLimit(thresholdPct float64) bool

IsNearLimit checks if usage is approaching budget limits. Returns true if usage is above the given percentage threshold.

func (*TokenBudget) NeedsWarning

func (tb *TokenBudget) NeedsWarning() bool

NeedsWarning checks if usage warrants a warning (>70%).

func (*TokenBudget) Reset

func (tb *TokenBudget) Reset()

Reset resets the used token count.

func (*TokenBudget) Set added in v1.4.0

func (tb *TokenBudget) Set(tokens int)

Set records absolute token usage, overwriting any prior value. Unlike Use it accepts counts above the available budget so usage can report the true load of an over-window context (UsagePercentage then exceeds 100), which is what drives compaction. Negative counts clamp to zero.

func (*TokenBudget) UsagePercentage

func (tb *TokenBudget) UsagePercentage() float64

UsagePercentage returns the percentage of budget used.

func (*TokenBudget) Use

func (tb *TokenBudget) Use(tokens int) bool

Use marks tokens as used. Returns false if budget exceeded.

type TokenBudgetConfig

type TokenBudgetConfig struct {
	MaxContextTokens     int     // Total context window (default: 200000)
	ReservedOutputTokens int     // Reserved for output (default: 20000)
	WarningThresholdPct  float64 // Warning threshold (default: 70.0)
	CriticalThresholdPct float64 // Critical threshold (default: 85.0)
	MaxOutputTokens      int     // Maximum output tokens (default: 8192)
	MinOutputTokens      int     // Minimum output tokens (default: 2048)
	OutputBudgetFraction float64 // Fraction of available for output (default: 0.5)
}

TokenBudgetConfig holds configuration for token budget management.

func DefaultTokenBudgetConfig

func DefaultTokenBudgetConfig() TokenBudgetConfig

DefaultTokenBudgetConfig returns default token budget configuration for Claude Sonnet 4.5.

type TokenCounter

type TokenCounter struct {
	// contains filtered or unexported fields
}

TokenCounter provides accurate token counting for LLM context management. Uses tiktoken with cl100k_base encoding (Claude-compatible approximation).

Internally uses a fixed-size channel pool of tiktoken encoders so that concurrent goroutines can count tokens without contending on a single mutex. Unlike sync.Pool, the channel pool is not subject to GC draining.

func GetTokenCounter

func GetTokenCounter() *TokenCounter

GetTokenCounter returns a singleton token counter instance.

func (*TokenCounter) CountTokens

func (tc *TokenCounter) CountTokens(text string) int

CountTokens returns the accurate token count for a given text. Borrows an encoder from the fixed-size channel pool so concurrent callers don't contend on a single mutex. If all encoders are in use, the caller blocks until one is returned — no allocation, no GC pressure.

func (*TokenCounter) CountTokensMultiple

func (tc *TokenCounter) CountTokensMultiple(texts ...string) int

CountTokensMultiple counts tokens across multiple text segments.

func (*TokenCounter) EstimateMessagesTokens

func (tc *TokenCounter) EstimateMessagesTokens(messages []Message) int

EstimateMessagesTokens estimates token count for a slice of messages. Includes formatting overhead for message structure.

func (*TokenCounter) EstimateToolResultTokens

func (tc *TokenCounter) EstimateToolResultTokens(results []CachedToolResult) int

EstimateToolResultTokens estimates token count for cached tool results.

type ToolCall

type ToolCall = types.ToolCall

type ToolExecution

type ToolExecution struct {
	ToolName string
	Input    map[string]interface{}
	Result   *shuttle.Result
	Error    error

	// AdmissionDecision is the audit verdict ("allow"|"deny"|"ask") for a call
	// matched by an audit binding, stamped by the executor onto
	// Result.Metadata["admission.decision"]. Empty means the call was not
	// audited; empty rows are not counted as audit records (SC-004).
	AdmissionDecision string
}

ToolExecution records a tool execution.

type ToolsConfigYAML

type ToolsConfigYAML struct {
	MCP     []MCPToolConfigYAML    `yaml:"mcp"`
	Custom  []CustomToolConfigYAML `yaml:"custom"`
	Builtin []string               `yaml:"builtin"`
}

ToolsConfigYAML represents tools configuration in YAML

type Usage

type Usage = types.Usage

type UserSessionCount added in v1.2.0

type UserSessionCount struct {
	UserID       string
	SessionCount int32
}

UserSessionCount holds the session count for a single user.

type WiredSkillSubsystem added in v1.3.0

type WiredSkillSubsystem struct {
	AgentName string
	Library   *skills.Library
	Builder   *skillindex.Builder
	Store     skillindex.Store
	Router    *skillindex.Router
}

WiredSkillSubsystem is the bundle of skills handles a single agent's router was constructed with. Stored on the Registry so the import service can call ReloadAllSkillRouters after writes.

AgentName is the agent the wiring belongs to (for logging). Library is the skills.Library serving this agent's catalog. Builder + Store + Router together drive index rebuilds that SetTree onto Router so the running agent picks up the new tree.

type WorkflowCommunicationContext added in v1.1.0

type WorkflowCommunicationContext struct {
	// Subscribed topics for pub-sub communication
	SubscribedTopics []string

	// Available agents for point-to-point communication (workflow:agent format)
	AvailableAgents []string

	// Workflow name (for constructing agent IDs)
	WorkflowName string
}

WorkflowCommunicationContext contains dynamic workflow communication info injected into prompts

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL