Skip to content

@agentforge/skills

The skills package provides SKILL.md-driven capability loading for agents. Skills are discovered from configurable directories and activated at runtime through tool calls.

Installation

bash
pnpm add @agentforge/core @agentforge/skills

@agentforge/core is a peer dependency of @agentforge/skills and must be installed alongside it.

TIP

For a step-by-step tutorial, see Building a Skill-Powered Agent. For usage patterns, see Agent Skills Examples.

SkillRegistry

Central registry that discovers, indexes, and provides access to SKILL.md-based skills.

typescript
import { SkillRegistry } from '@agentforge/skills';

const registry = new SkillRegistry({
  skillRoots: [
    { path: './.agentskills', trust: 'workspace' },
  ],
  enabled: true,
});

Constructor Options — SkillRegistryConfig

PropertyTypeDefaultDescription
skillRootsArray<string | SkillRootConfig>requiredDirectories to scan for skills
enabledbooleanfalseGates generatePrompt() output
maxDiscoveredSkillsnumberundefinedCap on skills included in prompt
allowUntrustedScriptsbooleanfalseAllow script access from untrusted roots

SkillRootConfig

PropertyTypeDescription
pathstringDirectory path to scan
trustTrustLevel'workspace' | 'trusted' | 'untrusted'

Plain string roots default to { path: value, trust: 'untrusted' }.

Query Methods

MethodReturnsDescription
get(name)Skill | undefinedGet a skill by name
getAll()Skill[]Get all discovered skills
has(name)booleanCheck if a skill exists
size()numberNumber of discovered skills
getNames()string[]Array of all skill names
getScanErrors()ReadonlyArray<{ path: string; error: string }>Errors from last scan
getAllowedTools(name)string[] | undefinedGet allowed-tools list for a skill
getAllowUntrustedScripts()booleanWhether untrusted script override is set

generatePrompt(options?)

Generates an <available_skills> XML block for the LLM system prompt.

typescript
// All skills
const prompt = registry.generatePrompt();

// Filtered subset
const prompt = registry.generatePrompt({ skills: ['code-review'] });

SkillPromptOptions:

PropertyTypeDescription
skillsstring[]Optional subset of skill names to include

Returns an empty string when enabled is false or no skills match.

toActivationTools()

Returns a tuple of two tools pre-wired to the registry instance:

typescript
const [activateSkill, readSkillResource] = registry.toActivationTools();
ToolSchemaDescription
activate-skill{ name: string }Loads the full SKILL.md body content for a skill
read-skill-resource{ name: string, path: string }Reads a resource file from a skill directory

Both tools are in the ToolCategory.SKILLS category.

discover()

Re-scans all configured roots and rebuilds the registry. Called automatically during construction.

typescript
registry.discover(); // Rescan after installing new skills

Event Methods

MethodSignatureDescription
on(event, handler)(SkillRegistryEvent, (data: unknown) => void) => voidSubscribe to event
off(event, handler)(SkillRegistryEvent, (data: unknown) => void) => voidUnsubscribe
emitEvent(event, data)(SkillRegistryEvent, unknown) => voidEmit an event (used by activation tools)

SkillRegistryEvent

Enum of events emitted by the registry and activation tools.

EventString ValuePayload Shape
SKILL_DISCOVERED'skill:discovered'Skill object
SKILL_WARNING'skill:warning'{ skillPath, rootPath, error, duplicateOf? }
SKILL_ACTIVATED'skill:activated'{ name, skillPath, bodyLength }
SKILL_RESOURCE_LOADED'skill:resource-loaded'{ name, resourcePath, resolvedPath, contentLength }
TRUST_POLICY_DENIED'trust:policy-denied'{ name, resourcePath, trustLevel, reason, message }
TRUST_POLICY_ALLOWED'trust:policy-allowed'{ name, resourcePath, trustLevel, reason }

TrustLevel

typescript
type TrustLevel = 'workspace' | 'trusted' | 'untrusted';
LevelReference FilesScript FilesUse Case
workspaceYesYesFirst-party project skills
trustedYesYesVetted community/team skills
untrustedYesNoUnknown or unreviewed sources

TrustPolicyReason

Enum returned in trust policy decisions for audit logging.

ReasonWhen
NOT_SCRIPTResource is not in scripts/ — always allowed
WORKSPACE_TRUSTRoot has workspace trust — scripts allowed
TRUSTED_ROOTRoot has trusted trust — scripts allowed
UNTRUSTED_SCRIPT_DENIEDUntrusted root, no override — scripts blocked
UNTRUSTED_SCRIPT_ALLOWEDUntrusted root but allowUntrustedScripts: true
UNKNOWN_TRUST_LEVELUnknown trust level — treated as denied

Skill Type

typescript
interface Skill {
  metadata: SkillMetadata;
  skillPath: string;      // Absolute path to skill directory
  rootPath: string;       // Which configured root this was discovered from
  trustLevel: TrustLevel;
}

SkillMetadata

typescript
interface SkillMetadata {
  name: string;                       // 1-64 chars, kebab-case, matches directory name
  description: string;                // 1-1024 chars
  license?: string;                   // SPDX identifier
  compatibility?: string[];           // Compatible frameworks
  metadata?: Record<string, unknown>; // Arbitrary key-value pairs
  allowedTools?: string[];            // Tools the skill is designed to use
}

Utility Functions

FunctionSignatureDescription
createActivateSkillTool(registry)(SkillRegistry) => ToolCreate standalone activate-skill tool
createReadSkillResourceTool(registry)(SkillRegistry) => ToolCreate standalone read-skill-resource tool
createSkillActivationTools(registry)(SkillRegistry) => [Tool, Tool]Create both tools as a tuple
resolveResourcePath(skillDir, resourcePath)(string, string) => { success: true; resolvedPath: string } | { success: false; error: string }Deprecated. Compatibility-only resource path validation; planned for removal in the next major release
evaluateTrustPolicy(resourcePath, trustLevel, allowUntrustedScripts?)(...) => TrustPolicyDecisionEvaluate whether a resource access is allowed
isScriptResource(resourcePath)(string) => booleanCheck if path targets scripts/ directory
normalizeRootConfig(root)(string | SkillRootConfig) => SkillRootConfigNormalize string to root config
parseSkillContent(content, dirName)(string, string) => SkillParseResultParse SKILL.md content and validate
validateSkillName(name)(string) => SkillValidationError[]Validate skill name format
scanSkillRoot(rootPath)(string) => SkillCandidate[]Scan a directory for skill candidates
scanAllSkillRoots(roots)(string[]) => SkillCandidate[]Scan multiple root directories

Deprecated resource-path helper

resolveResourcePath remains exported during the compatibility window, but Agent Skill access should use the read-skill-resource Tool returned by SkillRegistry.toActivationTools(). The standalone helper is planned for removal in the next major release.

Type Definitions

All exports include full TypeScript definitions. See the source code for complete type information.

Released under the MIT License.