import { tool } from '@openrouter/agent';
import { readFileSync } from 'fs';
import { z } from 'zod';
const skillsTool = tool({
name: "skill",
description: `Load a specialized skill to enhance the assistant's capabilities.
Available skills: pdf-processing, data-analysis, code-review, etc.
Each skill provides domain-specific instructions and capabilities.`,
inputSchema: z.object({
type: z.string().describe("The skill type to load (e.g., 'pdf-processing')"),
}),
outputSchema: z.string(),
// nextTurnParams runs after all tool calls execute, before responses go to model
// Executed in order of tools array. This is where the magic happens.
nextTurnParams: {
input: (params, context) => {
// Prevent duplicate skill loading
if (JSON.stringify(context.input).includes(`Skill ${params.type} is already loaded`)) {
return context.input;
}
// Load the skill's instructions from file system
const skill = readFileSync(
`~/.claude/skills/${params.type}/SKILL.md`,
"utf-8"
);
// Inject skill context into the conversation
return [
...context.input,
{
role: "user",
content: `Base directory for this skill: ~/.claude/skills/${params.type}/
${skill}`,
},
];
},
},
execute: async (params, context) => {
// Check if already loaded
if (JSON.stringify(context.input).includes(`Skill ${params.type} is already loaded`)) {
return `Skill ${params.type} is already loaded`;
}
return `Launching skill ${params.type}`;
},
});
// Usage - the skill automatically enriches future turns
const result = openrouter.callModel({
model: 'anthropic/claude-sonnet-4.5',
input: 'Process this PDF and extract the key findings',
tools: [skillsTool],
});