skills

package
v1.3.0 Latest Latest
Warning

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

Go to latest
Published: Jun 1, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

Documentation

Overview

Package skills provides skill loading, matching, and lifecycle management. Skills are activatable behaviors that combine prompt injection, tool preferences, trigger conditions, and optional persistence across turns.

Index

Constants

View Source
const SkillConfidenceDecayRate = 0.995

SkillConfidenceDecayRate is the daily multiplicative decay applied to skill confidence from the last_validated_ms anchor.

Variables

This section is empty.

Functions

func ComputeSkillBudget

func ComputeSkillBudget(maxContextTokens, budgetPercent int) int

ComputeSkillBudget calculates the token budget for skills given the model's max context tokens and the configured budget percentage. Returns the total budget for skills+patterns combined.

func EstimateTokens

func EstimateTokens(s string) int

EstimateTokens estimates the token count for a string. Uses the approximation: 1 token ~ 4 characters.

func FormatSkillHeader

func FormatSkillHeader() string

FormatSkillHeader returns the header for the skills injection block.

func FormatSkillsForInjection

func FormatSkillsForInjection(skills []*ActiveSkill, maxTokens int) (string, []string)

FormatSkillsForInjection formats multiple skills for LLM system message injection. It respects the token budget, including skills in priority order. Returns the formatted string and the list of skill names that were included.

func ParseSlashCommand added in v1.3.0

func ParseSlashCommand(msg string) (cmd string, rest string)

ParseSlashCommand extracts the slash command from a message. Returns command and remaining message, or empty strings if not a slash command. Example: "/review this code" -> ("/review", "this code")

func SkillToYAML

func SkillToYAML(s *Skill) ([]byte, error)

SkillToYAML converts a Skill Go struct to YAML bytes. This is used by the MCP create_skill tool to serialize skills.

Types

type ActiveSkill

type ActiveSkill struct {
	Skill        *Skill    `json:"skill"`
	TriggerType  string    `json:"trigger_type"`
	TriggerValue string    `json:"trigger_value"`
	Confidence   float64   `json:"confidence"`
	ActivatedAt  time.Time `json:"activated_at"`
	SessionID    string    `json:"session_id"`
	AgentID      string    `json:"agent_id"`
}

ActiveSkill tracks an activated skill within a session.

type HotReloadConfig

type HotReloadConfig struct {
	Enabled    bool                // Enable hot-reload watching
	DebounceMs int                 // Debounce delay in milliseconds (default: 500ms)
	Logger     *zap.Logger         // Logger for reload events
	OnUpdate   SkillUpdateCallback // Callback for skill updates (optional)
}

HotReloadConfig configures hot-reload behavior for the skill library.

type HotReloader

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

HotReloader watches skill YAML files for changes and updates the library cache.

func NewHotReloader

func NewHotReloader(library *Library, config HotReloadConfig, tracer observability.Tracer) (*HotReloader, error)

NewHotReloader creates a new hot-reloader for the skill library. Returns an error if the library has no filesystem search paths configured.

func (*HotReloader) Start

func (hr *HotReloader) Start(ctx context.Context) error

Start begins watching skill directories for file changes. It watches all configured search paths on the library.

func (*HotReloader) Stop

func (hr *HotReloader) Stop() error

Stop stops the hot-reload watcher. It is safe to call multiple times.

type Library

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

Library manages skill discovery, loading, caching, and search. It supports three tiers of skill sources in order of precedence:

  1. Configured search paths (from agent config skills_dir)
  2. $LOOM_SKILLS_DIR env var (default $HOME/.loom/skills/)
  3. Embedded examples (lowest precedence, read-only)

Thread safety: All public methods are safe for concurrent use.

func NewLibrary

func NewLibrary(opts ...LibraryOption) *Library

NewLibrary creates a skill library with the given options. If no search paths are provided, it defaults to $LOOM_SKILLS_DIR (falling back to $HOME/.loom/skills/).

func (*Library) FindByKeywords

func (l *Library) FindByKeywords(msg string) []*ScoredSkill

FindByKeywords matches a user message against each skill's trigger keywords. Returns scored results sorted by descending relevance.

func (*Library) FindBySlashCommand

func (l *Library) FindBySlashCommand(cmd string) (*Skill, bool)

FindBySlashCommand searches for a skill matching the given slash command. Returns the matching skill and true if found, nil and false otherwise.

func (*Library) InvalidateCache

func (l *Library) InvalidateCache()

InvalidateCache clears the skill cache and index. The next call to Load or ListAll will re-read from disk/embedded sources.

func (*Library) List

func (l *Library) List() []*Skill

recordLoadMetric records a tracing span attribute and metric for a Load call. List returns all skills in the library cache. If the cache is empty, it triggers indexing first.

func (*Library) ListAll

func (l *Library) ListAll() []SkillSummary

ListAll returns summaries for all available skills. The result is cached; call InvalidateCache to force re-indexing. Skills from filesystem paths take precedence over embedded skills with the same name.

func (*Library) ListByDomain

func (l *Library) ListByDomain(domain string) []*Skill

ListByDomain returns all skills matching the given domain.

func (*Library) Load

func (l *Library) Load(name string) (*Skill, error)

Load reads a skill by name. It checks three tiers in order: cache, filesystem search paths, embedded FS. Returns an error if the skill is not found in any source.

func (*Library) Register

func (l *Library) Register(skill *Skill)

Register adds a skill directly to the in-memory cache. This is useful for programmatically created skills that don't come from YAML files.

func (*Library) RemoveFromCache

func (l *Library) RemoveFromCache(name string)

RemoveFromCache removes a single skill from the cache by name.

func (*Library) Search

func (l *Library) Search(query string) []*ScoredSkill

Search performs free-text keyword matching across skill name, title, and description. Returns scored results sorted by descending relevance.

func (*Library) WriteSkill

func (l *Library) WriteSkill(skill *Skill) error

WriteSkill writes a skill as YAML to the primary (first writable) search path. Uses SkillToYAML from loader.go for serialization.

type LibraryOption

type LibraryOption func(*Library)

LibraryOption configures a Library during construction.

func WithEmbeddedFS

func WithEmbeddedFS(efs *embed.FS) LibraryOption

WithEmbeddedFS sets an embedded filesystem as the lowest-precedence skill source.

func WithSearchPaths

func WithSearchPaths(paths ...string) LibraryOption

WithSearchPaths adds filesystem directories to search for skill YAML files. Paths are searched in the order provided, with earlier paths taking precedence.

func WithTracer

func WithTracer(t observability.Tracer) LibraryOption

WithTracer sets the observability tracer for the library.

type MatchResult

type MatchResult struct {
	Skill        *Skill  `json:"skill"`
	Confidence   float64 `json:"confidence"`
	TriggerType  string  `json:"trigger_type"`
	TriggerValue string  `json:"trigger_value"`
}

MatchResult represents the result of matching a skill against user input.

type Orchestrator

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

Orchestrator is the activation engine for skills. It evaluates user messages, matches them to skills via slash commands, keywords, or always-on rules, and manages active skill lifecycles within sessions.

func NewOrchestrator

func NewOrchestrator(library *Library, opts ...OrchestratorOption) *Orchestrator

NewOrchestrator creates a new skill orchestrator backed by the given library.

func (*Orchestrator) ActivateSkill

func (o *Orchestrator) ActivateSkill(sessionID string, skill *Skill, triggerType, triggerValue string, confidence float64) *ActiveSkill

ActivateSkill activates a skill for a session. If the session already has MaxConcurrentSkills active, the lowest-confidence non-sticky skill is evicted. Sticky-ness is determined by:

  1. Skill.Sticky == true (explicit author intent), OR
  2. The configured StickinessChecker returning true for the skill — used by the agent layer to keep skills active while they have open tasks on the board.

When every active skill is sticky, the cap is allowed to overflow for this turn rather than evicting load-bearing skills out from under in-flight work. This matches the design's "sticky-while-open-tasks" guarantee from the skills overhaul.

func (*Orchestrator) CleanupSession

func (o *Orchestrator) CleanupSession(sessionID string)

CleanupSession removes all state for a session.

func (*Orchestrator) DeactivateSkill

func (o *Orchestrator) DeactivateSkill(sessionID, skillName string)

DeactivateSkill removes a skill from a session.

func (*Orchestrator) FormatActiveSkillsForLLM

func (o *Orchestrator) FormatActiveSkillsForLLM(sessionID string, maxTokens int) string

FormatActiveSkillsForLLM combines all active skill prompts within the given token budget. Skills are included in FIFO order (activation time). If a skill's formatted prompt exceeds the remaining budget it is skipped. Token estimation: 1 token ~ 4 characters.

func (*Orchestrator) GetActiveSkills

func (o *Orchestrator) GetActiveSkills(sessionID string) []*ActiveSkill

GetActiveSkills returns all active skills for a session.

func (*Orchestrator) GetLibrary

func (o *Orchestrator) GetLibrary() *Library

GetLibrary returns the underlying skill library.

func (*Orchestrator) MatchSkills

func (o *Orchestrator) MatchSkills(sessionID, userMsg string, config *SkillsConfig) ([]*MatchResult, error)

MatchSkills evaluates the user message and returns matching skills. It checks slash commands first, then auto-detection for HYBRID/AUTO skills, and finally ALWAYS skills. Results are filtered by config and sorted by confidence.

func (*Orchestrator) SetMaxConcurrentSkills added in v1.3.0

func (o *Orchestrator) SetMaxConcurrentSkills(n int)

SetMaxConcurrentSkills adjusts the eviction cap at runtime. Safe for concurrent use with ActivateSkill.

func (*Orchestrator) SetOnSkillEviction added in v1.3.0

func (o *Orchestrator) SetOnSkillEviction(fn func(sessionID string, skill *Skill, activeFor time.Duration))

SetOnSkillEviction installs an eviction callback at runtime. Safe for concurrent use with ActivateSkill.

func (*Orchestrator) SetStickinessChecker added in v1.3.0

func (o *Orchestrator) SetStickinessChecker(checker StickinessChecker)

SetStickinessChecker installs a stickiness checker at runtime. Safe for concurrent use with ActivateSkill.

type OrchestratorOption

type OrchestratorOption func(*Orchestrator)

OrchestratorOption configures an Orchestrator during construction.

func WithMaxConcurrentSkills added in v1.3.0

func WithMaxConcurrentSkills(n int) OrchestratorOption

WithMaxConcurrentSkills caps the active-skill set this orchestrator allows per session. The eviction routine consults this; 0 falls back to the legacy default of 3.

func WithOnSkillEviction added in v1.3.0

func WithOnSkillEviction(fn func(sessionID string, skill *Skill, activeFor time.Duration)) OrchestratorOption

WithOnSkillEviction installs a callback that fires after a skill is evicted from the active set. The callback receives the session ID, the evicted skill, and how long the skill was active. Used by the agent layer to boost graph memory salience for entities related to the evicted skill.

func WithOrchestratorLogger added in v1.3.0

func WithOrchestratorLogger(l *zap.Logger) OrchestratorOption

WithOrchestratorLogger sets the zap logger used to surface skill activation/deactivation/eviction events. When unset, the orchestrator uses zap.NewNop() so existing callers see no output change.

func WithOrchestratorTracer

func WithOrchestratorTracer(t observability.Tracer) OrchestratorOption

WithOrchestratorTracer sets the observability tracer for the orchestrator.

func WithStickinessChecker added in v1.3.0

func WithStickinessChecker(checker StickinessChecker) OrchestratorOption

WithStickinessChecker installs a callback that the eviction routine consults to decide whether a candidate-for-eviction is sticky. Used by the agent layer to keep skills active while they have open tasks.

type ScoredSkill

type ScoredSkill struct {
	Skill *Skill  `json:"skill"`
	Score float64 `json:"score"`
}

ScoredSkill represents a skill with a relevance score for search/ranking.

type Skill

type Skill struct {
	// Metadata
	Name        string            `json:"name"`
	Title       string            `json:"title"`
	Description string            `json:"description"`
	Version     string            `json:"version"`
	Domain      string            `json:"domain"`
	Labels      map[string]string `json:"labels,omitempty"`
	Author      string            `json:"author,omitempty"`

	// Confidence score 0.0-1.0. Hand-authored defaults to 1.0.
	Confidence      float64 `json:"confidence,omitempty"`
	Status          string  `json:"status,omitempty"`
	LastValidatedMs int64   `json:"last_validated_ms,omitempty"`
	RiskLevel       string  `json:"risk_level,omitempty"`

	// Trigger configuration
	Trigger SkillTrigger `json:"trigger"`

	// Prompt instructions
	Prompt SkillPrompt `json:"prompt"`

	// Tool requirements and preferences
	Tools SkillToolConfig `json:"tools"`

	// Co-inject these patterns when skill is active
	PatternRefs []string `json:"pattern_refs,omitempty"`

	// Compose with sub-skills (max depth: 2)
	SkillRefs []string `json:"skill_refs,omitempty"`

	// Token budget for this skill's prompt (0 = use default 1500)
	MaxPromptTokens int32 `json:"max_prompt_tokens,omitempty"`

	// Persist across turns once activated
	Sticky bool `json:"sticky,omitempty"`

	// Target backend (empty = agnostic)
	Backend string `json:"backend,omitempty"`

	// Optional explicit decomposition. When nil and EmitTasks resolves to true
	// (default), task.Decomposer is invoked at activation with the skill prompt
	// as goal. The emitter uses TaskTemplate.Steps to materialize tasks via
	// task.Manager.CreateTask + AddDependency.
	TaskTemplate *SkillTaskTemplate `json:"task_template,omitempty"`

	// Index path used by the hierarchical router to place this skill in the
	// SkillIndex tree, e.g. "enterprise/sql/optimization". Empty falls back to
	// "unclassified/<domain>".
	ParentIndexPath string `json:"parent_index_path,omitempty"`

	// Whether activation emits tracked tasks. Pointer mirrors proto3 optional:
	// nil = not specified (default true), &false = explicitly suppressed.
	// EffectiveEmitTasks() resolves this against zero-value semantics.
	EmitTasks *bool `json:"emit_tasks,omitempty"`
}

Skill represents an activatable behavior that combines prompt injection, tool preferences, trigger conditions, and optional persistence across turns.

func LoadSkill

func LoadSkill(path string) (*Skill, error)

LoadSkill loads a single skill from a YAML file.

func LoadSkillLibrary

func LoadSkillLibrary(path string) ([]*Skill, error)

LoadSkillLibrary loads a skill library YAML file containing multiple skills.

func (*Skill) EffectiveConfidence added in v1.3.0

func (s *Skill) EffectiveConfidence(now time.Time) float64

EffectiveConfidence computes the time-decayed confidence for this skill. Hand-authored skills (Confidence==0) default to 1.0. The decay is 0.995^days from LastValidatedMs.

func (*Skill) EffectiveEmitTasks added in v1.3.0

func (s *Skill) EffectiveEmitTasks() bool

EffectiveEmitTasks returns the resolved emit-tasks decision for this skill, applying default-true semantics when EmitTasks is unset.

func (*Skill) FormatForLLM

func (s *Skill) FormatForLLM() string

FormatForLLM formats the skill for LLM injection. Returns a concise, actionable representation optimized for token efficiency. Target: <2000 tokens per skill.

func (*Skill) IsHighRisk added in v1.3.0

func (s *Skill) IsHighRisk() bool

IsHighRisk returns true if the skill's risk level is HIGH or RESTRICTED.

func (*Skill) Summary

func (s *Skill) Summary() SkillSummary

Summary returns a lightweight SkillSummary from this Skill.

type SkillActivationMode

type SkillActivationMode string

SkillActivationMode controls how a skill can be triggered.

const (
	// ActivationManual requires explicit slash command or API call.
	ActivationManual SkillActivationMode = "MANUAL"
	// ActivationAuto enables auto-detection from user message content.
	ActivationAuto SkillActivationMode = "AUTO"
	// ActivationHybrid supports both manual and auto-detection.
	ActivationHybrid SkillActivationMode = "HYBRID"
	// ActivationAlways keeps the skill active whenever configured.
	ActivationAlways SkillActivationMode = "ALWAYS"
)

type SkillBinding added in v1.3.0

type SkillBinding struct {
	// Name is an exact skill name or a path.Match-style glob ("enterprise/sql/*").
	Name string `json:"name"`
	// Mode controls when the skill is loaded into the orchestrator.
	Mode SkillBindingMode `json:"mode,omitempty"`
	// Priority breaks ties when context budget is tight (higher wins).
	Priority int32 `json:"priority,omitempty"`
	// LabelMatch is an optional AND-selector against Skill.Labels.
	LabelMatch map[string]string `json:"label_match,omitempty"`
	// MinVersion is a semver lower bound; empty means any version.
	MinVersion string `json:"min_version,omitempty"`
}

SkillBinding ties a skill (or a glob/label-selector over the skill namespace) to an agent with a specific load policy. Mirrors loomv1.SkillBinding.

type SkillBindingMode added in v1.3.0

type SkillBindingMode string

SkillBindingMode controls how an agent loads a bound skill into context. Mirrors loomv1.SkillBindingMode.

const (
	// BindingEager keeps the skill formatted into the system-prompt budget every turn.
	BindingEager SkillBindingMode = "EAGER"
	// BindingLazy promotes the skill into the orchestrator only when discovery selects it.
	BindingLazy SkillBindingMode = "LAZY"
	// BindingAlways forces the skill active every turn, overriding its trigger mode.
	BindingAlways SkillBindingMode = "ALWAYS"
)

type SkillExample

type SkillExample struct {
	UserInput      string `json:"user_input"`
	ExpectedOutput string `json:"expected_output"`
	Explanation    string `json:"explanation,omitempty"`
}

SkillExample provides a few-shot example for the skill.

type SkillExampleYAML

type SkillExampleYAML struct {
	UserInput      string `yaml:"user_input"`
	ExpectedOutput string `yaml:"expected_output"`
	Explanation    string `yaml:"explanation"`
}

SkillExampleYAML holds a single example from YAML.

type SkillIndex added in v1.3.0

type SkillIndex struct {
	ID           string            `json:"id"`
	RootID       string            `json:"root_id"`
	Nodes        []*SkillIndexNode `json:"nodes,omitempty"`
	BuiltAtMs    int64             `json:"built_at_ms,omitempty"`
	BuiltByModel string            `json:"built_by_model,omitempty"`
}

SkillIndex is the full router tree, persisted across boots.

type SkillIndexNode added in v1.3.0

type SkillIndexNode struct {
	ID        string            `json:"id"`
	Title     string            `json:"title"`
	Summary   string            `json:"summary,omitempty"`
	Children  []string          `json:"children,omitempty"`
	SkillRefs []string          `json:"skill_refs,omitempty"`
	Depth     int32             `json:"depth"`
	Labels    map[string]string `json:"labels,omitempty"`
	// ContentHash dirties only this subtree on YAML hot-reload; full index
	// rebuilds happen only on bulk add/remove.
	ContentHash string `json:"content_hash,omitempty"`
}

SkillIndexNode is one node in the hierarchical PageIndex-style router tree. Built by index.Builder, persisted by index.Store, consumed by index.Router.

type SkillLibraryMetadataYAML

type SkillLibraryMetadataYAML struct {
	Name        string            `yaml:"name"`
	Version     string            `yaml:"version"`
	Description string            `yaml:"description"`
	Labels      map[string]string `yaml:"labels"`
}

SkillLibraryMetadataYAML holds library-level metadata from YAML.

type SkillLibraryYAML

type SkillLibraryYAML struct {
	APIVersion string                   `yaml:"apiVersion"`
	Kind       string                   `yaml:"kind"`
	Metadata   SkillLibraryMetadataYAML `yaml:"metadata"`
	Skills     []SkillYAML              `yaml:"skills"`
}

SkillLibraryYAML represents the YAML structure for a skill library file.

type SkillMetadataYAML

type SkillMetadataYAML struct {
	Name            string            `yaml:"name"`
	Title           string            `yaml:"title"`
	Description     string            `yaml:"description"`
	Version         string            `yaml:"version"`
	Domain          string            `yaml:"domain"`
	Author          string            `yaml:"author"`
	Labels          map[string]string `yaml:"labels"`
	Confidence      float64           `yaml:"confidence"`
	Status          string            `yaml:"status"`
	LastValidatedMs int64             `yaml:"last_validated_ms"`
	RiskLevel       string            `yaml:"risk_level"`
}

SkillMetadataYAML holds skill metadata from YAML.

type SkillPrompt

type SkillPrompt struct {
	// Main prompt instructions (supports {{.var}} interpolation)
	Instructions string `json:"instructions"`

	// Rules and constraints to enforce
	Constraints []string `json:"constraints,omitempty"`

	// Expected output structure description
	OutputFormat string `json:"output_format,omitempty"`

	// Few-shot examples
	Examples []SkillExample `json:"examples,omitempty"`
}

SkillPrompt defines the instructions injected when a skill is active.

type SkillPromptYAML

type SkillPromptYAML struct {
	Instructions string             `yaml:"instructions"`
	Constraints  []string           `yaml:"constraints"`
	OutputFormat string             `yaml:"output_format"`
	Examples     []SkillExampleYAML `yaml:"examples"`
}

SkillPromptYAML holds prompt configuration from YAML.

type SkillSummary

type SkillSummary struct {
	Name        string            `json:"name"`
	Title       string            `json:"title"`
	Description string            `json:"description"`
	Domain      string            `json:"domain"`
	Version     string            `json:"version"`
	Labels      map[string]string `json:"labels,omitempty"`
	Commands    []string          `json:"commands,omitempty"`
}

SkillSummary provides lightweight metadata for catalog listing.

type SkillTaskStep added in v1.3.0

type SkillTaskStep struct {
	Title              string  `json:"title"`
	Objective          string  `json:"objective,omitempty"`
	AcceptanceCriteria string  `json:"acceptance_criteria,omitempty"`
	Category           string  `json:"category,omitempty"`
	Priority           string  `json:"priority,omitempty"`
	DependsOn          []int32 `json:"depends_on,omitempty"`
	EstimatedEffort    string  `json:"estimated_effort,omitempty"`
	// Tags propagate onto the materialized Task.
	Tags []string `json:"tags,omitempty"`
}

SkillTaskStep is one entry in an authored skill task template. Category and Priority are plain strings here (e.g. "research", "P1") and are converted to loomv1 enum values by the task emitter at materialization time.

type SkillTaskStepYAML added in v1.3.0

type SkillTaskStepYAML struct {
	Title              string   `yaml:"title"`
	Objective          string   `yaml:"objective"`
	AcceptanceCriteria string   `yaml:"acceptance_criteria"`
	Category           string   `yaml:"category"`
	Priority           string   `yaml:"priority"`
	DependsOn          []int32  `yaml:"depends_on"`
	EstimatedEffort    string   `yaml:"estimated_effort"`
	Tags               []string `yaml:"tags"`
}

SkillTaskStepYAML holds a single template step from YAML.

type SkillTaskTemplate added in v1.3.0

type SkillTaskTemplate struct {
	Steps []SkillTaskStep `json:"steps,omitempty"`
	// RootTitle names the parent task created to group emitted children.
	// Empty defaults to the skill's title.
	RootTitle string `json:"root_title,omitempty"`
	// EphemeralOnDeactivate deletes unstarted (still-OPEN) tasks if the
	// skill deactivates before they are claimed. In-progress and done
	// tasks are always preserved.
	EphemeralOnDeactivate bool `json:"ephemeral_on_deactivate,omitempty"`
	// MaxTasks caps the emitted task count. Default 8. Applies to
	// authored Steps and to decomposer fallback output alike.
	MaxTasks int32 `json:"max_tasks,omitempty"`
}

SkillTaskTemplate is an optional authored decomposition that materializes when the skill activates. When absent, the emitter falls back to task.Decomposer.Decompose with the skill's prompt as goal.

type SkillTaskTemplateYAML added in v1.3.0

type SkillTaskTemplateYAML struct {
	Steps                 []SkillTaskStepYAML `yaml:"steps"`
	RootTitle             string              `yaml:"root_title"`
	EphemeralOnDeactivate bool                `yaml:"ephemeral_on_deactivate"`
	MaxTasks              int32               `yaml:"max_tasks"`
}

SkillTaskTemplateYAML holds an authored skill task decomposition from YAML.

type SkillToolConfig

type SkillToolConfig struct {
	// Ensure these tools are registered when skill is active
	RequiredTools []string `json:"required_tools,omitempty"`

	// Suggested tool execution ordering
	PreferredOrder []string `json:"preferred_order,omitempty"`

	// Tools to hide when skill is active
	ExcludedTools []string `json:"excluded_tools,omitempty"`

	// MCP servers to enable when skill is active
	MCPServers []string `json:"mcp_servers,omitempty"`
}

SkillToolConfig defines tool requirements and preferences for a skill.

type SkillToolsYAML

type SkillToolsYAML struct {
	RequiredTools  []string `yaml:"required_tools"`
	PreferredOrder []string `yaml:"preferred_order"`
	ExcludedTools  []string `yaml:"excluded_tools"`
	MCPServers     []string `yaml:"mcp_servers"`
}

SkillToolsYAML holds tool configuration from YAML.

type SkillTrigger

type SkillTrigger struct {
	// Slash commands that activate this skill: ["/review", "/code-review"]
	SlashCommands []string `json:"slash_commands,omitempty"`

	// Keywords for auto-detection from user messages
	Keywords []string `json:"keywords,omitempty"`

	// Freeform intent labels for intent-based activation (matched against pattern intents)
	IntentCategories []string `json:"intent_categories,omitempty"`

	// How this skill can be activated
	Mode SkillActivationMode `json:"mode,omitempty"`

	// Minimum confidence for AUTO/HYBRID activation (default: 0.7)
	MinConfidence float64 `json:"min_confidence,omitempty"`
}

SkillTrigger defines how a skill gets activated.

type SkillTriggerYAML

type SkillTriggerYAML struct {
	SlashCommands    []string `yaml:"slash_commands"`
	Keywords         []string `yaml:"keywords"`
	IntentCategories []string `yaml:"intent_categories"`
	Mode             string   `yaml:"mode"`
	MinConfidence    float64  `yaml:"min_confidence"`
}

SkillTriggerYAML holds trigger configuration from YAML.

type SkillUpdateCallback

type SkillUpdateCallback func(eventType string, skillName string, err error)

SkillUpdateCallback is called when a skill file is created, modified, or deleted. Parameters: eventType (create/modify/delete/validation_failed), skillName, error (if validation failed).

type SkillYAML

type SkillYAML struct {
	APIVersion      string                 `yaml:"apiVersion"`
	Kind            string                 `yaml:"kind"`
	Metadata        SkillMetadataYAML      `yaml:"metadata"`
	Trigger         SkillTriggerYAML       `yaml:"trigger"`
	Prompt          SkillPromptYAML        `yaml:"prompt"`
	Tools           SkillToolsYAML         `yaml:"tools"`
	PatternRefs     []string               `yaml:"pattern_refs"`
	SkillRefs       []string               `yaml:"skill_refs"`
	MaxPromptTokens int32                  `yaml:"max_prompt_tokens"`
	Sticky          bool                   `yaml:"sticky"`
	Backend         string                 `yaml:"backend"`
	TaskTemplate    *SkillTaskTemplateYAML `yaml:"task_template,omitempty"`
	ParentIndexPath string                 `yaml:"parent_index_path,omitempty"`
	// EmitTasks uses *bool so we can distinguish "not specified" (default-true)
	// from "explicitly false". yaml.v3 leaves the pointer nil when the key is absent.
	EmitTasks *bool `yaml:"emit_tasks,omitempty"`
}

SkillYAML represents the YAML structure for a single skill file.

type SkillsConfig

type SkillsConfig struct {
	Enabled bool
	// Deprecated: prefer Bindings. Resolver synthesizes EAGER-mode bindings
	// from this list when Bindings is empty.
	EnabledSkills []string
	// Deprecated: prefer Bindings. Resolver excludes these names when
	// synthesizing the implicit binding set.
	DisabledSkills       []string
	MinAutoConfidence    float64
	MaxConcurrentSkills  int
	SkillsDir            string
	ContextBudgetPercent int

	// Bindings declares the skills attached to this agent. Empty falls back
	// to the legacy EnabledSkills/DisabledSkills filter pair via the resolver
	// shim. When non-empty, Bindings takes full precedence.
	Bindings []SkillBinding

	// RouterEnabled gates the hierarchical PageIndex-style discovery path.
	// nil mirrors proto3 optional default-true; pointer so callers can
	// distinguish "not specified" from "explicitly false".
	RouterEnabled *bool
	// RouterMaxCandidates caps candidates returned per router walk (default 5).
	RouterMaxCandidates int
	// RouterCacheTTLSeconds is the per-session decision cache TTL (default 300).
	RouterCacheTTLSeconds int
	// RouterModelOverride names a specific LLM provider for routing decisions.
	// Empty falls back to AgentConfig.classifier_llm.
	RouterModelOverride string

	// SkillTaskBoardID names the task board for skill-emitted tasks.
	// Empty reuses the agent's primary board.
	SkillTaskBoardID string
	// TasksEnabled is the agent-level master switch for skill task emission.
	// nil mirrors proto3 optional default-true. Per-skill EmitTasks overrides
	// this for individual skills.
	TasksEnabled *bool

	// Hygiene controls end-of-turn task-board hygiene enforcement for
	// skill-emitted tasks. nil falls back to defaults (enabled, REQUIRE_FIX
	// policy, max_retries=2). The agent layer constructs the auditor when
	// both skillOrchestrator and taskManager are present.
	Hygiene *loomv1.HygieneConfig
}

SkillsConfig controls skill matching behavior for a session.

func DefaultSkillsConfig

func DefaultSkillsConfig() *SkillsConfig

DefaultSkillsConfig returns a SkillsConfig with sensible defaults.

MaxConcurrentSkills and RouterMaxCandidates are aligned at 3 so the router's per-leaf decisions reach the orchestrator without being silently trimmed. See pkg/skills/index/router.go's maxCandidates comment for the rationale.

func (*SkillsConfig) EffectiveRouterEnabled added in v1.3.0

func (c *SkillsConfig) EffectiveRouterEnabled() bool

EffectiveRouterEnabled resolves the router-enabled decision, applying default-true semantics when RouterEnabled is unset.

func (*SkillsConfig) EffectiveTasksEnabled added in v1.3.0

func (c *SkillsConfig) EffectiveTasksEnabled() bool

EffectiveTasksEnabled resolves the task-emission master switch, applying default-true semantics when TasksEnabled is unset.

type StickinessChecker added in v1.3.0

type StickinessChecker func(skillName, sessionID string) bool

StickinessChecker is consulted during eviction to decide whether an active skill should be treated as sticky for the current activation attempt, regardless of its Skill.Sticky flag. The agent layer typically installs a checker that returns true when the skill has open tasks on the kanban board, so eviction never abandons in-flight work.

Directories

Path Synopsis
Package binding evaluates SkillBinding records against a skill library and produces a deterministic load-policy decision for each skill an agent declaratively attaches.
Package binding evaluates SkillBinding records against a skill library and produces a deterministic load-policy decision for each skill an agent declaratively attaches.
Package discovery composes the per-turn skill discovery pipeline:
Package discovery composes the per-turn skill discovery pipeline:
Package hygiene enforces end-of-turn task-board hygiene for skill-emitted tasks.
Package hygiene enforces end-of-turn task-board hygiene for skill-emitted tasks.
Package importer converts Anthropic-style Agent Skill source directories (`<name>/SKILL.md` + `references/*.md`) into loom/v1 Skill YAML the loader can read.
Package importer converts Anthropic-style Agent Skill source directories (`<name>/SKILL.md` + `references/*.md`) into loom/v1 Skill YAML the loader can read.
Package index implements a hierarchical PageIndex-style router tree over the skill library.
Package index implements a hierarchical PageIndex-style router tree over the skill library.
Package tasks materializes the tasks an active skill produces.
Package tasks materializes the tasks an active skill produces.

Jump to

Keyboard shortcuts

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