1. 소개
이 실습에서는 에이전트 개발 키트 (ADK)를 사용하여 에이전트를 빌드합니다. ADK와 다양한 도구 유형을 사용하여 소프트웨어 버그 어시스턴트 에이전트를 빌드하는 방법을 알아봅니다. 기본 에이전트로 시작하여 함수 도구, 기본 제공 도구, 서드 파티 도구, Model Context Protocol (MCP) 도구 등 기능을 강화하는 도구를 점진적으로 추가합니다.
학습할 내용
- ADK 개발을 위한 Python 프로젝트를 설정하는 방법
- 기본 ADK 에이전트를 만드는 방법
- 함수 도구를 구현하고 사용하는 방법
- Google 검색과 같은 내장 도구를 통합하는 방법
- ADK 내에서 LangChain과 같은 프레임워크의 서드 파티 도구를 활용하는 방법
- MCP 도구를 사용하여 데이터베이스 (Cloud SQL) 및 API와 상호작용하는 방법
2. 개요
글로벌 커피 머신 회사인 QuantumRoast의 프로젝트 관리자라고 가정해 보세요.
엔지니어링 로드맵, 갑작스러운 전략 전환(이제 말차를 합니다!), 고객으로부터 접수되는 티켓(버그가 있는 인보이스 시스템부터 24시간 내내 고음이 나는 커피 머신까지)을 팀원들이 헤쳐나갈 수 있도록 지원합니다.
일반적인 날에는 내부 티켓 시스템, 이메일, 채팅, GitHub, Google 검색, StackOverflow 등 약 50개의 브라우저 탭이 열려 있습니다. 업무와 동료는 좋아하지만 때로는 압도감을 느낍니다.
소프트웨어 티켓을 만들고 분류하고 문제를 디버깅하는 데 도움이 되는 도우미를 만들 수 있다면 어떨까요? AI 에이전트가 이를 가능하게 합니다.
에이전트 개발 키트(ADK)
에이전트 개발 키트 (ADK)는 AI 에이전트를 개발하고 배포하기 위한 유연한 모듈식 프레임워크입니다. Gemini 및 Google 생태계에 최적화되어 있지만 ADK는 모델에 구애받지 않고 배포에 구애받지 않으며 다른 프레임워크와의 호환성을 위해 빌드됩니다. ADK는 에이전트 개발이 소프트웨어 개발과 유사하도록 설계되어 개발자가 간단한 작업부터 복잡한 워크플로에 이르기까지 다양한 에이전트 아키텍처를 쉽게 만들고, 배포하고, 오케스트레이션할 수 있습니다.
ADK는 QuantumRoast 소프트웨어 버그 어시스턴트를 빌드하는 데 사용할 프레임워크입니다.
도구 101
AI 에이전트는 하드 코딩된 로직뿐만 아니라 모델을 사용하여 문제를 해결합니다. 하지만 AI 에이전트는 LLM 기반 추론뿐만 아니라 외부 데이터를 수집한 다음 사용자를 대신하여 조치를 취할 수 있는 고유한 기능을 제공합니다. AI 에이전트는 문제를 해결하는 방법을 알려주는 대신 실제로 문제를 해결하는 데 도움을 줄 수 있습니다. 삭제는 어떻게 이루어질까요? 도구를 사용하세요.
도구는 AI 에이전트가 세상과 상호작용하는 데 도움이 되는 기능입니다. 도구는 인라인 함수, 호스팅 데이터베이스, 서드 파티 API , 다른 에이전트 등 거의 모든 것이 될 수 있습니다. 에이전트 개발 키트 (ADK)와 같은 AI 에이전트 프레임워크에는 도구에 대한 기본 지원이 내장되어 있으며, 다양한 도구 유형을 지원합니다.
하지만 에이전트는 특정 도구를 호출해야 하는 시점뿐만 아니라 호출하는 방법도 어떻게 알 수 있을까요? 여기서 에이전트의 모델은 몇 가지 중요한 역할을 합니다.
첫 번째는 도구 선택입니다. Google은 에이전트에게 도구 목록과 도구 사용 방법에 관한 안내를 제공합니다. 사용자가 에이전트를 프롬프트하면 에이전트의 모델은 사용자를 지원하기 위해 호출할 도구와 이유를 결정하는 데 도움을 줍니다.
두 번째 핵심 단계는 함수 호출입니다. 함수 호출은 모델이 실제로 도구를 호출하는 것이 아니라 프레임워크가 도구를 호출하는 데 사용하는 요청 본문을 포맷하여 호출을 준비하는 것이기 때문에 약간의 오해의 소지가 있습니다.
마지막으로 모델은 해당 도구의 응답(예: 데이터베이스의 미해결 버그 목록)을 해석하고 추가 조치를 취할지 또는 해당 정보로 사용자에게 응답할지 결정합니다.
이 모든 것을 직접 확인하려면 ADK Python을 사용하여 QuantumRoast 버그 어시스턴트 에이전트를 빌드해야 합니다.
3. 시작하기 전에
Google Cloud 프로젝트 설정
- 아직 Google 계정이 없다면 Google 계정을 만들어야 합니다.
- 직장 또는 학교 계정 대신 개인 계정을 사용하세요. 직장 및 학교 계정에는 이 실습에 필요한 API를 사용 설정하지 못하도록 하는 제한이 있을 수 있습니다.
- Google Cloud 콘솔에 로그인합니다.
- Cloud 콘솔에서 결제를 사용 설정합니다.
- 이 실습을 완료하는 데 드는 Cloud 리소스 비용은 미화 1달러 미만입니다.
- 이 실습이 끝나면 단계에 따라 리소스를 삭제하여 추가 요금이 발생하지 않도록 할 수 있습니다.
- 신규 사용자는 미화$300 상당의 무료 체험판을 사용할 수 있습니다.
- 새 프로젝트를 만들거나 기존 프로젝트를 재사용합니다.
Cloud Shell 편집기 열기
- Cloud Shell 편집기로 이동합니다.
- 터미널이 화면 하단에 표시되지 않으면 다음을 실행하여 엽니다.
- 햄버거 메뉴
를 클릭합니다.
- 터미널을 클릭합니다.
- 새 터미널을 클릭합니다.
- 햄버거 메뉴
- 터미널에서 다음 명령어를 사용하여 프로젝트를 설정합니다 (
YOUR_PROJECT_ID
대체).- 형식:
gcloud config set project YOUR_PROJECT_ID
- 예:
gcloud config set project lab-project-id-example
- 프로젝트 ID를 기억할 수 없는 경우 다음 단계를 따르세요.
- 다음 명령어를 사용하여 모든 프로젝트 ID를 나열할 수 있습니다.
gcloud projects list | awk '/PROJECT_ID/{print $2}'
- 다음 명령어를 사용하여 모든 프로젝트 ID를 나열할 수 있습니다.
- 형식:
- 승인하라는 메시지가 표시되면 승인을 클릭하여 계속합니다.
- 다음 메시지가 표시되어야 합니다.
Updated property [core/project].
WARNING
이 표시되고Do you want to continue (Y/N)?
이 표시되면 프로젝트 ID를 잘못 입력했을 수 있습니다.N
를 누르고Enter
를 누른 후gcloud config set project
명령어를 다시 실행해 보세요. - 터미널에서 이후 단계에서 사용할
PROJECT_ID
환경 변수를 설정합니다.export PROJECT_ID=$(gcloud config get project)
API 사용 설정
터미널에서 다음 명령어를 실행하여 필요한 Google Cloud API를 사용 설정합니다.
gcloud services enable sqladmin.googleapis.com \
compute.googleapis.com \
cloudresourcemanager.googleapis.com \
secretmanager.googleapis.com \
servicenetworking.googleapis.com \
aiplatform.googleapis.com \
run.googleapis.com \
artifactregistry.googleapis.com \
cloudbuild.googleapis.com
PostgreSQL용 Cloud SQL 인스턴스 만들기
QuantumRoast에는 모든 내부 티켓을 보유하는 버그 티켓 데이터베이스가 있습니다. PostgreSQL용 Cloud SQL 인스턴스를 만들어 설정해 보겠습니다.
gcloud sql instances create software-assistant \
--database-version=POSTGRES_16 \
--tier=db-custom-1-3840 \
--region=us-central1 \
--edition=ENTERPRISE \
--enable-google-ml-integration \
--database-flags cloudsql.enable_google_ml_integration=on \
--root-password=admin
인스턴스가 생성될 때까지 기다립니다 (몇 분 정도 걸릴 수 있음).
인스턴스를 만든 후에는 여기에서 Cloud Console을 통해 인스턴스를 볼 수 있습니다.
Cloud SQL 데이터베이스 만들기
SQL 데이터베이스 (tickets-db
)를 만들고 Cloud SQL 서비스 계정에 Vertex AI 액세스 권한을 부여합니다 (유사성 검색을 수행하기 위해 임베딩을 만들 수 있도록).
gcloud sql databases create tickets-db --instance=software-assistant
SERVICE_ACCOUNT_EMAIL=$(gcloud sql instances describe software-assistant --format="value(serviceAccountEmailAddress)")
echo $SERVICE_ACCOUNT_EMAIL
gcloud projects add-iam-policy-binding $PROJECT_ID --member="serviceAccount:$SERVICE_ACCOUNT_EMAIL" --role="roles/aiplatform.user"
tickets
테이블 설정
Cloud 콘솔 (Cloud SQL)에서 software-assistant
인스턴스의 Cloud SQL Studio를 엽니다.
postgres
사용자와 admin
를 비밀번호로 사용하여 tickets-db
데이터베이스에 로그인합니다.
새 Editor
탭을 엽니다.
그런 다음 다음 SQL 코드를 붙여넣어 테이블을 설정하고 벡터 임베딩을 만듭니다. Run
버튼을 눌러 명령어를 실행합니다.
CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE;
CREATE EXTENSION IF NOT EXISTS vector CASCADE;
GRANT EXECUTE ON FUNCTION embedding TO postgres;
CREATE TABLE tickets (
ticket_id SERIAL PRIMARY KEY, -- PostgreSQL's auto-incrementing integer type (SERIAL is equivalent to INT AUTO_INCREMENT)
title VARCHAR(255) NOT NULL, -- A concise summary or title of the bug/issue.
description TEXT, -- A detailed description of the bug.
assignee VARCHAR(100), -- The name or email of the person/team assigned to the ticket.
priority VARCHAR(50), -- The priority level (e.g., 'P0 - Critical', 'P1 - High').
status VARCHAR(50) DEFAULT 'Open', -- The current status of the ticket (e.g., 'Open', 'In Progress', 'Resolved'). Default is 'Open'.
creation_time TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, -- Timestamp when the ticket was first created. 'WITH TIME ZONE' is recommended for clarity and compatibility.
updated_time TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP -- Timestamp when the ticket was last updated. Will be managed by a trigger.
);
tickets
테이블이 생성되었습니다. Clear
를 클릭하여 이전 쿼리를 지웁니다.
이제 샘플 데이터를 삽입하고 Run
버튼을 다시 한번 누릅니다.
INSERT INTO tickets (title, description, assignee, priority, status) VALUES
('Login Page Freezes After Multiple Failed Attempts', 'Users are reporting that after 3 failed login attempts, the login page becomes unresponsive and requires a refresh. No specific error message is displayed.', 'samuel.green@example.com', 'P0 - Critical', 'Open');
INSERT INTO tickets (title, description, assignee, priority, status) VALUES
('Dashboard Sales Widget Intermittent Data Loading Failure', 'The "Sales Overview" widget on the main dashboard intermittently shows a loading spinner but no data. Primarily affects Chrome browser users.', 'maria.rodriguez@example.com', 'P1 - High', 'In Progress');
INSERT INTO tickets (title, description, assignee, priority, status) VALUES
('Broken Link in Footer - Privacy Policy', 'The "Privacy Policy" hyperlink located in the website footer leads to a 404 "Page Not Found" error.', 'maria.rodriguez@example.com', 'P3 - Low', 'Resolved');
INSERT INTO tickets (title, description, assignee, priority, status) VALUES
('UI Misalignment on Mobile Landscape View (iOS)', 'On specific iOS devices (e.g., iPhone 14 models), the top navigation bar shifts downwards when the device is viewed in landscape orientation, obscuring content.', 'maria.rodriguez@example.com', 'P2 - Medium', 'In Progress');
INSERT INTO tickets (title, description, assignee, priority, status) VALUES
('Critical XZ Utils Backdoor Detected in Core Dependency (CVE-2024-3094)', 'Urgent: A sophisticated supply chain compromise (CVE-2024-3094) has been identified in XZ Utils versions 5.6.0 and 5.6.1. This malicious code potentially allows unauthorized remote SSH access by modifying liblzma. Immediate investigation and action required for affected Linux/Unix systems and services relying on XZ Utils.', 'frank.white@example.com', 'P0 - Critical', 'Open');
INSERT INTO tickets (title, description, assignee, priority, status) VALUES
('Database Connection Timeouts During Peak Usage', 'The application is experiencing frequent database connection timeouts, particularly during peak hours (10 AM - 12 PM EDT), affecting all users and causing service interruptions.', 'frank.white@example.com', 'P1 - High', 'Open');
INSERT INTO tickets (title, description, assignee, priority, status) VALUES
('Export to PDF Truncates Long Text Fields in Reports', 'When generating PDF exports of reports containing extensive text fields, the text is abruptly cut off at the end of the page instead of wrapping or continuing to the next page.', 'samuel.green@example.com', 'P1 - High', 'Open');
INSERT INTO tickets (title, description, assignee, priority, status) VALUES
('Search Filter "Date Range" Not Applying Correctly', 'The "Date Range" filter on the search results page does not filter records accurately; results outside the specified date range are still displayed.', 'samuel.green@example.com', 'P2 - Medium', 'Resolved');
INSERT INTO tickets (title, description, assignee, priority, status) VALUES
('Typo in Error Message: "Unathorized Access"', 'The error message displayed when a user attempts an unauthorized action reads "Unathorized Access" instead of "Unauthorized Access."', 'maria.rodriguez@example.com', 'P3 - Low', 'Resolved');
INSERT INTO tickets (title, description, assignee, priority, status) VALUES
('Intermittent File Upload Failures for Large Files', 'Users are intermittently reporting that file uploads fail without a clear error message or explanation, especially for files exceeding 10MB in size.', 'frank.white@example.com', 'P1 - High', 'Open');
QuantumRoast에서는 버그/티켓이 마지막으로 업데이트된 시간을 알고 싶을 수 있습니다.
이렇게 하려면 레코드가 업데이트될 때마다 updated_time
필드를 업데이트하는 트리거를 만들면 됩니다.
Clear
를 클릭한 다음 다음 SQL을 붙여넣어 트리거를 구현합니다.
Run
버튼을 눌러 실행합니다.
CREATE OR REPLACE FUNCTION update_updated_time_tickets()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_time = NOW(); -- Set the updated_time to the current timestamp
RETURN NEW; -- Return the new row
END;
$$ language 'plpgsql';
CREATE TRIGGER update_tickets_updated_time
BEFORE UPDATE ON tickets
FOR EACH ROW -- This means the trigger fires for each row affected by the UPDATE statement
EXECUTE PROCEDURE update_updated_time_tickets();
description
필드에서 벡터 임베딩을 만듭니다. 이렇게 하면 상담사가 데이터베이스에서 유사성 검색을 실행할 수 있습니다. 예를 들어 '웹사이트 홈페이지와 관련된 미해결 문제가 있나요?'라고 질문할 수 있습니다.
ALTER TABLE tickets ADD COLUMN embedding vector(768) GENERATED ALWAYS AS (embedding('text-embedding-005',description)) STORED;
이제 데이터베이스를 쿼리하여 준비되었는지 확인할 수 있습니다.
SELECT * FROM tickets;
다음과 비슷한 10개의 행이 반환됩니다.
이제 재미있는 부분인 코드로 이동할 준비가 되었습니다.
4. Python 프로젝트 설정
에이전트 빌드를 시작하기 전에 적절한 Python 프로젝트가 설정되어 있는지 확인해야 합니다. 모든 작업은 Cloud Shell에서 진행합니다.
먼저 quantum-roast
폴더를 만들고 cd
를 만듭니다.
mkdir quantum-roast && cd quantum-roast
이제 프로젝트 폴더가 있으므로 프로젝트를 초기화하고 필요한 해당 파일을 만들 차례입니다.
프로젝트와 종속 항목을 관리하기 위해 Cloud Shell에 사전 설치되어 있는 uv
(Python의 매우 빠른 패키지 및 프로젝트 관리자)를 사용합니다. Uv는 파일을 설정하고 가상 환경, 종속 항목 등을 관리하는 데 도움이 되므로 직접 관리하지 않아도 됩니다.
uv init
로 새 프로젝트를 초기화합니다.
uv init --description "QuantumRoast Software Bug Assistant with ADK" --bare --python 3.10
명령어를 실행하면 프로젝트의 pyproject.toml
파일이 생성됩니다. 확인하려면 Cloud Shell 터미널에서 cat pyproject.toml
를 실행합니다.
cat pyproject.toml
다음과 같은 출력이 표시됩니다.
[project] name = "quantum-roast" version = "0.1.0" description = "QuantumRoast Software Bug Assistant with ADK" requires-python = ">=3.10" dependencies = []
이제 uv add
를 사용하여 google-adk
(ADK)를 프로젝트에 종속 항목으로 추가합니다.
uv add google-adk==1.11.0
이렇게 하면 Google의 pyproject.toml
에 있는 dependencies
목록에 google-adk
가 추가됩니다.
ADK는 최상의 결과를 얻기 위해 특정 프로젝트 구조를 요구합니다.
quantum-roast/ software_bug_assistant/ __init__.py agent.py .env
software_bug_assistant
폴더와 그 안에 파일을 만듭니다.
mkdir software_bug_assistant && touch software_bug_assistant/__init__.py \
software_bug_assistant/agent.py \
software_bug_assistant/tools.py \
software_bug_assistant/.env
ls
을 사용하여 파일 생성을 확인합니다.
ls -a software_bug_assistant/
아래와 같이 표시됩니다.
__init__.py . .. .env agent.py tools.py
이제 ADK가 Gemini 모델을 올바르게 호출하는 데 필요한 환경 변수로 .env
파일을 채울 차례입니다. Vertex API를 통해 Gemini에 액세스합니다.
echo "GOOGLE_GENAI_USE_VERTEXAI=TRUE" >> software_bug_assistant/.env \
&& echo "GOOGLE_CLOUD_PROJECT=$PROJECT_ID" >> software_bug_assistant/.env \
&& echo "GOOGLE_CLOUD_LOCATION=us-central1" >> software_bug_assistant/.env
.env
가 올바르게 채워졌는지 확인하려면 다음을 실행합니다.
cat software_bug_assistant/.env
your-project-id
이 프로젝트 ID인 다음이 표시됩니다.
GOOGLE_GENAI_USE_VERTEXAI=TRUE GOOGLE_CLOUD_PROJECT=your-project-id GOOGLE_CLOUD_LOCATION=us-central1
이제 ADK 에이전트 만들기를 시작할 수 있습니다.
5. 기본 ADK 에이전트
이 워크숍에서 도구를 하나씩 추가하여 강력한 버그 어시스턴트를 만들 수 있는 기본 ADK 에이전트를 설정해 보겠습니다.
Cloud Shell 편집기에서 agent.py
를 엽니다.
cloudshell edit software_bug_assistant/agent.py
다음 코드를 agent.py
에 붙여넣고 Ctrl + s
파일을 저장합니다.
from google.adk.agents import Agent
# --- Agent Definition (model, instructions, tools) ---
root_agent = Agent(
model="gemini-2.5-flash",
name="software_assistant",
instruction="""
You are a skilled expert in triaging and debugging software issues for a
coffee machine company, QuantumRoast.
""",
tools=[],
)
ADK의 개발 UI (adk web
)를 시작하여 새로 만든 에이전트를 실행합니다. uv run
을 사용하여 실행하면 ADK가 설치된 가상 환경이 자동으로 생성됩니다.
uv run adk web --port 8080 --reload_agents
콘솔에 ADK 웹 서버가 성공적으로 시작되었다고 표시됩니다.
INFO: Started server process [1557] INFO: Waiting for application startup. +-----------------------------------------------------------------------------+ | ADK Web Server started | | | | For local testing, access at http://localhost:8080. | +-----------------------------------------------------------------------------+ INFO: Application startup complete. INFO: Uvicorn running on http://127.0.0.1:8080 (Press CTRL+C to quit)
Cloud Shell의 웹 미리보기를 열어 UI를 확인합니다.
ADK 웹 UI가 표시됩니다.
ADK 에이전트와 채팅해 보세요.
에이전트에게 What day is it today?
요청
대답을 보면 상담사가 이 기본적인 질문에 답할 수 없음을 알 수 있습니다. LLM은 과거 데이터를 기반으로 학습된 고립된 시스템입니다. 도구를 제공하지 않는 한 최근 이벤트나 현재 날짜에 관한 실시간 컨텍스트가 없습니다.
이제 ADK의 첫 번째 도구 유형인 함수 도구를 구현할 차례입니다.
6. 함수 도구
가장 간단한 첫 번째 ADK 도구 유형은 함수 도구입니다. 말 그대로 에이전트가 호출하는 Python 함수입니다.
함수 도구는 에이전트가 계산 실행, API 호출, 데이터베이스 쿼리와 같은 도구로 호출할 맞춤 코드를 작성할 수 있으므로 매우 강력합니다. 단순한 함수일 수도 있고 복잡한 함수일 수도 있습니다.
QuantumRoast에서는 이 실습의 후반부에서 '지난주 버그를 보여줘' 또는 '오늘이 무슨 요일이야?'와 같은 질문을 처리하기 위해 현재 날짜를 가져오는 기본 함수를 정의하려고 합니다. (누구나 겪는 일입니다.)
/software_bug_assistant
폴더 내의 tools.py
파일은 이 실습 전반에 걸쳐 빌드하는 모든 도구를 정리하는 곳입니다.
+
아이콘을 클릭하여 새 터미널을 엽니다.
이제 새 터미널에서 PROJECT_ID
를 설정하고 tools.py
을 엽니다.
cd quantum-roast
export PROJECT_ID=$(gcloud config get project)
cloudshell edit software_bug_assistant/tools.py
이제 함수 도구로 사용될 get_current_date
함수를 정의합니다.
from datetime import datetime
# ----- Example of a Function tool -----
def get_current_date() -> dict:
"""
Get the current date in the format YYYY-MM-DD
"""
return {"current_date": datetime.now().strftime("%Y-%m-%d")}
이제 함수가 정의되었습니다. 이제 이 정보를 상담사에게 도구로 전달할 시간입니다.
Cloud Shell 편집기에서 agent.py
를 엽니다.
cloudshell edit software_bug_assistant/agent.py
tools.py
에서 get_current_date
함수를 가져와서 에이전트의 tools
인수에 함수를 전달하려고 합니다.
업데이트된 agent.py
는 다음과 같습니다.
from google.adk.agents import Agent
from .tools import get_current_date
# --- Agent Definition (model, instructions, tools) ---
root_agent = Agent(
model="gemini-2.5-flash",
name="software_assistant",
instruction="""
You are a skilled expert in triaging and debugging software issues for a
coffee machine company, QuantumRoast.
""",
tools=[get_current_date],
)
이제 ADK 웹 UI를 실행하는 웹 미리보기 탭으로 돌아가서 What day is it today?
에 다시 질문하면...
에이전트가 get_current_date
함수 도구를 호출하여 날짜를 정확하게 말할 수 있습니다. 🎉
이제 다음 ADK 도구 유형을 살펴볼 시간입니다.
7. 내장 도구
또 다른 유형의 ADK 도구는 기본 제공 도구입니다. 이러한 도구는 모델 자체 내의 코드 실행과 같은 Google의 대표 모델 기능과 함께 작동합니다. Google 검색 내장 도구를 버그 어시스턴트 에이전트에 연결하여 에이전트가 웹을 검색할 수 있도록 함으로써 관련 맥락을 파악하도록 할 수 있습니다. 이를 통해 상담사는 버그 또는 잘 알려진 취약점에 관한 최신 정보를 수집할 수 있습니다.
tools.py
파일을 열어 Google 검색 내장 도구 지원을 추가합니다.
cloudshell edit software_bug_assistant/tools.py
tools.py
하단에 다음을 추가합니다.
# ----- Built-in Tool Imports -----
from google.adk.agents import Agent
from google.adk.tools import google_search
from google.adk.tools.agent_tool import AgentTool
# ----- Example of a Built-in Tool -----
search_agent = Agent(
model="gemini-2.5-flash",
name="search_agent",
description="A specialist in Google Search.",
instruction="""
You're a specialist in Google Search.
""",
tools=[google_search],
)
search_tool = AgentTool(search_agent)
여기서는 Google 검색 도구를 자체 시스템 안내가 포함된 자체 에이전트로 래핑하여 에이전트를 도구로 효과적으로 사용합니다.
이제 search_tool
를 가져와 agent.py
의 루트 에이전트에 전달할 수 있습니다.
cloudshell edit software_bug_assistant/agent.py
agent.py
를 다음 코드로 바꿔 search_tool
를 포함할 수 있습니다.
from google.adk.agents import Agent
from .tools import get_current_date, search_tool
# --- Agent Definition (model, instructions, tools) ---
root_agent = Agent(
model="gemini-2.5-flash",
name="software_assistant",
instruction="""
You are a skilled expert in triaging and debugging software issues for a
coffee machine company, QuantumRoast.
""",
tools=[get_current_date, search_tool],
)
파일을 저장하고 ADK 웹 UI가 실행 중인 창으로 돌아갑니다.
QuantumRoast는 공개 사이버 보안 취약점인 일반적인 취약점 및 노출 (CVE)로부터 웹사이트와 소프트웨어를 보호하고자 합니다. 에이전트의 새로운 Google 검색 도구를 사용하여 웹에서 가장 최근에 발견된 CVE를 검색할 수 있습니다.
Do a web search for 5 of the most recent CVEs?
쿼리를 실행합니다.
상담사는 search_agent
을 호출하여 웹을 검색해야 합니다.
이제 상담사가 Google 검색용 ADK의 내장 도구를 통해 웹을 검색하는 기능을 성공적으로 잠금 해제했습니다. 🎉
다음 ADK 도구 유형으로 넘어갑니다.
8. 서드 파티 도구
ADK는 확장성이 높도록 설계되어 CrewAI, LangChain과 같은 다른 서드 파티 AI 에이전트 프레임워크의 도구를 원활하게 통합할 수 있습니다. 이 상호 운용성은 개발 시간을 단축하고 기존 도구를 재사용할 수 있으므로 매우 중요합니다.
버그 에이전트를 StackOverflow의 강력한 Q&A 데이터에 연결하기 위해 LangChain의 광범위한 도구 라이브러리, 특히 StackExchange API 래퍼 도구에서 가져올 수 있습니다. ADK는 LangChain과 같은 서드 파티 도구를 지원하므로 이 도구를 ADK 에이전트에 추가하는 데는 몇 줄의 코드만 있으면 됩니다.
먼저 LangChain 및 StackOverflow (langchain-community
및 stackapi
)의 새 종속 항목을 프로젝트에 추가해야 합니다.
uv add langchain-community==0.3.27 stackapi==0.3.1
tools.py
파일을 열어 LangChain StackExchange 도구 지원을 추가합니다.
cloudshell edit software_bug_assistant/tools.py
tools.py
하단에 다음을 추가합니다.
# ----- Example of a Third-Party Tool -----
from google.adk.tools.langchain_tool import LangchainTool
from langchain_community.tools import StackExchangeTool
from langchain_community.utilities import StackExchangeAPIWrapper
stack_exchange_tool = StackExchangeTool(api_wrapper=StackExchangeAPIWrapper())
langchain_tool = LangchainTool(stack_exchange_tool)
이제 langchain_tool
를 가져와 agent.py
의 루트 에이전트에 전달할 수 있습니다.
cloudshell edit software_bug_assistant/agent.py
agent.py
를 다음 코드로 바꿔 langchain_tool
를 포함할 수 있습니다.
from google.adk.agents import Agent
from .tools import get_current_date, langchain_tool, search_tool
# --- Agent Definition (model, instructions, tools) ---
root_agent = Agent(
model="gemini-2.5-flash",
name="software_assistant",
instruction="""
You are a skilled expert in triaging and debugging software issues for a
coffee machine company, QuantumRoast.
""",
tools=[get_current_date, search_tool, langchain_tool],
)
파일을 저장하고 ADK 웹 UI가 열린 탭으로 돌아갑니다.
이전 CVE("Are there similar issues on stack exchange?"
) 또는 새로운 내용("Our database queries with SQLAlchemy seem to be timing out, is there anything on StackExchange relevant to this?"
)에 관해 에이전트에게 질문해 보세요.
이제 에이전트가 ADK에서 LangChain 도구를 활용하여 StackOverflow에 쿼리했습니다. 🥳
다음 ADK 도구 유형을 살펴볼 시간입니다. MCP 도구
9. MCP 도구 (데이터베이스)
MCP는 Model Context Protocol의 약자입니다. 2024년에 Anthropic에서 도입한 개방형 프로토콜입니다. MCP는 AI 에이전트와 도구 '백엔드' (API, 데이터베이스) 간에 추상화 레이어를 제공합니다.
MCP에는 몇 가지 고유한 사양이 있습니다. 표준 HTTP와 달리 MCP는 클라이언트와 서버 간에 상태 저장 양방향 연결을 제공합니다. 도구 및 도구별 오류 메시지를 정의하는 자체 방식이 있습니다. 그러면 도구 제공업체는 API 위에 MCP 서버를 빌드하여 개발자와 사용자를 위한 하나 이상의 사전 빌드 도구를 노출할 수 있습니다. 그런 다음 에이전트 프레임워크는 에이전트 애플리케이션 내에서 MCP 클라이언트를 초기화하여 이러한 도구를 검색하고 호출할 수 있습니다.
QuantumRoast에는 내부 소프트웨어 버그를 위한 PostgreSQL용 Cloud SQL 데이터베이스가 있습니다. 에이전트가 데이터베이스에서 특정 쿼리를 실행할 수 있도록 ADK 도구를 만들고 싶습니다.
가장 쉬운 방법은 데이터베이스용 오픈소스 MCP 서버인 데이터베이스용 MCP 도구 상자를 사용하는 것입니다. 툴박스는 15개 이상의 데이터베이스를 지원하며 그중 하나가 Cloud SQL입니다.
툴박스는 다음을 제공합니다.
- 간소화된 개발: 10줄 미만의 코드로 에이전트에 도구를 통합하고, 여러 에이전트 또는 프레임워크 간에 도구를 재사용하고, 더 쉽게 새 버전의 도구를 배포하세요.
- 성능 개선: 연결 풀링, 인증 등의 권장사항
- 보안 강화: 데이터에 더 안전하게 액세스할 수 있도록 통합 인증
- 엔드 투 엔드 모니터링 가능성: OpenTelemetry를 기본적으로 지원하는 즉시 사용 가능한 측정항목 및 추적
ADK는 데이터베이스 도구용 MCP 도구 상자를 지원하므로 통합이 빠릅니다.
데이터베이스용 MCP 도구 상자 서버를 Cloud Run에 배포
먼저 데이터베이스 서버용 MCP 도구 상자를 Cloud Run에 배포하고 Cloud SQL 인스턴스를 가리킵니다.
툴박스에는 구성용 YAML 파일이 필요하며, 여기에서 데이터베이스 소스와 구성할 도구를 간략하게 설명합니다.
배포용 tools.yaml
파일을 만듭니다.
cloudshell edit tools.yaml
다음 콘텐츠를 tools.yaml
에 붙여넣습니다.
sources:
postgresql:
kind: cloud-sql-postgres
project: ${PROJECT_ID}
region: us-central1
instance: software-assistant
database: tickets-db
user: postgres
password: admin
tools:
search-tickets:
kind: postgres-sql
source: postgresql
description: Search for similar tickets based on their descriptions.
parameters:
- name: query
type: string
description: The query to perform vector search with.
statement: |
SELECT ticket_id, title, description, assignee, priority, status, (embedding <=> embedding('text-embedding-005', $1)::vector) as distance
FROM tickets
ORDER BY distance ASC
LIMIT 3;
get-ticket-by-id:
kind: postgres-sql
source: postgresql
description: Retrieve a ticket's details using its unique ID.
parameters:
- name: ticket_id
type: string
description: The unique ID of the ticket.
statement: SELECT * FROM tickets WHERE ticket_id = $1;
get-tickets-by-assignee:
kind: postgres-sql
source: postgresql
description: Search for tickets based on assignee (email).
parameters:
- name: assignee
type: string
description: The email of the assignee.
statement: SELECT * FROM tickets WHERE assignee ILIKE '%' || $1 || '%';
update-ticket-priority:
kind: postgres-sql
source: postgresql
description: Update the priority of a ticket based on its ID.
parameters:
- name: priority
type: string
description: The priority of the ticket. Can be one of 'P0 - Critical', 'P1 - High', 'P2 - Medium', or 'P3 - Low'.
- name: ticket_id
type: string
description: The ID of the ticket.
statement: UPDATE tickets SET priority = $1 WHERE ticket_id = $2;
update-ticket-status:
kind: postgres-sql
source: postgresql
description: Update the status of a ticket based on its ID.
parameters:
- name: status
type: string
description: The new status of the ticket (e.g., 'Open', 'In Progress', 'Closed', 'Resolved').
- name: ticket_id
type: string
description: The ID of the ticket.
statement: UPDATE tickets SET status = $1 WHERE ticket_id = $2;
get-tickets-by-status:
kind: postgres-sql
source: postgresql
description: Search for tickets based on their current status.
parameters:
- name: status
type: string
description: The status of the tickets to retrieve (e.g., 'Open', 'In Progress', 'Closed', 'Resolved').
statement: SELECT * FROM tickets WHERE status ILIKE '%' || $1 || '%';
get-tickets-by-priority:
kind: postgres-sql
source: postgresql
description: Search for tickets based on their priority.
parameters:
- name: priority
type: string
description: The priority of the tickets to retrieve (e.g., 'P0 - Critical', 'P1 - High', 'P2 - Medium', 'P3 - Low').
statement: SELECT * FROM tickets WHERE priority ILIKE '%' || $1 || '%';
create-new-ticket:
kind: postgres-sql
source: postgresql
description: Create a new software ticket.
parameters:
- name: title
type: string
description: The title of the new ticket.
- name: description
type: string
description: A detailed description of the bug or issue.
- name: assignee
type: string
description: (Optional) The email of the person to whom the ticket should be assigned.
- name: priority
type: string
description: (Optional) The priority of the ticket. Can be 'P0 - Critical', 'P1 - High', 'P2 - Medium', or 'P3 - Low'. Default is 'P3 - Low'.
- name: status
type: string
description: (Optional) The initial status of the ticket. Default is 'Open'.
statement: INSERT INTO tickets (title, description, assignee, priority, status) VALUES ($1, $2, $3, COALESCE($4, 'P3 - Low'), COALESCE($5, 'Open')) RETURNING ticket_id;
get-tickets-by-date-range:
kind: postgres-sql
source: postgresql
description: Retrieve tickets created or updated within a specific date range.
parameters:
- name: start_date
type: string
description: The start date (inclusive) for the range (e.g., 'YYYY-MM-DD').
- name: end_date
type: string
description: The end date (inclusive) for the range (e.g., 'YYYY-MM-DD').
- name: date_field
type: string
description: The date field to filter by ('creation_time' or 'updated_time').
statement: SELECT * FROM tickets WHERE CASE WHEN $3 = 'creation_time' THEN creation_time ELSE updated_time END BETWEEN $1::timestamp AND $2::timestamp;
toolsets:
tickets_toolset:
- search-tickets
- get-ticket-by-id
- get-tickets-by-assignee
- get-tickets-by-status
- get-tickets-by-priority
- get-tickets-by-date-range
- update-ticket-priority
- update-ticket-status
- create-new-ticket
YAML 파일은 QuantumRoast 티켓 데이터베이스와 관련된 9개 도구를 정의합니다.
이제 Toolbox Cloud Run 서비스의 서비스 계정을 구성하고, Cloud SQL 및 Secret Manager에 액세스할 수 있는 권한을 부여하고, tools.yaml
파일의 Secret Manager 보안 비밀을 만들어야 합니다.
Secret Manager는 민감한 Cloud SQL 사용자 인증 정보를 포함하므로 tools.yaml
파일을 저장하는 데 사용됩니다.
gcloud iam service-accounts create toolbox-identity
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member serviceAccount:toolbox-identity@$PROJECT_ID.iam.gserviceaccount.com \
--role roles/secretmanager.secretAccessor
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member serviceAccount:toolbox-identity@$PROJECT_ID.iam.gserviceaccount.com \
--role roles/cloudsql.client
gcloud secrets create tools --data-file=tools.yaml
이제 데이터베이스용 MCP 도구 상자를 Cloud Run에 배포할 시간입니다. MCP Toolbox 컨테이너 이미지의 최신 출시 버전을 사용합니다.
gcloud run deploy toolbox \
--image us-central1-docker.pkg.dev/database-toolbox/toolbox/toolbox:latest \
--service-account toolbox-identity \
--region us-central1 \
--set-secrets "/app/tools.yaml=tools:latest" \
--set-env-vars="PROJECT_ID=$PROJECT_ID" \
--args="--tools-file=/app/tools.yaml","--address=0.0.0.0","--port=8080" \
--allow-unauthenticated
배포가 완료될 때까지 기다립니다.
Cloud Run 로그를 쿼리하여 Toolbox가 실행 중인지 확인합니다.
gcloud run services logs read toolbox --region us-central1 --limit 10
다음과 같이 표시됩니다.
2025-08-20 18:03:55 2025-08-20T18:03:55.465847801Z INFO "Initialized 1 sources." 2025-08-20 18:03:55 2025-08-20T18:03:55.466152914Z INFO "Initialized 0 authServices." 2025-08-20 18:03:55 2025-08-20T18:03:55.466374245Z INFO "Initialized 9 tools." 2025-08-20 18:03:55 2025-08-20T18:03:55.466477938Z INFO "Initialized 2 toolsets." 2025-08-20 18:03:55 2025-08-20T18:03:55.467492303Z INFO "Server ready to serve!"
ADK 에이전트가 찾을 수 있도록 Toolbox 서비스의 Cloud Run URL을 환경 변수로 저장합니다.
export MCP_TOOLBOX_URL=$(gcloud run services describe toolbox --region us-central1 --format "value(status.url)")
echo MCP_TOOLBOX_URL=$MCP_TOOLBOX_URL >> software_bug_assistant/.env
QuantumRoast 에이전트 업데이트
두 번째로 데이터베이스용 MCP 도구 상자 SDK (toolbox-core
)의 종속 항목을 프로젝트에 추가해야 합니다.
uv add toolbox-core==0.5.0
tools.py
파일을 열어 MCP Toolbox 도구 지원을 추가합니다.
cloudshell edit software_bug_assistant/tools.py
tools.py
하단에 다음을 추가합니다.
# ----- Example MCP Toolbox for Databases tools -----
import os
from toolbox_core import ToolboxSyncClient
TOOLBOX_URL = os.getenv("MCP_TOOLBOX_URL", "http://127.0.0.1:5000")
# Initialize Toolbox client
toolbox = ToolboxSyncClient(TOOLBOX_URL)
# Load all the tools from toolset
toolbox_tools = toolbox.load_toolset("tickets_toolset")
이제 toolbox_tools
를 가져와 agent.py
의 루트 에이전트에 전달할 수 있습니다.
cloudshell edit software_bug_assistant/agent.py
agent.py
를 다음 코드로 바꿔 toolbox_tools
를 포함할 수 있습니다.
from google.adk.agents import Agent
from .tools import get_current_date, langchain_tool, search_tool, toolbox_tools
# --- Agent Definition (model, instructions, tools) ---
root_agent = Agent(
model="gemini-2.5-flash",
name="software_assistant",
instruction="""
You are a skilled expert in triaging and debugging software issues for a
coffee machine company, QuantumRoast.
""",
tools=[get_current_date, search_tool, langchain_tool, *toolbox_tools],
)
파일을 저장하고 ADK 웹 UI가 열린 탭으로 돌아갑니다.
이제 Cloud SQL 내부 티켓 데이터베이스에 저장된 티켓에 관해 질문할 수 있습니다.
다음과 같은 질문을 합니다.
I am seeing an issue with database timeouts, has anyone else seen a similar issue?
How many bugs are assigned to samuel.green@example.com? Show a table.
Can you bump the priority of ticket with ID 6 to to P0 - Critical priority
Create a new ticket
(상담사가 버그 생성을 안내하도록 함)
이제 ADK 에이전트가 데이터베이스용 MCP 도구 상자 도구를 통해 데이터베이스를 쿼리했습니다.🚀
10. 선택사항: MCP 도구 (API)
데이터베이스용 MCP 도구 상자와 같이 자체 SDK가 없는 MCP 도구에 ADK 에이전트를 연결하는 것은 어떤가요?
ADK는 MCPToolset
클래스를 통해 일반 MCP 도구를 지원합니다. MCPToolset
클래스는 MCP 서버의 도구를 통합하는 ADK의 기본 메커니즘입니다.
MCPToolset
를 사용하여 로컬 또는 원격 MCP 서버에 연결할 수 있습니다. QuantumRoast에서는 GitHub의 원격 MCP 서버에 에이전트를 연결하여 GitHub의 API를 쉽게 호출하려고 합니다. 이렇게 하면 상담사가 공개 소프트웨어 저장소 또는 Google 자체 코드베이스에서 문제에 관한 정보를 가져올 수 있습니다. GitHub MCP 서버는 문제 및 풀 요청부터 알림 및 코드 보안에 이르기까지 GitHub 기능의 다양한 부분을 노출합니다.
GitHub 개인 액세스 토큰 (PAT)
GitHub MCP 서버로 인증하려면 GitHub 개인 액세스 토큰이 필요합니다.
하나를 획득하려면 다음 단계를 따르세요.
- GitHub 개발자 설정으로 이동합니다.
- '개인 액세스 토큰' -> '토큰 (클래식)'을 클릭합니다.
- '새 토큰 생성' -> '새 토큰 생성 (클래식)'을 클릭합니다.
- 토큰에 설명이 포함된 이름을 지정합니다.
- 토큰의 만료일을 설정합니다.
- 중요: 보안을 위해 토큰에 필요한 가장 제한적인 범위를 부여하세요. 저장소에 대한 읽기 전용 액세스의 경우
repo:status
,public_repo
,read:user
범위로 충분한 경우가 많습니다. 꼭 필요한 경우가 아니라면 전체 저장소 또는 관리자 권한을 부여하지 마세요. Generate token
을 클릭합니다.- 생성된 토큰을 복사합니다.
Cloud Shell 터미널에서 다음을 실행하여 에이전트가 사용할 수 있도록 GitHub PAT를 설정합니다. YOUR_GITHUB_PAT
을 생성된 PAT로 바꿉니다.
export GITHUB_PAT=YOUR_GITHUB_PAT
QuantumRoast 에이전트 업데이트
버그 어시스턴트의 경우 QuantumRoast 직원이 오픈소스 종속 항목과 관련된 문제를 찾고 내부 티켓 시스템에서 확인되는 버그의 근본 원인을 파악할 수 있도록 일부 읽기 전용 GitHub 도구만 노출됩니다. ADK의 MCPToolset
와 tool_filter
를 사용하여 이를 설정합니다. tool-filter
는 필요한 GitHub 도구만 노출하므로 사용자가 액세스하지 못하도록 하려는 도구 (예: 민감한 저장소 작업)를 숨길 뿐만 아니라 작업을 위한 올바른 도구를 선택하려고 할 때 에이전트의 모델이 압도되지 않도록 보호합니다.
tools.py
파일을 열어 GitHub 도구 지원을 추가합니다.
cloudshell edit software_bug_assistant/tools.py
tools.py
하단에 다음을 추가합니다.
# ----- Example MCP Tools with MCPToolset (GitHub) -----
from google.adk.tools.mcp_tool import MCPToolset, StreamableHTTPConnectionParams
mcp_tools = MCPToolset(
connection_params=StreamableHTTPConnectionParams(
url="https://api.githubcopilot.com/mcp/",
headers={
"Authorization": "Bearer " + os.getenv("GITHUB_PAT"),
},
),
# Read only tools
tool_filter=[
"search_repositories",
"search_issues",
"list_issues",
"get_issue",
"list_pull_requests",
"get_pull_request",
],
)
코드에서 표준 API 클라이언트를 설정할 때 인증 토큰을 제공하는 것과 마찬가지로 GitHub 개인 액세스 토큰 (PAT)을 MCPToolset
정의에 제공해야 합니다. 이 PAT는 민감한 사용자 또는 저장소 작업과 관련된 범위 없이 공개 저장소 데이터에만 액세스할 수 있도록 범위가 지정됩니다.
이제 mcp_tools
를 가져와 agent.py
의 루트 에이전트에 전달할 수 있습니다.
cloudshell edit software_bug_assistant/agent.py
agent.py
를 다음 코드로 바꿔 mcp_tools
를 포함할 수 있습니다.
from google.adk.agents import Agent
from .tools import get_current_date, langchain_tool, mcp_tools, search_tool, toolbox_tools
# --- Agent Definition (model, instructions, tools) ---
root_agent = Agent(
model="gemini-2.5-flash",
name="software_assistant",
instruction="""
You are a skilled expert in triaging and debugging software issues for a
coffee machine company, QuantumRoast.
""",
tools=[get_current_date, search_tool, langchain_tool, *toolbox_tools, mcp_tools],
)
파일을 저장하고 ADK 웹 UI가 열린 탭으로 돌아갑니다.
이제 에이전트가 호출할 수 있는 GitHub MCP 도구 세트가 있습니다. QuantumRoast의 서비스는 데이터 압축 도구인 XZ 유틸리티를 사용합니다. Google의 내부 버그 티켓 시스템에서는 작년에 발생한 CVE (보안 취약점)를 추적하고 있으며, StackOverflow 및 Google 검색 도구를 사용하여 XZ Utils GitHub 저장소로 거슬러 올라갈 수 있습니다. 그런 다음 GitHub의 MCP 도구 중 하나인 search_issues
을 사용하여 해당 CVE가 언제 어떻게 패치되었는지 확인할 수 있습니다.
에이전트에게 다음과 같이 질문합니다.
Find the official XZ Utils GitHub repository
Search the repository for issues related to CVE-2024-3094
에이전트가 GitHub 도구를 호출하는 것을 확인할 수 있습니다.
이제 QuantumRoast ADK 에이전트가 GitHub MCP 서버 도구와 상호작용할 수 있습니다. 🤩
11. 마무리
축하합니다. 에이전트 개발 키트 (ADK)를 사용하여 QuantumRoast 버그 어시스턴트 에이전트를 빌드하고 다양한 도구 유형을 통합하여 기능을 개선했습니다. 기본 에이전트로 시작하여 함수 도구, 기본 제공 도구, 서드 파티 도구, MCP 도구를 점진적으로 추가했습니다.
학습한 내용
- ADK 개발을 위한 Python 프로젝트를 설정하는 방법
- 기본 ADK 에이전트를 만드는 방법
- 함수 도구를 구현하고 사용하는 방법
- Google 검색과 같은 내장 도구를 통합하는 방법
- ADK 내에서 LangChain과 같은 프레임워크의 서드 파티 도구를 활용하는 방법
- MCP 도구를 사용하여 데이터베이스 (Cloud SQL) 및 API와 상호작용하는 방법
삭제
추가 비용이 청구되지 않도록 Cloud 프로젝트를 삭제할 수 있습니다.
Cloud Run에서는 서비스를 사용하지 않을 때 비용이 청구되지 않지만 Artifact Registry에 컨테이너 이미지를 저장하는 데 요금이 부과될 수 있습니다. Cloud 프로젝트를 삭제하면 해당 프로젝트 내에서 사용되는 모든 리소스에 대한 청구가 중단됩니다.
원하는 경우 프로젝트를 삭제합니다.
gcloud projects delete $GOOGLE_CLOUD_PROJECT
cloudshell 디스크에서 불필요한 리소스를 삭제하는 것이 좋습니다. 다음과 같은 작업을 할 수 있습니다.
- Codelab 프로젝트 디렉터리를 삭제합니다.
rm -rf ~/quantum-roast
- 경고 이 작업은 되돌릴 수 없습니다. 공간을 확보하기 위해 Cloud Shell의 모든 항목을 삭제하려면 전체 홈 디렉터리를 삭제하면 됩니다. 보관할 모든 항목이 다른 곳에 저장되어 있는지 확인하세요.
sudo rm -rf $HOME