skills

package
v1.2.0 Latest Latest
Warning

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

Go to latest
Published: Mar 19, 2026 License: Apache-2.0 Imports: 15 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

This section is empty.

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 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 skill is evicted.

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.

type OrchestratorOption

type OrchestratorOption func(*Orchestrator)

OrchestratorOption configures an Orchestrator during construction.

func WithOrchestratorTracer

func WithOrchestratorTracer(t observability.Tracer) OrchestratorOption

WithOrchestratorTracer sets the observability tracer for the orchestrator.

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"`

	// 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"`
}

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) 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) 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 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 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"`
}

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 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"`

	// Maps to patterns.IntentCategory for intent-based activation
	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"`
}

SkillYAML represents the YAML structure for a single skill file.

type SkillsConfig

type SkillsConfig struct {
	Enabled              bool
	EnabledSkills        []string
	DisabledSkills       []string
	MinAutoConfidence    float64
	MaxConcurrentSkills  int
	SkillsDir            string
	ContextBudgetPercent int
}

SkillsConfig controls skill matching behavior for a session.

func DefaultSkillsConfig

func DefaultSkillsConfig() *SkillsConfig

DefaultSkillsConfig returns a SkillsConfig with sensible defaults.

Jump to

Keyboard shortcuts

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