1. 개요
여러 제약 조건이 있는 여행 요청(예: 교토에서 역사적인 사원, 현지 라멘, 현대 미술관을 제외한 100달러짜리 당일 여행 계획)을 처리하려면 정형화된 선호 사항을 추출하고, 장소를 동시에 조사하고, 항목별 초안을 합성하고, 총비용을 감사한 후 응답해야 합니다. ADK 1.x에서는 이러한 단계를 조정하려면 SequentialAgent, ParallelAgent, LoopAgent 래퍼를 중첩하고, 모든 중간 출력을 세션 상태에 저장하고, 정제 루프를 종료하기 위해 추가 LLM 도구 호출을 호출해야 했습니다.
이 Codelab에서는 에이전트 개발 키트(ADK) 2 그래프 워크플로(Workflow)를 사용하여 에이전트 플랫폼에서 멀티 에이전트 여행 플래너를 빌드합니다. 세 가지 단계에 걸쳐 순차적 에지 체인(node_input)에서 전문 Agent 노드(gemini-3.8-flash 기반)를 연결하고, JoinNode와 동기화된 동시 google_search 연구원을 팬아웃하고, 초기 초안이 감사를 통과할 때마다 미세 조정을 건너뛰는 결정론적 Python 라우터(Event(route=...))를 사용하여 예산 및 제외 규칙을 적용합니다.
기본 요건
- Python 프로그래밍에 대한 기본적 숙련도
- 생성형 AI 개념 및 AI 에이전트 기초에 대한 이해
학습 내용
Workflow에지 튜플을 사용하여 ADK 2에서 멀티 에이전트 파이프라인을 선언하는 방법- ADK 2가 에지를 따라 출력을
node_input로 직접 전달하고 세션 상태 키를 함수 매개변수로 바인딩하는 방법 JoinNode를 사용하여 동시 연구 브랜치를 팬아웃하고 출력을 병합하는 방법Event(route=...)를 사용하여 Python에서 제한된 메이커-체커 주기를 결정론적으로 라우팅하는 방법- ADK 웹 UI에서 컴파일된 워크플로 그래프, 동시 실행 타임라인, 상태 델타를 검사하는 방법
필요한 항목
- Google 계정(워크숍 크레딧을 신청하는 경우 개인
@gmail.com계정 사용) - 강사가 제공한 워크숍 크레딧 링크(QR 코드를 스캔할 휴대전화 카메라 포함) 또는 활성 Cloud Billing 계정
- Chrome(개인 계정과 직장 계정이 혼합되지 않도록 시크릿 창을 사용하는 것이 좋음)
2. Google Cloud 크레딧 신청(선택사항)
이벤트 크레딧 링크가 있는 워크숍에 참석하는 경우 Google Developer Program 크레딧을 신청하여 신용카드 없이 결제 계정을 프로비저닝하세요.
이벤트 크레딧 신청하기
- 시크릿 창에서 워크숍 크레딧 링크를 열고
@gmail.com계정으로 로그인합니다. - 혜택 신청에서 크레딧 신청을 클릭합니다.

- Google Developer Program 프로필을 만들라는 메시지가 표시되면 양식을 작성합니다.
- 스캔하여 사람임을 인증하세요가 표시되면 휴대전화로 QR 코드를 스캔하고 인증을 완료합니다. QR 코드가 표시되지 않으면 새로고침하고 크레딧 신청을 다시 클릭합니다.

- 이벤트 크레딧을 신청했습니다.가 표시되는지 확인한 후 결제 계정 열기를 클릭합니다.

🔍 작업 확인
결제 계정 설정에는 최대 3분이 소요됩니다.
- Google Cloud Billing을 열거나 URL을 시크릿 창에 복사하고 결제 계정을 선택합니다.
https://console.cloud.google.com/billing
GDP Credit계정에 활성 상태가 표시될 때까지 새로고침합니다.

3. Google Cloud 프로젝트 만들기(선택사항)
이 Codelab의 모든 리소스가 격리되고 쉽게 정리될 수 있도록 전용 Google Cloud 프로젝트를 만듭니다.
- 프로젝트 만들기를 열거나 URL을 시크릿 창에 복사합니다.
https://console.cloud.google.com/projectcreate
- 프로젝트 세부정보를 입력합니다.
- 프로젝트 이름: 예:
google-cloud-workshop - 결제 계정(표시되는 경우):
GDP Credit(또는 활성 결제 계정)를 선택합니다. - 상위 리소스: 조직 없음(또는 필요한 경우 조직 선택)
- 프로젝트 이름: 예:
- 프로젝트 이름 아래에 생성된 프로젝트 ID를 기록한 후 만들기를 클릭합니다.

🔍 작업 확인
오른쪽 상단 툴바에서 알림을 클릭하고 프로젝트 생성이 완료되면 프로젝트 선택을 클릭합니다.

4. 환경 설정
Google Cloud Shell을 구성하고, Agent Platform API를 사용 설정하고, uv를 사용하여 격리된 Python 3.12 가상 환경을 만듭니다.
Cloud Shell 구성
- Google Cloud 콘솔 툴바에서 Cloud Shell 활성화(
>_)를 클릭하거나 Google Cloud Shell을 직접 열거나 URL을 시크릿 창에 복사합니다.
https://shell.cloud.google.com/?show=ide,terminal

- 메시지가 표시되면 승인을 클릭합니다.

- 터미널의 번호가 매겨진 메뉴에서 활성 Google Cloud 프로젝트 ID를 선택합니다.
unset CLOUDSDK_CORE_PROJECT
PS3="Select your project (e.g. 1): "
select PROJECT_ID in $(gcloud projects list --format="value(projectId)"); do
[ -n "$PROJECT_ID" ] && gcloud config set project "$PROJECT_ID" && break
done
다음과 비슷한 출력이 표시됩니다. 태그가 지정되지 않은 프로젝트에도 정보 [environment: untagged] 줄이 출력됩니다.
1) google-cloud-workshop-4210 2) my-cloud-project-8812 Select your project (e.g. 1): 1 Updated property [core/project].
선택한 프로젝트 ID가 Cloud Shell 프롬프트에 노란색으로 강조 표시되는지 확인합니다.

필요한 API 사용 설정
ADK 에이전트가 Gemini 모델을 호출할 수 있도록 Agent Platform API를 사용 설정합니다.
gcloud services enable aiplatform.googleapis.com
다음과 비슷한 출력이 표시됩니다.
Operation "operations/acat.p2-..." finished successfully.
Python 가상 환경을 만들고 ADK 설치
~/adk-graph-agents 작업공간을 만들고 Python 3.12 가상 환경을 활성화합니다.
cd ~
mkdir -p adk-graph-agents && cd ~/adk-graph-agents
which uv >/dev/null 2>&1 || curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
uv venv .venv --python 3.12
source .venv/bin/activate
터미널 프롬프트 시작 부분에 (.venv) 프리픽스가 표시되는지 확인합니다.

활성 가상 환경 내에 ADK 2를 설치합니다.
uv pip install --no-cache "google-adk==2.14.0"
🔍 작업 확인
설치된 adk CLI 버전을 확인합니다.
adk --version
다음과 비슷한 출력이 표시됩니다.
adk, version 2.14.0
5. 여행 플래너 스캐폴드
adk create를 사용하여 시작 travel_planner 패키지를 생성하고 adk web에서 기본 단일 에이전트 기준을 테스트합니다.
시작 패키지 생성
~/adk-graph-agents에서 adk create를 실행합니다.
cd ~/adk-graph-agents
adk create travel_planner
메시지가 표시되면 다음 옵션을 선택합니다. 처음 실행할 때 Enable telemetry? [Y/n]: 메시지가 표시되면 Enter를 누르거나 n를 입력하고 Enter를 누릅니다.
- 루트 에이전트의 모델 선택:
2을 입력하여gemini-3.8-flash를 선택하고(옵션1는gemini-3.5-flash를 선택함) Enter를 누릅니다. - 백엔드 선택:
2를 입력하여 Google Cloud 에이전트 플랫폼 백엔드(아래 CLI 메뉴의 옵션2)를 선택하고 Enter를 누릅니다. - Google Cloud 프로젝트 ID 입력: Enter를 눌러 대괄호 안에 감지된 프로젝트 ID를 수락합니다.
- Google Cloud 리전 입력:
global를 입력하고(전역 Gemini 엔드포인트 사용) Enter를 누릅니다.
adk create는 GOOGLE_GENAI_USE_ENTERPRISE=1, 프로젝트 ID, GOOGLE_CLOUD_LOCATION=global를 travel_planner/.env에 작성하므로 나중에 agent.py를 바꿀 때 사용자 인증 정보가 그대로 유지됩니다.
다음과 비슷한 출력이 표시됩니다.
Choose a model for the root agent: 1. gemini-3.5-flash 2. gemini-3.8-flash 3. Other models (fill later) Choose model (1, 2, 3): 2 1. Google AI 2. Vertex AI 3. Login with Google Choose a backend (1, 2, 3): 2 You need an existing Google Cloud account and project, check out this link for details: https://google.github.io/adk-docs/get-started/quickstart/#gemini---google-cloud-vertex-ai Enter Google Cloud project ID [google-cloud-workshop-4210]: Enter Google Cloud region [us-central1]: global Agent created in /home/your_username/adk-graph-agents/travel_planner: - .env - .gitignore - __init__.py - agent.py ⚠️ WARNING: Secrets (like GOOGLE_API_KEY) are stored in .env. Next steps: - Chat with your agent in the terminal: adk run travel_planner - Or in the browser: adk web . - Have your coding agent evaluate and deploy it: uvx google-agents-cli setup (other install options: https://adk.dev/get-started/agents-cli/)
Cloud Shell 코드 편집기에서 ~/adk-graph-agents를 엽니다.
which cloudshell >/dev/null 2>&1 && cloudshell workspace ~/adk-graph-agents || true
새로고침된 터미널에서 가상 환경을 다시 활성화합니다.
cd ~/adk-graph-agents
source .venv/bin/activate
시작 단일 에이전트 테스트
ADK 웹 UI를 시작하여 조정되지 않은 단일 시작 에이전트가 여행 프롬프트에 어떻게 대답하는지 확인합니다.
cd ~/adk-graph-agents
adk web --allow_origins "*"
오른쪽 상단의 Cloud Shell 툴바에서 웹 미리보기 아이콘을 클릭하고 포트 변경을 선택한 후 8000을 입력하고 변경 및 미리보기를 클릭합니다.

🔍 작업 확인
adk web의 왼쪽 상단 드롭다운에서 travel_planner를 선택하고 "Help me plan a trip to Japan"를 전송합니다.

채팅 창에 단일 패스 대화형 답장이 표시됩니다(이벤트에 단일 root_agent 호출 포함).
root_agent -> responds in one pass without structured preference extraction, live search, or budget verification
다음 단계에서 파일을 수정하기 전에 Cloud Shell 터미널에서 Ctrl + C를 눌러 adk web를 중지합니다.
6. 선형 그래프 워크플로 빌드
첫 번째 ADK 2 Workflow를 빌드합니다. 예약된 "START" 진입점을 user_profiler_agent 및 itinerary_synthesizer_agent에 연결하는 순차적 체인입니다(나가는 에지가 없는 노드는 터미널 노드 역할을 함). 모든 에지 (a, b)는 격리된 single_turn 모드에서 Agent(LlmAgent의 별칭) 노드를 자동으로 실행하고 노드 a의 출력을 node_input(수신 사용자 메시지)로 노드 b에 전달하는 반면, 명령어 문자열의 {user_preferences}는 output_key를 통해 저장된 일치하는 세션 상태 키를 보간합니다.

초기 전문가 만들기
adk web가 중지되었는지 확인한 후(Ctrl + C) travel_planner/specialists.py라는 새 파일을 엽니다.
cloudshell edit ~/adk-graph-agents/travel_planner/specialists.py
다음 코드를 travel_planner/specialists.py에 붙여넣어 user_profiler_agent 및 itinerary_synthesizer_agent를 정의합니다(다음 단계를 위해 google_search를 미리 가져옴).
from google.adk import Agent
from google.adk.tools import google_search
MODEL = "gemini-3.8-flash"
# --- Specialist 1: The User Profiler ---
user_profiler_agent = Agent(
model=MODEL,
name="user_profiler_agent",
description="Extracts travel preferences and constraints from user input.",
instruction="""
Extract destination, duration (default 1 day), budget, interests, and exclusions.
Return a single JSON object with keys: "destination", "duration", "budget", "interests", "exclusions".
""",
output_key="user_preferences", # Saved for multi-hop constraints downstream
)
# --- Specialist 2: The Synthesizer ---
itinerary_synthesizer_agent = Agent(
model=MODEL,
name="itinerary_synthesizer_agent",
description="Compiles preferences and research into a final Markdown itinerary.",
instruction="""
You are an elite Travel Concierge. Using the incoming input and
User Preferences ({user_preferences}), write a Markdown itinerary
with an itemized USD and local currency cost breakdown.
""",
output_key="final_itinerary",
)
순차적 에지 체인 정의
travel_planner/workflows.py라는 새 파일을 엽니다.
cloudshell edit ~/adk-graph-agents/travel_planner/workflows.py
다음 Workflow 정의를 붙여넣습니다(여기서 3개 이상의 노드로 구성된 튜플은 "START"에서 순차적 체인으로 컴파일됨).
from google.adk import Workflow
from .specialists import (
itinerary_synthesizer_agent,
user_profiler_agent,
)
# 1. SEQUENTIAL GRAPH: START -> user_profiler_agent -> itinerary_synthesizer_agent
travel_workflow = Workflow(
name="travel_workflow",
description="Orchestrates the end-to-end travel planning process as a graph workflow.",
edges=[
("START", user_profiler_agent, itinerary_synthesizer_agent),
],
)
워크플로를 root_agent로 노출
travel_planner/agent.py 열기:
cloudshell edit ~/adk-graph-agents/travel_planner/agent.py
travel_planner/agent.py의 전체 콘텐츠를 다음 두 줄로 바꿉니다.
from .workflows import travel_workflow
root_agent = travel_workflow
🔍 작업 확인
~/adk-graph-agents에서 adk web를 시작합니다.
cd ~/adk-graph-agents
adk web --allow_origins "*"
포트 8000에서 웹 미리보기를 열고 + 새 세션을 클릭한 후 다음을 전송합니다.
Help me plan a trip to Kyoto
이벤트 뷰에 다음과 유사한 이벤트 시퀀스가 표시됩니다.
1. user_profiler_agent -> outputs JSON {"destination": "Kyoto", "duration": "1 day", ...} and writes state["user_preferences"]
2. itinerary_synthesizer_agent -> receives preferences via node_input and outputs the Markdown itinerary

이벤트에서 이벤트를 클릭하고 그래프 아이콘(이벤트 세부정보 툴바의 account_tree)을 클릭하여 컴파일된 START -> user_profiler_agent -> itinerary_synthesizer_agent 토폴로지를 검사한 다음 상태 탭을 확인하여 user_preferences 및 final_itinerary가 채워져 있는지 확인합니다.
계속하기 전에 터미널에서 Ctrl + C를 눌러 adk web를 중지합니다.
7. JoinNode를 사용한 팬아웃 및 조인
동시 실행되는 google_search 전문가 2개(activity_finder_agent 및 restaurant_finder_agent)를 추가하고 JoinNode와 동기화하여 실시간 웹 데이터로 운항 일정을 그라운딩합니다.
- 팬아웃 튜플: 에지 튜플 내에
(activity_finder_agent, restaurant_finder_agent)를 배치하면user_profiler_agent의 출력이node_input로 두 연구원에게 동시에 전달됩니다. - 팬인 장벽(
JoinNode): 튜플 바로 뒤에JoinNode(name="research_join")를 배치하면 모든 수신 브랜치가 완료될 때까지 기다린 후 병합된dict({"activity_finder_agent": ..., "restaurant_finder_agent": ...}) 하나를node_input로itinerary_synthesizer_agent에 전달합니다. 합성을 두 번 트리거하지 않습니다.

조사 전문가 추가
adk web가 중지되었는지 확인(Ctrl + C)한 다음 travel_planner/specialists.py를 엽니다.
cloudshell edit ~/adk-graph-agents/travel_planner/specialists.py
activity_finder_agent 및 restaurant_finder_agent를 travel_planner/specialists.py의 하단에 추가합니다(research_join가 node_input를 통해 두 출력을 직접 전달하므로 둘 다 output_key가 필요하지 않음).
# --- Specialist 3: The Activity Finder ---
activity_finder_agent = Agent(
model=MODEL,
name="activity_finder_agent",
description="Finds 3 attractions matching the user's destination and interests.",
instruction="""
Using the travel preferences in the input, call google_search to find 3 specific attractions
(including budget-friendly options).
Return a JSON list with keys: "attraction_name", "estimated_cost_local", "estimated_cost_usd", "notes".
""",
tools=[google_search],
)
# --- Specialist 4: The Restaurant Finder ---
restaurant_finder_agent = Agent(
model=MODEL,
name="restaurant_finder_agent",
description="Finds 3 restaurants matching the destination and budget.",
instruction="""
Using the travel preferences in the input, call google_search to find 3 highly-rated restaurants
across price points.
Return a JSON list with keys: "restaurant_name", "cuisine", "estimated_cost_local", "estimated_cost_usd".
""",
tools=[google_search],
)
workflows.py에 팬아웃 및 JoinNode 추가
travel_planner/workflows.py 열기:
cloudshell edit ~/adk-graph-agents/travel_planner/workflows.py
travel_planner/workflows.py의 전체 콘텐츠를 팬아웃 및 JoinNode 그래프로 바꿉니다.
from google.adk import Workflow
from google.adk.workflow import JoinNode
from .specialists import (
activity_finder_agent,
itinerary_synthesizer_agent,
restaurant_finder_agent,
user_profiler_agent,
)
research_join = JoinNode(name="research_join")
# 2. FAN-OUT / FAN-IN GRAPH: Profile -> (Activities || Restaurants) -> Join -> Synthesize
travel_workflow = Workflow(
name="travel_workflow",
description="Orchestrates the end-to-end travel planning process as a graph workflow.",
edges=[
(
"START",
user_profiler_agent,
(activity_finder_agent, restaurant_finder_agent),
research_join,
itinerary_synthesizer_agent,
),
],
)
🔍 작업 확인
adk web를 시작하여 동시 검색 및 JoinNode 동기화를 테스트합니다.
cd ~/adk-graph-agents
adk web --allow_origins "*"
포트 8000에서 웹 미리보기를 열고 + 새 세션을 클릭한 후 다음을 전송합니다.
Help me plan a trip to Kyoto focused on historic temples and ramen
이벤트 뷰에 다음과 유사한 이벤트 시퀀스가 표시됩니다.
1. user_profiler_agent -> emits JSON preferences via node_input
2. activity_finder_agent & restaurant_finder_agent -> invoke google_search concurrently
3. research_join -> merges both researcher outputs into one dict node_input
4. itinerary_synthesizer_agent -> drafts final_itinerary from the merged dict + {user_preferences}
계속하기 전에 터미널에서 Ctrl + C를 눌러 adk web를 중지합니다.
8. 경로 수정 주기
itinerary_critic_agent, itinerary_refiner_agent, ADK Event 객체를 반환하는 두 개의 결정론적 Python 함수 노드(route_critique 및 finalize_itinerary)를 추가하여 예산 및 음수 제약 조건을 적용합니다.
route: dict 에지({"revise": ..., "approved": ...})에서 다음에 실행할 이름이 지정된 브랜치 키를 선택합니다.output: 채팅 메시지를 렌더링하지 않고 에지를 따라 유형이 지정된 Python 값 또는 문자열을node_input로 다음 노드에 전달합니다.message및state:message는 채팅 스크립트에 사용자에게 표시되는 텍스트를 내보내고state는 키-값 업데이트(stateDelta)를 세션 상태에 커밋합니다.

비평가 및 정제 전문가 추가
adk web가 중지되었는지 확인(Ctrl + C)한 다음 travel_planner/specialists.py를 엽니다.
cloudshell edit ~/adk-graph-agents/travel_planner/specialists.py
itinerary_critic_agent 및 itinerary_refiner_agent를 travel_planner/specialists.py의 하단에 추가합니다(정제기는 이미 {final_itinerary}에 수집된 항목을 교체하고 route_critique가 "revise"를 선택할 때만 실행되므로 google_search 또는 exit_loop 도구가 필요하지 않음).
# --- Specialist 5: The Budget & Constraint Critic ---
itinerary_critic_agent = Agent(
model=MODEL,
name="itinerary_critic_agent",
description="Audits the itinerary draft against budget and negative constraints.",
instruction="""
Audit the itinerary in the input against User Preferences ({user_preferences}).
Verify that the USD total stays within the user's budget and no excluded venue types appear.
If all checks pass, respond EXACTLY with the single word "APPROVED".
Otherwise, output 1-2 concise revision instructions explaining what to swap or adjust.
""",
)
# --- Specialist 6: The Itinerary Refiner ---
itinerary_refiner_agent = Agent(
model=MODEL,
name="itinerary_refiner_agent",
description="Revises the itinerary draft using the critic's feedback.",
instruction="""
Revise Current Itinerary ({final_itinerary}) using the auditor critique in the input
so all USD budget and exclusion rules in {user_preferences} pass.
Output ONLY the updated Markdown itinerary.
""",
output_key="final_itinerary",
)
route_critique 및 주기 추가
travel_planner/workflows.py 열기:
cloudshell edit ~/adk-graph-agents/travel_planner/workflows.py
travel_planner/workflows.py의 전체 콘텐츠를 전체 그래프 워크플로로 바꿉니다.
from google.adk import Event, Workflow
from google.adk.workflow import JoinNode
from .specialists import (
activity_finder_agent, itinerary_critic_agent, itinerary_refiner_agent,
itinerary_synthesizer_agent, restaurant_finder_agent, user_profiler_agent,
)
MAX_REVISIONS = 2
research_join = JoinNode(name="research_join")
def route_critique(node_input: str, revision_count: int = 0):
"""Routes to 'approved' when constraints pass, or 'revise' up to MAX_REVISIONS."""
approved = node_input.strip().rstrip(".").upper() == "APPROVED"
if approved or revision_count >= MAX_REVISIONS:
return Event(route="approved", output=approved)
return Event(
route="revise", output=node_input, state={"revision_count": revision_count + 1}
)
def finalize_itinerary(node_input: bool, final_itinerary: str, revision_count: int = 0):
"""Emits the verified itinerary and resets revision_count for the next turn."""
status = (
f"Itinerary approved after {revision_count} revision(s)."
if node_input
else f"Max revisions ({revision_count}) reached; returning best-effort draft."
)
return Event(
message=f"{status}\n\n{final_itinerary}",
output=final_itinerary,
state={"revision_count": 0},
)
travel_workflow = Workflow(
name="travel_workflow",
description="Orchestrates the end-to-end travel planning process as a graph workflow.",
edges=[
(
"START",
user_profiler_agent,
(activity_finder_agent, restaurant_finder_agent),
research_join,
itinerary_synthesizer_agent,
itinerary_critic_agent,
route_critique,
),
(route_critique, {"revise": itinerary_refiner_agent, "approved": finalize_itinerary}),
(itinerary_refiner_agent, itinerary_critic_agent),
],
)
🔍 작업 확인
travel_planner/workflows.py가 정상적으로 컴파일되고 방향성 그래프 에지를 출력하는지 확인합니다.
cd ~/adk-graph-agents && source .venv/bin/activate
python3 -c "from travel_planner.agent import root_agent; print('\n'.join(f'{e.from_node.name} -> {e.to_node.name} (route={e.route})' for e in root_agent.graph.edges))"
다음과 비슷한 출력이 표시됩니다.
__START__ -> user_profiler_agent (route=None) user_profiler_agent -> activity_finder_agent (route=None) user_profiler_agent -> restaurant_finder_agent (route=None) activity_finder_agent -> research_join (route=None) restaurant_finder_agent -> research_join (route=None) research_join -> itinerary_synthesizer_agent (route=None) itinerary_synthesizer_agent -> itinerary_critic_agent (route=None) itinerary_critic_agent -> route_critique (route=None) route_critique -> itinerary_refiner_agent (route=revise) route_critique -> finalize_itinerary (route=approved) itinerary_refiner_agent -> itinerary_critic_agent (route=None)
그런 다음 adk web를 시작하여 즉시 승인과 예산 트리거 수정사항을 모두 테스트합니다.
adk web --allow_origins "*"
포트 8000에서 웹 미리보기를 열고 + 새 세션을 클릭한 후 여러 제약 조건이 있는 교토 프롬프트를 전송합니다.
Design a full-day itinerary for Kyoto with a total budget of $100. My main interests are historical landmarks, temples, and authentic local cuisine. Please do not include any modern art museums or galleries.
route="revise" 루프가 실행되는 것을 보려면 $15의 타이트한 예산으로 후속 프롬프트를 보냅니다.
Now design a full-day Kyoto itinerary with paid temple admissions, lunch, and dinner on a strict total budget of $15 USD.
이벤트 뷰에 다음과 유사한 실행 시퀀스가 표시됩니다.
1. user_profiler_agent -> writes JSON constraints to state["user_preferences"] 2. (activity_finder_agent, restaurant_finder_agent) -> run google_search concurrently -> research_join 3. itinerary_synthesizer_agent -> writes initial draft to state["final_itinerary"] 4. itinerary_critic_agent -> outputs "APPROVED" (or revision instructions when over budget) 5. route_critique -> emits route="approved" (skipping refiner) or route="revise" -> itinerary_refiner_agent -> itinerary_critic_agent 6. finalize_itinerary -> emits "Itinerary approved after N revision(s)." (or max-revisions notice) and resets revision_count=0
터미널에서 Ctrl + C를 눌러 adk web를 중지합니다.
9. 문제 해결
adk web에서 상담사 드롭다운이 비어 있음
- 원인:
adk web가 상위~/adk-graph-agents디렉터리가 아닌travel_planner/내에서 시작되었거나 Cloud Shell 세션이 다시 시작되었습니다. - 해결 방법:
Ctrl + C를 누르고 상위 디렉터리로 돌아간 후cd ~/adk-graph-agents && source .venv/bin/activate && adk web --allow_origins "*"로 다시 시작합니다.
404 NOT_FOUND 모델 오류
- 원인:
adk create중에global를 입력하는 대신 Enter를 눌러 기본us-central1리전을 수락했습니다. - 해결 방법:
~/adk-graph-agents/travel_planner/.env를 열고GOOGLE_CLOUD_LOCATION=global가 설정되어 있는지 확인합니다.
8000 포트의 ERROR: [Errno 98] address already in use
- 원인: 이전
adk web서버가 Cloud Shell에서 계속 실행 중입니다. - 해결 방법: 활성 터미널에서
Ctrl + C를 누르거나adk web를 다시 시작하기 전에pkill -f "adk web"로 기존 프로세스를 중지합니다.
10. 삭제
로컬 작업공간을 삭제하고 원하는 경우 API를 사용 중지하거나 전용 워크숍 프로젝트를 삭제합니다.
로컬 프로젝트 파일 삭제
~/adk-graph-agents 디렉터리와 가상 환경을 삭제합니다.
cd ~
rm -rf ~/adk-graph-agents
Agent Platform API 사용 중지(선택사항)
이 프로젝트에서 더 이상 필요하지 않은 경우 Agent Platform API를 사용 중지합니다.
gcloud services disable aiplatform.googleapis.com --quiet
🔍 작업 확인
~/adk-graph-agents가 삭제되었는지 확인합니다.
test ! -d ~/adk-graph-agents && echo "Workspace ~/adk-graph-agents removed"
다음과 비슷한 출력이 표시됩니다.
Workspace ~/adk-graph-agents removed
11. 축하합니다
ADK 2 Workflow를 사용하여 멀티 에이전트 여행 플래너를 빌드하고, 순차적 체인, JoinNode를 사용한 동시 google_search 팬아웃, 조건부 메이커-체커 주기를 단일 선언적 에지 그래프로 통합했습니다.
실습한 내용
- ADK 2를 사용하여 멀티 에이전트 파이프라인 선언
Workflow(edges=[...]) - 세션 상태를 최소한으로 유지하면서
node_input및 상태 바인딩 매개변수를 통해Agent,JoinNode, Python 함수 노드 간에 데이터를 직접 전달했습니다. - 동시
google_search브랜치를 팬아웃하고JoinNode와 동기화했습니다. LoopAgent및 도구 기반 루프 에스컬레이션을 승인된 초안에서 불필요한 LLM 호출을 건너뛰는 결정론적Event(route=...)라우터로 대체했습니다.
다음 단계
- ADK의 멀티 에이전트 시스템 살펴보기
- GEAR(Gemini Enterprise Agent Ready) 프로그램 및 자격증 취득 프로그램에 참여하여 실무 워크숍과 학습 과정을 이용하세요.