/** * SkillRegistry — centralized governance for Skills across one or * more Agents. * * Most apps register Skills directly on the Agent via `.skill(s)`. * Once you have multiple Agents that share a common skill catalog * (a customer-support pool, a research team, a multi-step workflow * where each step uses different overlapping skills), hand-syncing * `.skill()` calls per Agent gets fragile. * * `SkillRegistry` is the answer: register once, attach to many * Agents via `.skills(registry)`. Add a Skill to the registry and * every consumer Agent picks it up at next build. * * @example * const registry = new SkillRegistry(); * registry.register(billingSkill); * registry.register(refundSkill); * * const supportAgent = Agent.create({ provider }).skills(registry).build(); * const escalationAgent = Agent.create({ provider }).skills(registry).build(); * * // Add a new skill — both agents pick it up at next build. * registry.register(complianceSkill); */ import type { Injection } from './types.js'; import { type SkillToolPair } from './skillTools.js'; import { type SurfaceMode } from './factories/defineSkill.js'; /** * Options for `new SkillRegistry({...})`. All fields are optional; * the empty-object form (`new SkillRegistry()`) is the v2.4 surface. * * @see SkillRegistry.resolveForSkill — applies the cascade */ export interface SkillRegistryOptions { /** * Registry-level default `surfaceMode`. Applies to skills whose own * `surfaceMode` is `'auto'` (the `defineSkill` default). Per-skill * `surfaceMode` always wins; this is the fallback BEFORE the global * `resolveSurfaceMode(provider, model)` rule. * * Use case: a registry shared across agents pointed at the same * provider can lock surfaceMode here once instead of repeating it * on every `defineSkill`. */ readonly surfaceMode?: SurfaceMode; /** * Provider name used as a hint when resolving `surfaceMode: 'auto'` * inside this registry. Most consumers don't set this — runtime code * passes the provider name into `resolveForSkill(skill, provider, model)` * directly. This field is for cases where the registry is composed * far from the agent (test fixtures, design-time inspectors). * * Match the provider's `name` field — `'anthropic'`, `'openai'`, * `'mock'`, etc. */ readonly providerHint?: string; } export declare class SkillRegistry { private readonly skills; private readonly opts; /** * Construct an empty registry. Optional `{ surfaceMode, providerHint }` * fields set registry-level defaults; absent both, the registry is a * pure container (the v2.4 surface). */ constructor(opts?: SkillRegistryOptions); /** Registry-level default `surfaceMode`, or `undefined` if unset. */ get surfaceMode(): SurfaceMode | undefined; /** Registry-level provider hint, or `undefined` if unset. */ get providerHint(): string | undefined; /** * Register a skill. Throws if `skill.flavor !== 'skill'` or if a * skill with the same id is already registered (use `.replace(...)` * to overwrite intentionally). */ register(skill: Injection): this; /** Replace an existing skill by id. Throws if id is not registered. */ replace(id: string, skill: Injection): this; /** Remove a skill by id. No-op if not registered. */ unregister(id: string): this; /** Look up by id. Returns undefined if not registered. */ get(id: string): Injection | undefined; /** True iff a skill with the given id is registered. */ has(id: string): boolean; /** All registered skills. Order matches registration order. */ list(): readonly Injection[]; /** Number of registered skills. */ get size(): number; /** Drop all registrations. */ clear(): void; /** * Materialize the LLM-facing skill discovery tools from the current * registry contents. Returns `{ listSkills, readSkill }`: * * - `list_skills` — no-arg tool the LLM calls to enumerate * `{ id, description }` for every registered skill. Lets the * LLM discover skills without paying the prompt-token cost of * a static catalog in the system prompt. * * - `read_skill({ id })` — activates the named skill for the * NEXT iteration. The Agent's tool-calls subflow inspects this * tool call by name and updates `scope.activatedInjectionIds` * so the InjectionEngine on iter N+1 includes the skill in the * active set (body lands in the system slot; gated tools land * in the tools slot). * * Both entries are `undefined` when the registry is empty — filter * before adding to a tool list: * * const { listSkills, readSkill } = registry.toTools(); * const tools = [listSkills, readSkill, ...other].filter(Boolean) as Tool[]; * * Composes with `gatedTools` from `agentfootprint/tool-providers` * so PermissionPolicy can scope which roles see the skill discovery * surface. * * @returns A `SkillToolPair` (`{ listSkills, readSkill }`). */ toTools(): SkillToolPair; /** * Resolve the effective `surfaceMode` for a skill, applying the * cascade: * * 1. If the skill's own `metadata.surfaceMode` is concrete * (`'system-prompt'` / `'tool-only'` / `'both'`), return it. * Per-skill explicit choice always wins. * 2. Else if the registry was constructed with a concrete * `surfaceMode`, return that. * 3. Else delegate to `resolveSurfaceMode(provider, model)` using * the explicit `provider` arg (or `this.providerHint` if * omitted). Falls back to `'tool-only'` when no provider is * known. * * Forward-compat for Block C / v2.5 per-mode runtime routing: the * runtime calls this with the agent's provider + model to decide * how to materialize the skill's body into slots. * * Throws if the skill is not registered (catches typos at the * caller site rather than silently resolving against a stranger). * * @param skillOrId A registered Skill `Injection` OR its `id`. * @param provider Provider name override (wins over `providerHint`). * @param model Model name for the per-provider attention rule. */ resolveForSkill(skillOrId: Injection | string, provider?: string, model?: string): Exclude; } //# sourceMappingURL=SkillRegistry.d.ts.map