1과: 부팅과 설정: 설정 한 줄이 에이전트 전체를 바꾼다
한 문장 요약: DSH에서는 「설정은 곧 컴포지션」입니다 — 하나의
cordis.yml이 에이전트 전체가 어떤 플러그인을 로드하고, 어떤 모델을 사용하고, 어떤 도구를 가질지를 결정합니다. 설정 한 줄만 바꾸면 모델 교체, 도구 추가, 능력 조합 변경이 가능하며, 코드는 한 줄도 수정할 필요가 없습니다.
1. 사용자 스토리: 왜 「설정 변경」만으로 충분한가?
디(D) 군은 어제 dsh --profile headless "이 저장소를 요약해 줘"로 작업을 실행했고, agent는 deepseek-v4-flash 모델을 사용했습니다. 오늘 그가 하고 싶은 일은 세 가지입니다:
- agent를 다른 모델로 교체하기;
- agent에 「웹 검색」 도구 추가하기;
- 「읽기 전용 감사 버전」 agent 만들기 — 파일 읽기만 허용하고 명령 실행은 하지 않게 하기.
전통적인 프레임워크에서는 이 세 가지에 대한 답이 거의 하나로 같습니다: 소스 코드 수정. 모델 이름은 프레임워크에 하드코딩되어 있고, 도구는 메인 루프에 등록해야 하며, 능력 조합은 서로 다른 fork 브랜치를 유지하는 방식으로 관리합니다. 프레임워크를 업그레이드할 때는 자신이 수정한 코드를 고통스럽게 머지해야 합니다.
DSH에서는 답이 완전히 다릅니다: 모델, 도구, 정책, 심지어 agent의 메인 루프 자체까지 모두 플러그인입니다. 그리고 「어떤 플러그인을 로드하고, 매개변수는 무엇인가」는 전부 설정 파일이 결정합니다. 그래서:
| 하고 싶은 일 | 전통적인 프레임워크 | DSH |
|---|---|---|
| 모델 교체 | 소스를 fork하고 모델 이름을 하드코딩으로 변경 | cordis.yml에서 모델 관련 플러그인 항목의 설정을 변경 |
| 도구 추가 | 프레임워크 소스를 수정해 도구를 메인 루프에 등록 | 설정에 플러그인 항목 하나 추가 |
| 능력 조합 변경 | 여러 fork를 유지하며 각각 코드 수정 | profile 레이어로, 같은 기반 위에 여러 조합 구성 |
즉 DSH에서 「설정」은 「프로그램에 매개변수 몇 개를 전달하는 것」이 아니라 컴포지션(조합) — 어떤 블록이 이 에이전트에 조립될지를 결정하는 것입니다. 이것이 바로 이번 과 제목의 의미입니다: 설정 한 줄이 에이전트 전체를 바꾼다.
2. 설정은 곧 컴포지션: 하나의 cordis.yml이 agent 전체를 결정한다
DSH는 cordis.yml로 에이전트가 어떤 플러그인을 로드하고 각 플러그인이 어떤 매개변수를 갖는지를 기술합니다. 공식 문서는 명확하게 말합니다: 「설정 파일은 능력 조합을 담당한다」(출처: docs/user/develop/basic/config.zh.md).
최소한의 설정은 플러그인 항목들의 집합입니다(출처: docs/user/develop/basic/config.zh.md):
- id: llm-deepseek
name: '@deepseek-ai/dsh-llm-deepseek'
- id: bash
name: '@deepseek-ai/dsh-bash-local'
- id: agent-loop
name: '@deepseek-ai/dsh-agent-loop'
config:
agents:
- id: main
provider: deepseek-official
model: deepseek-v4-flash
이 파일을 이해하면 DSH의 절반을 이해한 것입니다:
name: 어떤 npm 패키지(또는cordis.yml기준 상대 경로의 로컬 모듈)를 로드할지 지정합니다;id: 이 플러그인 인스턴스에 안정적인 식별자를 부여해, 다른 설정 레이어가 id로 이 행을 찾아 패치할 수 있게 합니다;config: 플러그인 자신에게 전달하는 매개변수 — 예를 들어agent-loop의config.agents는 「main이라는 이름의 agent를 시작하고,deepseek-official제공자와deepseek-v4-flash모델을 사용한다」고 선언합니다.
따라서: 모델 교체 = model: 행의 값을 바꾸는 것(또는 다른 제공자 플러그인으로 교체하는 것); 도구 추가 = 도구 플러그인 항목을 추가하는 것; 어떤 능력 제거 = 항목을 삭제하거나 disabled: true를 표시해 일시적으로 건너뛰는 것.
현실 세계는 이 최소 예시보다 훨씬 풍부합니다: DSH는 「모든 profile이 공유하는」 능력을 dsh-base 번들로 패키징하고, 그 cordis.patch.yml은 긴 플러그인 목록입니다 — 모델 어댑터, 세션 영속화, 샌드박스, 파일 도구, 서브 에이전트, 워크플로, 텔레메트리……(출처: packages/bundle/base/cordis.patch.yml). 예를 들어 그 안에 정의된 기본 모델 라우팅은 다음과 같습니다:
- id: agent-default-model
name: '@deepseek-ai/dsh-agent-default-model'
config:
provider: deepseek-official
model: deepseek-v4-flash
🎁 비유:
cordis.yml은 에이전트의 「조립 지시서」와 같습니다 — 같은 생산 라인에서 조립 지시서를 바꾸면, 만들어지는 것은 다른 능력을 가진 기계입니다. 모델, 도구, 루프는 모두 조립 지시서에 적힌 부품입니다.
3. profile 레이어: 공식 기본 레이어 → profile 플러그인 레이어 → 사용자 오버라이드 레이어
「설정은 곧 컴포지션」에는 또 하나의 핵심 메커니즘이 있습니다: 레이어(layer). 완전한 설정을 처음부터 작성할 필요 없이, 다른 사람의 설정 위에 오버라이드하여 자신의 버전을 만듭니다.
CLI 문서는 dsh 명령을 「profiles(설정 프로필)를 위한 제품 런처: 순서가 정해진 플러그인 번들 패치 레이어의 스택으로, 그 아래에 사용자 자신의 오버라이드 레이어가 있다」로 정의합니다(출처: apps/cli/README.md). dsh web과 dsh --profile headless는 사실 서로 다른 profile의 조합일 뿐입니다:
dsh --profile headless "작업"은headlessprofile을 시작합니다:dsh-base와dsh-headless가 빈 루트 위에서 조합되고, 이어서 runner가 core의 Agent 및 Session 서비스를 직접 구동합니다(출처:docs/user/guide/index.zh.md);dsh web은--profile web의 별칭입니다:dsh-base와dsh-web-app이 조합되어 브라우저 호스트, HTTP 및 클라이언트 플러그인이 추가됩니다.
완전한 설정의 최종 형태는 여러 레이어가 쌓여 만들어지며, 뒤의 레이어가 앞의 레이어를 덮어씁니다 — 같은 행은 더 뒤의 레이어를 따릅니다. 레이어 순서의 원문(출처: apps/cli/README.md 20행):
컴포지션 트리는 빈 루트 위에 쌓입니다: 먼저
dsh.profile.bundles목록 순서대로 각 번들의 패치 레이어를 적용하고, 다음으로 profile 자신의cordis.patch.yml, 다음으로 home 수준의$DSH_HOME/cordis.patch.yml, 다음으로 각--patch <path>오버레이, 마지막으로 CLI 플래그 패치를 적용합니다.
配置即组合:一个 cordis.yml / profile 决定整个智能体的能力组合
3계층 직관으로 대응시키면:
| 레이어 | 어디에 있는가 | 누구의 것인가 |
|---|---|---|
| 공식 기본 레이어 | 번들에 내장된 패치(예: @deepseek-ai/dsh-base) | 플랫폼 측에서 제공 |
| profile 플러그인 레이어 | profile 디렉터리의 플러그인과 cordis.patch.yml(dsh plugin --profile <name> ...으로 관리) | 당신이 만든 「조립 방안」 |
| 사용자 오버라이드 레이어 | $DSH_HOME/profiles/<name>/cordis.patch.yml 등 | 당신 개인의 취향 |
⚠️ 자주 빠지는 함정: 패치는
config를 행 전체로 교체하는 것이지, 개별 키를 깊게 병합(deep merge)하는 것이 아닙니다(출처:docs/user/develop/basic/config.zh.md).llm-deepseek행을 패치하면서config: { thinking: disabled }만 작성하면, 그 행에 원래 있던apiKeyEnv와baseURL이 모두 지워집니다 — 오버라이드할 때는 유지해야 할 키를 전부 다시 작성해야 합니다.💡 레이어 적용 결과를 확인하고 싶나요?
--dump-default-config와--dump-config를 사용하면 실제로 시작하지 않고도 조합된 전체 설정 트리를 바로 볼 수 있습니다(출처:apps/cli/README.md).
4. 부팅 흐름: boot 조립 → 스코프가 적용된 ctx 준비 → agent 게시
설정은 작성했습니다. 그러면 dsh는 이것을 어떻게 「살아있는 agent」로 바꿀까요? 대략 네 단계입니다:
① boot 조립. app-boot는 각 app의 bin이 공유하는 시작 접착 레이어입니다: .env 로딩, 명확하게 오류를 보고하는 Loader 보호 메커니즘, 스냅샷을 인식하는 설정 파싱, 그리고 전체 트리가 안정될 때까지 기다리는 시작 시퀀스(출처: packages/boot/README.zh.md). 이것이 위의 레이어들을 하나의 최종 설정으로 해석하고 모든 플러그인 패키지를 로드합니다.
② 플러그인의 온디맨드 활성화. Cordis는 「서비스 가용성」으로 활성화를 구동합니다: 플러그인은 inject로 자신이 필요한 서비스를 선언하고, 의존성이 모두 갖춰져야 시작합니다 — 따라서 설정 파일의 기재 순서가 로드 순서를 결정하지 않습니다(출처: docs/user/develop/basic/config.zh.md).
③ 스코프가 적용된 ctx 준비. dsh-scope 패키지는 스코프가 적용된 등록 프리미티브를 제공합니다: createScope(ctx, key)는 레이블이 붙은 Cordis 컨텍스트를 생성하고, 이를 통해 이루어지는 모든 등록은 스코프 가시성을 가지며 스코프 수명 주기를 따릅니다(출처: packages/core/scope/README.zh.md). agent loop는 활성 agent마다 스코프를 생성합니다 — 각 agent는 자신만의 독립적인 ctx를 받고, 각자 등록한 도구와 서비스가 서로 간섭하지 않습니다. 이는 2장에서 다룬 「컨텍스트 타입」과 맥을 같이합니다: 컨텍스트 자체를 런타임에 조작 가능한 일급 엔티티로 구체화하는 것입니다(직관 참고: cordis.txt 300-304행).
④ agent 게시. 스코프가 준비된 후에야 agent가 공식적으로 「게시」됩니다: dsh --profile headless는 core의 Agent 및 Session 서비스를 직접 구동해 작업 하나를 끝내고 종료합니다; dsh web은 브라우저 레이어가 연결될 때까지 기다렸다가 세션을 생성합니다.
여기서 이번 과의 가장 중요한 문장이 나옵니다: 모든 능력은 플러그인이며, 플러그인은 등록을 통해 ctx에 연결된다 — 로드하면 즉시 적용되고, 언로드하면 원상복구된다. 이것이 바로 2장의 「시공간 컴포저빌리티」가 실제로 드러나는 장면입니다: 설치된 플러그인은 도구, 서비스, 정책을 컨텍스트에 등록하고; 언로드 시에는 Cordis가 스코프 수명 주기에 따라 등록을 함께 취소해 시스템이 조립 전 모습으로 돌아갑니다. 따라서 「설정 한 줄 변경」은 거친 치환이 아니라 깔끔한 재조립입니다.
핵심 정리
- 설정은 곧 컴포지션:
cordis.yml의 플러그인 항목(name+id+config)이 에이전트 전체의 능력 조합을 결정합니다; 모델 교체, 도구 추가, 정책 변경은 모두 설정 변경이며 코드를 바꾸지 않습니다. - 능력은 전부 플러그인: 모델 어댑터, 도구, 샌드박스, 심지어 agent loop 자체까지 플러그인입니다; ctx에 등록하면 즉시 적용되고 언로드하면 원상복구됩니다(2장과 상응).
- profile 레이어: 공식 기본 레이어 → profile 플러그인 레이어 → 사용자 오버라이드 레이어 순으로, 뒤의 레이어가 앞의 레이어를 덮어씁니다; 패치는
config의 행 전체 교체이지 깊은 병합이 아닙니다. - 부팅 4단계: boot 조립(레이어 해석) → 플러그인이 서비스 가용성에 따라 활성화 → agent loop가 활성 agent마다 스코프가 적용된 ctx 생성 → agent 게시.
🚀 다음 과에서는 「조립이 끝난 후」의 세계로 들어갑니다: 2과 「agent loop와 세션」 — 에이전트는 어떻게 루프가 돌아가고, 세션은 어떻게 영속화되는가.
셀프 테스트 · 부팅과 설정
답을 모두 선택한 후 「답안 제출」을 클릭하면 정답 여부와 해설을 확인할 수 있습니다.
