Skip to content

Skills System

Tau discovers and activates "skills" - markdown files with YAML frontmatter that provide instructions, context, and tool definitions to the agent. Skills are project-local or user-global and are injected into the system prompt.

Architecture

tree
internal/skills/
├── skills.go    - Skill type, discovery, parsing, rendering
├── manager.go   - Runtime skill lifecycle management
└── tracker.go   - Skill activation tracking

Skill Format

A skill file is a markdown document with YAML frontmatter:

markdown
---
name: my-skill
description: A concise description of what this skill does
user-invocable: true
---

# My Skill

Instructions and context for the agent...

Frontmatter Fields

FieldTypeDescription
namestringUnique skill identifier (lowercase, hyphens only)
descriptionstringHuman-readable description
user-invocableboolWhether the user can invoke this skill directly (default: false when absent)
enabledboolWhether the skill is active (default: true)
disable-model-invocationboolReserved for model-driven skill selection
licensestringLicense name or reference (agentskills.io spec)
compatibilitystringEnvironment requirements (agentskills.io spec)
metadatamap[string]stringArbitrary key-value metadata (agentskills.io spec)
allowed-toolsstringSpace-separated pre-approved tools (experimental)

Fields not in the YAML frontmatter (derived at runtime by the discovery system):

FieldSource
scopeSet from the discovery source root ("user" or "project")
prioritySet from the discovery source's configured priority
pathFilesystem path to the skill directory
skill_file_pathAbsolute path to the SKILL.md file

The frontmatter is separated from the body by --- delimiters and parsed as YAML. Unknown keys are silently ignored by the YAML parser.

Example with optional fields

markdown
---
name: pdf-processing
description: Extract PDF text, fill forms, merge files. Use when handling PDFs.
license: Apache-2.0
compatibility: Requires Python 3.10+
metadata:
  author: example-org
  version: "1.0"
---

# PDF Processing

Instructions...

Skill Type

go
type Skill struct {
    Name                   string
    Description            string
    UserInvocable          bool              // yaml:"user-invocable"
    DisableModelInvocation bool              // yaml:"disable-model-invocation"
    License                string            // yaml:"license"
    Compatibility          string            // yaml:"compatibility"
    Metadata               map[string]string // yaml:"metadata"
    AllowedTools           string            // yaml:"allowed-tools"
    Enabled                bool              // yaml:"enabled" (default: true)
    Instructions           string            // body after frontmatter
    Path                   string            // skill directory (runtime)
    SkillFilePath          string            // absolute path to SKILL.md (runtime)
    Scope                  Scope             // "user" or "project" (runtime)
    SourceRoot             string            // discovery source root (runtime)
    Priority               int               // from discovery source (runtime)
}

All fields match the agentskills.io specification for the skill format. Tau adds user-invocable, disable-model-invocation, and enabled as extensions.

Discovery

skills.Discover() walks configured source directories:

  • User sources: ~/.config/tau/skills/ - user-global skills.
  • Project sources: .tau/skills/ - project-local skills.
  • Default sources: Built-in skill directories.

Each directory is walked recursively. Files named SKILL.md or *.skill.md are parsed as skill files. Directories containing a SKILL.md are treated as single skills (the directory name becomes the skill name).

Discovery is triggered:

  • On startup by skills.Manager.
  • On /refresh (reloads all skills).
  • When the skills.Manager publishes skills.Event on the event bus.

Filtering

Skills can be filtered:

  • FilterDisabled() - Excludes skills with enabled: false.
  • FilterUserInvocable() - Excludes skills that cannot be invoked by the user.
  • HasErrors() - Checks for parsing errors in any skill's Diagnostics.

Prompt Rendering

Skills are rendered into the system prompt in two formats:

ToPromptIndex

go
func (s Skill) ToPromptIndex() string

Returns a compact index line: - **name**: description

This is used in the system prompt to list available skills without bloating the context window.

ToPromptXML

go
func (s Skill) ToPromptXML() string

Returns the full skill body wrapped in XML tags:

xml
<skill name="my-skill">
Body content...
</skill>

This is used when a skill is activated and its full instructions need to be injected into the prompt.

Skill Activation

When the agent determines a skill is relevant (based on the index), the skill's full body is injected into the prompt for that turn. The tracker.go module records which skills have been activated.

Manager

The skills.Manager provides runtime lifecycle:

go
type Manager struct {
    // ...
}

func NewManager(bus *eventbus.Bus, sources []Source) *Manager
func (m *Manager) Refresh() error
func (m *Manager) Skills() []Skill
func (m *Manager) ActiveSkills() []Skill
func (m *Manager) Close() error
  • Refresh() - Re-discover skills from all sources and publish skills.Event on the bus.
  • Skills() - Return all discovered skills.
  • ActiveSkills() - Return skills that have been activated in the current session.

The manager is a bus client named "skills" and publishes skills.Event when the catalog is refreshed. The TUI and Web UI can subscribe to this event to update their skill displays.

Tracker

internal/skills/tracker.go records skill activation:

  • When the agent activates a skill (injects its full body into the prompt), the tracker records the activation.
  • Activation records include the skill name, activation time, and turn number.
  • The tracker supports querying "what was activated this session" and "has this skill been used".

Event

go
type Event struct {
    Skills     []Skill
    Diagnostics []Diagnostic
    Timestamp  time.Time
}

Published on the event bus by the manager after each Refresh().

Configuration

Skill sources can be configured:

  • User skills directory: ~/.config/tau/skills/ (default).
  • Project skills directory: .tau/skills/ (project-local).
  • Custom sources can be added programmatically.

Skills can be disabled individually via enabled: false in frontmatter or filtered at the manager level.

Integration with Agent

The coordinator integrates skills into the prompt:

  1. On session start, the full skill index is appended to the system prompt (via ToPromptIndex()).
  2. During a turn, if the agent activates a skill, the full body is injected (via ToPromptXML()).
  3. The DiscoverContextFiles() function in internal/agent/prompt.go also discovers project-level context files like AGENTS.md.

Built with VitePress.