Documentation
¶
Overview ¶
Package skill is the consumer-facing vocabulary for agent skills.
A skill is a directory containing SKILL.md (plus optional reference files) that teaches an agent a repeatable workflow. This package provides constructors that produce Ref values accepted by adaptor.WithSkills:
adaptor.WithSkills(
skill.Dir("./skills/write-proof"), // local directory
skill.Key("code-review"), // provider-side catalogue key
skill.Inline("greet", "# Greeting\n..."), // literal SKILL.md content
skill.Archive("kit", skill.ArchiveFile("./kit.tgz")), // zip / tar / tar.gz bundle
)
Dir, FS, Inline, and Archive build self-contained skill definitions; Key references a skill resolved at run time by the host-installed Provider. Provider and Materializer are the two host extension points: a Provider translates catalogue keys into concrete skill definitions (and may inject tenant-mandatory required skills), while a Materializer controls how skill sources are written to disk before a driver consumes them.
This package also owns the host extension contracts, source values, default materializer, and skill-specific error identities used by errors.Is and errors.As.
Index ¶
- Constants
- Variables
- type ArchiveHTTPOption
- type ArchiveOption
- type ArchiveSource
- type Catalog
- type DefaultMaterializerOption
- type DirScanOption
- type FSSource
- type Format
- type InlineSource
- type Materializer
- type Opener
- type PathSource
- type Provider
- type Ref
- type Set
- type Skill
- type SkillKeyConflictError
- type SkillMaterializationError
- type Source
Constants ¶
const ( // MetadataRuntimeName is the metadata key for the provider-visible directory name. MetadataRuntimeName = driver.SkillMetadataRuntimeName // MetadataDisplayName is the metadata key for a human-readable skill name. MetadataDisplayName = driver.SkillMetadataDisplayName )
Reserved Metadata keys interpreted by the SDK and drivers. Setting MetadataRuntimeName on a Skill overrides the directory name the materializer writes and drivers mount. MetadataDisplayName provides a human-readable label for inspection and user interfaces.
const SkillCacheRootEnv = "AGENT_ADAPTOR_SKILL_CACHE_ROOT"
SkillCacheRootEnv names the AGENT_ADAPTOR_SKILL_CACHE_ROOT environment variable. It overrides the default materializer's cache root. Drivers use the same location to determine which materialized directories they may manage, so hosts should set it consistently for the whole process.
Variables ¶
var ( // ErrSkillKeyConflict identifies conflicting declarations of one skill key. ErrSkillKeyConflict = errors.New("agentadaptor: skill key defined with conflicting sources") // ErrSkillMaterializationFailed identifies a failure to stage a skill. ErrSkillMaterializationFailed = errors.New("agentadaptor: skill materialization failed") // ErrSkillSourceMissing identifies a skill declaration without a source. ErrSkillSourceMissing = errors.New("agentadaptor: skill source is required") // ErrSkillKeyMissing identifies a skill declaration without a key. ErrSkillKeyMissing = errors.New("agentadaptor: skill key is required") // ErrSkillNotFound identifies a catalogue key that a Provider cannot resolve. ErrSkillNotFound = errors.New("agentadaptor: skill not found in provider") )
Functions ¶
This section is empty.
Types ¶
type ArchiveHTTPOption ¶
type ArchiveHTTPOption func(*archiveHTTPConfig)
ArchiveHTTPOption configures the http.Request issued by ArchiveURL.
func WithArchiveHTTPClient ¶
func WithArchiveHTTPClient(client *http.Client) ArchiveHTTPOption
WithArchiveHTTPClient overrides the http.Client used by the ArchiveURL opener. Defaults to http.DefaultClient.
func WithArchiveHeader ¶
func WithArchiveHeader(key, value string) ArchiveHTTPOption
WithArchiveHeader adds a header to every request the ArchiveURL opener issues. Multiple WithArchiveHeader options accumulate.
type ArchiveOption ¶
type ArchiveOption func(*archiveConfig)
ArchiveOption configures the archive source built by Archive.
func WithFingerprint ¶
func WithFingerprint(fingerprint string) ArchiveOption
WithFingerprint supplies an opaque, stable source revision or identity. It is used to decide whether independently declared archive sources refer to the same logical revision and may also participate in Thread compatibility. It is not a cache key and is not an integrity check: the built-in materializer always keys its cache from the extracted content. Hosts that need authenticity or integrity verification must perform it in the Opener before returning the reader.
func WithFormat ¶
func WithFormat(f Format) ArchiveOption
WithFormat pins the archive format instead of relying on magic-byte sniffing. Explicit formats surface mismatches as decompression errors, which is preferable when the host already knows what it serves.
func WithSubpath ¶
func WithSubpath(subpath string) ArchiveOption
WithSubpath declares the prefix inside the archive where SKILL.md lives. Empty means the archive root. Entries that resolve outside the subpath are rejected during extraction.
type ArchiveSource ¶
type ArchiveSource struct {
// Archive opens the archive from its beginning for each materialization.
Archive Opener
// Format selects archive decoding; its zero value enables detection.
Format Format
// Subpath locates the skill root within the archive.
Subpath string
// Fingerprint is an optional stable source revision or identity.
Fingerprint string
}
ArchiveSource is the public archive-origin value stored in [Skill.Source]. Independently declared ArchiveSource values without a non-empty Fingerprint are intentionally not assumed equal because Go functions have no stable content identity.
func (ArchiveSource) SkillArchive ¶
func (s ArchiveSource) SkillArchive() (Opener, string, string, string)
SkillArchive returns the values consumed by a compatible materializer.
func (ArchiveSource) SkillSource ¶
func (ArchiveSource) SkillSource()
SkillSource implements Source.
type Catalog ¶
type Catalog interface {
Provider
// Catalogue returns the skills available from the provider.
Catalogue(ctx context.Context) ([]Skill, error)
}
Catalog extends Provider with deterministic catalogue enumeration.
type DefaultMaterializerOption ¶
type DefaultMaterializerOption func(*defaultMaterializerConfig)
DefaultMaterializerOption configures the materializer returned by NewDefaultSkillMaterializer.
func WithMaxArchiveEntries ¶
func WithMaxArchiveEntries(n int) DefaultMaterializerOption
WithMaxArchiveEntries caps the number of entries (files + dirs) in a single archive. Archives with more entries surface as an error before any file is written. Default 10000; values <= 0 are treated as the default.
func WithMaxArchiveSize ¶
func WithMaxArchiveSize(bytes int64) DefaultMaterializerOption
WithMaxArchiveSize caps the total compressed bytes the materializer reads from an Archive source. Streams that exceed the cap surface as an error before any extraction begins. Default 256 MiB; values <= 0 are treated as the default.
func WithMaxFileSize ¶
func WithMaxFileSize(bytes int64) DefaultMaterializerOption
WithMaxFileSize caps the uncompressed bytes a single archive entry may occupy. Decompression bombs surface as an error mid-extraction and the partially extracted temporary directory is removed. Default 64 MiB; values <= 0 are treated as the default.
func WithSkillCacheRoot ¶
func WithSkillCacheRoot(path string) DefaultMaterializerOption
WithSkillCacheRoot overrides the cache root the default materializer writes to. Empty input falls back to SkillCacheRootEnv, then os.UserCacheDir(), then os.TempDir().
type DirScanOption ¶
type DirScanOption func(*dirScanConfig)
DirScanOption configures LocalSkillsFromDir. Hosts that need non-default behaviour (custom key prefix, exact-name exclusions, custom SKILL.md filename) chain options into the call.
func WithDirIgnore ¶
func WithDirIgnore(names ...string) DirScanOption
WithDirIgnore declares directory names that the scan must skip. Useful for filtering generated or dependency directories such as "node_modules".
Multiple WithDirIgnore options accumulate; matching is exact (case-sensitive), not glob-style.
func WithDirSkillFile ¶
func WithDirSkillFile(name string) DirScanOption
WithDirSkillFile overrides the per-directory marker file name. Default "SKILL.md". Setting it to, for example, "AGENT.md" lets the scan identify directories that follow a different convention. This option only changes discovery; callers remain responsible for ensuring each returned directory has the files required by its eventual consumer.
func WithDirSkillKeyPrefix ¶
func WithDirSkillKeyPrefix(prefix string) DirScanOption
WithDirSkillKeyPrefix prepends prefix to every Skill.Key produced by the scan. A prefix of "team/" turns a directory named "code-review" into key "team/code-review". Prefixes that already end with "/" are honoured verbatim; other prefixes get a "/" separator appended.
Empty prefix is the default and produces bare directory names.
type FSSource ¶
type FSSource struct {
// FS contains the skill tree.
FS fs.FS
// Root locates the skill directory within FS. Empty and "." mean the FS root.
Root string
}
FSSource sources a skill from an io/fs.FS tree rooted at Root.
type Format ¶
type Format string
Format selects the decompressor applied to an Archive source. FormatAuto (the zero value) triggers magic-byte sniffing.
const ( // FormatAuto leaves format detection to the materializer's // magic-byte sniffing (zip local-file header, gzip magic, ustar // magic at offset 257). FormatAuto Format = "" // FormatZip is a ZIP archive (PKZIP format). FormatZip Format = "zip" // FormatTar is an uncompressed POSIX tar archive. FormatTar Format = "tar" // FormatTarGz is a tar archive wrapped in a gzip stream // (canonical .tar.gz / .tgz). FormatTarGz Format = "tar.gz" )
Supported archive formats accepted by the built-in materializer.
type InlineSource ¶
type InlineSource struct {
// SkillMD is the complete SKILL.md content.
SkillMD string
}
InlineSource carries a single SKILL.md document.
func (InlineSource) InlineSkillMD ¶
func (s InlineSource) InlineSkillMD() string
InlineSkillMD returns the SKILL.md content consumed by a compatible materializer.
type Materializer ¶
type Materializer interface {
// Materialize makes s available in a directory containing SKILL.md and
// returns that directory.
Materialize(ctx context.Context, s Skill) (sourcePath string, err error)
}
Materializer writes a skill source to a directory containing SKILL.md.
func NewDefaultSkillMaterializer ¶
func NewDefaultSkillMaterializer(opts ...DefaultMaterializerOption) Materializer
NewDefaultSkillMaterializer returns the SDK's built-in materializer, which handles the sources produced by Dir, FS, Inline, and Archive. Agents install it automatically; construct one explicitly only to tune the options above or to compose a chain-of-responsibility around it:
type storeMaterializer struct {
fallback skill.Materializer
store *MyStoreClient
}
func (m *storeMaterializer) Materialize(ctx context.Context, s skill.Skill) (string, error) {
if src, ok := s.Source.(myCustomSource); ok {
return m.store.Fetch(ctx, src)
}
return m.fallback.Materialize(ctx, s)
}
type Opener ¶
type Opener = func(ctx context.Context) (io.ReadCloser, error)
Opener produces a fresh reader over the archive bytes. It is invoked at materialization time and read to completion (subject to the configured size cap), so implementations MUST be idempotent: a second invocation should produce the same content. Build one with ArchiveBytes, ArchiveFile, or ArchiveURL, or supply your own.
func ArchiveBytes ¶
ArchiveBytes returns an Opener that serves the given data from memory. The slice is captured by reference; callers MUST NOT mutate it afterwards.
func ArchiveFile ¶
ArchiveFile returns an Opener that opens the given file each time the materializer needs to read it. Useful when the host has already downloaded the archive to disk.
func ArchiveURL ¶
func ArchiveURL(url string, opts ...ArchiveHTTPOption) Opener
ArchiveURL returns an Opener that GETs the URL with the configured headers and HTTP client. Non-2xx responses surface as errors. It performs no integrity checking, and WithFingerprint is only a declared source identity—it does not add integrity verification. The opener itself must verify authenticity when required. ArchiveURL imposes no default timeout: either supply an http.Client with a Timeout via WithArchiveHTTPClient or make sure the run context carries a deadline.
type PathSource ¶
type PathSource struct {
// Path is the skill directory.
Path string
}
PathSource sources a skill from a local directory containing SKILL.md.
func (PathSource) SkillPath ¶
func (s PathSource) SkillPath() string
SkillPath returns the directory consumed by a compatible materializer.
type Provider ¶
type Provider interface {
// GetSkills resolves the requested catalogue keys. Implementations may also
// include skills marked Required.
GetSkills(ctx context.Context, keys []string) (map[string]Skill, error)
}
Provider resolves catalogue keys into concrete skills for a run. Providers may additionally return Required skills that were not explicitly requested.
type Ref ¶
Ref is what adaptor.WithSkills accepts: either a provider catalogue key (built with Key) or a fully-defined Skill value (built with Dir, FS, Inline, or Archive).
func Key ¶
Key returns a Ref that references a provider-side skill by its catalogue key. The key is resolved by the Provider installed on the agent; unknown keys fail the run before the driver is invoked.
func SkillsAsRefs ¶
SkillsAsRefs converts a []Skill into a []Ref so hosts can pass a scanned skill set into variadic options:
adaptor.WithSkills(skill.SkillsAsRefs(skills)...)
The conversion preserves order and does not deep-clone nested values such as Metadata.
type Set ¶
Set is a static map-backed Catalog.
type Skill ¶
Skill is the full description of one skill: identity (Key), origin (Source), Required marker, human-readable Reason, and optional Metadata. Skill values act as Ref, so constructor results can be passed straight to adaptor.WithSkills.
func Archive ¶
func Archive(key string, open Opener, opts ...ArchiveOption) Skill
Archive builds a Skill sourced from an archive stream (zip, tar, or tar.gz). The archive must contain SKILL.md at its root, or under the prefix declared via WithSubpath. Key is required; open supplies the archive bytes and is typically built with ArchiveBytes, ArchiveFile, or ArchiveURL:
skill.Archive("deploy-kit", skill.ArchiveFile("./deploy-kit.tgz"))
skill.Archive("deploy-kit",
skill.ArchiveURL("https://store.example.com/kits/deploy.zip",
skill.WithArchiveHeader("Authorization", "Bearer "+token)),
skill.WithFingerprint(knownDigest),
)
Format defaults to FormatAuto (magic-byte sniffing); use WithFormat to pin it explicitly.
func Dir ¶
Dir builds a Skill sourced from a local directory that contains SKILL.md (and optional reference files). The skill key defaults to the directory basename; callers may override it by assigning to the returned Skill's Key field.
func FS ¶
FS builds a Skill sourced from an io/fs.FS tree rooted at root. The root entry must contain SKILL.md; "" or "." mean the FS root. The skill key defaults to the basename of root ("skill" when root is empty); callers may override it by assigning to the returned Skill's Key field.
func Inline ¶
Inline builds a Skill whose entire content is the given SKILL.md string. Key is required. Skills that need auxiliary reference files should use FS or Archive instead.
func LocalSkillsFromDir ¶
func LocalSkillsFromDir(root string, opts ...DirScanOption) ([]Skill, error)
LocalSkillsFromDir scans root and produces one Skill per subdirectory that contains the SKILL marker file (default "SKILL.md"). The scan is deterministic: subdirectories are processed in lexical order, so the returned slice is stable across runs on the same filesystem.
Each produced Skill has:
- Key: directory basename, optionally prefixed via WithDirSkillKeyPrefix
- Source: the same local-directory source Dir builds, pointing at the absolute path of the subdirectory
- Required / Reason / Metadata: zero values (the scan does NOT parse SKILL.md frontmatter; hosts that need that should post-process the slice)
Subdirectories without a SKILL marker file are silently skipped so the scan tolerates a mixed root (some skills, some plain directories). Hidden entries (starting with ".") are skipped by default; pass WithDirIgnore to skip additional names.
Error semantics:
- root doesn't exist or isn't a directory → error
- root is unreadable (permission) → error
- individual subdirectory unreadable → error (better to fail loudly than silently miss a skill the host expected)
The returned []Skill feeds the skill options via SkillsAsRefs:
skills, err := skill.LocalSkillsFromDir("/opt/skills")
if err != nil { return err }
agent := adaptor.New(drv,
adaptor.WithSkills(skill.SkillsAsRefs(skills)...),
)
type SkillKeyConflictError ¶
type SkillKeyConflictError struct {
// Key is the conflicting skill key.
Key string
// Sources describes the declarations that conflict.
Sources []string
// Detail contains optional diagnostic context.
Detail string
}
SkillKeyConflictError reports two structurally different declarations with the same skill key.
func (*SkillKeyConflictError) Error ¶
func (e *SkillKeyConflictError) Error() string
Error implements error.
func (*SkillKeyConflictError) Unwrap ¶
func (e *SkillKeyConflictError) Unwrap() error
Unwrap exposes ErrSkillKeyConflict for errors.Is.
type SkillMaterializationError ¶
type SkillMaterializationError struct {
// Key is the logical skill key.
Key string
// RuntimeName is the provider-visible directory name, when known.
RuntimeName string
// Cause is the underlying materialization failure.
Cause error
}
SkillMaterializationError reports a failure to stage a resolved skill into a provider-visible directory.
func (*SkillMaterializationError) Error ¶
func (e *SkillMaterializationError) Error() string
Error implements error.
func (*SkillMaterializationError) Is ¶
func (e *SkillMaterializationError) Is(target error) bool
Is also classifies the error as ErrSkillMaterializationFailed.
func (*SkillMaterializationError) Unwrap ¶
func (e *SkillMaterializationError) Unwrap() error
Unwrap preserves the underlying materializer cause.
type Source ¶
type Source = driver.SkillSource
Source is the open marker interface for a Skill's origin. Hosts may define custom Source types as long as a matching Materializer is installed to handle them.