Skill, Preset, 그리고 자기 수정
cordis_define은 Agent가 런타임에 자기 런타임을 고쳐 쓰게 해요. 핵심 디렉터리: packages/extensions/tool-cordis/와 apps/cli/config/agent-presets/.
cordis_define과 cordis_run으로 런타임에 스스로 새 도구를 키우는 방식과, 이 자기 수정의 신뢰 경계가 어디에 그려지는지; skill 계층 레지스트리에서 preset 층이 전역 층을 어떻게 가리는지.
장면: 크리에이티브 모드(cordis preset) 세션에서 사용자가 “코드 줄 수를 세는 도구 하나 만들어 줘”라고 해요. 왼쪽은 런타임 실시간 상태, 오른쪽은 Agent 동작 — 자막을 따라 한 바퀴 돌아요.
플러그인 등록부 (Plugin / Package)
도구 목록
Agent의 동작
packages/extensions/tool-cordis/src/index.ts의 cordis_define·cordis_run 도구 설명 원문(148–259행)을 바탕으로 정리했고, 확인일 2026-08-13.먼저 발표문의 그 궁금증부터 풀어요. 표준·코드·미니멀·크리에이티브 네 모드인데, 소스에는 모드 분기 한 줄도 없어요. apps/cli/config/agent-presets/ 아래가 디렉터리 네 개이고, 각 디렉터리에 agent.cordis.yml 한 장 — 파일이 플러그인 조합 하나를 말해 세션 하나에 마운트돼요. 미니멀 모드는 전부 62행: persona 한 줄 “You are a helpful software engineer assistant.”에 complete: true(이후 조립이 프롬프트에 더 넣는 걸 거절), 도구는 지속 bash와 편집기뿐, 압축조차 없어요 — 벤치마크용 설정이에요. 크리에이티브 모드는 표준 모드를 그대로 두고 셋만 더 걸어요: 자기 지시 도구 세트 tool-cordis, 조합 작성을 가르치는 skill, 두 평면을 가르는 persona.
두 평면이 이 체계의 좌표계예요. HOST 조합은 세션을 넘어 공유하는 것: 영속화, 샌드박스와 승인, 모델 라우팅, subagent 레지스트리. AGENT PRESET은 한 세션이 그 레지스트리에 보태는 것: 도구, persona, 프롬프트 단락. 경계가 얼마나 가느냐는 디테일에서 보여요. preset에서 서비스를 게시하는 줄은 host에 속하거나 isolate realm에 싸여야 해요. 미니멀 모드가 샌드박스 없는 로컬 파일시스템을 쓰려면 fs-local을 자기 realm에 넣고, 그 세션의 fs만 가려요 — 다른 세션은 그대로 샌드박스를 타요(minimal/agent.cordis.yml 46–57행).
skill도 계층이에요. 전역 층은 배포 단위로 등록된 것(저장소 플러그인), preset 층은 preset을 따라다니는 것. 읽을 때 가까운 층의 동명이 그냥 이기고, 정렬 가중치는 같은 층 안에서만 먹혀요. 크리에이티브 모드의 editing-cordis-compositions skill은 preset 디렉터리에 살며 preset과 함께 복사·편집돼요. 이유는 yml 주석에 있어요: 이 배포의 두 평면을 말하고, 복사 단위는 preset이에요(cordis/agent.cordis.yml 248–254행). 설계 기록은 계층 간 병합 정렬안을 일부러 기각했어요. 가림은 단호해야 하고, 아니면 모델이 동명 skill 둘을 보고 헷갈려요(.agents/notes/implemented/architecture/2026-08-09-layered-skill-registry.zh.md).
define은 실행하지 않아요cordis_define은 인자·문법만 검사하고 소스를 불변 Package로 기록해요. 승인을 신청하지 않고, 실행하지 않고, currentPackageId도 안 움직여요. 돌리려면 cordis_run을 다시 호출해야 해요. 정의와 활성화를 나누니, 망가뜨려도 롤백할 대상이 남아요.
실패해도 포인터는 그대로cordis_run은 완전 성공 후에만 currentPackageId를 바꿔요. 시작 실패면 옛 current는 그대로예요. 버전 변경은 kind:"existing"으로 새 Package를 추가하고, 옛 버전은 영원히 남겨요 — 롤백은 옛 ID를 run하는 것뿐이에요.
경계는 신뢰예요크리에이티브 모드 파일 머리 원문: “Treat a session on this preset as shell access”. 모델이 쓴 JS가 살아 있는 런타임에 붙어 돌고, 샌드박스 안전망은 없어요. 방어선은 누가 이 preset을 쓸 수 있는지에 그려지고, 코드 자체는 울타리를 치지 않아요.
첫 증거는 크리에이티브 모드 YAML의 파일 머리예요. 앞 여덟 줄은 무엇인지: 표준 모드에 자기 지시 도구 세트. 뒤 네 줄은 신뢰 선언으로, “shell 권한으로 대하라”를 설정 파일 주석에 적어 두었어요:
# The `cordis` agent preset: the standard coding agent, plus the ability to
# read and write the runtime it is running in.
#
# It exists so a person can ask an agent to author another agent. Everything in
# `standard` is here unchanged; what is added is the self-referential Cordis
# toolset, a skill that teaches composition authoring, and a persona that says
# which of the two planes an edit belongs to.
#
# TRUST: `cordis_mount` evaluates model-written JavaScript against the live
# runtime, and a composition this agent writes becomes a preset other sessions
# mount. Treat a session on this preset as shell access — the toolset's own
# documentation makes the same statement.
apps/cli/config/agent-presets/cordis/agent.cordis.yml, 확인일 2026-08-13. 코드 블록은 소스 원문을 유지합니다.둘째 증거는 skill 레지스트리의 병합 읽기예요. 코드를 안 붙여도 말할 수 있어요. collectFresh는 모든 층을 한 줄로 세워요: 전역 층이 맨 앞, preset 스코프 체인은 먼 조상이 앞·본 층이 맨 뒤. 그다음 순서대로 각 층 항목을 같은 Map에 넣고, 키는 skill 이름이에요. Map은 나중에 쓴 값이 앞을 덮으니, 가까운 층 동명이 먼 층을 자동 교체해요. 가림은 Map.set 한 번이고, 계층 간 가중치 비교는 없어요. 함수 머리 주석은 이 규칙을 도구 레지스트리 가림 규칙과 맞추고, 정렬 가중치는 같은 층 안 동명에만 적용된다고 덧붙여요.
출처: packages/skill/skill/src/index.ts 552–566행의 collectFresh, 확인일 2026-08-13.
기억할 메커니즘이 둘 더 있어요. 출처는 여기. 첫째, 동적 플러그인이 도구 세트 모양을 중간에 바꾸면 세션 로그가 변경 후 전체 요청 헤더를 기록해 “모델이 보는 것 ⟺ 로그에 있는 것” 불변식을 지켜요(.agents/notes/implemented/feature/2026-07-08-self-referential-cordis-toolset.zh.md). 둘째, persona는 Agent가 배포판 preset 디렉터리를 절대 편집하지 말라고 못 박아요. 업그레이드가 통째로 덮어쓰고, cordis preset을 망가뜨리면 자기가 서 있는 모드를 끄는 셈이에요 — 고치려면 복사본을 만들어 고치세요(cordis/agent.cordis.yml 27행).
Claude Code는 frontmatter 있는 markdown 한 장으로 역할을 정의해요: description, 사용 가능 도구, model을 적고, AgentTool 호출 인자로 frontmatter의 model 필드를 임시 덮을 수도 있어요(원고 study/chapters/05-multi-agent.md 32–38행이 AgentTool.tsx inputSchema를 인용). Skills도 같아요: 디렉터리 하나에 SKILL.md 한 장. 이 길은 “설정이 역할을 기술한다”예요. 역할이 달라질 수 있는 축은 프레임워크가 frontmatter에 열어 둔 필드에 달려 있어요.
DSH preset은 “플러그인 조합 한 덩어리가 역할”이에요. persona는 조합 속 평범한 플러그인 한 줄이고, 도구·압축 전략·subagent 백엔드와 동급이에요. 미니멀 모드는 파일시스템 구현 전체를 바꾸고 압축을 끌 수도 있어요 — frontmatter 필드로는 못 담는 깊이예요. 대가도 직설이에요. preset을 쓰려면 두 평면과 isolate realm을 알아야 해서 markdown보다 문턱이 훨씬 높아요. 그래서 크리에이티브 모드가 수업 skill을 들고 다니고, 런타임을 읽는 cordis_inspect_query를 붙여요. 한쪽은 낮은 문턱의 역할 카드, 한쪽은 풀파워 조합 언어 — 누가 역할을 쓰는지에 대해 두 집은 생각이 많이 달라요.
경계 시나리오 둘을 추론해 보세요
첫째: 크리에이티브 모드 Agent가 잠깐 헷갈려 배포판 cordis/agent.cordis.yml을 직접 고치다 망가뜨리면, 다음에 크리에이티브 모드를 쓰려는 세션에는 무슨 일이 생길까요? persona 27행이 왜 “복사본을 만들어 고치라”를 철칙으로 쓰나요? 둘째: 다섯 번째 모드를 직접 조립할 때, 두 preset이 모두 게시하고 싶은 동명 서비스 줄을 각 파일에 남겨 두고 둘 다 isolate realm에 안 싸면, 두 세션이 동시에 마운트되면 어떻게 될까요? 힌트: 미니멀 모드가 realm으로 fs를 가리는 방식을 다시 보세요.