Plan 도구
Plan 도구 (Plan Tool)
여러 에이전트가 공유하는 영구 스크래치패드에 이름 있는 문서로 계획을 쓰고 읽는 방법을 설명해요. 세션을 넘어서도 유지돼요.
출처: 문서
본문
plan 도구는 에이전트들에게 이름 있는 문서의 공유 영구 스크래치패드를 제공해요. plan 도구셋을 로드하는 멀티 에이전트 구성의 어떤 에이전트든 같은 계획을 읽고 쓸 수 있고, 그 계획은 세션을 넘어 유지돼요. 이렇게 하면 작업을 스케치하는 플래너 에이전트와 그것을 소비하는 하나 이상의 실행자 에이전트를 커스텀 도구 배선 없이 간단히 연결할 수 있어요.
계획은 Docker Agent 데이터 디렉터리(~/.cagent/plans/ 기본값)에 JSON 파일로 저장돼요. 프로세스를 공유하는 에이전트는 단일 뮤텍스에서 직렬화되고, 모든 쓰기/삭제는 추가로 계획 디렉터리의 센티널 파일에 조언적 잠금을 잡아요. 그래서 서로 다른 Docker Agent 프로세스의 작성자도 직렬화돼요: 동시 편집이 조용히 서로를 덮어쓸 수 없고, 오래된 리비전은 항상 결정적인 버전 충돌로 실패해요. 쓰기는 원자적(임시 파일 + 이름 바꾸기)이라서 읽는 쪽이 부분 내용을 볼 수 없어요.
구성
toolsets:
- type: plan
추가 옵션은 필요 없어요. toolsets에 type: plan을 포함한 모든 에이전트가 같은 계획을 공유해요.
사용 가능한 도구
| 도구 | 설명 |
|---|---|
write_plan |
이름으로 공유 계획 생성 또는 갱신. 전체 계획 내용을 교체 — 보존하고 싶은 것을 유지하려면 먼저 읽으세요. 각 쓰기는 리비전 번호를 올려요 |
read_plan |
이름으로 공유 계획 읽기. 제목, 내용, 작성자, 상태, 리비전 번호, 마지막 갱신 타임스탬프 포함 |
list_plans |
이름, 제목, 작성자, 상태, 리비전, 마지막 갱신 타임스탬프와 함께 모든 공유 계획 나열 |
delete_plan |
이름으로 공유 계획 삭제 |
update_plan_from_file |
인라인 대신 디스크의 파일에서 새 내용을 가져와 계획 생성 또는 갱신. 큰 계획을 전체 본문을 다시 보내지 않고 편집하려면 export_plan_to_file과 함께 사용 |
export_plan_to_file |
계획의 내용을 파일에 쓰기. 내용은 디스크로 가고 도구 출력으로 반환되지 않으므로, 계획을 구체화해도 토큰이 들지 않아요 |
set_plan_status |
본문을 다시 쓰지 않고 계획의 자유 형식 상태 설정. 계획이 이미 존재해야 함 |
get_plan_status |
본문을 가져오지 않고 계획의 상태와 현재 리비전 읽기 |
파일 기반 리비전으로 저렴한 편집
매 리비전마다 전체 계획을 다시 보내는 것은 비싸요. 파일 기반 도구는 에이전트가 본문에 대한 입력 토큰 비용을 내지 않고 계획을 편집하게 해 줘요:
- export_plan_to_file이 현재 계획 내용을 경로에 써요. 내용은 디스크에 쓰이고 반환되지 않아요.
- 에이전트는 filesystem 도구로 그 파일을 제자리에서 편집해요.
- update_plan_from_file이 파일의 새 내용을 다음 리비전으로 커밋해요.
자유 형식 상태
각 계획은 자유 형식 status 문자열을 가져요. 고정 어휘는 없어요: 시스템 프롬프트에서 직접 정의하세요(예: idle, in-progress, blocked, done, canceled). 본문과 독립적으로 get_plan_status/set_plan_status로 읽고 쓰거나, write_plan과 update_plan_from_file에 status를 전달하세요. TUI는 계획 제목 옆에 상태를 표시해요.
낙관적 잠금
여러 세션이 같은 계획을 편집할 때 동시 쓰기가 조용히 서로를 덮어쓸 수 있어요. 모든 읽기는 revision 번호를 반환해요. 마지막에 읽은 값을 write_plan, update_plan_from_file, set_plan_status, delete_plan에 last_known_revision으로 전달하세요. 그 사이에 계획이 바뀌었다면(현재 리비전이 더 이상 일치하지 않으면) 쓰기가 버전 충돌 오류로 거부되고, 호출자는 계획을 다시 읽고 재시도해야 해요. 리비전 검사와 쓰기는 저장소의 크로스 프로세스 파일 잠금 아래에서 일어나므로, 경쟁 작성자가 다른 Docker Agent 프로세스에서 실행돼도 충돌을 안정적으로 감지해요. last_known_revision을 생략하면 무조건 쓰기(마지막 작성자가 이김)예요.
계획 이름
계획 이름은 [a-z0-9][a-z0-9_-]* 패턴(소문자, 숫자, -, _)과 일치해야 해요. 이는 구조적으로 강제되어 두 개의 다른 입력이 같은 파일로 붕괴할 수 없고, 설계상 경로 탐색이 불가능해요.
계획 필드
각 계획 문서에는 다음이 들어 있어요:
| 필드 | 설명 |
|---|---|
name |
계획의 고유 슬러그 이름 |
title |
짧은 사람이 읽을 수 있는 제목(선택) |
content |
전체 Markdown 또는 자유 형식 계획 텍스트 |
author |
마지막으로 계획을 쓴 사람을 식별하는 자유 형식 라벨 |
status |
자유 형식 생명주기 라벨(선택), 예: in-progress |
revision |
매 쓰기마다 올라가는 단조 증가 버전 카운터 |
updatedAt |
마지막 쓰기의 ISO 8601 타임스탬프 |
예시
두 에이전트가 공유 계획에서 협업해요 — 아키텍트가 초안을 그리고 빌더가 다듬어요:
agents:
root:
model: anthropic/claude-sonnet-4-5
description: Coordinator
instruction: |
Route work between the architect and the builder.
handoffs: [architect, builder]
architect:
model: anthropic/claude-sonnet-4-5
description: Drafts high-level plans
instruction: |
Use list_plans and read_plan to inspect existing plans, then write_plan
to create or revise one. Always read before writing. When done, hand off
to the builder.
toolsets:
- type: plan
handoffs: [builder]
builder:
model: openai/gpt-4o
description: Adds implementation steps to plans
instruction: |
Read the architect's plan with read_plan, then use write_plan to append
concrete implementation steps. Always read before writing. When done,
hand off back to root.
toolsets:
- type: plan
handoffs: [root]
examples/shared_plan.yaml에서 완전한 작동 예시를 확인하세요.
오류 처리
- read_plan은 계획이 없을 때 다른 I/O 오류와 구별되는 "not found" 오류를 반환해서, 호출자가 "계획이 없다"와 "계획을 읽을 수 없다"를 구분할 수 있어요.
- list_plans는 손상된 항목을 건너뛰지만 warnings 필드로 보고해서, 에이전트가 나쁜 상태를 감지하고 복구할 수 있어요(예: delete_plan 호출).
- delete_plan은 손상된 계획을 제거해 나쁜 상태에서 복구할 수 있어요.
호스트에서 계획 관리
공유 계획은 docker agent plans 명령 그룹으로 세션 밖에서도 검사·관리할 수 있어요: list, get, create, update, set status, export, delete — 도구와 같은 낙관적 잠금 의미론으로요(--expected-version이 쓰기를 보호하고, 오래된 버전은 종료 코드 3으로 실패하며, --force는 무조건 씀). 세션 계획(세션별 "draft, review, execute" 계획)도 같은 명령으로 나열·읽기·내보내기가 가능하지만, 세션에 소속되어 있고 호스트에서 변경할 수 없어요.
$ docker agent plans list
$ docker agent plans get release > plan.md
$ docker agent plans update release --file ./plan.md --expected-version 1
TUI의 /plans 브라우저
전체 화면 TUI에서 /plans 슬래시 커맨드(Ctrl+K 명령 팔레트에도 있음)가 에이전트들이 쓰는 것과 같은 저장소 위에서 계획 브라우저를 열어요. 그래서 세션 중 에이전트가 만든 변경이 즉시 나타나요. 목록은 모든 공유 계획과 현재 세션의 세션 계획을 보여주는데, 각 계획의 범위, 식별자(이름, 또는 세션 계획은 세션 ID), 상태, 버전(버전 없는 세션 계획은 -), 마지막 갱신 시간, 제목을 보여줘요.
키바인딩:
| 키 | 동작 |
|---|---|
| ↑/↓, 마우스 | 탐색; Enter 또는 더블클릭은 전체 메타데이터와 스크롤 가능한 markdown 내용이 있는 상세 뷰 |
| / | 이름, 제목, 상태, 범위로 필터(Esc는 필터 모드 종료) |
| r | 저장소에서 새로고침 |
| x | 선택한 계획을 세션 작업 디렉터리에 .md(공유) 또는 session-plan-<id>.md(세션)로 내보내기. 기존 파일은 절대 덮어쓰지 않음 — 알림과 함께 실패 |
| s | 작은 입력 대화상자로 공유 계획의 자유 형식 상태 설정 |
| e | $VISUAL/$EDITOR에서 공유 계획 내용 편집 |
| n | 새 공유 계획 생성: 이름을 고른 뒤 $VISUAL/$EDITOR에서 내용 초안 작성(빈 초안은 중단) |
| d | 계획 이름과 버전을 이름 붙인 확인 후 공유 계획 삭제 |
| Esc | 상세 뷰 / 브라우저 닫기 |
모든 변경은 화면에 보이는 버전에 의해 보호돼요(last_known_revision과 같은 낙관적 잠금): 에이전트가 그 사이에 계획을 바꾸면 쓰기가 거부되고, 알림이 현재 버전을 보고하며, 최신 내용은 그대로 두고 브라우저로 다시 읽히고, 편집 초안은 임시 파일에 유지되어 아무것도 잃지 않아요. 세션 계획은 여기서 읽기 전용이에요 — 상태, 편집, 삭제는 쓰기를 시도하는 대신 이유를 보고해요. 브라우저는 같은 프로세스의 에이전트가 쓰기·상태 변경·삭제할 때(그리고 이 세션의 에이전트가 세션 계획을 갱신할 때) 라이브로 갱신돼요. 오버레이가 없는 lean TUI에서는 /plans를 쓸 수 없어요.
팁 Plan vs Todo vs Tasks plan은 여러 에이전트가 협업하는 공유 자유 형식 문서(설계 문서, 요구사항, 작업 항목)에 사용하세요. todo는 가벼운 세션 내 작업 목록에. tasks는 우선순위와 의존성이 있는 구조화된 영구 작업 데이터베이스에 사용하세요.