Skip to content

スキルシステム

源码版本v0.73.1

skills.ts は Agent Skills 仕様(https://agentskills.io/integrate-skills 参照)を実装する。スキルは markdown ファイルで、frontmatter がスキルの用途を記述する。LLM はシステムプロンプト内のスキルリストを見て、read ツールで対応する SKILL.md を読んで詳細な指示を取る。このファイルはスキルの発見、ロード、検証、重複除去、プロンプトセクションへのフォーマットを担う。

責務

  1. 発見規則:loadSkillsFromDirInternal はディレクトリを再帰的に走査する——SKILL.md に出会ったらスキルのルートとみなし再帰しない。さもなくば子ディレクトリとルートの .md ファイルを走査する。packages/coding-agent/src/core/skills.ts:173-280 参照。
  2. frontmatter 検証:validateName は名前を検査する(a-z0-9-、64 文字以内、ハイフンで始め/終わらない、-- なし、親ディレクトリ名と一致)。validateDescription は描述が必須かつ 1024 文字以内かを検査する。packages/coding-agent/src/core/skills.ts:93-117packages/coding-agent/src/core/skills.ts:122-132 参照。
  3. 多来源ロード:loadSkills はユーザグローバル(~/.pi/agent/skills)、プロジェクト(./.pi/skills)、明示的 skillPaths の三来源からロードする。衝突時は先に登録されたものを残し collision 診断を生成する。packages/coding-agent/src/core/skills.ts:405-504 参照。
  4. 重複除去:realpath でシンボリックリンクを解決し、同一ファイルを別パスで登録しても一回だけカウントする。同名スキルは先着順。packages/coding-agent/src/core/skills.ts:416-445 参照。
  5. プロンプトフォーマット:formatSkillsForPrompt<available_skills> XML セクションを生成する。各スキルは <name>/<description>/<location> の三組で表現し、disableModelInvocation: true のスキルはプロンプトに入れない(!/skill:name で明示的呼び出しのみ)。packages/coding-agent/src/core/skills.ts:340-366 参照。
  6. ignore 規則:.gitignore / .ignore / .fdignore を尊重し、再帰走査時にディレクトリプレフィックスをパスパターンに追加する。packages/coding-agent/src/core/skills.ts:48-66packages/coding-agent/src/core/skills.ts:25-46 参照。

設計動機

なぜ SKILL.md なのか。すべての .md を直接走査するのではなく?一つのスキルが複数ファイル(スクリプト、サブドキュメント)を含み得るからだ。SKILL.md は入口のしるしで、これに出会ったら再帰を止め、ディレクトリ全体をスキルパッケージとみなす。これでスキル作者は複数ファイルを一つのスキルとしてまとめられるし、複数の独立スキルとして誤って分割されることもない。

なぜ frontmatter なのか。コメントではなく?frontmatter は YAML で、構造化され、解析でき、検証できる。名称、描述、disable-model-invocation といったフィールドは LLM とプログラムの両方が読める必要がある。validateName は名前と親ディレクトリ名の一致を強制し(name "x" does not match parent directory "y")、スキルファイルを移動した後の名前の drift を防ぐ。

なぜ disableModelInvocation が必要なのか。ユーザ自身で使うプロンプトテンプレートのようなスキルは LLM に自動発火してほしくない(「コードを書くときはこのスタイルで」など)場合があり、ユーザが明示的に /skill:name したときだけロードされるべきだ。formatSkillsForPrompt はこうしたスキルをフィルタし、プロンプトには LLM が自動呼び出しを許可されたものだけを晒す。

なぜ realpath で重複除去するのか。ユーザが --skills ./my-skills を指定しつつ ./my-skills~/.pi/agent/skills/my-skills にシンボリックリンクで張ることがある。二回の走査で同一ファイルの異なるパスが取れる。canonicalizePath がシンボリックリンクを解決してから比較し、同一スキルの重複ロードを防ぐ。

主要ファイル

formatSkillsForPrompt は XML タグでスキルリストを包み、XML 特殊文字をエスケープする:

typescript
// packages/coding-agent/src/core/skills.ts:340-366
export function formatSkillsForPrompt(skills: Skill[]): string {
	const visibleSkills = skills.filter((s) => !s.disableModelInvocation);

	if (visibleSkills.length === 0) {
		return "";
	}

	const lines = [
		"\n\nThe following skills provide specialized instructions for specific tasks.",
		"Use the read tool to load a skill's file when the task matches its description.",
		"When a skill file references a relative path, resolve it against the skill directory (parent of SKILL.md / dirname of the path) and use that absolute path in tool commands.",
		"",
		"<available_skills>",
	];

	for (const skill of visibleSkills) {
		lines.push("  <skill>");
		lines.push(`    <name>${escapeXml(skill.name)}</name>`);
		lines.push(`    <description>${escapeXml(skill.description)}</description>`);
		lines.push(`    <location>${escapeXml(skill.filePath)}</location>`);
		lines.push("  </skill>");
	}
	lines.push("</available_skills>");
	return lines.join("\n");
}

loadSkillsFromDirInternalSKILL.md に出会ったら即座に return し、再帰しない:

typescript
// packages/coding-agent/src/core/skills.ts:199-226
for (const entry of entries) {
	if (entry.name !== "SKILL.md") {
		continue;
	}
	const fullPath = join(dir, entry.name);
	let isFile = entry.isFile();
	if (entry.isSymbolicLink()) {
		try {
			isFile = statSync(fullPath).isFile();
		} catch {
			continue;
		}
	}
	const relPath = toPosixPath(relative(root, fullPath));
	if (!isFile || ig.ignores(relPath)) {
		continue;
	}
	const result = loadSkillFromFile(fullPath, source);
	if (result.skill) {
		skills.push(result.skill);
	}
	diagnostics.push(...result.diagnostics);
	return { skills, diagnostics };
}

データフロー

スキルがディスクからプロンプトに至るまで:

境界と失敗

まとめ

skills.ts は Agent Skills 仕様を実装し、三来源ロード(ユーザグローバル、プロジェクト、明示的パス)、frontmatter 検証、realpath 重複除去、XML フォーマットでプロンプトに注入する。スキルはシステムプロンプトから参照された後 read ツールで読まれる。システムプロンプト構築ツール集合 read/bash/edit/write/grep/find/ls 参照。スキルパスを装配する入口は CLI 入口とディスパッチ 参照。