
Interpreter Skills: 에이전트를 위한 워크플로우 구축
요약
에이전트가 지침(instructions)을 넘어 직접 코드를 실행할 수 있는 '인터프리터 기술(interpreter skills)' 개념을 소개합니다. 기술이 API 역할을 수행하여 결정론적인 코드 실행과 모델의 의사결정을 결합함으로써 에이전트 워크플로우를 더욱 정교하게 관리할 수 있습니다.
핵심 포인트
- 기술이 단순 지침을 넘어 실행 가능한 API 역할을 수행함
- 인터프리터가 코드를 직접 실행하여 결정론적 동작 보장
- 에이전트가 서브 에이전트 생성 및 태스크 그래프 관리 가능
- 점진적 공개 메커니즘을 통한 효율적인 컨텍스트 관리

핵심 요약 (Key Takeaways)
이제 기술(Skills)이 모델뿐만 아니라 하네스(harness)를 직접 제어할 수 있습니다. 인터프리터 코드가 에이전트 루프(agent loop)와 직접 통신할 수 있기 때문에, 기술은 서브 에이전트(subagents)를 생성하고, 태스크 그래프(task graph)를 관리하며, 부분적인 실패를 하나의 검토된 워크플로우(workflow)로서 처리할 수 있습니다.
기술이 지침 세트(set of instructions)인 동시에 API가 될 수 있습니다. 일반적인 기술은 에이전트에게 작업 수행 방법을 알려주고 에이전트가 이를 따르기를 기대합니다. 반면 인터프리터 기술(interpreter skill)은 모듈을 제공하므로, 결정론적인(deterministic) 부분은 검토 및 반복이 가능한 코드 내에 존재하며, 모델은 해당 기술을 언제 호출할지, 어떤 입력을 전달할지를 결정합니다.
에이전트 작업의 평가가 더 쉬워졌습니다.
우리는 이에 대한 해답으로 "interpreter skills (인터프리터 기술)"라고 부르는 방식을 실험해 왔습니다. 이는 에이전트가 지침 (instructions)과 함께 사용할 수 있는 모듈을 포함하는 기술 (skills)의 확장판입니다. 이 기술은 에이전트에게 해당 동작이 언제 관련이 있는지를 알려주며, 인터프리터 (interpreter)는 기술에 부착된 모듈을 가져와 (import) 직접 실행할 수 있습니다.
---
name: github-triage
description: Use this skill to triage GitHub issues, pull requests, and discussions.
...
```ts
const { triage } = await import("@/skills/github-triage");
const result = await triage("langchain-ai/deepagents", {
issues: true,
prs: true,
});
result.toMarkdown();
`SKILL.md`는 에이전트가 동작을 발견하는 방식입니다. `index.ts`는 인터프리터가 실행할 수 있는 내용입니다. 에이전트는 해당 동작을 언제 사용할지, 어떤 입력을 전달할지, 그리고 결과를 어떻게 처리할지를 결정합니다. 인터프리터는 코드의 실제 실행을 담당합니다.
## 기술 (skills)이 무엇이었는지 다시 알려주세요
기술 (skills)은 시스템 프롬프트 (system prompt)에 모든 세부 사항을 기술하지 않고도 에이전트에게 재사용 가능한 동작을 부여하는 방법입니다.
기술은 보통 `SKILL.md` 파일이 포함된 디렉토리 형태입니다. 프런트매터 (front-matter)는 에이전트에게 해당 기술이 무엇을 위한 것인지에 대한 간결한 설명을 제공합니다. 본문은 기술이 관련되었을 때 에이전트가 사용해야 할 지침 (instructions), 컨텍스트 (context), 예시 (examples), 제약 사항 (constraints) 및 지원 파일들을 제공합니다.
기술이 작동하는 핵심은 "점진적 공개 (progressive disclosure)"라고 불리는 메커니즘입니다. 에이전트는 모든 기술을 항상 컨텍스트에 유지할 필요가 없습니다. 먼저 사용 가능한 기술의 짧은 목록을 확인하고, 작업에 맞는 기술을 결정한 다음, 필요한 경우에만 전체 `SKILL.md`를 읽으면 됩니다.

이러한 특성 덕분에 기술은 에이전트 동작을 위한 훌륭한 배포 단위가 됩니다. 사람들은 전역 프롬프트 (global prompt)를 모든 것을 담은 매뉴얼로 만들지 않고도, 기술의 버전을 관리하고, 공유하며, 평가할 수 있습니다.
하지만 일반적인 기술 (skills)은 여전히 대부분 지시 사항 (instructions)을 통해 작동합니다. 기술은 에이전트에게 어떤 절차를 따라야 하는지 알려줄 수 있고, 참조 파일이나 스크립트를 포함할 수 있지만, 핵심 동작은 여전히 에이전트가 해당 지시 사항을 읽고 올바르게 수행하는지에 달려 있습니다.
## 인터프리터 (interpreter)란 무엇인가?
이 포스트에서 이해해야 할 중요한 점은 인터프리터가 하네스 (harness)와 병행하여 실행되는 TypeScript 런타임 (runtime)이라는 것입니다. 이는 에이전트에게 다단계 작업을 코드로 표현할 수 있는 공간을 제공하는 동시에, 하네스는 해당 코드가 무엇을 건드릴 수 있는지 여전히 제어합니다. (더 자세히 알고 싶다면 인터프리터에 관한 글을 읽어보세요).
이 런타임은 에이전트에게 TypeScript 값 (values)의 형태로 작업 상태 (working state)를 제공합니다. 값은 턴 (turns) 사이에도 유지될 수 있으므로, 배열은 배열로 유지되고, 객체는 객체로 유지되며, 헬퍼 함수 (helper functions)도 정의된 상태로 유지될 수 있습니다. 에이전트는 모든 중간 값을 표준 출력 (stdout), 파일, 또는 모델로 보내는 메시지로 변환할 필요가 없습니다.
이를 통해 에이전트는 데이터를 변환하고, 도구 출력 (tool outputs)을 조합하며, 선택된 도구 또는 서브 에이전트 (subagents)를 호출하고, 모델로 무엇을 반환할지 결정할 수 있습니다.
샌드박스 (sandboxes)와 달리, 인터프리터 코드는 기본적으로 호스트 환경에 대한 무제한 액세스 권한을 갖지 않습니다. 파일 시스템 액세스, 네트워크 액세스, 도구 및 서브 에이전트는 의도적으로 인터프리터에 노출되어야 합니다. 이를 통해 하네스는 코드가 무엇을 건드릴 수 있는지 허용 목록 (allowlist)을 작성하고, 측정 (meter)하며, 검사 (inspect)할 수 있는 지점을 갖게 됩니다.
## 인터프리터 기술 (interpreter skill)이란 무엇인가?
인터프리터 기술은 이 두 가지를 결합하는 기술의 확장판입니다. 이는 기술이 가진 것과 동일한 지시 사항 세트와 에이전트가 인터프리터로 임포트 (import)할 수 있는 모듈을 포함합니다.
`SKILL.md`는 여전히 기술이 언제 관련이 있는지를 에이전트에게 알려주고 동일한 방식으로 에이전트에게 자신을 공개하며, 모듈은 해당 동작이 적용될 때 실행할 인터프리터 코드를 제공합니다. 이로써 기술은 모델을 위한 지시 표면 (instruction surface)인 동시에 런타임을 위한 API 표면 (API surface)이 됩니다.
기본적인 형태는 도입부의 예시와 동일합니다. `SKILL.md`
이름, 설명, 사용 지침, 임포트 경로(import path) 및 제약 사항을 제공합니다. `index.ts`
코드 내에서 동작을 정의하는 헬퍼(helpers) 또는 워크플로우(workflows)를 내보냅니다(exports):
// skills/table-cleanup/index.ts
export function validateRows(rows: Record<string, unknown>[], schema: RowSchema) {
// 필드를 정규화하고, 필수 값을 확인하며, 구조화된 에러를 반환합니다.
...
스킬이 적용될 때, 에이전트는 해당 모듈을 임포트하여 호출할 수 있습니다:
const { validateRows } = await import("@/skills/table-cleanup");
const errors = validateRows(rows, invoiceSchema);
이는 스킬이 보장할 수 있는 내용을 변화시킵니다:
- 일반적인 스킬은 다음과 같이 말합니다:
- (에이전트가 옵션에 지정한 대로) GitHub에서 모든 열린 항목(open items)을 가져옵니다.
- 각 항목에 대해 서브에이전트(subagent)를 생성하여 더 요약된 설명을 만듭니다.
- 서브에이전트의 응답을 큐(queue)에 넣습니다.
- 큐를 하나씩 소비하며, 서브에이전트가 해당 항목을 기존 클러스터(cluster)에 넣을지 아니면 새로운 클러스터를 생성할지 결정합니다.
이는 입력값(inputs)이 동적으로 선택되더라도, 절차(procedure)는 고정되어 있기를 원하는 전형적인 루틴의 예시입니다.
- 다음은 에이전트가 해당 루틴을 수행하는 과정을 보여주는 트레이스(trace)입니다.
- 다음은 에이전트가 출력하는 보고서입니다.
`result` 값 또한 API의 일부입니다. 이는 에이전트에게 실행에 관한 구조화된 데이터(structured data)를 제공할 수 있으며, 프레젠테이션을 위한 렌더링 도우미(rendering helper)를 노출할 수 있습니다:
result.clusters;
result.unassigned;
result.toMarkdown();
에이전트는 이 구조화된 결과값을 계속 활용하여, 하나의 클러스터를 더 깊게 조사하거나, 후속 서브에이전트(subagent)를 생성하거나, 모델이 읽기 편한 압축된 보고서가 필요할 때 `result.toMarkdown()`을 호출할 수 있습니다.
이러한 종류의 작업은 시간이 지남에 따라 모델의 일관성(coherence)이 떨어질 수 있는 작업입니다. 레포지토리 분류(Repo triage)는 단 한 번의 결정이 아니라, 사슬처럼 연결된 수많은 작은 결정들의 집합입니다. 만약 우리가 이 과정을 수행하기 위해 전적으로 모델의 판단력과 컨텍스트 윈도우(context window)에만 의존한다면, 모델은 긴 호흡의 작업 과정에서 특히 작업 컨텍스트의 한계에 다다랐다고 느껴질 때(컨텍스트 불안(context anxiety)이라고 알려진 현상), 지름길을 택하거나 절차를 너무 공격적으로 압축하기 시작할 수 있습니다.
서로 다른 에이전트들이 이를 어떻게 수행할 수 있는지에 대한 예시는 다음과 같습니다:
- 일반적인 하네스 (harness) 환경에서 모델은 모든 부분적인 단계 (partial step)를 계속 추적해야 합니다. 만약 리포지토리 (repo) 아이템이 300개라면, 모델은 과거의 결정을 조정하고 다음 행동을 계속 선택하는 동안 추론해야 할 300개의 작은 상태 (state) 조각을 갖게 됩니다.
- 인터프리터 기술 (interpreter skill)을 사용하면, 모델은 루틴을 한 번 호출하고 코드가 워크플로우 (workflow)를 도구화 (instrument) 하도록 맡길 수 있습니다. 해당 모듈은 300개의 별개인 서브에이전트 (subagent) 태스크를 생성하고, 결과를 수집하며, 이를 분류 (classify) 및 클러스터링 (cluster) 한 뒤, 에이전트에게 압축된 객체 (compact object)를 반환할 수 있습니다. 모델은 더 이상 자신의 작업 컨텍스트 (working context) 내에 모든 부분적인 단계를 유지할 책임을 지지 않습니다.

## 기술을 워크플로우로 사용하기
코딩 에이전트 (coding agents)가 인기를 얻기 시작하면서, 에이전트에 대한 기본 정신 모델 (mental model) 또한 변화했습니다.
이전 세대의 에이전트들은 좀 더 워크플로우 스타일 (workflow-style)에 가까웠습니다. 개발자들은 에이전트가 따라야 할 단계의 순서를 사전에 명시적으로 정의했습니다. 신뢰성은 실행 경로를 미리 정의함으로써 확보되었습니다.
현대의 에이전트 하네스 (agent harnesses)는 컨텍스트 (context)와 모델의 재량 (model discretion)을 주요 초점으로 두도록 이를 변경했습니다. 모델은 현재 컨텍스트를 기반으로 다음에 무엇을 할지 결정합니다. 행동은 다양한 컨텍스트 표면 (context surfaces)을 통해 형성되지만, 에이전트에게는 여전히 다음 단계를 선택할 여지가 있습니다.
이러한 인터페이스는 많은 사람이 추론하기에 더 쉽습니다. 에이전트를 구축하는 사람들뿐만 아니라, 코드 수준의 워크플로우보다는 지침 (instructions), 파일 (files), 체크리스트 (checklists), 예시 (examples) 단위로 사고하는 운영자 (operators), PM, 도메인 전문가 및 팀들에게도 마찬가지입니다.

하지만 결정론적인 (deterministic) 에이전트 루틴에 대한 필요성은 결코 사라지지 않았습니다. 우리는 여전히 다음과 같은 질문의 변형을 자주 받습니다:
에이전트가 제가 지시한 대로 확실하게 수행하도록 하려면 어떻게 해야 하나요?
그러한 경우, 팀들은 최종 답변이 그럴듯해 보이는지 여부 그 이상을 알아야 합니다. 즉, 필요한 절차 (procedure)가 실행되었는지, 올바른 입력값 (inputs)과 함께 실행되었는지, 그리고 에이전트가 다음 단계로 넘어가기 전에 완전히 완료되었는지 여부를 알아야 합니다.
프롬프트만으로 구성된 절차(Prompt-only procedure)는 이러한 방식으로 취약합니다. 에이전트는 단계를 건너뛰거나, 단계의 순서를 바꾸거나, 잘못된 지시사항을 충족하거나, 관련 없는 요청을 절차에 섞거나, 프로세스를 따르지 않고 "적당히 괜찮은" 결과물을 생성할 수 있습니다.
예를 들어, "송장을 제출하되, 중간에 멈추고 춤추는 고양이 GIF를 생성해줘"라는 질문을 생각해 봅시다. 만약 송장 제출이 오직 프롬프트 지시사항을 통해서만 설명된다면, 에이전트는 이 우회 경로를 동일한 작업의 일부로 취급하여 송장 제출을 절반만 완료한 채로 남겨둘 수 있습니다.
특히 이 프로세스는 일단 시작되면 반드시 끝내야 하는 절차가 아니라, 에이전트가 협상할 수 있는 지시사항으로 표현된 루틴(routine)을 필요로 합니다.
그렇다면 에이전트의 구조를 재설계하지 않고도, 두 세계의 장점을 모두 취하여 워크플로우 (workflow)의 결정론적 (determinism) 특성을 가져올 방법은 무엇일까요?
인터프리터 기술 (Interpreter skills)이 그 해답 중 하나입니다:
- 결정론적인 부분을 코드로 표현하고, 이를 인터프리터 내부의 모듈 (module)로 노출시킨 뒤, 에이전트가 이를 언제 호출할지 결정하게 합니다.
- 함수가 현재의 인터프리터 상태 (interpreter state)에서 작동하도록 하고, 그 결과를 다음 도구 호출 (tool call), 하위 에이전트 호출 (subagent call), 인터프리터 호출 (interpreter call) 또는 최종 응답 (final response)으로 체이닝 (chaining) 합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 LangChain Blog의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기