제6과: 세상을 감지하기: 스킬, 검색, 컨텍스트
한 줄 요약: 에이전트는 「손을 움직이는」 것만으로는 부족하고 「감지」도 할 수 있어야 합니다 — 재사용 가능한 스킬 팩(skill)으로 새로운 능력을 배우고, 웹 검색과 페치로 자료를 찾고, LSP로 코드 의미를 읽고, 워크스페이스로 자신이 어느 프로젝트에 있는지 기억하고, 컨텍스트 압축으로 아주 긴 세션에서도 「기억상실」이 되지 않아야 합니다. 그리고 DSH에서는 이 모든 감각이 교체 가능한 플러그인 심(seam)입니다.
1. 먼저 이야기 하나: 손만 움직일 줄 아는 에이전트에게 부족한 것
새 동료를 한 명 고용했다고 상상해 보세요 — 막 시작된 DSH 에이전트입니다. 이 에이전트는 타고난 「손발」이 있습니다. 파일을 읽고 쓰고, 명령을 실행하고, 코드를 편집할 수 있습니다. 하지만 첫 출근 날, 자신이 세상에 대해 아무것도 모른다는 사실을 깨닫습니다.
- 「리포지토리 규칙에 따라 PR을 제출해 줘」라고 시켜도, 규칙이 어디에 쓰여 있는지, PR이 어떤 절차를 거쳐야 하는지 모릅니다.
- 「어떤 프레임워크의 최신 사용법을 찾아 줘」라고 시켜도, 네트워크가 없기 때문에 코드베이스만 멍하니 바라봅니다.
- 「이 함수의 모든 호출 지점을 찾아 줘」라고 시켜도, 문자열 하나를 grep할 뿐이라 파일 간 참조를 놓칩니다.
- 대화가 3시간째에 이르면, 처음에 당신이 말한 「여기는 프로덕션 환경이니 변경은 신중하게」라는 말조차 잊어버립니다.
손발만 있고 감각이 없는 에이전트는 눈을 가린 인턴과 같습니다. 힘은 세지만 방향 감각이 전혀 없습니다. DSH는 다섯 종류의 「감각」으로 이 문제를 해결합니다.
| 감각 | 해결하는 문제 | 대응하는 능력 |
|---|---|---|
| 스킬(skill) | 새로운 능력을 배우기 | 재사용 가능한 명령 패키지, 사용할 때만 펼침 |
| 검색(web) | 자료 찾기 | 웹 검색과 페이지 페치 |
| 코드 의미(lsp) | 코드 이해하기 | 정의로 이동, 참조 찾기 |
| 워크스페이스(workspace) | 자신이 어디에 있는지 알기 | 영구 워크스페이스 디렉터리 |
| 컨텍스트(context) | 긴 세션에서 기억상실 방지 | 컨텍스트 확장과 압축 |
感官接缝:技能渐进披露、Web 搜索、LSP 语义、工作区与上下文压缩
위 그림이 DSH의 「감각 지도」입니다. 중앙의 에이전트(뇌 + 몸)가 다섯 종류의 감각에 둘러싸여 있습니다. 점선에 주목하세요 — 실선 연결이 아니라 「심」입니다. 각 감각은 개별적으로 뽑아서 새 것으로 교체할 수 있습니다. 가장 중요한 스킬부터 이야기해 봅시다.
2. 스킬(skill): 재사용 가능한 「능력 패키지」, 사용할 때만 펼침
2.1 skill이란 무엇인가?
skill(스킬)은 재사용 가능한 능력 패키지입니다. 에이전트에게 보여 주기 위해 작성된 「작업 설명서」로, 특정 종류의 작업을 어떻게 완료하는지 가르칩니다 — 예를 들어 「리포지토리 규칙에 따라 PR을 제출하는 방법」 「monorepo를 조직하는 방법」 「어떤 프레임워크의 테스트를 작성하는 방법」 같은 것입니다. skill 능력 패밀리에 대한 DSH 공식 정의는 다음과 같습니다.
「이 패밀리는 재사용 가능한 agent(에이전트) 명령을 발견하고, 프로바이더와 무관한 카탈로그와 loader를 통해 모델에 공개한다.」 —— packages/skill/README.zh.md
쉽게 말하면, skill 패밀리는 재사용 가능한 명령을 「찾아내는」 역할을 하며, 이를 출처와 무관한 방식으로 모델에 전달합니다. 스킬은 로컬 파일, 내장 플러그인 데이터, 심지어 원격 서버에서 올 수도 있습니다. 레지스트리(ctx.skills)는 발견, 조회, 로딩만 담당할 뿐, 스킬이 어디에 저장되어 있는지는 신경 쓰지 않습니다.
2.2 점진적 공개: 사용할 때만 펼침
이제 문제가 생깁니다. 시스템에 수백 개의 skill이 설치되어 있을 수 있습니다. 모든 skill의 전체 본문을 시스템 프롬프트에 넣는다면, 그 목록만으로 컨텍스트 윈도우가 터져 버립니다.
DSH의 답은 **점진적 공개(progressive disclosure)**입니다 — 이것은 우리의 발명이 아닙니다. 아키텍처 문서의 능력 목록에서 ctx.skills의 공식 라벨이 바로 「skill(스킬) 프로바이더 레지스트리와 점진적 공개」입니다.
「정의는 여전히 점진적 로딩을 채택한다.
get()은 호출할 때마다 승자 프로바이더에 본문을 요청하며, 이 레지스트리에 본문을 캐시하지 않는다.」 —— packages/skill/skill/README.zh.md
이 메커니즘은 두 단계로 작동합니다.
- 먼저 목록 제공: 모델은 처음에 각 skill의 「요약」 — 이름과 한 줄 설명 — 만 봅니다. 한 줄이면 됩니다. 두꺼운 설명서가 책장에 꽂혀 있고 책등에는 제목만 있는 것과 같습니다.
- 사용할 때만 펼침: 모델이 「이 작업에는 어떤 skill이 필요하다」고 판단한 후에야
skill도구로 전체 본문을 로드합니다. 본문은<skill_content>블록 형태로 도구 결과로서 컨텍스트에 들어오고, 사용이 끝나면 사라집니다.
왜 토큰이 절약될까요? 한 번의 작업에는 보통 한두 개의 skill만 필요하기 때문입니다. 점진적 공개는 「수백 권의 설명서」를 「수백 줄의 목록 + 필요 시 펼치는 한두 편의 본문」으로 낮추고, 나머지는 한 글자도 낭비하지 않습니다.
🎁 비유하자면: 스마트폰 앱 스토어는 앱 이름과 한 줄 소개만 보여 주고, 「설치」를 눌러야 전체 앱을 다운로드합니다. 스토어의 모든 앱을 강제로 사전 설치했다면, 스마트폰은 벌써 가득 찼을 것입니다.
3. 감지 심: 검색, 코드 의미, 워크스페이스
1장 「DSH 첫걸음」에서 「능력은 곧 심(seam)」이라고 이야기했습니다. 교체 가능한 능력은 Service Definition(어떤 모습인가), Service Provider(누가 하는가), Consumer(누가 쓰는가) 세 부분으로 구성됩니다. 감각도 예외가 아닙니다 — 아래 세 가지 감각은 모두 심입니다. 모델이 보는 어휘는 고정되어 있고, 일하는 쪽은 마음대로 교체할 수 있습니다.
3.1 웹 검색과 페치: 에이전트에게 「눈」 달아 주기
에이전트가 자료를 찾고 싶을 때 의지하는 것이 web 능력 패밀리입니다.
「이 패밀리는 프로바이더와 무관한 웹 검색 및 페치 연산과, 이를 소비하는 모델 지향 도구를 제공한다.」 —— packages/web/README.zh.md
- 검색: Exa, Perplexity, 또는 DeepSeek 네이티브 검색에 연결할 수 있습니다 — 여러 프로바이더 중에서 선택합니다.
- 페치: 로컬의
web-fetch-http가 공개 HTTP 및 HTTPS 리소스를 페치하여 페이지 본문을 가져옵니다.
모델이 아는 도구는 두 개뿐입니다. web_search(검색)와 web_fetch(URL 페치)입니다. 오늘은 Exa를 쓰고 내일은 Perplexity로 바꾸고 싶다고요? 설정만 바꾸면 되며, 모델 쪽의 약속은 한 글자도 변하지 않습니다. 검색과 페치는 의도적으로 하나의 심(ctx.web)을 공유합니다. 「이 harness가 웹에 어떻게 접근하는가」는 애초에 같은 설정 문제이기 때문입니다.
3.2 LSP: 에이전트에게 「현미경」 달아 주기
grep은 텍스트 매칭이고, LSP는 코드 의미입니다. 에이전트가 문자열을 「매칭」하는 것이 아니라 코드를 「이해」하고 싶을 때, lsp 능력 패밀리를 호출합니다.
「이 seam은
goToDefinition,findReferences,goToImplementation,hover라는 정확히 네 가지 의미 연산만을 공개하며, 범용 JSON-RPC 탈출구를 제공하지 않는다. 따라서 프로바이더를 바꿔도 모델이 내비게이션을 요청하는 방식은 바뀌지 않는다.」 —— packages/lsp/README.zh.md
네 가지 연산을 IDE 사용자의 말로 번역하면 정의로 이동(F12), 참조 찾기(우클릭 → Find All References), 구현으로 이동, 호버하여 문서 보기입니다. 두 가지 세부 사항에 주목하세요.
- 정확히 네 가지: 어수선한 범용 프로토콜 탈출구가 없어, 모델이 요청할 수 있는 내비게이션 능력은 닫혀 있고 예측 가능합니다.
- 프로바이더는 마음대로 교체 가능: 밑에서 어떤 언어 서버(TypeScript, Python……)가 실행되는지는
lsp-stdio가 담당하며, 모델은 항상 같은 네 가지 연산으로 길을 묻습니다.
3.3 Workspace: 에이전트가 자신이 어디에 있는지 알게 하기
「내가 어느 프로젝트에 있지? 이 세션은 누구의 것이지?」 이런 질문에 답하는 것이 workspace 패밀리입니다.
「이 패밀리는 영구 workspace를 소유한다. 제목과 순서 있는 세션 멤버십을 가진 사용자 디렉터리이다.」 —— packages/workspace/README.zh.md
workspace는 영구 사용자 디렉터리입니다. 제목이 있고, 어떤 세션이 자기 아래에 매달려 있는지 알고 있습니다. 에이전트가 세션을 열면 자신이 어느 workspace에서 작업하고 있는지 알게 되고, 경로와 프로젝트 컨텍스트가 이 선을 따라 조직됩니다. 여러 세션이 같은 workspace에 속할 수 있으며, 하나의 프로젝트 아래 매달린 여러 작업대와 같습니다.
3.4 정리: 감각은 모두 소켓
| 감각 | 심 | 모델이 보는 고정 어휘 | 교체 가능한 프로바이더 |
|---|---|---|---|
| 검색 | ctx.web | web_search | Exa / Perplexity / DeepSeek 네이티브 |
| 페치 | ctx.web | web_fetch | 로컬 fetch |
| 코드 의미 | ctx.lsp | 네 가지 의미 연산 | 각종 언어 서버 |
| 워크스페이스 | ctx.workspaceRegistry | workspace 엔티티 | 스토리지 백엔드 |
어떤 감각을 바꿔도 모델은 알아차리지 못합니다 — 이것이 바로 심의 의미입니다.
4. 컨텍스트 관리: 왜 「가득 차는가」, 압축은 어떻게 핵심을 잃지 않는가
4.1 먼저 더하기: 컨텍스트 확장 플러그인
「부담 줄이기」 전에, 「감지」의 나머지 절반인 컨텍스트 확장을 봅시다. 도구로 조회할 필요 없이 모든 요청에 직접 추가되어야 하는 컨텍스트가 있습니다 — 예를 들어 「지금이 몇 시인지」 「어느 workspace에서 작업 중인지」 「다른 세션의 요약」 같은 것입니다. DSH는 context 패밀리로 이를 구현합니다.
「도구를 정의하지 않고 모델 지향 요청 컨텍스트를 추가하는 제품 플러그인.」 —— packages/context/README.zh.md
번역하면, 도구를 정의하지 않는다 — 에이전트가 굳이 무언가를 호출할 필요 없이, 이 정보는 자동으로 요청에 나타납니다. 대표적인 멤버는 agent-instructions(워크스페이스 명령, 기본 번들에 포함), time-context(현재 시간과 소요 시간), session-reference(다른 세션의 유계 스냅샷)입니다. 확장은 컨텍스트에 「더하고」, 압축은 컨텍스트의 「부담을 줄입니다」. 둘이 협력하여 긴 세션을 빠짐없이, 과부하 없이 유지합니다.
4.2 왜 컨텍스트는 「가득 차는가」?
모델의 컨텍스트 윈도우는 유한합니다(예: 수십만 토큰). 에이전트의 모든 사고, 모든 도구 호출과 그 반환 결과가 윈도우에 무언가를 계속 채워 넣습니다. 긴 세션은 필연적으로 한계에 부딪히며, 「가득 차는」 방식은 두 가지입니다.
- 압력(pressure): 대화가 윈도우 상한에 가까워졌지만 아직 벽에 부딪히지는 않은 상태 — 능동적으로 압축.
- 오버플로(context-overflow): 요청이 이미 윈도우를 초과하여 모델 프로바이더에게 거부된 상태(오류 코드
CONTEXT_WINDOW_EXCEEDED) — 압축 후 재시도.
4.3 압축: 요약 하나로 전체 이력과 교환하기
압축(compaction)의 공식 정의는 절제되어 있습니다.
「이력이 너무 큰지 판정하고, 더 이른 범위를 단일 표층 노드로 요약하되, 구현 방법은 규정하지 않는다.」 —— packages/compaction/compaction/README.zh.md
어떻게 「핵심을 잃지 않는」 것일까요? 비결은 세 겹에 있습니다.
- 가지치기(prune): 먼저 거대한 도구 결과를 작게 줄입니다 — 예를 들어 한 번의 명령 출력이 10만 줄이라면 요점까지 다듬습니다.
- 요약(summarize): 다음으로 모델이 더 이른 대화 구간을 한 문단으로 농축하여, 「요약 체크포인트」 하나로 원문을 대체합니다.
- 꼬리 유지: 최근 대화는 한 글자도 건드리지 않습니다.
「백엔드는 요약 하나로 원래 유지되던 여러 이력 토큰과 교환하며, 최근 꼬리는 변경하지 않는다.」 —— packages/compaction/compaction/README.zh.md
가장 중요한 점은 원본 이벤트가 삭제되지 않는다는 것입니다. 이들은 세션 로그에 온전히 보존되어 있으며, 모델의 메시지에 더 이상 들어가지 않을 뿐입니다. 즉, 압축이 건드리는 것은 「모델의 작업 기억」이고, 「시스템의 완전한 기록」은 건드리지 않습니다. 재생은 여전히 결정론적입니다.
🎁 비유하자면: 500페이지짜리 책을 읽다가 400페이지에서 처음 부분이 기억나지 않는다고 합시다. 책을 버리고 다시 읽는 대신, 앞의 300페이지를 한 페이지의 독서 노트로 정리해 끼워 넣고 계속 읽습니다. 노트는 세부를 잃지만 주된 줄기는 지킵니다 — 정말 중요한 원문은 여전히 책장(로그)에 있습니다.
4.4 오버플로 재시도: 벽에 부딪히면 어떻게 할까
요청이 정말 「컨텍스트가 가득 참」으로 거부되면, DSH는 포기하지도, 맹목적으로 재시도하지도 않고, 규범화된 복구 흐름을 따릅니다.
「
dsh-compaction-basic은 요청 파생 전에agent/pre-step으로 압력을 처리하고,agent/request-error는 규범적 컨텍스트 오버플로에만 사용된다. 어느 트리거 조건이든 충족되면, 시스템은 먼저 선택적 도구 결과 가지치기를 수행한 후 요약을 선택한다.」 —— docs/agent-lifecycle.zh.md
전체 흐름은 오버플로 → 가지치기 → 요약 → 재시도입니다. 마지막 단계의 규율에 주목하세요. 가지치기나 요약이 실제로 표층을 진전시킨 경우(실제 압축이 발생한 경우)에만 시스템이 완전히 새로운 재시도 라운드를 시작합니다. 압축이 이루어지지 않았다면, 무한 루프로 재시도하는 대신 원래 오류를 보존합니다.
또한 압축 자체 항목도 심(ctx.compaction 심)입니다. 자동 압력 검사, 오버플로 복구, 수동 /compact 명령이 모두 같은 서비스를 공유하며, 백엔드(compaction-basic)는 통째로 교체할 수 있습니다. 여기까지 오면 눈치채셨을 것입니다 — 「기억을 관리하는 일」조차 DSH는 교체 가능한 플러그인으로 만들었다는 것을요.
핵심 복습
이 과의 정보량이 적지 않지만, 다음 다섯 문장만 기억하면 충분합니다.
- 에이전트는 손만 움직일 줄 알아서는 부족합니다 — 도구 외에도 다섯 종류의 감각이 필요합니다. 스킬, 검색, 코드 의미, 워크스페이스, 컨텍스트.
- skill은 능력 패키지이며 점진적 공개 — 레지스트리는 모델에 목록 요약만 보여 주고, 모델은 「사용할 때만」 전체 본문을 펼칩니다. 이것이 토큰 절약의 핵심입니다.
- 감지는 모두 심 — 웹 검색/페치, LSP의 네 가지 의미 연산, workspace 경로 모두 모델 어휘는 고정, 프로바이더는 자유롭게 교체 가능합니다.
- 컨텍스트는 가득 차고, 압축은 핵심을 잃지 않습니다 — 압력에서는 능동적으로 압축하고, 오버플로에서는 가지치기 → 요약 → 재시도. 요약이 대체하는 것은 「모델의 작업 기억」이며, 원본 로그는 그대로입니다.
- 기억 관리도 플러그인 — 컨텍스트 확장과 압축 백엔드 모두 교체 가능한 심이며, 「모든 것은 플러그인」이라는 철학이 감지 계층을 관통합니다.
🚀 다음 과(제6과)에서는 「목표, 계획, 협업」을 다룹니다 — 감각이 갖춰진 에이전트가 어떻게 「단독 작전」에서 「군단 협업」으로 바뀌는지 알아봅니다.
셀프 테스트 · 세상을 감지하기
답을 모두 선택한 후 「답안 제출」을 클릭하면 정답 여부와 해설을 확인할 수 있습니다.
