에이전트 행동 공간 설계하기
에이전트 하네스를 구축할 때 가장 어려운 부분 중 하나는 바로 행동 공간(action space)을 구성하는 것입니다.
Claude는 Tool Calling을 통해 작동하지만, Claude API에서는 bash, skills, 최근에는 코드 실행(code execution)과 같은 프리미티브를 사용해 다양한 방식으로 도구를 구성할 수 있습니다(Claude API에서 프로그래매틱 방식의 도구 호출에 대한 자세한 내용은 @RLanceMartin의 새 글에서 확인하세요).
이 모든 옵션을 고려할 때, 에이전트의 도구를 어떻게 설계해야 할까요? 코드 실행이나 bash 같은 단 하나의 도구만 있으면 충분할까요? 아니면 에이전트가 마주칠 수 있는 모든 사용 사례별로 50개의 도구를 준비해야 할까요?
저는 모델의 입장에서 생각해보기 위해 어려운 수학 문제를 푸는 상황을 상상해보곤 합니다. 문제를 해결하기 위해 어떤 도구가 필요할까요? 그것은 자신의 실력에 달려 있습니다!
종이가 최소한의 도구겠지만, 수동 계산이라는 한계가 있습니다. 계산기가 더 낫지만, 고급 기능을 사용하려면 사용법을 알아야 합니다. 가장 빠르고 강력한 옵션은 컴퓨터지만, 코드를 작성하고 실행할 줄 알아야 합니다.
이것이 에이전트를 설계하는 데 유용한 프레임워크입니다. 에이전트의 능력에 맞는 도구를 제공해야 합니다. 하지만 그 능력이 무엇인지 어떻게 알 수 있을까요? 주의를 기울이고, 출력 결과를 읽고, 실험해보면 됩니다. 에이전트처럼 보는 법을 배워야 합니다.
다음은 Claude Code를 구축하면서 Claude를 관찰하며 얻은 몇 가지 교훈입니다.
Elicitation 개선 및 AskUserQuestion 도구

AskUserQuestion 도구를 구축할 때 우리의 목표는 Claude가 질문을 더 잘할 수 있도록 하는 것이었습니다(종종 elicitation이라고 부릅니다).
Claude가 일반 텍스트로 질문을 할 수는 있었지만, 그 질문에 답변하는 데 불필요하게 시간이 많이 걸린다는 것을 발견했습니다. 사용자와 Claude 사이의 마찰을 줄이고 커뮤니케이션 대역폭을 어떻게 높일 수 있을까요?
시도 #1 - ExitPlanTool 수정
가장 먼저 시도한 것은 ExitPlanTool에 질문 배열을 계획과 함께 추가하는 파라미터를 넣는 것이었습니다. 이것이 구현하기 가장 쉬운 방법이었지만, 계획과 계획에 대한 질문을 동시에 요청하다 보니 Claude가 혼란스러워했습니다. 사용자의 답변이 계획 내용과 충돌하면 어떻게 될까요? Claude가 ExitPlanTool을 두 번 호출해야 할까요? 다른 접근 방식이 필요했습니다.
(ExitPlanTool을 만든 이유에 대한 자세한 내용은 프롬프트 캐싱에 관한 글에서 확인할 수 있습니다)
시도 #2 - 출력 형식 변경
다음으로는 Claude의 출력 지침을 수정하여 질문을 할 수 있는 약간 변형된 마크다운 형식을 제공하도록 시도했습니다. 예를 들어, 대괄호 안에 대안이 있는 불릿 포인트 질문 목록을 출력하도록 요청할 수 있었습니다. 그런 다음 해당 질문을 파싱하여 사용자에게 UI로 표시할 수 있었습니다.
이것이 가장 일반적인 변경 사항이었고 Claude도 이를 출력하는 데 꽤 능숙해 보였지만, 완벽하게 보장되지는 않았습니다. Claude가 추가 문장을 덧붙이거나, 옵션을 생략하거나, 완전히 다른 형식을 사용하기도 했습니다.
시도 #3 - AskUserQuestion 도구

마지막으로, Claude가 언제든지 호출할 수 있는 도구를 만들기로 결정했지만, 특히 계획 모드에서 호출하도록 프롬프트를 설정했습니다. 도구가 트리거되면 모달을 표시하여 질문을 보여주고 사용자가 답변할 때까지 에이전트의 루프를 차단했습니다.
이 도구를 통해 Claude에게 구조화된 출력을 요청할 수 있었고, Claude가 사용자에게 여러 옵션을 제공하도록 보장할 수 있었습니다. 또한 사용자가 Agent SDK에서 호출하거나 skills에서 참조하는 등 이 기능을 구성할 수 있는 방법도 제공했습니다.
가장 중요한 것은, Claude가 이 도구를 호출하는 것을 선호하는 것 같았고 출력 결과도 잘 작동한다는 점이었습니다. 아무리 잘 설계된 도구라도 Claude가 호출 방법을 이해하지 못하면 소용이 없습니다.
이것이 Claude Code에서 elicitation의 최종 형태일까요? 확실하지 않습니다. 다음 예시에서 보여드리겠지만, 한 모델에 잘 맞는 것이 다른 모델에는 최선이 아닐 수 있습니다.
기능 업데이트 - Tasks와 Todos

Claude Code를 처음 출시했을 때, 모델이 작업을 계속 추적하려면 Todo 리스트가 필요하다는 것을 깨달았습니다. Todos는 시작 시 작성되고 모델이 작업을 수행하면서 체크 표시할 수 있었습니다. 이를 위해 Claude에게 TodoWrite 도구를 제공했는데, 이 도구는 Todos를 작성하거나 업데이트하고 사용자에게 표시했습니다.
하지만 그때도 Claude가 해야 할 일을 잊어버리는 경우가 자주 발생했습니다. 이를 해결하기 위해 5턴마다 목표를 상기시키는 시스템 알림을 삽입했습니다.
하지만 모델이 개선됨에 따라 Todo 리스트를 상기시킬 필요가 없을 뿐만 아니라 오히려 제한적으로 느낄 수 있다는 것을 알게 되었습니다. Todo 리스트 알림을 받으면 Claude가 리스트를 수정하는 대신 고수해야 한다고 생각하게 되었습니다. 또한 Opus 4.5가 서브에이전트를 훨씬 더 잘 사용하게 된 것을 확인했지만, 서브에이전트들이 공유 Todo 리스트에서 어떻게 조율할 수 있을까요?
이를 확인한 후, TodoWrite를 Task 도구로 대체했습니다(Tasks에 대한 자세한 내용은 여기에서 확인하세요). Todos가 모델을 올바른 방향으로 유지하는 데 초점을 맞췄다면, Tasks는 에이전트들이 서로 소통하는 데 더 중점을 두었습니다. Tasks는 종속성을 포함할 수 있고, 서브에이전트 간에 업데이트를 공유할 수 있으며, 모델이 이를 수정하고 삭제할 수도 있었습니다.
모델의 역량이 향상됨에 따라, 한때 필요했던 도구가 오히려 모델을 제약할 수 있습니다. 어떤 도구가 필요한지에 대한 이전의 가정을 지속적으로 재검토하는 것이 중요합니다. 이것이 비슷한 역량 프로필을 가진 소수의 모델을 지원하는 것이 유용한 이유이기도 합니다.
검색 인터페이스 설계하기
Claude에게 특히 중요한 도구 세트는 자체 컨텍스트를 구축하는 데 사용할 수 있는 검색 도구입니다.
Claude Code가 처음 나왔을 때, 우리는 RAG 벡터 데이터베이스를 사용하여 Claude의 컨텍스트를 찾았습니다. RAG는 강력하고 빠르지만 인덱싱과 설정이 필요했고 다양한 환경에서 취약할 수 있었습니다. 더 중요한 것은, Claude가 이 컨텍스트를 직접 찾는 대신 제공받고 있었다는 점입니다.
하지만 Claude가 웹에서 검색할 수 있다면, 왜 코드베이스에서는 검색하지 못할까요? Claude에게 Grep 도구를 제공함으로써 파일을 검색하고 스스로 컨텍스트를 구축할 수 있게 했습니다.
Claude가 똑똑해질수록 올바른 도구가 주어지면 컨텍스트를 구축하는 데 점점 더 능숙해지는 패턴을 확인했습니다.
Agent Skills를 도입하면서 점진적 공개(progressive disclosure) 개념을 공식화했는데, 이를 통해 에이전트가 탐색을 통해 관련 컨텍스트를 점진적으로 발견할 수 있습니다.
Claude는 skill 파일을 읽을 수 있고, 해당 파일은 모델이 재귀적으로 읽을 수 있는 다른 파일을 참조할 수 있습니다. 실제로 skills의 일반적인 사용 사례 중 하나는 API 사용 방법이나 데이터베이스 쿼리 방법에 대한 지침을 제공하여 Claude에 더 많은 검색 기능을 추가하는 것입니다.
1년 동안 Claude는 자체 컨텍스트를 제대로 구축하지 못하는 상태에서 여러 파일 계층에 걸쳐 중첩 검색을 수행하여 필요한 정확한 컨텍스트를 찾을 수 있는 수준으로 발전했습니다.
점진적 공개는 이제 도구를 추가하지 않고도 새로운 기능을 추가하기 위해 사용하는 일반적인 기술입니다.
점진적 공개 - Claude Code Guide 에이전트
Claude Code에는 현재 약 20개의 도구가 있으며, 우리는 이 모든 도구가 정말 필요한지 끊임없이 자문하고 있습니다. 새 도구를 추가하는 기준은 높은데, 그 이유는 모델이 고려해야 할 옵션이 하나 더 늘어나기 때문입니다.
예를 들어, Claude가 Claude Code 사용 방법에 대해 충분히 알지 못한다는 것을 발견했습니다. MCP를 추가하는 방법이나 슬래시 명령어가 무엇을 하는지 물어보면 제대로 답변하지 못했습니다.
이 모든 정보를 시스템 프롬프트에 넣을 수도 있었지만, 사용자가 이에 대해 거의 묻지 않는다는 점을 고려하면 컨텍스트 부패(context rot)를 유발하고 Claude Code의 주요 임무인 코드 작성에 방해가 될 수 있었습니다.
대신, 점진적 공개 형태를 시도했습니다. Claude에게 문서 링크를 제공하여 로드한 후 더 많은 정보를 검색할 수 있게 했습니다. 이 방법은 작동했지만, Claude가 정답을 찾기 위해 많은 결과를 컨텍스트에 로드하는 경향이 있었고, 실제로 필요한 것은 정답뿐이었습니다.
그래서 Claude Code Guide 서브에이전트를 구축했습니다. 사용자가 Claude 자체에 대해 물을 때 Claude가 호출하도록 프롬프트가 설정되어 있으며, 이 서브에이전트는 문서를 효과적으로 검색하고 무엇을 반환할지에 대한 광범위한 지침을 가지고 있습니다.
완벽하지는 않습니다. Claude가 설정 방법에 대해 질문을 받으면 여전히 혼란스러워할 수 있지만, 예전보다 훨씬 나아졌습니다! 도구를 추가하지 않고도 Claude의 행동 공간에 기능을 추가할 수 있었습니다.
과학이 아닌 예술
도구 구축에 대한 엄격한 규칙을 기대하셨다면, 안타깝게도 이 가이드는 그런 내용이 아닙니다. 모델을 위한 도구를 설계하는 것은 과학인 동시에 예술입니다. 사용하는 모델, 에이전트의 목표, 작동 환경에 크게 의존합니다.
자주 실험하고, 출력 결과를 읽고, 새로운 것을 시도해보세요. 에이전트처럼 보는 법을 배우세요.





