DeepSeek의 오픈소스 에이전트 하네스 저장소를 클론하여 온종일 코드를 뜯어보았다. 내가 발견한 것은 지금까지 출시된 그 어떤 에이전트 프레임워크보다 아키텍처적 야심이 넘치는 결과물이었다. 가장 세련되거나 가장 인기 있는 프레임워크는 아닐지 몰라도, 가장 원칙에 충실한(principled) 프레임워크임은 분명하다.

이 프로젝트의 이름은 dsh다. MIT 라이선스이며, 현재 버전은 0.1.0-rc.5(개발자 프리뷰 단계, 호환성을 깨는 변경 예정)이다. 그리고 이 프레임워크는 단 하나의 급진적인 사상 위에 세워져 있다. 바로 **“모든 것은 플러그인이다”**라는 철학이다. “플러그인 시스템도 지원합니다”라거나 “몇 가지 기능을 확장할 수 있습니다” 수준이 아니다. 정말로 모든 것이 플러그인이다. 에이전트 루프, 모델 어댑터, 도구 레지스트리, 세션 로그, UI까지—전부 Cordis 기반 플러그인으로 구성되어 설정만으로 갈아 끼우거나, 패치하거나, 교체할 수 있다.

특권을 가진 코어 커널(privileged kernel) 따위는 존재하지 않는다.

숫자로 보는 규모

코드베이스의 규모부터 정리해 보자:

  • 40개 이상의 그룹으로 나뉜 219개의 패키지
  • 약 94,000줄의 TypeScript 코드
  • 약 1,981개의 소스 파일
  • 640개의 테스트 파일
  • 2026년 6월 이후 작성된 12,293건의 커밋

마지막 숫자에 주목해야 한다. 대략 10주 동안 1만 2천 건이 넘는 커밋이 쌓였다. 이것은 취미로 만든 사이드 프로젝트가 아니다. 풀 스피드로 달리고 있는 전담 엔지니어링 팀의 결과물이다.

Cordis 프레임워크의 실체

밑바탕에 깔린 프레임워크의 이름은 Cordis이며, “시공간 결합성(spatiotemporal composability)“을 다룬 학술 논문에서 설명된 구조를 따른다. 전형적인 컴퓨터 과학계의 현학적인 표현처럼 들릴 수 있지만, 핵심 아이디어는 매우 실용적이다. 플러그인이 공유 컨텍스트 트리에 서비스, 타입화된 이벤트, 되돌릴 수 있는 효과(reversible effects)를 제공한다. 모든 등록 행위는 하나의 부수 효과(effect)로 취급되어, 플러그인이 언로드되면 그 플러그인이 등록했던 모든 자원이 자동으로 깨끗이 정리된다.

의존성 주입(DI) 컨테이너가 이벤트 버스, 수명 주기 관리자, 설정 계층의 역할을 동시에 겸하는 구조라고 이해하면 쉽다. 플러그인 A가 ctx에 서비스를 등록하면 다른 플러그인들은 ctx.serviceName을 통해 이를 소비한다. 그리고 플러그인 A가 언로드되는 순간, 이를 참조하던 모든 소비자의 연결 고리가 자동으로 끊어진다.

DeepSeek은 Cordis 프레임워크 전체(9개 패키지)를 vendor/ 디렉터리에 벤더링하여 @deepseek-ai 스코프로 다시 배포했다. 그리고 업스트림 원본에서 한 번도 겪어보지 못했던 재진입 정리(reentrant disposal) 결함을 해결하는 수명 주기 강화 조치를 포함해, 18가지 로컬 수정 사항을 꼼꼼하게 문서화해 두었다. 대단한 집념이다.

역량 솔기(Capability Seam) 패턴

이 전체 시스템을 지탱하는 핵심 디자인 패턴이다. 여기서 ’솔기(seam)’란 다음 세 가지 역할을 가진 교체 가능한 역량을 뜻한다:

  1. 서비스 정의(Service Definition): 인터페이스 선언
  2. 서비스 제공자(Service Provider): 인터페이스 구현
  3. 소비자(Consumer): 이를 활용하는 모델 대면 도구

파일 시스템 솔기, 서브프로세스 솔기, 셸 솔기, LLM 솔기가 모두 이 패턴을 철저히 따른다. 이 구조가 강력한 이유는, 파일 시스템과 프로세스 제공자의 엔드포인트를 원격 샌드박스로 가리키도록 설정 하나만 바꾸면 Bash, PTY, LSP가 통째로 원격 환경으로 이전되기 때문이다. 코드를 포크할 필요도, 별도의 어댑터 계층을 짤 필요도 없다. 제공자들이 동일한 실행 세계를 공유하기 때문이다.

DeepSeek 모델 대신 Claude를 사용하고 싶은가? ctx.llm에 새로운 LLM 어댑터를 등록하면 된다. 영속적인 터미널 세션을 추가하고 싶은가? ctx.terminals 백엔드를 등록하면 된다. 에이전트가 런타임에 스스로 플러그인 트리를 수정하도록 만들고 싶은가? 이를 위한 extensions/ 패키지가 이미 준비되어 있다. 그렇다, 에이전트는 실행 중에 자신의 플러그인을 직접 검사하고 마운트하거나 언마운트할 수 있다.

턴 흐름 (The Turn Flow)

에이전트 루프 자체도 하나의 플러그인(dsh-agent-loop)이다. 에이전트가 메시지를 처리할 때 벌어지는 흐름은 다음과 같다:

turn/start
  입력 청구 + 큐에 쌓인 메시지 확인
  프롬프트 + 도구 스키마 조립
  -> agent/pre-step (진입 또는 거절)
     step/start
     세션 로그로부터 모델 히스토리 파생
     agent/request -> llm/stream -> assistant/message
     tool/call -> tools/pre-execute -> tools/execute -> tools/post-execute
     step/end
  -> agent/turn-stopping
turn/end

**스텝(step)**은 하나의 모델 요청과 그에 수반되는 도구 호출들로 이루어진다. **턴(turn)**은 0개 이상의 스텝으로 구성된다. 핵심 이벤트들은 워터폴(waterfall) 구조를 따른다. 리스너는 다음 단계로 위임하기 위해 반드시 next()를 호출해야 하며, 그렇지 않으면 체인이 즉시 단락(short-circuit)된다. 이는 루프 자체를 수정하지 않고도 파이프라인의 어느 지점에서든 훅(hook)이 개입하여 가로채거나, 변조하거나, 차단할 수 있음을 의미한다.

이 모든 것을 하나로 묶는 설계 철학은 **“모델에 보이는 것은 곧 로그에 기록된다(model-visible = logged)”**는 규칙이다. 모델에 도달하는 모든 정보는 세션 로그로부터 완벽하게 재구성될 수 있어야 한다. 모델에 새로운 입력을 보여주고 싶은가? 그렇다면 새로운 세션 이벤트가 선행되어야 한다. 이 원칙 덕분에 재생(replay), 포크(fork), 장애 복구, 텔레메트리 모두를 단 하나의 데이터 소스에서 파생시킬 수 있다.

10단계 도구 실행 파이프라인

대부분의 에이전트 프레임워크는 “도구 호출 → 결과 반환” 수준의 단순한 흐름을 갖는다. DeepSeek은 이를 10단계 파이프라인으로 구성했다:

  1. tools/pre-execute 워터폴 (훅, 권한 검사, 샌드박스 래핑)
  2. 단조 가드(Monotonic guards) (거부 또는 기권 — 한 번 거부되면 번복 불가)
  3. 승인 프롬프트 (선택적 일회성 사용자 승인)
  4. tools/execute 워터폴 (타임아웃, 재시도, 메트릭 래핑)
  5. 도구 본체 실행
  6. 파일 시스템 쓰기 의도 게이트 (파일 변경 작업 전용)
  7. 도구 소유 세션 이벤트 발행 (할 일 목록 작성, fs 관찰 결과, 훅 호출 등)
  8. tools/post-execute 워터폴 (수락, 차단, 대체, 컨텍스트 추가)
  9. 정규화 및 finalizeContent 처리
  10. tools/result — 동결된 확정 결과 생성

단순한 토이 프로젝트라면 명백한 오버엔지니어링이다. 하지만 도구를 특정 정책 서비스에 하드코딩하지 않고 매 단계마다 기업 보안 정책을 유연하게 주입해야 하는 프로덕션 시스템에서는 이것이 정확히 들어맞는 설계다.

보안 모델

보안 아키텍처는 대단히 엄격하다:

  • 샌드박스 백엔드: Landlock(Linux 커널), bwrap(bubblewrap), Seatbelt(macOS)
  • 정제된 환경 변수: 새로 생성되는 하위 프로세스는 *KEY*, *SECRET*, *TOKEN*, *PASSWORD* 패턴을 가진 모든 환경 변수가 자동으로 제거된 상태로 실행됨
  • 임시 파일 보호: 0700 권한의 전용 디렉터리, 무작위 파일명, 소유자 전용 독점 열기 강제
  • 심볼릭 링크 안전성: lstatSync().isSymbolicLink() 확인 후 unlinkSync 실행 — 링크를 따라 대상 타깃으로 침투하는 위험 원천 차단
  • 승인 워크플로: 민감한 작업 실행 전 일회성 확인 프롬프트
  • 단조 가드(Monotonic guards): 어떤 가드가 실행을 한 번 거부하면 하위 리스너가 이를 절대 번복할 수 없음

방어 패턴 문서는 마치 실전 전투 일지를 읽는 듯하다. 모든 규칙이 실제로 프로덕션에서 발생했거나 터지기 직전이었던 버그 클래스들과 1:1로 매핑되어 있다. “직교적 결과는 독립적으로 보고하라”는 규칙은 시그널을 가로채서 타임아웃이 발생했음에도 종료 코드 0을 반환해 버린 프로세스 버그에서 비롯되었다. “정리 작업은 완전한 정적 상태에 도달해야 한다”는 원칙은 프로세스에 kill 시그널만 날리고 작업이 완전히 멈추기 전에 함수가 리턴되어 좀비 프로세스가 남았던 문제에서 비롯되었다.

지원 인터페이스

인터페이스 실행 명령어 설명
Web UI npx @deepseek-ai/dsh web 브라우저 기반 대시보드 (localhost:3080)
CLI 단발 실행 dsh --profile headless "task" 헤드리스 명령줄 자동화
ACP 서버 Agent Client Protocol 에이전트 자동화 프로토콜
JSON-RPC Python SDK 연동 stdio를 통해 파이썬에서 에이전트 구동
소스 실행 pnpm dsh 리포지토리 체크아웃 직접 빌드

파이썬 SDK(deepseek-harness-sdk)는 별도 패키지로 제공되며, stdio 상에서 개행으로 구분된 JSON-RPC를 통해 번들된 런타임과 통신한다. 깔끔한 책임 분리다. 복잡하고 무거운 작업은 TypeScript 런타임이 처리하고, 파이썬은 얇은 클라이언트로만 기능한다.

진정으로 독창적인 부분들

다른 곳에서는 한 번도 보지 못했던 세 가지 특징이 있다:

1. 런타임 자체 수정(Self-modification): extensions/ 패키지 덕분에 에이전트는 실행 중에 자신의 Cordis 플러그인 트리를 스스로 검사하고 수정할 수 있다. 새로운 플러그인을 마운트하고, 기존 플러그인을 제거하며, 자신의 서비스 그래프를 직접 들여다본다. 대화 도중에 에이전트가 자신의 능력을 실시간으로 바꾸는 데모(pnpm run demo:cordis)까지 포함되어 있다.

2. 단일 진실 공급원으로서의 세션 로그: 추가 전용(append-only)의 SessionEvent 로그는 단순한 기록용 파일이 아니다. 모델 히스토리, 포크, 리플레이, 텔레메트리, 영속성을 위한 단 하나의 절대적 진실 공급원(source of truth)이다. deriveMessages() 함수는 이 로그를 투영하여 모델 컨텍스트를 동적으로 재구성한다. 로그에 없는 내용은 모델도 볼 수 없다.

3. 완전한 이중 언어 지원: 모든 기술 문서, README, 사용자 대면 문자열이 영어와 중국어로 완벽히 병기되어 제공된다. 번역 검증 게이트, 페어링 충돌 해결 절차, 문서 예산 시스템까지 갖춰져 있다. 글로벌 개발자 경험(DX)을 진지하게 고민하는 중국 AI 랩의 진면목을 보여준다.

솔직한 총평

강점:

  • 플러그인 아키텍처가 단순 마케팅이 아닌 실체임
  • 파일당 100% 테스트 커버리지 게이트를 둘 만큼 엄격한 프로덕션급 엔지니어링 규율
  • 웹, CLI, ACP, JSON-RPC, 파이썬 등 처음부터 다중 인터페이스를 고려한 설계
  • 3가지 OS 레벨 백엔드를 지원하는 보안 우선 샌드박싱
  • 런타임 자체 수정 기능의 기술적 신선함

우려되는 점:

  • 여전히 개발자 프리뷰 상태이며, 호환성 파괴가 예고되어 있음
  • 219개의 패키지는 지나치게 넓은 표면적이며 의존성 그래프가 매우 복잡함
  • Cordis 프레임워크를 18개의 로컬 수정과 함께 벤더링했다는 것은 단순 의존성이 아니라 사실상의 유지보수 포크(fork)를 의미함
  • 기본 최적화가 DeepSeek 모델에 집중되어 있음. 구조적으로는 중립적이나 기본 설정 경로는 DeepSeek을 전제함
  • 아직 정식 태그 릴리스가 없음 (AGENTS.md에 “첫 태그 릴리스 시 이 항목을 삭제하라”고 적혀 있음)

결론

DeepSeek 하네스는 자금력이 풍부한 AI 연구소가 챗봇 API에 적당히 도구를 덧붙이는 방식 대신, 기초 원리(first principles)에서부터 에이전트 프레임워크를 설계했을 때 어떤 결과물이 나오는지를 보여주는 전형적인 사례다. Cordis 논문은 장식용이 아니다. 시공간 결합성 모델이 설계 전반을 강력하게 지배하고 있다. 첫날부터 교체 가능성을 전제로 설계되었기에 모든 부품을 손쉽게 갈아 끼울 수 있다.

오버엔지니어링인가? 주말 토이 프로젝트 용도라면 분명 그렇다. 하지만 다중 모델 백엔드, 다중 인터페이스, 다중 샌드박스 전략, 그리고 런타임 자체 수정을 지원해야 하는 프로덕션 에이전트 플랫폼을 만든다면 이야기가 다르다. 문제가 요구하는 복잡성 딱 그만큼 정교하게 설계된 시스템이다.

진짜 관건은 생태계가 이를 받아들일 것인가이다. 오픈소스 에이전트 프레임워크의 성패는 아키텍처가 아니라 커뮤니티에 달려 있다. DeepSeek은 훌륭한 아키텍처를 확보했다. 이제 그들에게 필요한 것은 플러그인 생태계와 튜토리얼, 그리고 개발자들이 API를 직접 호출하는 대신 dsh를 선택하게 만들 “30분 만에 헬로월드에서 프로덕션까지” 이어지는 훌륭한 개발자 경험이다.

하지만 에이전트 인프라를 직접 구축하고 있고, “모든 것이 플러그인인 시스템”이 실제 코드에서 어떻게 구현되는지 알고 싶다면, 이 코드베이스는 반드시 분석해 보아야 할 교과서다.


아키텍처 다이어그램, 패키지별 상세 분석, 참고 문헌이 포함된 전체 분석 보고서는 연구 보관소에 저장되어 있습니다.