Anthropic이 Claude Code를 개발하면서 AskUserQuestion, Task 도구 같은 에이전트 도구를 어떻게 설계하고 개선해 왔는지 소개한다. 도구의 효과를 극대화하려면 점진적 공개(progressive disclosure) 원칙을 적용하고, '에이전트의 눈으로 보는' 시각을 갖추는 것이 핵심이다.
에이전트 하네스를 구축할 때 가장 어려운 부분 중 하나는 바로 도구를 설계하는 일이다.
Claude는 전적으로 도구 호출(tool calling)을 통해 작동하는데, Claude API에서는 bash, 스킬, 코드 실행 같은 기본 요소를 활용해 다양한 방식으로 도구를 구성할 수 있다. (Claude API에서의 프로그래밍 방식 도구 호출에 대해 더 알고 싶다면 @RLanceMartin의 새 아티클을 참고하자.)
그렇다면 에이전트의 도구를 어떻게 설계해야 할까? bash나 코드 실행처럼 범용 도구 하나를 줄 것인가, 아니면 사용 사례마다 특화된 도구 50개를 줄 것인가?
모델의 입장에서 생각해보자. 어려운 수학 문제가 주어졌다고 상상해보라. 이 문제를 풀기 위해 어떤 도구가 필요할까? 정답은 자신의 능력에 따라 다르다.
종이와 펜이면 최소한의 도구는 갖춘 셈이지만, 손 계산의 한계를 벗어나기 어렵다. 계산기라면 더 낫겠지만, 고급 기능을 제대로 다룰 줄 알아야 한다. 가장 빠르고 강력한 선택은 컴퓨터지만, 코드를 작성하고 실행하는 방법을 알아야만 그 위력을 발휘할 수 있다.
이는 에이전트를 설계할 때 유용한 관점이다. 에이전트에게는 그 능력에 맞는 도구를 제공해야 한다. 그렇다면 그 능력이 어느 정도인지 어떻게 알 수 있을까? 출력 결과를 꼼꼼히 읽고, 실험하고, 관찰하는 수밖에 없다. 그렇게 에이전트의 눈으로 보는 법을 익히게 된다.
에이전트를 개발하다 보면 우리와 똑같은 고민에 부딪히게 된다. 언제 도구를 추가하고, 언제 제거하며, 그 판단 기준은 무엇인가. 이 글에서는 Claude Code를 개발하면서 이 질문들에 어떻게 답해왔는지 소개한다. 처음에 틀렸던 시도들도 함께.

AskUserQuestion 도구를 개발할 당시, 우리의 목표는 Claude가 질문하는 능력, 즉 흔히 '질문 유도(elicitation)'라고 부르는 기능을 개선하는 것이었다.
Claude가 평문으로 질문을 던질 수는 있었지만, 사용자가 그에 답하는 과정이 불필요하게 느껴질 만큼 번거로웠다. 사용자와 Claude 사이의 소통을 더 매끄럽고 밀도 있게 만들 방법이 없을까?
첫 번째 시도는 ExitPlanTool에 파라미터를 추가해, 플랜과 함께 질문 배열도 포함하는 방식이었다. 구현하기는 가장 쉬웠지만, 플랜 작성과 그에 관한 질문을 동시에 요구하는 구조가 Claude를 혼란스럽게 했다. 사용자의 답변이 플랜 내용과 충돌하면 어떻게 할 것인가? Claude가 ExitPlanTool을 두 번 호출해야 하는 걸까? 이 방식이 통하지 않는다는 판단이 서자 우리는 처음부터 다시 생각했다. (ExitPlanTool을 만든 이유에 대해서는 프롬프트 캐싱 관련 포스트에서 더 자세히 읽을 수 있다.)
다음으로 시도한 방법은 Claude의 출력 지침을 수정해, 질문에 특화된 마크다운 형식을 활용하는 것이었다. 예를 들어, 선택지를 괄호 안에 넣은 불릿 포인트 형식으로 질문 목록을 출력하도록 요청하고, 이를 파싱해 사용자 UI로 표시하는 방식이었다.
Claude는 대체로 이 형식을 따랐지만, 일관성이 없었다. 불필요한 문장을 덧붙이거나, 선택지를 빠뜨리거나, 구조 자체를 무시하는 경우도 있었다. 다음 방법으로 넘어갈 시간이었다.

결국 우리가 선택한 방법은, Claude가 언제든 호출할 수 있는 도구를 만드는 것이었다. 특히 플랜 모드에서는 이 도구를 적극적으로 활용하도록 유도했다. 도구가 실행되면 모달 창으로 질문을 표시하고, 사용자가 답변을 완료할 때까지 에이전트 루프를 멈추도록 했다.
이 도구 덕분에 구조화된 출력을 유도할 수 있었고, Claude가 사용자에게 여러 선택지를 제공하도록 보장할 수 있었다. 또한 에이전트 SDK에서 직접 호출하거나 스킬에서 참조하는 방식으로, 사용자가 이 기능을 유연하게 조합해 활용할 수 있게 되었다.
무엇보다 중요한 것은, Claude가 이 도구를 즐겨 호출했고 출력 결과도 훌륭했다는 점이다. 아무리 잘 설계된 도구라도 Claude가 올바르게 호출하지 못한다면 아무 소용이 없으니까.
이것이 Claude Code에서 질문 유도의 최종 형태일까? 아마 아닐 것이다. Claude의 역량이 성장하는 만큼, 그것을 지원하는 도구도 함께 진화해야 한다. 다음 섹션에서는 한때 유용했던 도구가 오히려 걸림돌이 된 사례를 살펴본다.

Claude Code를 처음 출시했을 때, 우리는 모델이 작업 흐름을 유지하려면 할 일 목록(todo list)이 필요하다는 사실을 깨달았다. 작업 시작 시 할 일을 작성하고, 하나씩 완료해 나가는 방식이었다. 이를 위해 Claude에게 TodoWrite 도구를 제공했고, 이 도구로 할 일 목록을 작성·수정하고 사용자에게 표시할 수 있었다.
그럼에도 Claude가 해야 할 일을 잊어버리는 경우가 잦았다. 이에 대응하기 위해 5턴마다 목표를 상기시키는 시스템 알림을 삽입했다.
모델 성능이 향상되면서 할 일 목록이 오히려 제약이 되기 시작했다. 목록을 반복해서 상기시키면, Claude는 방향을 바꿔야 할 상황에서도 목록을 수정하는 대신 그대로 따라야 한다고 인식했다. Opus 4.5가 서브에이전트 활용 능력을 크게 끌어올린 것도 관찰했는데, 이때 여러 서브에이전트가 하나의 할 일 목록을 어떻게 공유하고 조율할 것인지가 새로운 과제로 떠올랐다.
이러한 상황을 인식한 우리는 TodoWrite 기능을 태스크(Task) 도구로 대체했다. 할 일 목록이 모델의 작업 흐름 유지에 초점을 맞췄다면, 태스크 도구는 에이전트 간 소통을 위한 것이다. 태스크는 의존성을 포함할 수 있고, 서브에이전트 간에 업데이트를 공유할 수 있으며, 모델이 직접 수정하거나 삭제하는 것도 가능하다.
모델 역량이 높아질수록, 한때 필요했던 도구가 이제는 오히려 발목을 잡을 수 있다. 어떤 도구가 필요한지에 대한 기존 가정을 꾸준히 재검토하는 것이 중요하다. 비슷한 역량 수준을 가진 소수의 모델에 집중해 지원하는 것이 유리한 이유도 여기에 있다.
우리가 개발한 도구 중 가장 중요한 것은, Claude가 스스로 컨텍스트를 찾을 수 있게 해주는 도구들이다.
Claude Code를 내부적으로 처음 출시했을 때는 RAG를 사용했다. 벡터 데이터베이스로 코드베이스를 사전 인덱싱하고, 하네스가 관련 코드 조각을 검색해 응답 전에 Claude에게 전달하는 방식이었다. RAG는 강력하고 빠르지만, 인덱싱과 초기 설정이 필요하고 다양한 환경에서 불안정할 수 있었다. 무엇보다, Claude가 컨텍스트를 직접 찾는 것이 아니라 단순히 전달받는 구조였다는 점이 문제였다.
Claude가 웹을 검색할 수 있다면, 코드베이스도 검색하지 못할 이유가 없지 않을까? Grep 도구를 제공함으로써, Claude가 직접 파일을 검색하고 스스로 컨텍스트를 구성할 수 있게 되었다.
Claude가 똑똑해질수록, 적절한 도구가 주어졌을 때 컨텍스트를 구성하는 능력도 함께 향상된다.
에이전트 스킬(Agent Skills)을 도입하면서 우리는 점진적 공개(progressive disclosure)라는 개념을 체계화했다. 이는 에이전트가 탐색을 통해 관련 컨텍스트를 점진적으로 발견해 나가는 방식이다.
이제 Claude는 스킬 파일을 읽고, 그 파일에서 참조하는 다른 파일을 재귀적으로 읽어나갈 수 있게 되었다. 실제로 스킬의 대표적인 활용 사례 중 하나는 API 사용법이나 데이터베이스 쿼리 방법을 안내함으로써 Claude의 검색 능력을 확장하는 것이다.
1년이라는 시간 동안, Claude는 자체적으로 컨텍스트를 구성하지 못하는 수준에서 출발해, 이제는 여러 파일 계층을 넘나드는 중첩 검색으로 필요한 컨텍스트를 정확히 찾아낼 수 있는 수준으로 성장했다.
점진적 공개는 이제 도구를 추가하지 않고도 새로운 기능을 확장할 때 우리가 즐겨 쓰는 기법이 되었다. 그 이유는 다음 섹션에서 설명한다.
현재 Claude Code에는 약 20개의 도구가 있으며, 팀은 이 모두가 정말 필요한지 꾸준히 검토한다. 새 도구를 추가하는 기준은 높다. 도구가 하나 늘어날 때마다 모델이 고려해야 할 선택지도 하나씩 늘어나기 때문이다.
예를 들어, Claude가 Claude Code 사용법 자체에 대해 충분히 알지 못한다는 점을 발견했다. MCP를 추가하는 방법이나 슬래시 커맨드의 기능을 물어보면 답하지 못했다.
이 정보를 시스템 프롬프트에 넣을 수도 있었겠지만, 사용자가 이런 질문을 하는 경우가 드문 만큼 불필요한 컨텍스트 낭비(context rot)를 일으켜 Claude Code의 본업인 코드 작성에 방해가 될 것이었다.
대신 점진적 공개 방식을 시도했다. 필요할 때 Claude가 불러와 검색할 수 있도록 문서 링크를 제공했다. 효과는 있었지만, 한 문장으로 답할 수 있는 내용을 찾기 위해 문서의 방대한 부분을 컨텍스트로 끌어오는 문제가 생겼다.
그래서 우리는 Claude Code Guide를 만들었다. 사용자가 Claude Code 자체에 대해 질문하면 호출되는 서브에이전트다. 이 서브에이전트는 자신의 컨텍스트 안에서 문서를 검색하고, 무엇을 어떻게 찾아 추출할지에 대한 세부 지침을 따르며, 최종 답변만을 메인 에이전트에게 돌려준다. 덕분에 메인 에이전트의 컨텍스트는 깔끔하게 유지된다.
완벽한 해결책은 아니다(Claude Code의 초기 설정 방법을 물어보면 여전히 혼란스러워할 수 있다). 그러나 새로운 도구를 추가하지 않고도 Claude의 행동 공간을 확장할 수 있었다.
모델을 위한 도구를 설계하는 일은 과학인 동시에 예술이다. 사용하는 모델, 에이전트의 목표, 그리고 운영 환경에 따라 답이 크게 달라진다.
우리의 조언을 한마디로 요약하자면: 자주 실험하고, 출력 결과를 꼼꼼히 읽으며, 새로운 시도를 멈추지 마라. 그리고 무엇보다, 에이전트의 눈으로 보려고 노력하라.
지금 바로 시작해보세요 Claude Code.
글쓴이 소개: Thariq Shihipar은 Anthropic의 테크니컬 스태프로, Claude Code를 개발하고 있다.