Skip to content

Skills

A skill is a typed, single-shot AI function — an LLM call with structured input and output, no tool loop. Use it anywhere you'd call an AI like a service: extraction, classification, summarisation, translation.

When to use a skill vs an agent

skill()agent()
InputTyped structured object or stringFree-form string
Tool loopNo — one LLM callYes — iterates until done
OutputTyped structured resultText + optional structured
Use forDeterministic transformationsAutonomous reasoning

Functions

skill(config)

ts
function skill<TInput = unknown, TOutput = unknown>(
  config: SkillConfig<TInput>,
): SkillRunner<TInput, TOutput>

Create a skill runner. The runner is stateless — each invoke() call is independent.

ts
import { skill } from '@daedalus-ai-dev/ai-sdk';
import { z } from 'zod';

const classify = skill<{ text: string }, { label: string; confidence: number }>({
  instructions: 'Classify the sentiment of the provided text.',
  input: z.object({ text: z.string() }),
  output: z.object({
    label: z.enum(['positive', 'neutral', 'negative']),
    confidence: z.number().min(0).max(1),
  }),
});

const result = await classify.invoke({ text: 'I love this product!' });
console.log(result.structured.label);      // 'positive'
console.log(result.structured.confidence); // 0.94

registerSkill(name, config) / getSkill(name)

ts
function registerSkill<TInput = unknown>(name: string, config: SkillConfig<TInput>): void
function getSkill<TInput = unknown, TOutput = unknown>(name: string): SkillRunner<TInput, TOutput>

Register a skill globally and retrieve it by name from anywhere in your application.

ts
registerSkill('classify-sentiment', {
  instructions: 'Classify the sentiment of the provided text.',
  output: z.object({ label: z.enum(['positive', 'neutral', 'negative']) }),
});

// Later, anywhere in your app:
const runner = getSkill<string, { label: string }>('classify-sentiment');
const result = await runner.invoke('This is great!');

hasSkill(name) / listSkills() / clearSkills()

ts
function hasSkill(name: string): boolean
function listSkills(): string[]
function clearSkills(): void

Standard registry utilities. clearSkills() is useful in tests to reset state between cases.


parseSkill(content) / loadSkill(filePath) / loadSkillsFrom(dir)

ts
function parseSkill(content: string): SkillRunner
async function loadSkill(filePath: string): Promise<SkillRunner>
async function loadSkillsFrom(dir: string): Promise<void>

Load skills from markdown files. loadSkillsFrom registers all skills found in a directory.

See Markdown Skills below.


SkillConfig

ts
interface SkillConfig<TInput = unknown> {
  instructions: string;
  input?: SchemaInput;
  output?: SchemaInput;
  model?: string;
  temperature?: number;
  maxTokens?: number;
  template?: (input: TInput) => string;
}
FieldDescription
instructionsSystem prompt for the skill.
inputInput schema. If Zod, input is validated before calling the LLM.
outputOutput schema for structured responses. Accepts Zod, fluent builder, or raw JSON Schema.
modelModel identifier. Falls back to the global default set by configure().
temperatureSampling temperature.
maxTokensMax output tokens.
templateCustom function to render the input into a prompt string. Defaults to JSON.stringify for objects, or the value itself for strings.

SkillResult

ts
interface SkillResult<TOutput = unknown> {
  text: string;
  structured: TOutput;
  usage: { inputTokens: number; outputTokens: number };
}

Input handling

How the input is rendered into a prompt:

Input typeNo templateWith template
stringPassed directlytemplate(input)
objectJSON.stringify(input, null, 2)template(input)

Use template when you want narrative framing rather than raw JSON:

ts
const summarize = skill<{ title: string; body: string }>({
  instructions: 'Summarize the article in three sentences.',
  template: ({ title, body }) => `Title: ${title}\n\n${body}`,
});

Markdown format

markdown
---
name: extract-entities
model: anthropic/claude-3-5-sonnet
input:
  text: string!
output:
  people: string[]
  places: string[]
  organisations: string[]
---
Extract all named entities from the provided text.
Group them by type: people, places, and organisations.
FieldRequiredDescription
nameYesRegistry key used by getSkill().
modelNoModel override. Falls back to global default.
inputNoInput schema in YAML shorthand or object form.
outputNoOutput schema in YAML shorthand or object form.
temperatureNoSampling temperature.
maxTokensNoMax output tokens.
BodyYesThe system instructions.
ts
await loadSkillsFrom('./skills');

const runner = getSkill('extract-entities');
const result = await runner.invoke({ text: 'Tim Cook visited Berlin last Tuesday.' });

YAML schema shorthand

See yamlSchemaToJsonSchema for the full shorthand reference (string!, string[], etc.).

Released under the MIT License.