
Claude Agent SDK로 커스텀 AI 에이전트를 직접 만드는 구현 절차와 주의사항【2026】
요약
Claude Agent SDK(Python)를 사용하여 커스텀 AI 에이전트를 구축하는 방법과 주의사항을 다룹니다. 도구 정의를 위한 @tool 데코레이터 사용법부터 MCP 서버 연동, 권한 설정 모드(permission_mode)에 따른 자동화 구현 방식을 상세히 설명합니다.
핵심 포인트
- Claude Agent SDK를 활용한 독자적 도구(Tool) 구현 및 MCP 서버 연동 방법
- @tool 데코레이터 사용 시 도구 이름 변환 규칙(mcp__서버명__함수명) 주의
- 자동화 목적에 따른 4가지 permission_mode(default, acceptEdits, bypassPermissions, plan) 활용
- 단발성 태스크는 query()를, 지속적인 대화는 ClaudeSDKClient를 사용
Claude Agent SDK(Python 버전)를 사용하여, 독자적인 도구를 가진 자작 AI 에이전트를 구동하는 과정까지를 작성한다.
상정 독자는 다음과 같다.
- Claude Code는 업무에서 사용하고 있지만, SDK를 통해 "자신의 앱에 통합하는 것"은 처음인 경우
- LangChain 등의 다른 프레임워크로 Agent 구현 경험은 있지만, Claude Agent SDK는 만져본 적이 없는 경우
- "실행해 보았더니 권한 문제로 막혔다"라는 상황을 미리 알고 싶은 경우
전제 환경은 다음과 같다.
-
Python 3.11 이상
-
claude-agent-sdk(pip 패키지, 2026년 시점의 최신 계열) -
Anthropic API 키 (환경 변수
ANTHROPIC_API_KEY) -
query()함수만으로 최소 구성의 에이전트는 몇 줄 만에 구동 가능 -
독자적인 도구는
@tool데코레이터 +create_sdk_mcp_server로 로컬 MCP 서버로서 생성 -
permission_mode를 명시하지 않으면, 도구 실행 시마다 승인 대기 상태로 멈춤 (자동화 용도로는 문제 발생) -
멀티 턴(Multi-turn)으로 만들려면
query()를 일회성으로 쓰는 것이 아니라ClaudeSDKClient를 사용
pip install claude-agent-sdk
export ANTHROPIC_API_KEY="sk-ant-..."
먼저 도구가 없는 일문일답부터 시작한다.
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions
async def main():
...
query()는 비동기 제너레이터(Asynchronous Generator)로, 텍스트나 도구 실행 결과 메시지를 순차적으로 스트리밍한다. 단발성 태스크라면 이것으로 충분하다.
에이전트에게 사내 API를 호출하게 하는 등 독자적인 도구를 갖게 하고 싶다면, @tool 데코레이터로 로컬 함수를 정의하고 create_sdk_mcp_server로 묶어서 MCP 서버화한다.
from claude_agent_sdk import tool, create_sdk_mcp_server, ClaudeAgentOptions
@tool("get_deploy_status", "지정된 서비스의 최신 배포 상황을 가져온다", {"service_name": str})
async def get_deploy_status(args):
...
도구 이름은 SDK 내부에서 mcp__<서버명>__<함수명> 형태로 변환된다. allowed_tools에는 이 변환된 이름을 작성해야 한다는 점에 주의해야 한다. 함수 이름만 작성하면 인식되지 않는다.
기본 설정 상태에서는 도구 실행 시마다 승인 확인이 개입된다. 배치 처리나 자동화 스크립트에서는 명시적으로 지정한다.
options = ClaudeAgentOptions(
mcp_servers={"deploy": my_server},
allowed_tools=["mcp__deploy__get_deploy_status"],
...
주요 선택지는 다음 4가지다.
| 모드 | 동작 |
|---|---|
default | 매번 확인 (대화 용도 적합) |
acceptEdits | 파일 편집은 자동 승인, 그 외에는 확인 |
bypassPermissions | 모든 도구 자동 승인 (신뢰할 수 있는 샌드박스 한정) |
plan | 실행하지 않고 계획만 세우게 함 |
bypassPermissions는 편리하지만, 실행 환경을 격리하지 않으면 위험한 명령어도 그대로 통과된다. CI나 일회성 컨테이너 이외의 환경에서는 피하는 것이 좋다.
Slack 봇처럼 대화를 지속시키고 싶다면 ClaudeSDKClient를 사용한다.
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions
async def chat_loop():
options = ClaudeAgentOptions(permission_mode="acceptEdits")
...
client 인스턴스가 세션 상태(대화 이력)를 유지해주므로, 매 턴마다 system_prompt를 다시 구성할 필요는 없다.
@tool
@tool의 세 번째 인자(파라미터 정의)와 실제로 전달되는 args의 타입이 일치하지 않으면, 도구 호출(tool call) 자체는 성공하더라도 함수 내부에서 KeyError나 TypeError가 발생한다. 숫자를 str로 정의해버려서 모델이 문자열로 전달했을 때 고생한 적이 있다. 파라미터 정의는 간이 타입 힌트(type hint)일 뿐이므로, 실행 시점의 유효성 검사(validation)는 직접 구현해야 한다.
permission_mode를 지정하는 것을 잊으면, 대화 환경이 없는 실행(cron이나 백그라운드 작업) 시 승인 프롬프트가 누구에게도 표시되지 않은 채 프로세스가 중단(hang)된다. 로그를 봐도 단순히 "도구를 호출하려다 멈춘 것"처럼만 보여서 원인 파악에 시간이 걸렸다. 자동 실행용 스크립트에서는 반드시 이를 명시하도록 철저히 관리해야 한다.
ClaudeSDKClient로 세션을 재사용하면 도구 실행 결과나 과거 응답이 축적되어 컨텍스트(context)가 비대해진다. 장시간 가동되는 챗봇의 경우 수십 턴 정도 지나면 응답이 느려지고 비용도 급증한다. 일정 간격으로 세션을 새로 생성하는(대화 요약을 system_prompt에 포함하여 재시작하는) 운영 방식이 필요하다.
Claude Agent SDK는 본래 Claude Code의 내부 구현을 라이브러리로 분리한 것으로, 도구 실행, 권한 관리, MCP 연동과 같은 "에이전트를 안전하게 구동하는" 기반을 그대로 사용할 수 있다. LangChain 등과 달리 Anthropic 모델 운용을 전제로 권한 모델이 처음부터 내장되어 있다는 것이 특징이며, permission_mode는 그 상징적인 기능이라고 할 수 있다.
- 최소 구성이라면
query()한 번, 독자적인 도구가 필요하다면@tool+create_sdk_mcp_server사용 permission_mode는 자동화 용도라면 반드시 명시할 것. 지정 누락은 무한 대기로 직결됨- 커스텀 도구의 인자는 직접 유효성 검사를 넣을 것. SDK 측의 타입 힌트는 실행 시점의 체크까지 해주지는 않음
- 멀티 턴(multi-turn) 운용 시에는 컨텍스트 비대화를 고려하여 세션을 재설정하는 시점을 설계해 둘 것
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기