Skills
Load reusable instruction packages through storage-neutral skill providers.
Skills are reusable instruction packages that an agent can load on demand. They are useful when a workflow needs durable instructions, examples, or reference material, but those details should not be placed in every agent prompt.
PAI models skills as normal backend tools with hidden outputs:
- discovery metadata is rendered into the agent instructions;
loadSkillloads the full skill instructions;readSkillReferenceloads package-relative supporting files;- the chat renderer can omit those tool calls while the runtime still persists them for replay and debugging.
Basic Setup
For demos, tests, or embedded skill lists, use @pai/skills-inmemory.
import { defineAgent } from "@pai/core";
import {
createInMemorySkills,
type SkillPackage,
} from "@pai/skills-inmemory";
import { z } from "zod";
const apiReviewSkill = {
name: "api-review",
description:
"Review public TypeScript APIs for consumer ergonomics. Use when assessing a proposed SDK or component API.",
instructions: `# API Review
1. Identify what the consumer knows at the call site.
2. Separate the common path from escape hatches.
3. Read references/rubric.md before the final recommendation.`,
references: [
{
path: "references/rubric.md",
description: "API review checklist.",
content: "- Look for casts, duplicated ids, unclear sequencing, and hidden state.",
},
],
} satisfies SkillPackage;
const skills = createInMemorySkills({
skills: [apiReviewSkill],
});
export const agent = defineAgent({
name: "api-reviewer",
identity: z.object({ id: z.string(), workspaceId: z.string() }),
model: ({ runtimeContext }) => runtimeContext.models.primary,
instructions: async (input) =>
[
"Review APIs with a focus on consumer-facing behavior.",
await skills.renderInstructions({ signal: input.signal }),
].join("\n\n"),
tools: skills.tools,
});The consumer imports only from @pai/skills-inmemory for this path. That
package re-exports the core skills API for advanced composition.
Package Shape
SkillPackage is the in-memory provider representation of a skill package. It
maps to SKILL.md concepts, but it is not the raw filesystem format.
type SkillPackage = {
id?: string;
name: string;
description: string;
version?: string;
instructions: string;
references?: readonly SkillPackageReference[];
contentHash?: string;
sourceType?: string;
};
type SkillPackageReference = {
path: string;
description?: string;
content: string;
contentHash?: string;
mediaType?: string;
};name and description match Agent Skills SKILL.md frontmatter. They are
the discovery fields the model sees before a skill is loaded.
instructions is the Markdown body of SKILL.md.
references represents package-relative files such as
references/rubric.md. In a filesystem provider those files would be read from
disk. In the in-memory provider, each reference includes content.
id, version, and contentHash are PAI runtime metadata for stable tool
calls, replay, audit, and cache/debug behavior. They are not required
frontmatter fields in the Agent Skills format.
sourceType is optional display/debug metadata, useful in demos when comparing
filesystem, registry, or embedded sources.
Agent Tools
createInMemorySkills() returns a SkillIntegration:
type SkillIntegration = {
tools: {
loadSkill: ToolDefinition;
readSkillReference: ToolDefinition;
};
/** The literal names the two tools are registered under. */
toolNames: { loadSkill: "loadSkill"; readSkillReference: "readSkillReference" };
renderInstructions(input?: { signal?: AbortSignal }): Promise<string>;
isSkillToolName(
toolName: string,
): toolName is "loadSkill" | "readSkillReference";
};loadSkill({ skillId }) returns the loaded instructions, reference metadata,
version/hash metadata, and visibility: "hidden".
readSkillReference({ skillId, path }) returns one package-relative reference
file and visibility: "hidden".
There is no model-facing listSkills tool. Discovery happens through
renderInstructions(), which renders compact metadata into the agent prompt.
The model can then choose to call loadSkill, and can call
readSkillReference after it knows a needed reference path.
Providers
@pai/skills owns the storage-neutral contracts and generated tool behavior.
Provider packages own storage-specific loading.
Current provider:
@pai/skills-inmemory: virtual packages for demos, tests, and embedded registries.
Expected future providers:
@pai/skills-fs: readSKILL.mddirectories from a filesystem root.- hosted or registry providers: resolve immutable skill versions from database records, object storage, or package archives.
Provider packages should expose a shorthand helper for the common path and a source helper for advanced composition:
createInMemorySkills({ skills });
createInMemorySkillSource({ skills });The agent integration should still receive a single SkillSource. A composite
source can merge filesystem, registry, and embedded providers later without
changing how the agent consumes skills.
Visibility
Skill tool calls are execution context, not user-facing chat content. A product can keep them out of the visible transcript while still preserving them in the runtime transcript for replay and debugging.
If a UI wants to show that skills were used, render a redacted activity view such as "Loaded api-review" or "Read references/rubric.md" instead of showing raw skill instructions.
When To Use Skills
Use skills for reusable procedures, style guides, domain workflows, or task-specific playbooks that the model should load only when relevant.
Use a RAG or search tool when the model needs to retrieve arbitrary knowledge from a large corpus. Skills are curated instruction packages; RAG tools are retrieval mechanisms.