스킬 소스
인라인 스킬은 데모에는 적합하지만 실제 스킬은 저장소의 폴더, 빌드 타임에 포함한 번들 또는 데이터베이스의 행에 있습니다. SkillSource를 통해 withSkills가 이를 읽습니다. 이 페이지에서는 세 가지 기본 제공 소스와 결합 방법을 설명합니다.
모든 소스는 바이트만 다루므로 동일한 미들웨어가 edge, Worker 또는 서버에서 작동합니다. 스킬이 저장된 위치에 맞는 소스를 선택하세요.
폴더에서
skillDirectory는 폴더에서 SKILL.md 파일을 탐색합니다. 파일 시스템을 읽으므로 /node entry point 아래에 있으며 edge가 아닌 서버에서 사용하세요.
import { chat, toServerSentEventsResponse } from '@tanstack/ai'
import { anthropicText } from '@tanstack/ai-anthropic'
import { withSkills } from '@tanstack/ai-skills'
import { skillDirectory } from '@tanstack/ai-skills/node'
export async function POST(request: Request) {
const { messages } = await request.json()
const stream = chat({
adapter: anthropicText('claude-sonnet-4-5'),
messages,
middleware: [withSkills(skillDirectory('./skills'))],
})
return toServerSentEventsResponse(stream)
}
스킬 폴더는 SKILL.md를 포함하는 모든 디렉터리입니다. references/와 assets/ 아래의 번들 파일은 스킬의 리소스가 되고, scripts/ 아래의 파일도 나열됩니다(이 릴리스에서는 목록만 만들고 실행하지 않습니다).
기본적으로 skillDirectory는 strict합니다. 잘못된 SKILL.md는 오류이므로 손상된 파일이 조용히 카탈로그에 들어가지 않습니다. 잘못된 파일을 건너뛰고 나머지를 로드하려면 { strict: false }를 전달하세요.
빌드 타임 번들에서(edge 안전)
edge에 배포하면 요청 시 파일 시스템을 읽을 수 없습니다. Vite plugin이 빌드 타임에 스킬을 glob하여 번들에 포함하므로 staticSkills는 런타임에 파일 시스템이 필요하지 않습니다.
Vite 설정에 플러그인을 추가합니다:
import { defineConfig } from 'vite'
import { skillsCatalogPlugin } from '@tanstack/ai-skills/node'
export default defineConfig({
plugins: [skillsCatalogPlugin({ dir: 'skills' })],
})
그런 다음 생성된 카탈로그를 감쌉니다.
import { chat, toServerSentEventsResponse } from '@tanstack/ai'
import { anthropicText } from '@tanstack/ai-anthropic'
import { withSkills } from '@tanstack/ai-skills'
import { staticSkills } from '@tanstack/ai-skills/static'
import { catalog } from 'virtual:tanstack-skills'
const skills = staticSkills(catalog)
export async function POST(request: Request) {
const { messages } = await request.json()
const stream = chat({
adapter: anthropicText('claude-sonnet-4-5'),
messages,
middleware: [withSkills(skills)],
})
return toServerSentEventsResponse(stream)
}
카탈로그가 빌드 타임에 포함되므로 skills.names는 스킬 이름의 typed list이고 load_skill 도구의 name은 이 목록으로 제한됩니다.
자체 저장소에서
DB, S3 또는 registry 기반 스킬은 직접 SkillSource를 정의합니다. 스킬을 나열하고 이름으로 하나를 로드하는 작은 interface입니다. 자세한 설명은
스킬 소스 작성에서 전체 안내와 어댑터 동작을 검증하는 conformance suite를 확인하세요.
소스 결합
실제 설정에서는 조직 전체, 프로젝트별, tenant별로 스킬을 계층화합니다. combinator로 결합한 뒤 결과를 withSkills에 전달합니다.
import { aggregate, dedupe } from '@tanstack/ai-skills'
// Org skills plus this tenant's skills, org first on a name clash.
const source = dedupe(aggregate([orgSkills, tenantSkills]))
| Combinator | 동작 |
|---|---|
aggregate([a, b]) | 순서대로 소스를 연결합니다. 중복 제거하지 않습니다. |
dedupe(source) | 이름의 첫 번째 발생이 우선하며 충돌 시 경고합니다. |
filter(source, fn) | predicate가 거부하는 스킬을 숨깁니다. 숨겨진 스킬은 카탈로그에 도달하지 않습니다. |
cache(source) | list()와 load()를 메모이즈합니다. 동시 호출에서 하나의 fetch를 공유합니다. |
배열을 withSkills([a, b])에 직접 전달하는 것은 다음의 축약형입니다.
dedupe(aggregate([a, b]))의 축약형입니다. 단일 소스는 그대로 사용되고 래핑되지 않으므로 tenant 범위 소스가 실수로 공유 bucket에 캐시되지 않습니다. 공유해도 안전한 소스일 때만 직접 cache를 사용하세요.
다음 단계
- Portable Agent Skills — 미들웨어, 카탈로그 및
load_skill흐름을 설명합니다. - 스킬 소스 작성 — 자체 저장소로 스킬을 제공합니다.