Skills Loader Example

Map local skill modules to typed tools and execute them through the call loop.

Complete Example

TypeScript
import { TheRouter.ai } from "@therouter/sdk";

interface Skill {
  name: string;
  description: string;
  schema: Record<string, unknown>;
  run: (args: Record<string, unknown>) => Promise<unknown>;
}

const registry: Skill[] = [
  {
    name: "summarize_markdown",
    description: "Summarize markdown content",
    schema: {
      type: "object",
      properties: { markdown: { type: "string" } },
      required: ["markdown"],
    },
    run: async ({ markdown }) => String(markdown).slice(0, 120),
  },
];

const tools = registry.map((skill) => ({
  type: "function",
  function: {
    name: skill.name,
    description: skill.description,
    parameters: skill.schema,
  },
}));

const client = new TheRouter.ai({ apiKey: process.env.THEROUTER_API_KEY! });

const first = await client.callModel({
  model: "anthropic/claude-sonnet-4.5",
  input: [{ role: "user", content: "Summarize this markdown and highlight risks." }],
  tools,
});

for (const item of first.items) {
  if (item.type !== "tool_call") continue;
  const skill = registry.find((entry) => entry.name === item.name);
  if (!skill) continue;
  const output = await skill.run(item.arguments as Record<string, unknown>);
  await client.callModel({
    ...first.next_turn,
    input: [{ type: "tool_result", call_id: item.call_id, output }],
  });
}

Skill Metadata

NameTypeRequiredDescription
name
stringRequiredUnique skill key used as tool name.
description
stringRequiredNatural language description for model planning.
schema
JSON SchemaRequiredInput parameter schema.
run
functionRequiredSkill runtime implementation.

Expected Output

skills-loader-output.json
{
  "skill": "summarize_markdown",
  "status": "executed",
  "output_preview": "Top risks: rollout timing, migration sequencing..."
}
Skill registry hygiene
Version skills explicitly and keep schemas backward compatible to avoid breaking long-running automations.