Next '26 개발자 기조연설: 기술과 도구를 사용한 ADK 에이전트 빌드

1. 소개

이 Codelab에서는 에이전트 개발 키트 (ADK)를 사용하여 정교한 마라톤 계획 에이전트를 빌드합니다. 잘 구조화된 시스템 프롬프트부터 동적 스킬 로드 및 MCP 도구 매핑에 이르기까지 에이전트의 기능을 점진적으로 검토합니다. 마지막으로 에이전트를 로컬에서 테스트하고 에이전트 런타임 (Agent Engine)에 배포합니다.

실습할 내용

  • ADK 에이전트 프로젝트 초기화
  • 구조화된 빌더를 사용하여 강력한 시스템 프롬프트 작성
  • 실제 위치 컨텍스트를 위한 Google 지도 MCP 도구 추가
  • 에이전트의 도구 모음에 기술을 동적으로 로드
  • 로컬에서 에이전트 실행 테스트
  • Agent Engine (Cloud Run)에 에이전트를 배포합니다.

필요한 항목

  • 웹브라우저(예: Chrome)
  • 결제가 사용 설정된 Google Cloud 프로젝트
  • Python에 대한 기본적인 지식

이 Codelab은 전문 생성형 AI 에이전트를 빌드하려는 중급 개발자를 대상으로 합니다.

예상 소요 시간: 45분

이 Codelab에서 만든 리소스의 비용은 2달러 미만이어야 합니다.

2. 시작하기 전에

Google Cloud 프로젝트 만들기

  1. Google Cloud 콘솔의 프로젝트 선택기 페이지에서 Google Cloud 프로젝트를 선택하거나 만듭니다.
  2. Cloud 프로젝트에 결제가 사용 설정되어 있는지 확인합니다. 프로젝트에 결제가 사용 설정되어 있는지 확인하는 방법을 알아보세요.

Cloud Shell 시작

Cloud Shell은 Google Cloud에서 실행되는 명령줄 환경으로, 필요한 도구가 미리 로드되어 제공됩니다.

  1. Google Cloud 콘솔 상단에서 Cloud Shell 활성화를 클릭합니다.
  2. Cloud Shell에 연결되면 인증을 확인합니다.
    gcloud auth list
    
  3. 프로젝트가 구성되었는지 확인합니다.
    gcloud config get project
    
  4. 프로젝트가 예상대로 설정되지 않은 경우 설정합니다.
    export PROJECT_ID=<YOUR_PROJECT_ID>
    gcloud config set project $PROJECT_ID
    

인증을 확인합니다.

gcloud auth list

프로젝트를 확인합니다.

gcloud config get project

필요한 경우 설정합니다.

export PROJECT_ID=<YOUR_PROJECT_ID>
gcloud config set project $PROJECT_ID

API 사용 설정

다음 명령어를 실행하여 필요한 모든 API를 사용 설정합니다.

gcloud services enable \
  aiplatform.googleapis.com \
  run.googleapis.com \
  secretmanager.googleapis.com \
  mapstools.googleapis.com \
  storage.googleapis.com \
  cloudresourcemanager.googleapis.com \
  serviceusage.googleapis.com

Google 지도 API 키 만들기

Google 지도 MCP 도구를 사용하려면 지도 API 키를 생성해야 합니다.

  1. Google Cloud 콘솔에서 검색창을 사용하여 Google Maps Platform > 사용자 인증 정보로 이동합니다.
  2. 메시지가 표시되면 Google Cloud 프로젝트를 확인합니다.
  3. 사용자 인증 정보 만들기를 클릭한 후 API 키를 선택합니다.
  4. 생성된 API 키를 복사합니다. 다음 단계에 이 항목이 필요합니다.

3. 환경 설정

이 Codelab의 코드는 GitHub에서 호스팅됩니다. 디렉터리 구조와 필수 하위 구성요소 (예: skills/ 디렉터리)가 포함된 저장소를 클론합니다.

  1. 저장소를 클론하고 프로젝트 폴더로 이동합니다.
git clone https://github.com/GoogleCloudPlatform/next-26-keynotes
cd next-26-keynotes/devkey/demo-1
  1. Python 가상 환경을 설정하고 ADK를 설치합니다.
uv venv
source .venv/bin/activate
uv sync
  1. 지도 API 키를 설정합니다. 애플리케이션이 환경 변수에서 읽습니다.
export GOOGLE_MAPS_API_KEY="<YOUR_MAPS_API_KEY>"

환경 변수 구성

시뮬레이터 에이전트는 구성을 위해 .env 파일을 사용합니다. 샘플 파일을 복사하고 프로젝트 ID로 업데이트합니다.

  1. 샘플 환경 파일을 복사합니다.
cp planner_agent/sample.env planner_agent/.env
  1. planner_agent/.env을 열고 GOOGLE_CLOUD_PROJECT 필드를 실제 Google Cloud 프로젝트 ID로 업데이트하고 GOOGLE_MAPS_API_KEY 필드를 생성한 Google 지도 API 키로 업데이트합니다.

파일은 다음과 비슷하게 표시됩니다.

GOOGLE_GENAI_USE_VERTEXAI=1
GOOGLE_CLOUD_PROJECT=<YOUR_PROJECT_ID>
GOOGLE_CLOUD_LOCATION=us-west1
GOOGLE_MAPS_API_KEY=<YOUR_MAPS_API_KEY>
GOOGLE_CLOUD_AGENT_ENGINE_ENABLE_TELEMETRY=true
OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=true
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true
ADK_CAPTURE_MESSAGE_CONTENT_IN_SPANS=true

4. 새 ADK 에이전트 만들기

에이전트를 정의하는 핵심 파일 planner_agent/agent.py을 살펴봅니다.

build-agents-with-skills 저장소에서 에이전트는 ADK의 Agent 클래스를 사용하여 초기화됩니다. 기본 모델과 ID 이름을 지정하고 다른 모듈에 정의된 지침과 도구를 가져옵니다.

planner_agent/agent.py를 열어 초기화 코드를 검사합니다.

instruction="Answer user questions to the best of your knowledge"
description="A helpful assistant for user questions."
tools=[]

# ...

root_agent = Agent(
    model='gemini-3-flash-preview',
    name='planner_agent',
    description=description,
    instruction=instruction,
    tools=tools
)

Agent 클래스는 메시지 기록, 도구 조정, LLM 통신을 추상화하여 에이전트의 동작에 집중할 수 있도록 합니다.

현재 에이전트는 매우 일반적입니다. 다른 LLM과 마찬가지로 상호작용할 수 있습니다.

uv run adk run planner_agent

이 명령어는 에이전트와의 채팅을 시작합니다. gemini-3-flash-preview를 모델로 사용하며 기본적인 질문에 답변할 수 있습니다.

Running agent planner_agent, type exit to exit.
[user]: What is the length of a Marathon
[planner_agent]: The official length of a marathon is **26.2 miles**, which is
equivalent to **42.195 kilometers**.

에이전트는 마라톤에 관한 몇 가지 사실을 이미 알고 있습니다. 하지만 규칙과 경로 계획이 포함된 적절한 마라톤을 계획하기에는 충분하지 않습니다.

5. 시스템 프롬프트 만들기

시스템 프롬프트 (요청 사항)는 에이전트의 동작을 지시합니다. 이 프로젝트는 하나의 거대한 문자열 대신 PromptBuilder (planner_agent/utils.py)를 사용하여 동적으로 안내를 구성합니다.

planner_agent/prompts.py을 열어 프롬프트가 논리적 섹션으로 구조화되는 방식을 확인합니다.

from collections import OrderedDict
from .utils import PromptBuilder

ROLE = """\
...
"""

RULES = """\
...
"""

WORKFLOW = """\
...
"""

###

# Planner instructions with no tools mentioned
PLANNER_INSTRUCTION_NO_TOOLS = PromptBuilder(
    OrderedDict(
        role=ROLE,
        rules=RULES,
        tools=TOOLS_PROMPT_ONLY,
        workflow=WORKFLOW_PROMPT_ONLY,
    )
).build()

# Planner instruction with skills and tools defined
PLANNER_INSTRUCTION = PromptBuilder(
    OrderedDict(
        role=ROLE,
        rules=RULES,
        skills=SKILLS,
        tools=TOOLS,
        workflow=WORKFLOW,
    )
).build()

planner_agent/agent.py에서는 이미 가져왔습니다.

TODO: Replace Instruction and Description이 있는 섹션을 찾아 instructiondescription 변수 재할당의 주석 처리를 삭제합니다.

해당 코드 섹션은 다음과 같이 표시됩니다.

instruction=PLANNER_INSTRUCTION_NO_TOOLS
description="Expert GIS analyst for marathon route and event planning."

도구를 참조하지 않는 에이전트용 프롬프트 버전을 가져오고 있습니다. 이후 단계에서 도구를 추가합니다.

이 버전의 에이전트를 테스트할 수 있습니다.

uv run adk run planner_agent

채팅 창에서 다음 프롬프트를 전송합니다.

Plan a marathon for 10000 participants in Las Vegas on April 24, 2027 in the
evening timeframe

잠시 후 다음과 비슷한 응답이 표시됩니다.

Running agent planner_agent, type exit to exit.
[user]: Plan a marathon for 10000 participants in Las Vegas on April 24, 2027 in the evening timeframe
[planner_agent]: Here is the comprehensive marathon plan for Las Vegas.

As requested, I have designed this event for an evening start on April 24, 2027. Because certain parameters (theme and budget) were not specified, I have applied pragmatic defaults: this will be a "Neon Nights" scenic theme to capitalize on the evening Strip, operating on a moderate-to-high budget given the infrastructure needed to secure major Las Vegas corridors.

### 1. Intent Alignment
*   **City & Theme:** Las Vegas, Nevada. Theme: "Neon Nights" an evening race maximizing the visual impact of the illuminated city.
*   **Date & Time:** Saturday, April 24, 2027. Late April evenings in Las Vegas offer optimal running weather (temperatures dropping from ~70°F at sunset to ~60°F). Race start is 6:30 PM (sunset is approx. 7:20 PM).
...
...

프롬프트를 잘 정의하면 출력이 이미 예상 결과에 훨씬 더 가까워집니다. 다음 단계에서는 에이전트를 한 단계 더 발전시킬 도구를 추가합니다.

6. 기술 및 도구 추가

planner_agent/agent.py에서 스킬과 도구를 사용 설정하려면 TODO: Replaces Tools이 있는 섹션을 찾아 다음 두 줄의 주석 처리를 삭제합니다. 코드는 다음과 같습니다.

instruction=PLANNER_INSTRUCTION
tools=get_tools()

이 단계에서 필요한 코드 변경사항은 이것이 전부입니다. 이 섹션의 나머지 부분에서는 스킬과 도구의 개념을 설명합니다.

특기

에이전트 스킬은 ADK 에이전트가 특정 작업을 실행하는 데 사용할 수 있는 독립형 기능 단위입니다. 에이전트 기술은 에이전트 기술 사양에 따라 작업에 필요한 안내, 리소스, 도구를 캡슐화합니다. 스킬의 구조를 통해 에이전트의 운영 컨텍스트 창에 미치는 영향을 최소화하기 위해 스킬을 점진적으로 로드할 수 있습니다.

마라톤 계획 에이전트의 경우 다음과 같은 3가지 스킬이 정의되어 있습니다.

  1. gis-spatial-engineering - GeoJSON 데이터를 처리하여 마라톤 경로를 만드는 역할을 합니다.
  2. 매핑 - Google 지도 도구를 사용하여 장소와 날씨 정보를 검색합니다.
  3. race-director - 마라톤 경로가 계획 가이드라인을 따르는지 확인합니다.

스킬에는 스크립트, 추가 애셋, 참조가 있을 수 있습니다.

애플리케이션은 모든 스킬을 로드하고 이를 planner_agent/tools.py의 도구로 제공합니다. get_tools() 함수에서 이 작업이 어떻게 이루어지는지 확인하세요.

def get_tools() -> list:
    """Build the planner's tool list with lazy-loaded skills."""
    from google.adk.code_executors.unsafe_local_code_executor import UnsafeLocalCodeExecutor

    skills_dir = pathlib.Path(__file__).parent / "skills"

    skills = []
    if skills_dir.exists():
        skills = [
            load_skill_from_dir(d)
            for d in sorted(skills_dir.iterdir())
            if d.is_dir() and not d.name.startswith("_") and (d / "SKILL.md").exists()
        ]

    additional_tools = _load_additional_tools(skills_dir)

    skill_toolset = SkillToolset(
        skills=skills,
        code_executor=UnsafeLocalCodeExecutor(),
        additional_tools=additional_tools,
    )

    tools = [
        skill_toolset,
        PreloadMemoryTool(),
    ]

    tools.extend(get_maps_tools())

    return tools

가장 흥미로운 부분은 ADK의 load_skill_from_dir 메서드입니다. ADK에서 스킬을 만드는 또 다른 방법은 인라인입니다. 이 Codelab에서는 사용되지 않지만 다음과 같습니다.

from google.adk.skills import models

greeting_skill = models.Skill(
    frontmatter=models.Frontmatter(
        name="greeting-skill",
        description=(
            "A friendly greeting skill that can say hello to a specific person."
        ),
    ),
    instructions=(
        "Step 1: Read the 'references/hello_world.txt' file to understand how"
        " to greet the user. Step 2: Return a greeting based on the reference."
    ),
    resources=models.Resources(
        references={
            "hello_world.txt": "Hello! So glad to have you here!",
            "example.md": "This is an example reference.",
        },
    ),
)

매핑 도구 추가

마라톤 계획자는 경로를 생성하기 위해 공간 컨텍스트가 필요합니다. Google 지도 MCP (모델 컨텍스트 프로토콜) 서버를 통합하여 이를 제공합니다.

planner_agent/tools.py에서 MCP 서버가 ApiRegistry 도구에 등록되는 방식을 확인하세요.

from google.adk.integrations.api_registry import ApiRegistry

class MapsApiRegistry(ApiRegistry):
    """ApiRegistry subclass that strips ADC headers to force API key auth."""

    def get_toolset(self, *args, **kwargs):  # noqa: ANN002, ANN003
        toolset = super().get_toolset(*args, **kwargs)
        conn = getattr(toolset, "_connection_params", None)
        headers = getattr(conn, "headers", None) if conn else None
        if headers:
            headers.pop("Authorization", None)  # type: ignore[union-attr]
            headers.pop("x-goog-user-project", None)  # type: ignore[union-attr]
        return toolset

def get_maps_tools() -> list:
    """Return Maps MCP toolset if configured."""
    project_id = os.getenv("GOOGLE_CLOUD_PROJECT", "").strip()
    maps_key = _resolve_maps_key()

    if not project_id or not maps_key:
        return []

    # Map the MCP server location on Google Cloud
    mcp_server_name = f"projects/{project_id}/locations/global/mcpServers/google-mapstools.googleapis.com-mcp"
    
    # Initialize the custom API registry that supports header injection
    api_registry = MapsApiRegistry(
        api_registry_project_id=project_id,
        header_provider=header_provider,
    )
    return [api_registry.get_toolset(mcp_server_name=mcp_server_name)]

MCP 도구 모음을 추가하면 에이전트가 Google 지도에 경로, 고도, 위치 세부정보를 쿼리하는 기능을 자동으로 얻게 됩니다.

7. 에이전트를 로컬에서 실행

이제 에이전트, 프롬프트, 도구가 연결되었으므로 에이전트를 로컬에서 실행합니다. 이번에는 adk web를 사용하여 스킬 로드 및 도구 호출 이벤트를 확인할 수 있습니다.

uv run adk web

다음과 비슷한 내용이 표시됩니다.

INFO:     Started server process [99665]
INFO:     Waiting for application startup.

+-----------------------------------------------------------------------------+
| ADK Web Server started                                                      |
|                                                                             |
| For local testing, access at http://127.0.0.1:8000.                         |
+-----------------------------------------------------------------------------+

INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
  1. 브라우저를 열고 터미널에 표시된 URL (일반적으로 http://localhost:8000)로 이동합니다.
  2. 왼쪽 상단의 드롭다운에서 planner_agent을 선택합니다.
  3. 채팅 창에서 다음 프롬프트를 전송합니다.
Plan a marathon for 10000 participants in Las Vegas on April 24, 2027 in the
evening timeframe

스킬이 로드되고 도구가 호출되는 것을 확인할 수 있습니다. 잠시 후 에이전트가 마라톤 계획을 생성합니다.

UI는 다음과 유사하게 표시됩니다.

ADK 웹 UI

8. 에이전트 배포

에이전트가 로컬에서 작동하는 방식에 만족하면 Cloud Run에서 에이전트를 안전하게 호스팅하는 Agent Engine에 에이전트를 배포할 수 있습니다.

에이전트를 배포하려면 ADK CLI 배포 명령어를 사용합니다.

uv run adk deploy agent_engine \
  --env_file planner_agent/.env \
  planner_agent

배포가 완료되면 CLI에서 에이전트의 보안 호스팅 엔드포인트를 출력합니다. 이제 이 엔드포인트를 프런트엔드 애플리케이션, 챗봇 또는 기타 백엔드 시스템에 통합할 수 있습니다. 에이전트 런타임 Playground를 사용하여 에이전트를 테스트할 수도 있습니다.

출력은 다음과 같이 표시됩니다.

Files and dependencies resolved
Deploying to agent engine...
✅ Created agent engine: projects/<PROJECT_ID>/locations/us-west1/reasoningEngines/<AGENT_ID>

제공된 Python 스크립트를 사용하여 에이전트와 통신할 수 있습니다.

  1. 샘플 환경 파일을 복사합니다.
cp sample.env .env
  1. .env를 열고 GOOGLE_CLOUD_PROJECT 필드를 실제 Google Cloud 프로젝트 ID로 업데이트합니다.

파일이 다음과 같이 표시됩니다.

GOOGLE_CLOUD_PROJECT=<YOUR_PROJECT_ID>
GOOGLE_CLOUD_LOCATION=us-west1
  1. 프로젝트의 에이전트를 나열할 수 있습니다.
python main.py list

다음과 비슷한 내용이 표시됩니다.

Listing deployed agents...

ID: <AGENT_ID> | Display Name: planner_agent

배포된 에이전트 ID가 있으면 프롬프트를 보낼 수 있습니다.

export AGENT_ID=<AGENT_ID>
python main.py prompt --agent-id ${AGENT_ID} --message "Plan a marathon for
10000 participants in Las Vegas on April 24, 2027 in the evening timeframe"

다음과 같은 출력이 표시됩니다.

Streaming response from agent <AGENT_ID>:

{'model_version': 'gemini-3-flash-preview', 'content': {'parts': [{'text': 'Here is a comprehensive
...
...
...

9. 삭제

Google Cloud 계정에 지속적으로 비용이 청구되지 않도록 하려면 이 Codelab 중에 만든 리소스를 삭제하세요.

배포로 생성된 Cloud Run 서비스를 삭제합니다.

python main.py delete --agent-id ${AGENT_ID}

Secret Manager에 Maps API 키를 저장한 경우 보안 비밀을 삭제합니다.

gcloud secrets delete maps-api-key --project=$PROJECT_ID

이 Codelab을 위해 새 Google Cloud 프로젝트를 만든 경우 전체 프로젝트를 삭제하여 연결된 모든 리소스와 API를 삭제할 수 있습니다.

gcloud projects delete $PROJECT_ID

10. 축하합니다

축하합니다. ADK를 사용하여 정교한 마라톤 계획 도우미 에이전트를 빌드했습니다.

학습한 내용

  • 에이전트 개발 키트 (ADK) 프로젝트 초기화
  • 모듈식 시스템 프롬프트에 PromptBuilder 활용
  • MCP 도구 및 ApiRegistry를 사용하여 매핑 기능 통합
  • SkillToolset을 사용하여 기술을 조건부로 로드
  • 로컬에서 테스트하고 Agent Engine에 배포

참조 문서