Skills

Skills (스킬)

:::note Skills API는 실험적이에요. API와 동작이 향후 릴리스에서 바뀔 수 있어요. :::

Skills는 LLM에 재사용 가능하고 자족적인 행동 지침을 장착하는 메커니즘이에요. 스킬은 이름(name), 짧은 설명(description), 그리고 지침 본문(그 content)을 묶고, 선택적으로 리소스(예: references, assets, templates 등)를 함께 담아요. LLM은 스킬을 요청 시에만 로드해서 초기 컨텍스트를 작게 유지하고, 실제로 필요할 때만 상세 지침을 가져와요.

:::note Skills는 Agent Skills 스펙에 따라 설계됐어요. :::

출처: 공식문서 - Skills

스킬 만들기

파일 시스템에서

보통 각 스킬은 SKILL.md 파일을 담은 자기 디렉토리에 존재해요. 파일은 스킬의 namedescription을 선언하는 YAML front matter 블록으로 시작해야 해요. front matter 아래의 모든 내용이 스킬의 content, 즉 스킬이 활성화될 때 LLM에 주어지는 지침이 돼요.

skills/
├── docx/
│   ├── SKILL.md
│   └── references/
│       └── tracked-changes.md   ← loaded as a resource
└── data-analysis/
    └── SKILL.md

SKILL.md 예시:

---
name: docx
description: Edit and review Word documents using tracked changes
---

When the user asks you to edit a Word document:

1. Always use tracked changes so edits can be reviewed.
   ...

스킬 디렉토리의 어떤 파일이든(SKILL.md 자체와 scripts/ 하위 디렉토리의 파일 제외) LLM이 요청 시 읽을 수 있는 SkillResource로 자동 로드돼요.

langchain4j-skills 모듈의 FileSystemSkillLoader를 사용해 파일 시스템에서 스킬을 로드해요.

<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-skills</artifactId>
    <version>1.20.0-beta30</version>
</dependency>
// Load all skills found in immediate subdirectories:
List<FileSystemSkill> skills = FileSystemSkillLoader.loadSkills(Path.of("skills/"));

// Or load a single skill by its directory:
FileSystemSkill skill = FileSystemSkillLoader.loadSkill(Path.of("skills/docx"));

클래스패스에서

ClassPathSkillLoaderFileSystemSkillLoader처럼 동작하지만 파일 시스템 대신 클래스패스에서 스킬 디렉토리를 찾아요. 스킬을 JAR 안에 번들하거나 src/main/resources 아래에 둘 때 유용해요. 기본적으로 ClassPathSkillLoader는 스레드의 컨텍스트 클래스 로더를 사용해요. 같은 SKILL.md 형식과 리소스 로딩 규칙, scripts/ 제외 규칙이 적용돼요.

프로그래밍 방식으로

스킬이 파일 시스템 기반일 필요는 없어요. 데이터베이스, 원격 API, 런타임 생성 등 어떤 소스에서든 빌더 API로 만들 수 있어요.

Skill skill = Skill.builder()
        .name("incident-response")
        .description("Step-by-step runbook for diagnosing and resolving production incidents")
        .content("""
                When a production alert fires:
                1. Call `fetchRecentLogs(serviceName)` to retrieve the last 5 minutes of logs.
                2. Call `checkServiceHealth(serviceName)` to get current health metrics.
                3. Based on the findings, call `createIncidentTicket(summary, severity)`.
                4. If severity is CRITICAL, also call `pageOnCall(incidentId)`.
                """)
        .build();

SkillResource를 프로그래밍 방식으로 붙일 수도 있어요.

모드

스킬은 필요로 하는 제어와 신뢰 수준에 따라 AI Service에 두 가지 방식으로 통합할 수 있어요.

Tool Mode (권장)

클래스는 Skills(langchain4j-skills 모듈)예요. 이 모드는 Agent Skills 스펙의 Tool-based agents 통합 방식에 대응해요. 이 모드에서 LLM은 스킬을 활성화해 단계별 지침을 받은 뒤, 여러분이 명시적으로 등록한 도구를 호출해 그 지침을 수행해요. LLM은 추론 시점에 파일 시스템에 접근하지 못해요 — 모든 스킬 콘텐트와 리소스는 미리 메모리에 로드되고, activate_skillread_skill_resource 도구가 그 미리 로드된 콘텐트를 반환하지 디스크에서 읽지 않아요. 미리 정의된 도구만 호출할 수 있으므로 임의 코드 실행 위험이 없어요.

작동 방식은 다음과 같아요.

  1. 시스템 메시지가 사용 가능한 스킬들(이름과 설명)을 나열해서 LLM이 고를 수 있게 해요.
  2. 사용자가 특정 스킬이 필요한 질문을 해요.
  3. LLM이 activate_skill("my-skill")을 호출해 지침을 받아요.
  4. LLM이 그 지침을 따라 작업을 완료하고, 필요하면 리소스 파일을 읽어요.

연결하는 방법은 다음과 같아요. Skills에서 ToolProvider를 가져와 일반 도구 옆에 AI Service 빌더로 전달하고, formatAvailableSkills()로 스킬 카탈로그를 시스템 메시지에 주입해 LLM이 활성화할 수 있는 스킬을 알게 해요.

Skills skills = Skills.from(FileSystemSkillLoader.loadSkills(Path.of("skills/")));

MyAiService service = AiServices.builder(MyAiService.class)
        .chatModel(chatModel)
        .tools(new OrderTools()) // your tools
        .toolProvider(skills.toolProvider()) // or .toolProviders(myToolProvider, skills.toolProvider()) if you already have a tool provider configured
        .systemMessage("You have access to the following skills:\n" + skills.formatAvailableSkills()
                + "\nWhen the user's request relates to one of these skills, activate it first using the `activate_skill` tool before proceeding.")
        .build();

formatAvailableSkills()는 각 스킬의 이름과 설명을 나열한 XML 형식 블록을 반환해요.

각 도구의 이름·설명·파라미터 메타데이터는 빌더의 해당 config 클래스로 재정의할 수 있어요. activate_skill 도구는 항상 등록되고, 스킬에 리소스가 하나라도 있으면 read_skill_resource 도구가 등록돼요.

스킬 범위 도구 (Skill-Scoped Tools)

도구를 스킬에 직접 붙일 수도 있어요. 이런 도구는 activate_skill 도구로 스킬이 활성화된 후에만 LLM에 노출돼요. LLM의 도구 목록을 작고 집중적으로 유지하고, 관련될 때만 스킬 전용 도구가 나타나게 만들 수 있어요. @Tool 애너테이션 메서드를 넘기는 가장 간단한 방식부터, ToolProvider를 붙이는 방식(MCP 서버 도구를 스킬 활성화 후에만 노출), Map<ToolSpecification, ToolExecutor>를 직접 넘기는 방식까지 지원하며, 세 가지를 조합할 수도 있어요.

class OrderTools {

    @Tool("Validates a customer order by ID")
    String validateOrder(String orderId) {
        // validation logic
        return "valid";
    }

    @Tool("Charges payment for a customer order")
    String chargePayment(String orderId) {
        // payment logic
        return "charged";
    }
}

Skill skill = Skill.builder()
        .name("process-order")
        .description("Processes a customer order end-to-end")
        .content("""
                To process an order:
                1. Call `validateOrder(orderId)` to check the order is valid.
                2. Call `chargePayment(orderId)`.
                """)
        .tools(new OrderTools())
        .build();

작동 방식을 정리하면, 스킬 활성화 전에는 LLM이 activate_skill(그리고 read_skill_resource) 도구만 보고 스킬 범위 도구는 도구 목록에 없어요. LLM이 activate_skill("process-order")를 호출하면 활성화가 ToolExecutionResultMessage에 기록되고, 같은 AI Service 호출 내에서 스킬 범위 도구가 보이게 돼 LLM이 즉시 호출할 수 있어요. 스킬 범위 도구는 다음 AI Service 호출에서도 계속 보이고, 스킬이 비활성화될 때만 안 보여요.

Tool Search와 함께 사용하기

Tool Search와 함께 사용할 때 서로 독립적으로 동작해요. 스킬 범위 도구는 검색 대상이 되지 않아요(검색 가능한 도구 풀에 나타나지 않고, tool_search_tool로 찾을 수도 없어요). 일반 도구는 검색 대상으로 남아요. activate_skillALWAYS_VISIBLE로 표시되어 Tool Search가 켜져 있어도 항상 호출할 수 있어요.

Shell Mode (실험적)

클래스는 ShellSkills(langchain4j-experimental-skills-shell 모듈)예요. Agent Skills 스펙의 Filesystem-based agents 통합 방식에 대응해요. 이 모드에서 LLM은 단일 run_shell_command 도구를 받고, 셸 명령으로 파일 시스템에서 스킬 지침을 직접 읽어요. activate_skill이나 read_skill_resource 도구는 없고, LLM이 사람 개발자처럼 스킬 파일을 탐색해요.

:::warning 셸 실행은 본질적으로 안전하지 않아요. 명령이 샌드박스·컨테이너화·권한 제한 없이 호스트 프로세스 환경에서 직접 실행돼요. 오작동하거나 프롬프트 주입된 LLM이 애플리케이션이 실행되는 머신에서 임의의 명령을 실행할 수 있어요. 입력을 완전히 신뢰하고 관련 위험을 받아들일 수 있는 통제된 환경에서만 쓰세요. :::

이 모드의 등록 도구는 항상 등록되는 run_shell_command 하나뿐이에요. 이 모드는 실험과 프로토타이핑에 가장 적합해요. 커뮤니티에서 배포한 타사 스킬(예: agentskills.io 에코시스템)을 Java로 먼저 포팅하지 않고 바로 쓸 때도 유용해요. 빠르게 동작하는 워크플로우를 구성한 뒤, 솔루션이 성숙해지면 개별 동작을 도구로 옮기면 돼요.

더 알아보기