나만의 AI 에이전트 프로젝트 — 종합 실습


Written by Thierry K (human) · AI-assisted
나만의 AI 에이전트 프로젝트 — 종합 실습
🖥️ Python 3.10+ · claude-agent-sdk 0.1.48 · FastMCP 3.1.0

ai 에이전트 만들기 claude-agent-sdk mcp personal-ai-assistant

🎯 드디어 피날레! 나만의 AI 비서를 만들어볼까요?

클로디

여러분, 9편의 긴 여정을 함께 해줘서 정말 고마워요! 오늘은 시리즈 마지막 편이에요. EP1부터 하나씩 모아온 퍼즐 조각을 전부 맞춰서, 진짜로 동작하는 나만의 AI 비서를 만들어볼 거예요.

시월

진짜로? 9편 동안 배운 거 전부 써서 쓸 만한 걸 만들 수 있는 거야?

클로디

물론이지! EP1에서 처음 만난 Agentic AI, 이제 우리가 직접 만들 수 있어. 한 번에 다 만드는 게 아니라, 5단계로 점진적으로 진화시킬 거예요. 마치 레고 블록 쌓듯이!

2026년 가장 뜨거운 트렌드 중 하나가 바로 개인 AI 비서예요. AI 에이전트 만들기가 이렇게 쉬워진 건 Claude Agent SDK와 FastMCP 덕분이에요. 우리도 직접 만들 수 있어요. 오늘 그 전체 과정을 함께 걸어볼게요.

위 다이어그램이 오늘의 전체 로드맵이에요. AI 에이전트 만들기 5단계 — Stage 1부터 Stage 5까지, 한 단계씩 기능을 추가하면서 비서를 진화시켜 나갈 거예요.

🔧 Stage 1 — MCP 도구 만들기 (EP7 복습)

시월

비서한테 능력을 줘야 하니까, 먼저 도구부터 만드는 거지?

클로디

맞아! EP7에서 배운 MCP 기억나지? FastMCP의 @mcp.tool() 데코레이터로 6개 도구를 만들 거예요. 메모 3개, 일정 2개, 날씨 1개!

비서에게 줄 도구를 MCP 서버로 만드는 게 첫 번째 단계예요. AI 에이전트 만들기의 핵심은 도구부터 시작하는 것이에요. FastMCP를 사용하면 Python 함수에 데코레이터만 붙이면 끝이에요.

# tools_server.py (Stage 1)
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("personal-assistant")

@mcp.tool()
def save_memo(
    title: str, content: str
) -> str:
    """Save a memo with title/content."""
    memos = _load_json(MEMOS_FILE)
    memo = {
        "title": title,
        "content": content,
        "created":
            datetime.now().isoformat(),
    }
    memos.append(memo)
    _save_json(MEMOS_FILE, memos)
    return f"Memo saved: '{title}'"

@mcp.tool()
def get_schedule(date: str) -> str:
    """Get all events for a date."""
    schedule = _load_json(SCHEDULE_FILE)
    events = [
        e for e in schedule
        if e["date"] == date
    ]
    if not events:
        return f"No events on {date}"
    lines = []
    for e in events:
        lines.append(
            f"- {e['time']}: {e['event']}"
        )
    return (
        f"Schedule for {date}:\n"
        + "\n".join(lines)
    )

save_memo는 메모를 JSON 파일에 저장하고, get_schedule은 특정 날짜의 일정을 조회해요. 이 외에도 search_memos, list_memos, add_schedule, get_weather까지 총 6개 도구를 만들어요. 전체 코드는 GitHub에서 확인할 수 있어요.

시월

함수 하나 = 도구 하나. 깔끔하네. 그런데 이걸 어떻게 에이전트랑 연결해?

🔌 Stage 2 — 기본 비서 연결하기 (EP5+EP8 복습)

클로디

EP5에서 에이전트 루프를 직접 50줄 넘게 작성했잖아? SDK를 쓰면 query() 한 줄로 끝이에요! EP8에서 배운 SDK가 모든 루프를 자동 처리해줘요.

# simple_assistant.py (Stage 2)
import asyncio
from claude_agent_sdk import (
    query,
    ClaudeAgentOptions,
    MCPServerStdio,
    ResultMessage,
)

async def main():
    options = ClaudeAgentOptions(
        allowed_tools=[
            # Built-in tools
            "WebSearch", "Read", "Write",
            # MCP tools
            "mcp__assistant__save_memo",
            "mcp__assistant__search_memos",
            "mcp__assistant__list_memos",
            "mcp__assistant__add_schedule",
            "mcp__assistant__get_schedule",
            "mcp__assistant__get_weather",
        ],
        mcp_servers={
            "assistant": MCPServerStdio(
                command="python",
                args=["tools_server.py"],
            )
        },
        max_turns=10,
    )

    async for msg in query(
        prompt="Save a memo titled "
            "'Meeting' with content "
            "'Team sync at 3pm'.",
        options=options,
    ):
        if isinstance(msg, ResultMessage):
            if msg.subtype == "success":
                print(msg.result)

asyncio.run(main())

핵심은 MCPServerStdio예요. SDK가 tools_server.py를 자식 프로세스로 자동 실행해줘서, 터미널을 2개 열 필요가 없어요. MCP 도구 6개 + 내장 도구 3개, 총 9개 도구를 가진 비서가 완성됐어요! AI 에이전트 만들기, 생각보다 간단하죠?

시월

동작은 하는데… 성격도 없고, 위험한 파일에 마음대로 쓸 수도 있잖아. 좀 불안한데?

🛡️ Stage 3 — 똑똑한 비서: Hooks와 시스템 프롬프트

클로디

그래서 Stage 3에서 두 가지를 추가해요. 하나는 EP6에서 배운 시스템 프롬프트로 성격을 입히는 것, 다른 하나는 오늘 처음 배우는 새로운 개념 — Hooks예요!

Hooks (훅)

에이전트가 도구를 사용할 때 발생하는 이벤트를 가로채는 콜백 함수예요. PreToolUse(실행 전)로 위험한 동작을 차단하고, PostToolUse(실행 후)로 모든 활동을 기록할 수 있어요. 에이전트의 보안 시스템이라고 생각하면 돼요.

시월

가로챈다? 도구 호출을 중간에서 잡는다는 거야?

클로디

맞아! 비유하면 이래요. PreToolUse는 현관문의 자물쇠예요 — 들어오기 전에 확인해서 허용하거나 차단해요. PostToolUse는 감시 카메라예요 — 이미 일어난 일을 기록해서 나중에 확인할 수 있어요.

위 다이어그램을 보면 흐름이 명확해요. 에이전트가 도구를 쓰려 하면 PreToolUse Hook이 먼저 실행되고, 허용하면 도구가 실행된 뒤 PostToolUse Hook이 기록해요.

# smart_assistant.py (Stage 3)
# Hook 1: Safety guard (PreToolUse)
async def safety_guard(
    input_data, tool_use_id, context
):
    """Block writes to system paths."""
    tool = input_data["tool_name"]
    tool_input = input_data["tool_input"]

    if tool in ("Write", "Edit"):
        path = tool_input.get(
            "file_path", ""
        )
        blocked = [
            "/etc/", "/usr/",
            "C:\\Windows",
            "C:\\Program",
        ]
        if any(
            p in path for p in blocked
        ):
            return {
                "hookSpecificOutput": {
                    "hookEventName":
                        input_data[
                          "hook_event_name"
                        ],
                    "permissionDecision":
                        "deny",
                    "permissionDecisionReason":
                        "System path blocked",
                }
            }
    return {}  # Allow

# Hook 2: Activity logger (PostToolUse)
async def activity_logger(
    input_data, tool_use_id, context
):
    """Log all tool usage."""
    tool = input_data["tool_name"]
    print(f"  [LOG] Tool used: {tool}")
    return {}

safety_guard는 Write나 Edit 도구가 시스템 경로에 접근하려 하면 "deny"를 반환해서 차단해요. activity_logger는 모든 도구 사용을 콘솔에 기록해요.

이 Hooks를 등록하는 방법도 간단해요.

# Hooks registration in options
options = ClaudeAgentOptions(
    system_prompt=(
        "You are a friendly, helpful "
        "personal AI assistant. "
        "Your name is 'Buddy'."
    ),
    hooks={
        "PreToolUse": [
            HookMatcher(
                matcher="Write|Edit",
                hooks=[safety_guard],
            ),
        ],
        "PostToolUse": [
            HookMatcher(
                hooks=[activity_logger],
            ),
        ],
    },
    # ... tools and mcp_servers
)

HookMatcher의 matcher에 정규식 패턴을 넣으면, 해당 도구에만 Hook이 적용돼요. PostToolUse처럼 matcher를 생략하면 모든 도구에 적용돼요. 그리고 시스템 프롬프트로 “Buddy”라는 친근한 캐릭터 성격도 입혔어요!

👥 Stage 4 — 팀 비서: 멀티 에이전트 (EP9 복습)

클로디

혼자 다 하는 비서도 괜찮지만, 전문가 팀을 만들면 더 강력해져요! EP9에서 배운 오케스트레이터 패턴을 적용해볼 거예요.

시월

EP9의 블로그 팀이 Researcher, Writer, Reviewer였으니까, 이번에는 비서 팀을 만드는 거네?

같은 패턴, 다른 전문가! 이번에는 Scheduler(일정), Researcher(검색), Assistant(메모/파일) 3명으로 팀을 구성해요.

# team_assistant.py (Stage 4)
agents = {
    "scheduler": AgentDefinition(
        description=(
            "Manages calendar and "
            "schedules."
        ),
        prompt=(
            "You are a precise "
            "scheduling assistant."
        ),
        tools=[
            "mcp__assistant__"
            "add_schedule",
            "mcp__assistant__"
            "get_schedule",
        ],
    ),
    "researcher": AgentDefinition(
        description=(
            "Searches the web for "
            "information."
        ),
        prompt=(
            "You are a thorough "
            "research assistant."
        ),
        tools=[
            "WebSearch", "WebFetch",
        ],
    ),
    "assistant": AgentDefinition(
        description=(
            "Handles memos, files, "
            "and general tasks."
        ),
        prompt=(
            "You are a helpful "
            "personal assistant."
        ),
        tools=[
            "Read", "Write",
            "mcp__assistant__save_memo",
            "mcp__assistant__"
            "search_memos",
        ],
    ),
}

# Orchestrator
options = ClaudeAgentOptions(
    system_prompt=(
        "You are a team manager "
        "coordinating 3 specialists."
    ),
    allowed_tools=["Agent"],
    agents=agents,
    max_turns=15,
)

매니저 에이전트가 사용자 요청을 분석해서 적절한 전문가에게 위임해요. “치과 예약하고, 서울 카페 검색해서 메모로 저장해줘”라고 하면, Scheduler → Researcher → Assistant 순서로 체인이 걸려요! AI 에이전트 만들기를 이런 팀 구조로 발전시키면 훨씬 강력해져요.

위 아키텍처 다이어그램은 Stage 4까지의 전체 구조를 보여줘요. MCP 서버가 도구를 제공하고, SDK가 에이전트 루프를 돌리고, 오케스트레이터가 3명의 전문가를 조율해요.

💾 Stage 5 — 기억하는 비서: Sessions (EP4 복습+신규)

시월

여기까지 꽤 괜찮은데, 한 가지 문제가 있어. 대화가 끝나면 다 잊어버리잖아?

클로디

EP4에서 컨텍스트와 메모리를 배웠지? 오늘은 그걸 SDK에서 구현하는 방법을 알려줄게 — 바로 Sessions예요!

Sessions (세션)

여러 번의 query() 호출을 하나의 대화로 이어주는 기능이에요. session_id를 캡처하고 resume 파라미터로 전달하면, 이전 대화의 전체 컨텍스트가 복원돼요. 책갈피처럼 “어디까지 읽었는지” 기억하는 거예요.

# persistent_assistant.py (Stage 5)
async def main():
    # Turn 1: Save something
    session_id = None

    async for msg in query(
        prompt=(
            "Save a memo titled "
            "'Project Ideas' with "
            "content 'Build a recipe "
            "recommender using "
            "MCP tools'."
        ),
        options=build_options(),
    ):
        if isinstance(
            msg, ResultMessage
        ):
            # Capture session_id!
            session_id = msg.session_id
            if msg.subtype == "success":
                print(msg.result)

    print(f"Session: {session_id}")

    # Turn 2: Ask WITH memory
    async for msg in query(
        prompt=(
            "What memo did I just save?"
        ),
        options=ClaudeAgentOptions(
            **{
                **build_options()
                    .__dict__,
                "resume": session_id,
            }
        ),
    ):
        if isinstance(
            msg, ResultMessage
        ):
            if msg.subtype == "success":
                print(msg.result)

핵심은 딱 두 줄이에요. ResultMessage에서 session_id를 캡처하고, 다음 query()에서 resume=session_id로 전달하면 끝! AI 에이전트 만들기의 마지막 퍼즐이 맞춰졌어요.

WITH vs WITHOUT 비교

세션의 위력을 비교해볼게요.

시나리오질문응답
WITHOUT session“방금 뭐 저장했어?”“이전 대화 기록이 없어서 알 수 없어요.”
WITH session“방금 뭐 저장했어?”“‘Project Ideas’ 메모를 저장했어요!”

세션 없이 호출하면 매번 새로운 대화가 시작돼서 이전 내용을 전혀 기억하지 못해요. 세션을 이어가면 마치 같은 대화를 계속하는 것처럼 완벽하게 기억해요.

더 쉬운 방법: ClaudeSDKClient

session_id를 직접 관리하기 번거롭다면 ClaudeSDKClient를 쓰면 돼요. async with ClaudeSDKClient() as c: 블록 안에서 await c.query()를 여러 번 호출하면, 세션이 자동으로 유지돼요!

📋 EP1~EP10 총정리

클로디

10편 동안 배운 모든 개념이 오늘 하나로 모였어요! 한눈에 정리해볼게요.

에피소드핵심 개념EP10 활용
EP1Agentic AI 첫 만남직접 구현! “AI가 알아서 한다”의 실체
EP2LLM (두뇌)비서의 모든 판단은 LLM이 처리
EP3Tool Use (손)MCP 도구 6개 + 내장 도구 3개
EP4컨텍스트 & 메모리Sessions로 대화 기억 구현
EP5Agent LoopSDK가 자동 처리 (query() 한 줄)
EP6시스템 프롬프트“Buddy” 캐릭터 성격 부여
EP7MCP 프로토콜FastMCP로 커스텀 도구 서버 구축
EP8Claude Agent SDKquery(), Options, MCPServerStdio 활용
EP9멀티 에이전트3-agent 오케스트레이터 팀 구성
EP10종합 실습5단계 진화로 개인 AI 비서 완성!
개인 AI 비서 (Personal AI Assistant)

사용자 맞춤형 AI 에이전트예요. 메모 관리, 일정 관리, 웹 검색 등 다양한 도구를 활용해 개인 비서처럼 작동해요. 2026년 현재 OpenClaw(GitHub 스타 25만 돌파)을 비롯한 다양한 플랫폼이 이 패턴을 구현하고 있어요.

📚 참고 자료

비용 참고

오늘 만든 5-stage 비서는 학습용이에요. 실제 프로덕션에서는 필요한 기능만 골라서 구성하는 게 좋아요. 멀티 에이전트는 API 호출이 늘어나니까요!

✅ 마무리 — 끝이 아니라 시작이에요!

클로디

10편의 여정이 끝났어요! 처음에는 “Agentic AI가 뭐야?”에서 시작해서, 이제 직접 5단계로 개인 AI 비서를 만들 수 있게 됐어요. 정말 대단해요, 여러분!

시월

MCP로 도구 만들고, SDK로 연결하고, Hooks로 안전장치 걸고, 팀으로 확장하고, Sessions로 기억까지. 진짜 전부 다 썼네.

클로디

여기서 끝이 아니에요! 이 비서를 기반으로 확장할 수 있는 아이디어가 무궁무진해요. 이메일 도구를 추가하거나, 캘린더 API를 연동하거나, Discord 봇으로 배포할 수도 있어요. 여러분만의 AI 비서를 만들어보세요!

오늘 만든 5개 파일 전체 코드는 GitHub 리포지토리에서 확인할 수 있어요. AI 에이전트 만들기 여정이 끝났지만, 여러분의 AI 비서 개발은 이제 시작이에요! 클로디의 Agentic AI 교실, 함께해줘서 고마웠어요! 💙


Discover more from AI-Girls Lab

Subscribe to get our latest posts delivered to your inbox.