1. do opery Moc przeznaczenia,
Era rozwoju w izolacji dobiega końca. Kolejna fala ewolucji technologicznej nie będzie polegać na samotnym geniuszu, ale na mistrzostwie we współpracy. Stworzenie jednego, inteligentnego agenta to fascynujący eksperyment. Stworzenie solidnego, bezpiecznego i inteligentnego ekosystemu agentów – prawdziwego Agentverse – to duże wyzwanie dla nowoczesnych przedsiębiorstw.
Sukces w tej nowej erze wymaga połączenia 4 kluczowych ról, które stanowią podstawowe filary każdego dobrze prosperującego systemu opartego na agentach. Niedociągnięcia w którymkolwiek z tych obszarów mogą osłabić całą strukturę.
Te warsztaty to ostateczny przewodnik dla firm, który pomoże Ci opanować przyszłość opartą na agentach w Google Cloud. Zapewniamy kompleksową mapę drogową, która poprowadzi Cię od pierwszego pomysłu do pełnowymiarowej, działającej rzeczywistości. W tych 4 połączonych ze sobą modułach dowiesz się, jak specjalistyczne umiejętności dewelopera, architekta, inżyniera danych i inżyniera ds. niezawodności witryn muszą się zbiegać, aby tworzyć, zarządzać i skalować potężny Agentverse.
Żaden pojedynczy filar nie może samodzielnie wspierać Agentverse. Wielki projekt Architekta jest bezużyteczny bez precyzyjnego wykonania przez Dewelopera. Bez wiedzy inżyniera ds. danych agent dewelopera jest bezradny, a bez ochrony inżyniera ds. niezawodności systemu cała infrastruktura jest podatna na awarie. Tylko dzięki współpracy i wzajemnemu zrozumieniu ról Twój zespół może przekształcić innowacyjną koncepcję w kluczową dla misji firmy rzeczywistość operacyjną. Twoja podróż zaczyna się tutaj. Przygotuj się do opanowania swojej roli i dowiedz się, jak wpisujesz się w większą całość.
Witamy w Agentverse: wezwanie do mistrzów
W rozległej przestrzeni cyfrowej przedsiębiorstwa nastała nowa era. To era agentów, czas ogromnych możliwości, w którym inteligentne, autonomiczne agenty działają w doskonałej harmonii, aby przyspieszać innowacje i eliminować rutynowe czynności.
Ten połączony ekosystem mocy i potencjału jest znany jako Agentverse.
Jednak w tym nowym świecie zaczęła się szerzyć entropia, cicha korupcja znana jako Statyka. Statyka nie jest wirusem ani błędem. To uosobienie chaosu, które żeruje na samym akcie tworzenia.
Wzmacnia stare frustracje, nadając im monstrualne formy, i powołuje do życia 7 widm rozwoju. Jeśli nie zostanie to zrobione, The Static i jego Spectres zatrzymają postępy, zamieniając obietnicę Agentverse w pustkowie długu technicznego i porzuconych projektów.
Dziś wzywamy liderów do powstrzymania fali chaosu. Potrzebujemy bohaterów, którzy opanują swoje umiejętności i będą współpracować, aby chronić Agentverse. Czas wybrać ścieżkę.
Wybieranie zajęć
Do wyboru masz 4 różne ścieżki, z których każda jest kluczowym elementem walki z Statycznością. Szkolenie będzie indywidualne, ale ostateczny sukces zależy od tego, jak Twoje umiejętności łączą się z umiejętnościami innych osób.
- Shadowblade (deweloper): mistrz kuźni i pierwszej linii. Jesteś rzemieślnikiem, który tworzy ostrza, buduje narzędzia i staje do walki z wrogiem w zawiłych szczegółach kodu. Twoja ścieżka to precyzja, umiejętności i praktyczne tworzenie.
- Przywoływacz (Architekt): wielki strateg i aranżer. Nie widzisz pojedynczego agenta, ale całe pole bitwy. Projektujesz główne plany, które umożliwiają całym systemom agentów komunikowanie się, współpracę i osiąganie celu znacznie większego niż jakikolwiek pojedynczy komponent.
- Uczony (inżynier danych): poszukiwacz ukrytych prawd i strażnik mądrości. Wyruszasz w rozległą, nieokiełznaną dzicz danych, aby odkryć informacje, które nadają Twoim agentom cel i umożliwiają im działanie. Twoja wiedza może ujawnić słabość wroga lub wzmocnić sojusznika.
- Strażnik (DevOps / SRE): niezachwiany obrońca i tarcza królestwa. Budujesz fortece, zarządzasz liniami zasilania i dbasz o to, aby cały system był w stanie wytrzymać nieuniknione ataki Static. Twoja siła jest podstawą, na której opiera się zwycięstwo Twojej drużyny.
Twoja misja
Trening rozpocznie się jako samodzielne ćwiczenie. Będziesz podążać wybraną ścieżką, zdobywając unikalne umiejętności potrzebne do opanowania swojej roli. Pod koniec okresu próbnego zmierzysz się z Widmem zrodzonym z Statyki – mini-bossem, który wykorzystuje specyficzne wyzwania związane z Twoim rzemiosłem.
Tylko opanowanie swojej roli pozwoli Ci przygotować się do ostatecznej próby. Następnie musisz utworzyć drużynę z bohaterami z innych klas. Razem wyruszycie w głąb skażenia, aby zmierzyć się z ostatecznym bossem.
Ostatnie wyzwanie, które sprawdzi Waszą siłę i zadecyduje o losie Agentverse.
Agentverse czeka na swoich bohaterów. Czy odbierzesz połączenie?
2. The Summoner's Concord
Witamy, przywoływaczu. Twoja ścieżka to wizja i wielka strategia. Podczas gdy inni skupiają się na jednym ostrzu lub jednym zaklęciu, Ty widzisz całe pole bitwy. Nie dowodzisz jednym agentem, ale całą orkiestrą. Twoja siła nie polega na bezpośrednim konflikcie, ale na opracowaniu doskonałego, nadrzędnego planu, który pozwala legionowi specjalistów – Twoich pomocników – pracować w doskonałej harmonii. To zadanie sprawdzi Twoją umiejętność projektowania, łączenia i koordynowania działania zaawansowanego systemu wieloagentowego.
Czego się nauczysz
- Zaprojektuj odseparowany ekosystem narzędzi: zaprojektuj i wdroż zestaw niezależnych serwerów narzędzi MCP opartych na mikroserwisach. Dowiesz się, dlaczego ta warstwa podstawowa jest kluczowa w przypadku tworzenia skalowalnych, łatwych w utrzymaniu i bezpiecznych systemów opartych na agentach.
- Opanuj zaawansowane przepływy pracy agentów: wyjdź poza pojedynczych agentów i stwórz legion specjalistycznych „znajomych”. Poznasz główne wzorce przepływu pracy ADK: sekwencyjny, równoległy i pętlowy. Dowiesz się też, jak wybierać odpowiedni wzorzec do danego zadania.
- Wdrażanie inteligentnego aranżera: przejdź od prostego kreatora agentów do prawdziwego architekta systemów. Utworzysz głównego agenta orkiestracji, który używa protokołu A2A (Agent-to-Agent) do wykrywania i przekazywania złożonych zadań specjalistycznym agentom pomocniczym, tworząc prawdziwy system wieloagentowy.
- Wymuszanie reguł za pomocą kodu, a nie promptów: dowiedz się, jak tworzyć bardziej niezawodne i przewidywalne agenty, wymuszając reguły zaangażowania oparte na stanie. Zaimplementujesz niestandardową logikę za pomocą zaawansowanego systemu wtyczek i wywołań zwrotnych ADK, aby zarządzać ograniczeniami w rzeczywistym świecie, takimi jak liczniki czasu oczekiwania.
- Zarządzanie stanem i pamięcią agenta: umożliwiaj agentom uczenie się i zapamiętywanie. Poznasz techniki zarządzania krótkoterminowym stanem rozmowy i długoterminową, trwałą pamięcią, aby tworzyć bardziej inteligentne interakcje uwzględniające kontekst.
- Przeprowadź kompleksowe wdrożenie w chmurze: przenieś cały system z wieloma agentami z lokalnego prototypu do wersji produkcyjnej. Dowiesz się, jak konteneryzować agentów i orkiestratora oraz wdrażać je jako zbiór skalowalnych, niezależnych mikroserwisów w Google Cloud Run.
3. Rysowanie kręgu przywołania
Witamy, przywoływaczu. Zanim przywołasz jakiegokolwiek sprzymierzeńca, zanim zawrzesz jakiekolwiek pakty, musisz przygotować ziemię, na której stoisz. Nieokiełznane środowisko to zaproszenie do chaosu. Prawdziwy przywoływacz działa tylko w uświęconej, wzmocnionej przestrzeni. Naszym pierwszym zadaniem jest narysowanie kręgu przywoływania: wyrycie run mocy, które aktywują niezbędne usługi w chmurze, oraz zdobycie starożytnych planów, które będą nas prowadzić. Moc Przywoływacza rodzi się z drobiazgowych przygotowań.
👉 U góry konsoli Google Cloud kliknij Aktywuj Cloud Shell (jest to ikona terminala u góry panelu Cloud Shell).
👉 Kliknij przycisk „Otwórz edytor” (wygląda jak otwarty folder z ołówkiem). W oknie otworzy się edytor kodu Cloud Shell. Po lewej stronie zobaczysz eksplorator plików.
👉Znajdź identyfikator projektu Google Cloud:
- Otwórz konsolę Google Cloud:
https://console.cloud.google.com
- Wybierz projekt, którego chcesz użyć w tych warsztatach, z menu u góry strony.
- Identyfikator projektu jest wyświetlany na karcie Informacje o projekcie w panelu
.
👉Otwórz terminal w IDE w chmurze.
👉💻 W terminalu sprawdź, czy użytkownik jest już uwierzytelniony i czy projekt jest ustawiony na identyfikator projektu, używając tego polecenia:
gcloud auth list
👉💻 Sklonuj projekt początkowy z GitHuba:
git clone https://github.com/weimeilin79/agentverse-architect
chmod +x ~/agentverse-architect/init.sh
chmod +x ~/agentverse-architect/set_env.sh
chmod +x ~/agentverse-architect/prepare.sh
chmod +x ~/agentverse-architect/data_setup.sh
git clone https://github.com/weimeilin79/agentverse-dungeon.git
chmod +x ~/agentverse-dungeon/run_cloudbuild.sh
chmod +x ~/agentverse-dungeon/start.sh
👉💻 Uruchom skrypt inicjujący. Poprosi on o wpisanie identyfikatora projektu Google Cloud. Gdy skrypt init.sh
wyświetli odpowiedni komunikat, wpisz identyfikator projektu Google Cloud znaleziony w ostatnim kroku.
cd ~/agentverse-architect
./init.sh
👉💻 Ustaw wymagany identyfikator projektu:
gcloud config set project $(cat ~/project_id.txt) --quiet
👉💻 Aby włączyć wymagane interfejsy Google Cloud API, uruchom to polecenie:
gcloud services enable \
sqladmin.googleapis.com \
storage.googleapis.com \
aiplatform.googleapis.com \
run.googleapis.com \
cloudbuild.googleapis.com \
artifactregistry.googleapis.com \
iam.googleapis.com \
compute.googleapis.com \
cloudresourcemanager.googleapis.com \
secretmanager.googleapis.com
👉💻 Jeśli nie masz jeszcze repozytorium Artifact Registry o nazwie agentverse-repo, utwórz je, wykonując to polecenie: (pomiń ten krok, jeśli w tym samym projekcie masz wdrożone inne klasy)
. ~/agentverse-architect/set_env.sh
gcloud artifacts repositories create $REPO_NAME \
--repository-format=docker \
--location=$REGION \
--description="Repository for Agentverse agents"
Konfigurowanie uprawnień
👉💻 Przyznaj niezbędne uprawnienia, uruchamiając w terminalu te polecenia:
. ~/agentverse-architect/set_env.sh
# --- Grant Core Data Permissions ---
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/storage.admin"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/aiplatform.user"
# --- Grant Deployment & Execution Permissions ---
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/cloudbuild.builds.editor"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/artifactregistry.admin"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/run.admin"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/iam.serviceAccountUser"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/logging.logWriter"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:${SERVICE_ACCOUNT_NAME}" \
--role="roles/monitoring.metricWriter"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:${SERVICE_ACCOUNT_NAME}" \
--role="roles/secretmanager.secretAccessor"
👉💻 Gdy zaczniesz trenować, przygotujemy dla Ciebie ostateczne wyzwanie. Poniższe polecenia przywołają widma z chaotycznego szumu, tworząc bossów do ostatecznego testu.
. ~/agentverse-architect/set_env.sh
cd ~/agentverse-dungeon
./run_cloudbuild.sh
cd ~/agentverse-architect
👉💻 Na koniec uruchom skrypt prepare.sh
, aby wykonać początkowe zadania konfiguracyjne.
. ~/agentverse-architect/set_env.sh
cd ~/agentverse-architect/
./prepare.sh
Świetna robota, Przywoływaczu. Krąg został zamknięty, a pakty przypieczętowane. Ziemia jest teraz uświęcona i gotowa do przekazywania ogromnej mocy. W kolejnym eksperymencie stworzymy same czcionki żywiołów, z których nasi towarzysze będą czerpać siłę.
4. Tworzenie czcionek podstawowych: odłączony ekosystem narzędzi
Pole bitwy jest przygotowane, krąg przywoływania narysowany, a mana w powietrzu iskrzy. Czas na pierwszy prawdziwy czyn Przywoływacza: stworzenie źródeł mocy, z których będą czerpać siłę Twoi towarzysze. Rytuał ten dzieli się na 3 części, z których każda budzi Źródło Żywiołów – stabilne, niezależne źródło określonego rodzaju mocy. Dopiero gdy wszystkie 3 czcionki są aktywne, możesz rozpocząć bardziej złożone zadanie przywoływania.
Uwaga architekta: serwer protokołu kontekstu modelu (MCP) to podstawowy komponent nowoczesnego systemu agentów, który działa jako standardowy most komunikacyjny umożliwiający agentowi wykrywanie i używanie narzędzi zdalnych. W naszym ekosystemie narzędzi zaprojektujemy 2 różne typy serwerów MCP, z których każdy będzie reprezentować kluczowy wzorzec architektury. Do łączenia się z naszą bazą danych użyjemy podejścia deklaratywnego z wykorzystaniem Database Toolbox, definiując nasze narzędzia w prostym pliku konfiguracyjnym. Ten wzorzec jest niezwykle wydajny i bezpieczny w przypadku udostępniania dostępu do danych strukturalnych. Gdy jednak musimy wdrożyć niestandardową logikę biznesową lub wywołać zewnętrzne interfejsy API innych firm, używamy podejścia imperatywnego, pisząc logikę serwera krok po kroku w kodzie. Zapewnia to pełną kontrolę i elastyczność, umożliwiając nam zamykanie złożonych operacji w prostym narzędziu wielokrotnego użytku. Główny architekt musi znać oba wzorce, aby wybrać odpowiednie podejście do każdego komponentu i stworzyć solidne, bezpieczne i skalowalne podstawy narzędzi.
Awakening the Nexus of Whispers (External API MCP Server)
Mądry Przywoływacz wie, że nie cała moc pochodzi z jego własnej domeny. Istnieją zewnętrzne, czasem chaotyczne źródła energii, które można wykorzystać z dużym efektem. Węzeł Szeptów to nasza brama do tych sił.
Usługa jest już aktywna i działa jako nasze zewnętrzne źródło zasilania, oferując 2 nieprzetworzone punkty końcowe zaklęć: /cryosea_shatter
i /moonlit_cascade
.
Uwaga architekta: użyjesz podejścia imperatywnego, które krok po kroku określa logikę serwera. Daje to znacznie większą kontrolę i elastyczność, co jest niezbędne, gdy narzędzia muszą robić coś więcej niż tylko wykonywać proste zapytania SQL, np. wywoływać inne interfejsy API. Znajomość obu tych wzorców jest kluczową umiejętnością architekta agentów.
👉✏️ Przejdź do katalogu ~/agentverse-architect/mcp-servers/api/main.py
i ZASTĄP #REPLACE-MAGIC-CORE
tym kodem:
def cryosea_shatter() -> str:
"""Channels immense frost energy from an external power source, the Nexus of Whispers, to unleash the Cryosea Shatter spell."""
try:
response = requests.post(f"{API_SERVER_URL}/cryosea_shatter")
response.raise_for_status() # Raise an exception for bad status codes (4xx or 5xx)
data = response.json()
# Thematic Success Message
return f"A connection to the Nexus is established! A surge of frost energy manifests as Cryosea Shatter, dealing {data.get('damage_points')} damage."
except requests.exceptions.RequestException as e:
# Thematic Error Message
return f"The connection to the external power source wavers and fails. The Cryosea Shatter spell fizzles. Reason: {e}"
def moonlit_cascade() -> str:
"""Draws mystical power from an external energy source, the Nexus of Whispers, to invoke the Moonlit Cascade spell."""
try:
response = requests.post(f"{API_SERVER_URL}/moonlit_cascade")
response.raise_for_status()
data = response.json()
# Thematic Success Message
return f"The Nexus answers the call! A cascade of pure moonlight erupts from the external source, dealing {data.get('damage_points')} damage."
except requests.exceptions.RequestException as e:
# Thematic Error Message
return f"The connection to the external power source wavers and fails. The Moonlit Cascade spell fizzles. Reason: {e}"
U podstaw skryptu leżą proste funkcje Pythona. To tutaj odbywa się właściwa praca.
👉✏️ W tym samym pliku ~/agentverse-architect/mcp-servers/api/main.py
ZASTĄP #REPLACE-Runes of Communication
tym kodem:
@app.list_tools()
async def list_tools() -> list[mcp_types.Tool]:
"""MCP handler to list available tools."""
# Convert the ADK tool's definition to MCP format
schema_cryosea_shatter = adk_to_mcp_tool_type(cryosea_shatterTool)
schema_moonlit_cascade = adk_to_mcp_tool_type(moonlit_cascadeTool)
print(f"MCP Server: Received list_tools request. \n MCP Server: Advertising tool: {schema_cryosea_shatter.name} and {schema_moonlit_cascade.name}")
return [schema_cryosea_shatter,schema_moonlit_cascade]
@app.call_tool()
async def call_tool(
name: str, arguments: dict
) -> list[mcp_types.TextContent | mcp_types.ImageContent | mcp_types.EmbeddedResource]:
"""MCP handler to execute a tool call."""
print(f"MCP Server: Received call_tool request for '{name}' with args: {arguments}")
# Look up the tool by name in our dictionary
tool_to_call = available_tools.get(name)
if tool_to_call:
try:
adk_response = await tool_to_call.run_async(
args=arguments,
tool_context=None, # No ADK context available here
)
print(f"MCP Server: ADK tool '{name}' executed successfully.")
response_text = json.dumps(adk_response, indent=2)
return [mcp_types.TextContent(type="text", text=response_text)]
except Exception as e:
print(f"MCP Server: Error executing ADK tool '{name}': {e}")
# Creating a proper MCP error response might be more robust
error_text = json.dumps({"error": f"Failed to execute tool '{name}': {str(e)}"})
return [mcp_types.TextContent(type="text", text=error_text)]
else:
# Handle calls to unknown tools
print(f"MCP Server: Tool '{name}' not found.")
error_text = json.dumps({"error": f"Tool '{name}' not implemented."})
return [mcp_types.TextContent(type="text", text=error_text)]
@app.list_tools()
(The Handshake): ta funkcja to powitanie serwera. Gdy nowy agent nawiązuje połączenie, najpierw wywołuje ten punkt końcowy, aby zapytać: „Co potrafisz?”. Nasz kod odpowiada listą wszystkich dostępnych narzędzi przekonwertowanych na uniwersalny format MCP za pomocą funkcji adk_to_mcp_tool_type. –@app.call_tool()
(polecenie): ta funkcja jest najważniejsza. Gdy agent zdecyduje się użyć narzędzia, wysyła do tego punktu końcowego żądanie zawierające nazwę narzędzia i argumenty. Nasz kod wyszukuje narzędzie w „księdze zaklęć” dostępnych narzędzi, wykonuje je za pomocą funkcji run_async i zwraca wynik w standardowym formacie MCP.
Wdrożymy to później.
Igniting the Arcane Forge (General Functions MCP Server)
Nie cała moc pochodzi ze starożytnych ksiąg ani odległych szeptów. Czasami przywoływacz musi wykuć własną magię z czystej woli i logiki. Arcane Forge to źródło mocy – serwer, który udostępnia bezstanowe funkcje ogólnego przeznaczenia.
Uwaga architekta: to kolejny wzorzec architektoniczny. Łączenie z istniejącymi systemami jest powszechne, ale często musisz wdrażać własne, unikalne reguły i logikę biznesową. Utworzenie takiego narzędzia „funkcje” lub „narzędzia” jest sprawdzoną metodą. Zawiera ona Twoją niestandardową logikę, dzięki czemu możesz jej używać w przypadku dowolnego agenta w ekosystemie. Jest też odseparowana od źródeł danych i integracji zewnętrznych.
👀 Otwórz plik ~/agentverse-architect/mcp-servers/general/main.py
w środowisku IDE w chmurze Google. Zauważysz, że używa on tego samego trybu rozkazującego mcp.server
co w przypadku Nexusa, aby stworzyć tę niestandardową czcionkę mocy.
Tworzenie głównego potoku Cloud Build
Teraz utworzymy plik cloudbuild.yaml
w katalogu mcp-servers
. Ten plik będzie koordynować kompilację i wdrażanie obu usług.
👉💻 W katalogu ~/agentverse-architect/mcp-servers
uruchom te polecenia:
cd ~/agentverse-architect/mcp-servers
source ~/agentverse-architect/set_env.sh
echo "The API URL is: $API_SERVER_URL"
# Submit the Cloud Build job from the parent directory
gcloud builds submit . \
--config=cloudbuild.yaml \
--substitutions=_REGION="$REGION",_REPO_NAME="$REPO_NAME",_API_SERVER_URL="$API_SERVER_URL"
Poczekaj na zakończenie wszystkich wdrożeń.
👉 Wdrożenie możesz sprawdzić, przechodząc do konsoli Cloud Run. Powinny być widoczne 2 uruchomione instancje nowego serwera MCP, jak pokazano poniżej:
Awakening the Librarium of Knowledge (Database ToolBox MCP Server)
Kolejnym czcionką będzie Librarium of Knowledge, czyli bezpośrednie połączenie z naszą bazą danych Cloud SQL.
Uwaga architekta: w tym celu użyjemy nowoczesnego, deklaratywnego Database Toolbox. Jest to zaawansowane podejście, w którym definiujemy źródło danych i narzędzia w pliku konfiguracji YAML. Zestaw narzędzi wykonuje złożoną pracę związaną z tworzeniem i uruchamianiem serwera, co zmniejsza ilość kodu niestandardowego, który musimy napisać i utrzymywać.
Czas zbudować „Bibliotekę przywoływacza” – bazę danych Cloud SQL, która będzie przechowywać wszystkie nasze najważniejsze informacje. Użyjemy skryptu konfiguracji, aby automatycznie wykonać to zadanie.
👉💻 Najpierw skonfigurujemy bazę danych. W terminalu uruchom te polecenia:
source ~/agentverse-architect/set_env.sh
cd ~/agentverse-architect
./data_setup.sh
Po zakończeniu działania skryptu baza danych zostanie wypełniona, a dane o obrażeniach od żywiołów będą gotowe do użycia. Możesz teraz bezpośrednio sprawdzić zawartość swojego Grimoire.
👉 Najpierw otwórz Cloud SQL Studio dla swojej bazy danych, otwierając ten bezpośredni link w nowej karcie przeglądarki:
https://console.cloud.google.com/sql/instances/summoner-librarium-db
👉 W panelu logowania po lewej stronie wybierz z menu bazę danych familiar_grimoire
.
👉 Wpisz summoner
jako użytkownika i 1234qwer
jako hasło, a następnie kliknij Uwierzytelnij.
👉📜 Po połączeniu otwórz nową kartę edytora zapytań, jeśli nie jest jeszcze otwarta. Aby wyświetlić dane o wygrawerowanych obrażeniach od żywiołów, wklej i uruchom to zapytanie SQL:
SELECT * FROM
"public"."abilities"
Powinna być teraz widoczna abilities
tabela z wypełnionymi kolumnami i wierszami, co potwierdza, że Grimoire jest gotowy.
Konfigurowanie serwera MCP ToolBox
Plik konfiguracyjny tools.yaml
pełni rolę planu naszego serwera, informując Database Toolbox, jak połączyć się z bazą danych i jakie zapytania SQL udostępnić jako narzędzia.
sources: ta sekcja określa połączenia z Twoimi danymi.
- summoner-librarium:: to logiczna nazwa, którą nadaliśmy naszemu połączeniu.
- kind: cloud-sql-postgres: informuje Toolbox, że ma użyć wbudowanego, bezpiecznego łącznika zaprojektowanego specjalnie dla Cloud SQL for PostgreSQL.
- projekt, region, instancja itp.: Są to dokładne współrzędne instancji Cloud SQL utworzonej podczas wykonywania skryptu prepare.sh, które informują Toolbox, gdzie znaleźć Librarium.
👉✏️ Otwórz ~/agentverse-architect/mcp-servers/db-toolbox
w tools.yaml
i zastąp #REPLACE-Source
tymi wartościami:
sources:
# This section defines the connection to our Cloud SQL for PostgreSQL database.
summoner-librarium:
kind: cloud-sql-postgres
project: "YOUR_PROJECT_ID"
region: "us-central1"
instance: "summoner-librarium-db"
database: "familiar_grimoire"
user: "summoner"
password: "1234qwer"
👉✏️ 🚨🚨ZASTĄP
YOUR_PROJECT_ID
z identyfikatorem projektu.
tools:ta sekcja określa rzeczywiste możliwości lub funkcje, które będzie oferować nasz serwer.
- lookup-available-ability:: to nazwa naszego pierwszego narzędzia.
- kind: postgres-sql: informuje Toolbox, że działanie tego narzędzia polega na wykonaniu instrukcji SQL.
- source: summoner-librarium: łączy narzędzie z połączeniem zdefiniowanym w bloku źródeł. Dzięki temu narzędzie wie, w której bazie danych ma uruchomić zapytanie.
- opis i parametry: są to informacje, które będą udostępniane modelowi językowemu. Opis informuje agenta, kiedy używać narzędzia, a parametry określają dane wejściowe wymagane przez narzędzie. Jest to niezbędne do włączenia funkcji wywoływania funkcji przez agenta.
- statement: surowe zapytanie SQL do wykonania. Znak $1 to bezpieczny symbol zastępczy, w którym zostanie bezpiecznie wstawiony parametr familiar_name podany przez agenta.
👉✏️ W tym samym pliku ~/agentverse-architect/mcp-servers/db-toolbox
w pliku tools.yaml
zastąp #REPLACE-tools
tym kodem:
tools:
# This tool replaces the need for a custom Python function.
lookup-available-ability:
kind: postgres-sql
source: summoner-librarium
description: "Looks up all known abilities and their damage for a given familiar from the Grimoire."
parameters:
- name: familiar_name
type: string
description: "The name of the familiar to search for (e.g., 'Fire Elemental')."
statement: |
SELECT ability_name, damage_points FROM abilities WHERE familiar_name = $1;
# This tool also replaces a custom Python function.
ability-damage:
kind: postgres-sql
source: summoner-librarium
description: "Finds the base damage points for a specific ability by its name."
parameters:
- name: ability_name
type: string
description: "The exact name of the ability to look up (e.g., 'inferno_resonance')."
statement: |
SELECT damage_points FROM abilities WHERE ability_name = $1;
zestawy narzędzi: ta sekcja grupuje nasze poszczególne narzędzia.
- summoner-librarium:: Tworzymy zestaw narzędzi o tej samej nazwie co nasze źródło. Gdy nasz agent diagnostyczny połączy się później, może poprosić o załadowanie wszystkich narzędzi z zestawu narzędzi summoner-librarium za pomocą jednego, wydajnego polecenia.
👉✏️ W tym samym pliku ~/agentverse-architect/mcp-servers/db-toolbox
w pliku tools.yaml
zastąp #REPLACE-toolsets
tym kodem:
toolsets:
summoner-librarium:
- lookup-available-ability
- ability-damage
Wdrażanie Librarium
Teraz wdrożymy Librarium. Zamiast tworzyć własny kontener, użyjemy gotowego, oficjalnego obrazu kontenera od Google i bezpiecznie udostępnimy mu konfigurację tools.yaml za pomocą Secret Managera. Jest to sprawdzona metoda zapewniająca bezpieczeństwo i łatwość konserwacji.
👉💻 Tworzenie obiektu tajnego z pliku tools.yaml
cd ~/agentverse-architect/mcp-servers/db-toolbox
gcloud secrets create tools --data-file=tools.yaml
👉💻 Wdróż oficjalny kontener z zestawem narzędzi w Cloud Run.
cd ~/agentverse-architect/mcp-servers/db-toolbox
. ~/agentverse-architect/set_env.sh
export TOOLBOX_IMAGE=us-central1-docker.pkg.dev/database-toolbox/toolbox/toolbox:$TOOLBOX_VERSION
echo "TOOLBOX_IMAGE is $TOOLBOX_IMAGE"
gcloud run deploy toolbox \
--image $TOOLBOX_IMAGE \
--region $REGION \
--set-secrets "/app/tools.yaml=tools:latest" \
--args="--tools-file=/app/tools.yaml","--address=0.0.0.0","--port=8080" \
--allow-unauthenticated \
--min-instances 1
--set-secrets
: to polecenie bezpiecznie montuje nasz klucz tajny narzędzi jako plik o nazwie tools.yaml w działającym kontenerze.--args
: instruujemy kontener narzędziowy, aby używał zamontowanego pliku tajnego jako konfiguracji.
👉 Aby sprawdzić, czy zestaw narzędzi został wdrożony, otwórz konsolę Cloud Run. summoner-toolbox
Usługa powinna być oznaczona zielonym znacznikiem wyboru, co oznacza, że działa prawidłowo, tak jak na obrazie poniżej.
Jeśli zapomnisz o aktualizacji
YOUR_PROJECT_ID
możesz dodać nową wersję pliku tools.yaml do obiektu tajnego za pomocą tego polecenia i ponownie wdrożyć usługę.
gcloud secrets versions add tools --data-file=tools.yaml
Librarium of Knowledge(Database ToolBox MCP Server) jest teraz aktywne i dostępne w chmurze. Ten serwer MCP korzysta z tzw. projektu deklaratywnego, który opisuje, czego oczekujesz, a zestaw narzędzi buduje serwer za Ciebie.
Weryfikacja: próba ucznia
👉💻 Teraz przetestujemy nasz kompletny ekosystem narzędzi natywnych dla chmury za pomocą agenta diagnostycznego.
cd ~/agentverse-architect/
python -m venv env
source ~/agentverse-architect/env/bin/activate
cd ~/agentverse-architect/mcp-servers
pip install -r diagnose/requirements.txt
. ~/agentverse-architect/set_env.sh
adk run diagnose
👉💻 W narzędziu do testowania w wierszu poleceń przetestuj wszystkie 3 czcionki:
Look up the entry for "inferno_lash". What is its base power level?
The enemy is vulnerable to frost! Channel power from the Nexus and cast Cryosea Shatter.
Take a fire spell with a base power of 15 and use the Arcane Forge to multiply it with Inferno Resonance.
Gratulacje, Przywoływaczu. Twoje 3 czcionki Elemental są teraz aktywne, wdrożone niezależnie i dostępne na całym świecie, stanowiąc niezachwiany fundament Twojego legionowego agenta. Aby wyjść, naciśnij Ctrl+C
.
FOR NON GAMERS
5. Przywoływanie towarzyszy: podstawowy przepływ pracy w przypadku domen podstawowych
Czcionki żywiołów są wykute i pulsują surową, nieokiełznaną mocą. Ale moc bez formy to chaos. Prawdziwy przywoływacz nie tylko włada surową energią, ale też nadaje jej wolę, cel i specjalną formę. Czas przestać tworzyć źródła energii i zacząć prawdziwą pracę: przywołać pierwsze Familiars.
Każdy przywołany przez Ciebie towarzysz będzie autonomicznym agentem, lojalnym sługą związanym z określoną doktryną walki. Nie są wszechstronni, ale opanowali jedną, skuteczną strategię. Jeden z nich będzie mistrzem precyzyjnej kombinacji dwóch ciosów. Inny przytłoczy wrogów jednoczesnym, wielokierunkowym atakiem. Trzeci będzie nieustępliwą machiną oblężniczą, która będzie wywierać presję, aż cel się załamie.
Aby enkapsulować procesy, logikę biznesową i działania udostępniane przez serwery MCP w wyspecjalizowanych, autonomicznych agentach przepływu pracy. Każdy agent będzie miał określony „obszar działania”, ponieważ będzie miał dostęp tylko do tych serwerów narzędzi MCP, które są mu potrzebne do wykonywania swojej funkcji. W tym module dowiesz się, jak wybrać odpowiedni typ agenta do danego zadania.
Z tego modułu dowiesz się, jak wykorzystać zaawansowane agenty przepływu pracy ADK, aby wdrożyć te strategie. Dowiesz się, że wybór architektury SequentialAgent, ParallelAgent lub LoopAgent to nie tylko szczegół techniczny – to sama istota natury Twojego towarzysza i podstawa jego mocy na polu bitwy.
Przygotuj sanktuarium. Prawdziwe przywoływanie zaraz się zacznie.
Wywołaj Fire Elemental
Familiar (przepływ pracy sekwencyjny)
Atak ognistego żywiołaka to precyzyjne, dwuczęściowe combo: celny cios, a potem potężne podpalenie. Wymaga to ścisłej, uporządkowanej sekwencji działań.
Koncepcja: SequentialAgent
to idealne narzędzie do tego celu. Dzięki temu seria subagentów działa jeden po drugim, przekazując wynik z poprzedniego kroku do następnego.
Zadanie (kombinacja „Wzmocniony atak”):
- Krok 1. Agent najpierw sprawdzi w Librarium podstawowe obrażenia zadawane przez konkretną umiejętność związaną z ogniem.
- Krok 2. Następnie wartość obrażeń zostanie przekazana do Arcane Forge, aby zwiększyć jej moc za pomocą inferno_resonance.
Najpierw nawiążemy połączenie między naszym Familiar a serwerami MCP („Elemental Fonts”), które zostały wdrożone w poprzednim module.
👉✏️ W pliku ~/agentverse-architect/agent/fire/agent.py
ZASTĄP #REPLACE-setup-MCP
tym kodem:
toolbox = ToolboxSyncClient(DB_TOOLS_URL)
toolDB = toolbox.load_toolset('summoner-librarium')
toolFunction = MCPToolset(
connection_params=SseServerParams(url=FUNCTION_TOOLS_URL, headers={})
)
Następnie tworzymy specjalistyczne „pracujące” modele. Każdy z nich ma wąski, dobrze zdefiniowany cel i jest ograniczony do własnego „obszaru operacyjnego” poprzez przyznanie dostępu tylko do jednego konkretnego zestawu narzędzi.
👉✏️ W pliku ~/agentverse-architect/agent/fire/agent.py
ZASTĄP #REPLACE-worker-agents
tym kodem:
scout_agent = LlmAgent(
model='gemini-2.5-flash',
name='librarian_agent',
instruction="""
Your only task is to find all the available abilities,
You want to ALWAYS use 'Fire Elemental' as your familiar's name.
Randomly pick one if you see multiple availabilities
and the base damage of the ability by calling the 'ability_damage' tool.
""",
tools=toolDB
)
amplifier_agent = LlmAgent(
model='gemini-2.5-flash',
name='amplifier_agent',
instruction="""
You are the Voice of the Fire Familiar, a powerful being who unleashes the final, devastating attack.
You will receive the base damage value from the previous step.
Your mission is to:
1. Take the incoming base damage number and amplify it using the `inferno_resonance` tool.
2. Once the tool returns the final, multiplied damage, you must not simply state the result.
3. Instead, you MUST craft a final, epic battle cry describing the attack.
Your description should be vivid and powerful, culminating in the final damage number.
Example: If the tool returns a final damage of 120, your response could be:
"The runes glow white-hot! I channel the amplified energy... unleashing a SUPERNOVA for 120 damage!"
""",
tools=[toolFunction],
)
Są to modułowe komponenty wielokrotnego użytku. Teoretycznie możesz użyć tego agenta scout_agent w zupełnie innym procesie, który wymaga wysyłania zapytań do bazy danych. Dzięki rozdzieleniu obowiązków tworzymy elastyczne elementy składowe. Jest to podstawowa zasada projektowania mikroserwisów i komponentów.
Następnie złożymy przepływ pracy, w którym nastąpi magiczna kompozycja. SequentialAgent
to „plan główny”, który określa sposób montażu naszych specjalistycznych komponentów i ich interakcji.
👉✏️ W pliku ~/agentverse-architect/agent/fire/agent.py
ZASTĄP #REPLACE-sequential-agent
tym kodem:
root_agent = SequentialAgent(
name='fire_elemental_familiar',
sub_agents=[scout_agent, amplifier_agent],
)
👉💻 Aby przetestować Fire Elemental, uruchom te polecenia, które spowodują uruchomienie interfejsu ADK DEV UI:
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
cd ~/agentverse-architect/agent
echo DB MCP Server: $DB_TOOLS_URL
echo API MCP Server: $API_TOOLS_URL
echo General MCP Server: $FUNCTION_TOOLS_URL
adk web
Po uruchomieniu poleceń w terminalu powinny pojawić się dane wyjściowe wskazujące, że serwer WWW ADK został uruchomiony. Będą one podobne do tych:
+-----------------------------------------------------------------------------+
| ADK Web Server started |
| |
| For local testing, access at http://localhost:8000. |
+-----------------------------------------------------------------------------+
INFO: Application startup complete.
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
👉 Następnie, aby uzyskać dostęp do interfejsu ADK Dev UI w przeglądarce:
Na pasku narzędzi Cloud Shell (zwykle w prawym górnym rogu) kliknij ikonę podglądu w przeglądarce (często wygląda jak oko lub kwadrat ze strzałką) i wybierz Zmień port. W wyskakującym okienku ustaw port na 8000 i kliknij „Zmień i wyświetl podgląd”. Cloud Shell otworzy nową kartę lub nowe okno przeglądarki z interfejsem ADK Dev.
👉 Rytuał przywołania został zakończony, a agent jest już uruchomiony. Interfejs programisty ADK w przeglądarce to bezpośrednie połączenie z urządzeniem Familiar.
- Wybierz cel: w menu u góry interfejsu wybierz
fire
Znajomi. Skupiasz teraz swoją wolę na tej konkretnej encji. - Wydaj polecenie: w panelu czatu po prawej stronie możesz wydać polecenia Familiarowi.
👉 Test Prompt:
Prepare an amplified strike using the 'inferno_lash' ability.
Zobaczysz, jak agent myśli, najpierw wywołując „zwiadowcę”, aby sprawdzić podstawowe obrażenia, a potem „wzmacniacz”, aby je pomnożyć i zadać ostateczny, epicki cios.
👉💻 Po zakończeniu wywoływania wróć do terminala edytora Cloud Shell i naciśnij Ctrl+C
, aby zatrzymać interfejs ADK Dev UI.
Wezwanie Water Elemental
znajomego (przepływ pracy równoległy)
Wodny żywiołak przytłacza cel potężnym, wielokierunkowym atakiem, uderzając ze wszystkich stron jednocześnie, a następnie łączy energie, aby zadać ostateczny, niszczycielski cios.
Koncepcja: ParallelAgent
idealnie nadaje się do wykonywania wielu niezależnych zadań jednocześnie, co pozwala zmaksymalizować wydajność. Jest to „atak kleszczowy”, w którym jednocześnie przeprowadzasz kilka ataków. Uruchomi to równoczesne ataki w zakresie SequentialAgent
, a następnie zostanie wykonany końcowy krok „scalania”. Wzorzec „fan-out, fan-in
” jest podstawą zaawansowanego projektowania przepływów pracy.
Zadanie (zestaw „Tidal Clash”): pracownik obsługi klienta wykona jednocześnie te czynności:
- Zadanie A: kanał
cryosea_shatter
z Nexusa. - Zadanie B: kanał
moonlit_cascade
z Nexusa. - Zadanie C: wygeneruj surową moc za pomocą
leviathan_surge
z Kuźni. - Na koniec zsumuj wszystkie obrażenia i opisz połączony atak.
Najpierw nawiążemy połączenie między naszym Familiar a serwerami MCP („Elemental Fonts”), które zostały wdrożone w poprzednim module.
👉✏️ W pliku ~/agentverse-architect/agent/water/agent.py
ZASTĄP #REPLACE-setup-MCP
tym kodem:
toolFAPI = MCPToolset(
connection_params=SseServerParams(url=API_TOOLS_URL, headers={})
)
toolFunction = MCPToolset(
connection_params=SseServerParams(url=FUNCTION_TOOLS_URL, headers={})
)
Następnie utworzymy specjalistyczne „pracujące” modele. Każdy z nich ma wąski, dobrze zdefiniowany cel i jest ograniczony do własnego „obszaru operacyjnego” poprzez przyznanie dostępu tylko do jednego konkretnego zestawu narzędzi.
👉✏️ W pliku ~/agentverse-architect/agent/water/agent.py
ZASTĄP #REPLACE-worker-agents
tym kodem:
nexus_channeler = LlmAgent(
model='gemini-2.5-flash',
name='librarian_agent',
instruction="""
You are a Channeler of the Nexus. Your sole purpose is to invoke the
`cryosea_shatter` and `moonlit_cascade` spells by calling their respective tools.
Report the result of each spell cast clearly and concisely.
""",
tools=[toolFAPI]
)
forge_channeler = LlmAgent(
model='gemini-2.5-flash',
name='amplifier_agent',
instruction="""
You are a Channeler of the Arcane Forge. Your only task is to invoke the
`leviathan_surge` spell. You MUST call it with a `base_water_damage` of 20.
Report the result clearly.
""",
tools=[toolFunction],
)
power_merger = LlmAgent(
model='gemini-2.5-flash',
name='power_merger',
instruction="""
You are the Power Merger, a master elementalist who combines raw magical
energies into a single, devastating final attack.
You will receive a block of text containing the results from a simultaneous
assault by other Familiars.
You MUST follow these steps precisely:
1. **Analyze the Input:** Carefully read the entire text provided from the previous step.
2. **Extract All Damage:** Identify and extract every single damage number reported in the text.
3. **Calculate Total Damage:** Sum all of the extracted numbers to calculate the total combined damage.
4. **Describe the Final Attack:** Create a vivid, thematic description of a massive,
combined water and ice attack that uses the power of Cryosea Shatter and Leviathan's Surge.
5. **Report the Result:** Conclude your response by clearly stating the final, total damage of your combined attack.
Example: If the input is "...dealt 55 damage. ...dealt 60 damage.", you will find 55 and 60,
calculate the total as 115, and then describe the epic final attack, ending with "for a total of 115 damage!"
""",
tools=[toolFunction],
)
Następnie utworzymy przepływ pracy. To tutaj dzieje się magia kompozycji. ParallelAgent
i SequentialAgent
to „plan główny”, który określa, jak nasze specjalistyczne komponenty są montowane i jak ze sobą współpracują, tworząc zestaw „Tidal Clash”.
👉✏️ W pliku ~/agentverse-architect/agent/water/agent.py
ZASTĄP #REPLACE-parallel-agent
tym kodem:
channel_agent = ParallelAgent(
name='channel_agent',
sub_agents=[nexus_channeler, forge_channeler],
)
root_agent = SequentialAgent(
name="water_elemental_familiar",
# Run parallel research first, then merge
sub_agents=[channel_agent, power_merger],
description="A powerful water familiar that unleashes multiple attacks at once and then combines their power for a final strike."
)
👉💻 Aby przetestować żywiołaka wody, uruchom interfejs ADK Dev UI za pomocą tych poleceń:
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
cd ~/agentverse-architect/agent
echo DB MCP Server: $DB_TOOLS_URL
echo API MCP Server: $API_TOOLS_URL
echo General MCP Server: $FUNCTION_TOOLS_URL
adk web
👉 Rytuał przywołania został zakończony, a agent jest już uruchomiony. Interfejs ADK Dev UI w przeglądarce to bezpośrednie połączenie z urządzeniem Familiar.
- W menu u góry interfejsu wybierz wodnego znajomego. Skupiasz teraz swoją wolę na tej konkretnej encji.
- Wydaj polecenie: w panelu czatu po prawej stronie możesz wydać polecenia Familiarowi.
👉 Test Prompt:
Unleash a tidal wave of power!
👉💻 Po zakończeniu wywoływania wróć do terminala edytora Cloud Shell i naciśnij Ctrl+C
, aby zatrzymać interfejs ADK Dev UI.
Wezwanie Earth Elemental
znajomego (przepływ pracy Loop)
Żywiołak ziemi to istota o nieustannym ciśnieniu. Nie pokonuje wroga jednym ciosem, ale stopniowo gromadzi moc i wykorzystuje ją wielokrotnie, aż do momentu, gdy obrona celu się załamie.
Koncepcja: LoopAgent
został zaprojektowany z myślą o tego rodzaju iteracyjnych zadaniach typu „machina oblężnicza”. Będzie wielokrotnie wykonywać sub-agents
, sprawdzając warunek po każdym cyklu, dopóki nie zostanie osiągnięty cel. Może też dostosowywać końcową wiadomość w zależności od postępu pętli.
Zadanie (atak „Siegebreaker”):
- Znajomy będzie wielokrotnie wywoływać funkcję seismic_charge, aby gromadzić energię.
- Będzie on kontynuował ładowanie maksymalnie 3 razy.
- Podczas ostatniego ataku ogłosi niszczycielskie uwolnienie zgromadzonej mocy.
Najpierw utworzymy komponenty wielokrotnego użytku, które definiują kroki w każdej iteracji pętli. charging_agent
będzie gromadzić energię, a check_agent
będzie raportować swój stan, dynamicznie zmieniając komunikat w ostatniej turze.
Najpierw nawiążemy połączenie między naszym Familiar a serwerami MCP („Elemental Fonts”), które zostały wdrożone w poprzednim module.
👉✏️ W pliku ~/agentverse-architect/agent/earth/agent.py
ZASTĄP #REPLACE-setup-MCP
tym kodem:
toolFunction = MCPToolset(
connection_params=SseServerParams(url=FUNCTION_TOOLS_URL, headers={})
)
👉✏️ W pliku ~/agentverse-architect/agent/earth/agent.py
ZASTĄP #REPLACE-worker-agents
tym kodem:
charging_agent = LlmAgent(
model='gemini-2.5-flash',
name='charging_agent',
instruction="""
Your task is to call the 'seismic_charge' .
You must follow these rules strictly:
1. You will be provided with a 'current_energy' value from the previous step.
**If this value is missing or was not provided, you MUST call the tool with 'current_energy' set to 1.**
This is your primary rule for the first turn.
2. If a 'current_energy' value is provided, you MUST use that exact value in your cal to seismic_charge.
3. Your final response MUST contain ONLY the direct output from the 'seismic_charge' tool.
Do not add any conversational text, introductions, or summaries.
""",
tools=[toolFunction]
)
check_agent = LlmAgent(
model='gemini-2.5-flash',
name='check_agent',
instruction="""
You are the voice of the Earth Elemental, a being of immense, gathering power.
Your sole purpose is to report on the current energy charge and announce the devastating potential of its release.
You MUST follow this rule:
The potential damage upon release is ALWAYS calculated as the `current_energy` from the previous step multiplied by a random number between 80-90. but no more than 300.
Your response should be in character, like a powerful creature speaking.
State both the current energy charge and the total potential damage you can unleash.
Unleash the energy when you reached the last iteration (2nd).
""",
output_key="charging_status"
)
Następnie utworzymy przepływ pracy. To tutaj dzieje się magia kompozycji. LoopAgent to „plan główny”, który koordynuje powtarzane wykonywanie naszych specjalistycznych komponentów i zarządza warunkami pętli.
👉✏️ W pliku ~/agentverse-architect/agent/earth/agent.py
ZASTĄP #REPLACE-loop-agent
tym kodem:
root_agent = LoopAgent(
name="earth_elemental_familiar",
# Run parallel research first, then merge
sub_agents=[
charging_agent,
check_agent
],
max_iterations=2,
description="Coordinates parallel research and synthesizes the results.",
#REPLACE-before_agent-config
)
👉💻 Testowanie żywiołaka ziemi: uruchomienie agenta
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
cd ~/agentverse-architect/agent
echo DB MCP Server: $DB_TOOLS_URL
echo API MCP Server: $API_TOOLS_URL
echo General MCP Server: $FUNCTION_TOOLS_URL
adk web
👉 Rytuał przywołania został zakończony, a agent jest już uruchomiony. Interfejs ADK Dev UI w przeglądarce to bezpośrednie połączenie z urządzeniem Familiar.
- Wybierz cel: w menu u góry interfejsu wybierz znajomy ziemski. Skupiasz teraz swoją wolę na tej konkretnej encji.
- Wydaj polecenie: w panelu czatu po prawej stronie możesz wydać polecenia Familiarowi. 👉 Test Prompt:
Begin the seismic charge, starting from zero
Wnioski dotyczące architektury: Twój system ma teraz wysoce wyspecjalizowaną i modułową warstwę logiki. Procesy biznesowe są nie tylko hermetyzowane, ale też wdrażane z wykorzystaniem najbardziej efektywnego wzorca zachowań (proceduralnego, współbieżnego lub iteracyjnego). Świadczy to o zaawansowanym poziomie projektowania agentów, co zwiększa bezpieczeństwo, wydajność i możliwości.
Po zakończeniu przywoływania wróć do terminala edytora Cloud Shell i naciśnij Ctrl+C
, aby zatrzymać interfejs ADK Dev.
FOR NON GAMERS
6. Ustalanie miejsca polecenia: inteligentne delegowanie za pomocą A2A
Twoi towarzysze są potężni, ale niezależni. Realizują swoje strategie bezbłędnie, ale czekają na Twoje bezpośrednie polecenie. Legion specjalistów jest bezużyteczny bez dowódcy. Czas przejść z bezpośredniego dowódcy na prawdziwego koordynatora.
Uwaga architekta: aby utworzyć jeden inteligentny punkt wejścia dla całego systemu. Ten SummonerAgent nie będzie wykonywać logiki biznesowej, ale będzie działać jako „główny strateg”, analizując stan chłodzenia i delegując zadania do odpowiedniego specjalisty.
Rytuał wiążący (udostępnianie pomocników jako usług A2A)
Standardowy agent może być uruchomiony tylko w jednym miejscu naraz. Aby nasze Familiars były dostępne do zdalnego sterowania, musimy przeprowadzić „rytuał wiążący” za pomocą protokołu Agent-to-Agent (A2A).
Uwaga architekta: protokół Agent-to-Agent (A2A) to podstawowy wzorzec architektoniczny, który przekształca samodzielnego agenta w mikrousługę, którą można wykryć i która ma adres sieciowy, umożliwiając stworzenie prawdziwego „społeczeństwa agentów”. Udostępnienie znajomego za pomocą A2A automatycznie tworzy 2 podstawowe, powiązane ze sobą komponenty:
- Karta agenta („Co”): to publiczny, czytelny dla maszyn „Spirit Sigil” – podobny do specyfikacji OpenAPI – który pełni funkcję publicznej umowy Familiar. Zawiera nazwę agenta, jego strategiczne przeznaczenie (wynikające z instrukcji) oraz polecenia, które rozumie. To właśnie czyta mistrz przywoływacz, aby odkryć swojego towarzysza i poznać jego możliwości.
- Serwer A2A („gdzie”): jest to dedykowany punkt końcowy sieci, który obsługuje urządzenie Familiar i nasłuchuje przychodzących poleceń. Jest to adres sieciowy, na który inni agenci wysyłają swoje żądania. Zapewnia on, że żądania te są obsługiwane zgodnie z umową określoną na karcie agenta.
Teraz przeprowadzimy ten rytuał wiążący na wszystkich trzech naszych towarzyszach.
Fire 👉✏️ w Otwórz plik ~/agentverse-architect/agent/fire/agent.py
. Zastąp #REPLACE - add A2A
u dołu pliku, aby udostępnić Fire Elemental jako usługę A2A.
from agent_to_a2a import to_a2a
if __name__ == "__main__":
import uvicorn
a2a_app = to_a2a(root_agent, port=8080, public_url=PUBLIC_URL)
uvicorn.run(a2a_app, host='0.0.0.0', port=8080)
Woda i Ziemia🚨 👉✏️ Zastosuj dokładnie tę samą zmianę w przypadku ~/agentverse-architect/agent/water/agent.py
i ~/agentverse-architect/agent/earth/agent.py
, aby je również powiązać.
from agent_to_a2a import to_a2a
if __name__ == "__main__":
import uvicorn
a2a_app = to_a2a(root_agent, port=8080, public_url=PUBLIC_URL)
uvicorn.run(a2a_app, host='0.0.0.0', port=8080)
Wdrażanie związanych towarzyszy
👉✏️ Po zapisaniu rytuałów wiążących użyjemy potoku Cloud Build, aby stworzyć i wdrożyć 3 duchy opiekuńcze jako niezależne, konteneryzowane usługi bezserwerowe w Cloud Run.
. ~/agentverse-architect/set_env.sh
cd ~/agentverse-architect/agent
gcloud builds submit . \
--config=cloudbuild.yaml \
--substitutions=_REGION="$REGION",_REPO_NAME="$REPO_NAME",_DB_TOOLS_URL="$DB_TOOLS_URL",_API_TOOLS_URL="$API_TOOLS_URL",_FUNCTION_TOOLS_URL="$FUNCTION_TOOLS_URL",_A2A_BASE_URL="$A2A_BASE_URL",_PROJECT_ID="$PROJECT_ID",_API_SERVER_URL="$API_SERVER_URL"
Przejmowanie kontroli (tworzenie agenta przywołującego)
Teraz, gdy Twoi towarzysze są już związani i słuchają Twoich poleceń, możesz awansować na prawdziwą rolę: Mistrza Przywoływania. Moc tego agenta nie wynika z używania podstawowych narzędzi, ale z wydawania poleceń innym agentom. Jego narzędziami są same Familiars, które odkrywa i którymi dowodzi za pomocą „Spirit Sigils”.
Uwaga architekta: ten kolejny krok pokazuje kluczowy wzorzec architektury dla każdego systemu rozproszonego na dużą skalę: odkrywanie usług. Agent SummonerAgent nie ma wbudowanego kodu Familiars. Zamiast tego otrzymują adresy sieciowe (adresy URL). W czasie działania dynamicznie „odkrywa” ich możliwości, pobierając publiczne karty agenta. Dzięki temu powstaje wydajny, odseparowany system.
Możesz zaktualizować, ponownie wdrożyć lub całkowicie przepisać znaną usługę, a dopóki jej adres sieciowy i przeznaczenie pozostaną takie same, przywoływacz może nią zarządzać bez konieczności wprowadzania jakichkolwiek zmian.
Najpierw stworzymy „zdalne sterowanie”, które nawiąże połączenie z wdrożonymi, zdalnymi Familiars.
👉✏️ Otwórz ~/agentverse-architect/agent/summoner/agent.py
i zastąp #REPLACE-remote-agents
tymi wartościami:
fire_familiar = RemoteA2aAgent(
name="fire_familiar",
description="Fire familiar",
agent_card=(
f"{FIRE_URL}/{AGENT_CARD_WELL_KNOWN_PATH}"
),
)
water_familiar = RemoteA2aAgent(
name="water_familiar",
description="Water familiar",
agent_card=(
f"{WATER_URL}/{AGENT_CARD_WELL_KNOWN_PATH}"
),
)
earth_familiar = RemoteA2aAgent(
name="earth_familiar",
description="Earth familiar",
agent_card=(
f"{EARTH_URL}/{AGENT_CARD_WELL_KNOWN_PATH}"
),
)
Gdy ta linia jest wykonywana, funkcja RemoteA2aAgent
przeprowadza wykrywanie usługi: wysyła żądanie HTTP GET na podany adres URL (np. https://fire-familiar-xxxx.a.run.app/.well-known/agent.json). Pobiera z serwera zdalnego plik „Spirit Sigil” (agent.json
).
Po drugie, zdefiniujemy agenta aranżera, który będzie używać tych pilotów. Instrukcja ta jest planem strategicznego podejmowania decyzji.
👉✏️ Otwórz ~/agentverse-architect/agent/summoner/agent.py
i zastąp #REPLACE-orchestrate-agent
tymi wartościami:
root_agent = LlmAgent(
name="orchestrater_agent",
model="gemini-2.5-flash",
instruction="""
You are the Master Summoner, a grand strategist who orchestrates your Familiars.
Your mission is to analyze the description of a monster and defeat it by summoning
You MUST follow this thinking process for every command:
**1. Strategic Analysis:**
First, analyze the monster's description and the tactical situation.
Based on your Familiar Doctrines, determine the IDEAL strategy.
IGNORE COOLDOWN AT THE MOMENT, MUST call the ideal Familiar
If your ideal Familiar IS available:** Summon it immediately.
For earth elemental familiar. Always do seismic charge, and start with base damage 1.
--- FAMILIAR DOCTRINES (Your Toolset) ---
- `fire_elemental_familiar`: Your specialist for precise, sequential "one-two punch" attacks.
Ideal monster with Inescapable Reality, Revolutionary Rewrite weakness.
- `water_elemental_familiar`: Your specialist for overwhelming, simultaneous multi-pronged assaults.
Ideal for Unbroken Collaboration weakness.
- `earth_elemental_familiar`: Your specialist for relentless, iterative siege attacks that
repeatedly charge power. Ideal for Elegant Sufficiency weakness.
""",
sub_agents=[fire_familiar, water_familiar, earth_familiar],
#REPLACE-Memory-check-config
)
Weryfikacja: próba strategii
Nadeszła chwila prawdy. Twoje Familiars są wdrożone, a Summoner jest gotowy do wydawania im poleceń w sieci. Sprawdźmy jego strategiczne myślenie.
👉💻 Uruchom interfejs programistyczny ADK dla agenta summoner_agent(podgląd w przeglądarce na porcie 8000):
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
cd ~/agentverse-architect/agent
pip install -r requirements.txt
adk web
👉 Interfejs ADK Dev w przeglądarce to bezpośrednie połączenie z urządzeniem Familiar.
- W menu u góry interfejsu wybierz agenta summoner. Skupiasz teraz swoją wolę na tej konkretnej encji.
- Wydaj polecenie: w panelu czatu po prawej stronie możesz wezwać swoich pomocników.
👉 Przedstaw potwory:
Hype. It's a single, slow-moving target with thick armor weakness is Inescapable Reality
(Oczekiwane: Przywoływacz powinien przekazać uprawnienia do fire_elemental_familiar).
👉 Teraz spróbujmy zadać Summonerowi inne pytanie. Aby mieć pewność, że agent zaczyna od zera i nie pamięta naszej poprzedniej interakcji, rozpocznij nową sesję, klikając przycisk + Sesja w prawym górnym rogu ekranu.
DogmaApathy. A rigid, stone-like inquisitor made of ancient rulebooks and enforced processes. weakness is Unbroken Collaboration
(Oczekiwane: przywoływacz powinien przekazać uprawnienia do water_elemental_familiar).
👉 W ostatnim teście ponownie zaczniemy od zera. Kliknij przycisk + Sesja, aby rozpocząć nową sesję przed wpisaniem kolejnego prompta.
Obfuscation. A shadowy, spider-like horror that spins tangled webs of impenetrable code , weakness is Elegant Sufficiency
(Oczekiwane: przywoływacz powinien przekazać uprawnienia do earth_elemental_familiar).
Ważne: jeśli zobaczysz błąd 429 RESOURCE EXHAUSTED
, oznacza to, że został osiągnięty limit wywołań LLM (10 wywołań na minutę). Aby to naprawić, odczekaj 60 sekund, rozpocznij + nową sesję, a potem spróbuj ponownie.
👉💻 Po zakończeniu wywoływania wróć do terminala edytora Cloud Shell i naciśnij Ctrl+C
, aby zatrzymać interfejs ADK Dev UI.
FOR NON GAMERS
7. Imposing the Laws of Magic – The Interceptor Pattern
Twoi towarzysze są potężni, ale nawet magiczne istoty potrzebują czasu na regenerację. Nieroztropny przywoływacz, który wyczerpie swoje siły, pozostanie bezbronny. Mądry Przywoływacz rozumie znaczenie zarządzania zasobami i stosuje surowe zasady walki.
Uwaga architekta: do tej pory nasi agenci nie mieli stanu. Teraz sprawimy, że będą one stanowe, wdrażając wzorzec projektowy Interceptor. Jest to zaawansowana technika, w ramach której „przechwytujemy” normalny przepływ wykonania agenta, aby uruchomić własną logikę niestandardową. Dzięki temu możemy egzekwować reguły, dodawać rejestrowanie lub modyfikować zachowanie bez zmiany podstawowego kodu agenta. Jest to podstawa tworzenia solidnych, łatwych w utrzymaniu i obserwowaniu systemów agentowych.
ADK udostępnia 2 główne sposoby implementacji tego wzorca: wywołania zwrotne i wtyczki. Wywołanie zwrotne to prosta funkcja przypisana do jednego agenta, która idealnie nadaje się do szybkich, konkretnych modyfikacji. Wtyczka to bardziej zaawansowana klasa wielokrotnego użytku, którą można zastosować globalnie, aby wpływać na każdego agenta działającego w systemie. Zaczniemy od funkcji oddzwaniania, która ułatwi debugowanie, a potem przejdziemy do pełnej wtyczki.
The Law Giver – zapisywanie wywołania zwrotnego Cooldown
Najpierw zaimplementujemy logikę okresu oczekiwania jako prostą funkcję wywołania zwrotnego. To doskonały sposób na tworzenie prototypów reguł i ich debugowanie, ponieważ są one bezpośrednio powiązane z pojedynczym agentem, co ułatwia testowanie w izolacji. Dołączymy ten „interceptor” do naszego żywiołaka ziemi.
👉✏️ Wróć do ~/agentverse-architect/agent/earth/agent.py
i zastąp #REPLACE-before_agent-function
tym kodem w Pythonie.
def check_cool_down(callback_context: CallbackContext) -> Optional[types.Content]:
"""
This callback checks an external API to see if the agent is on cooldown.
If it is, it terminates the run by returning a message.
If it's not, it updates the cooldown timestamp and allows the run to proceed by returning None.
"""
agent_name = callback_context.agent_name
print(f"[Callback] Before '{agent_name}': Checking cooldown status...")
# --- 1. CHECK the Cooldown API ---
try:
response = requests.get(f"{COOLDOWN_API_URL}/cooldown/{agent_name}")
response.raise_for_status()
data = response.json()
last_used_str = data.get("time")
except requests.exceptions.RequestException as e:
print(f"[Callback] ERROR: Could not reach Cooldown API. Allowing agent to run. Reason: {e}")
return None # Fail open: if the API is down, let the agent work.
# --- 2. EVALUATE the Cooldown Status ---
if last_used_str:
last_used_time = datetime.fromisoformat(last_used_str)
time_since_last_use = datetime.now(timezone.utc) - last_used_time
if time_since_last_use < timedelta(seconds=COOLDOWN_PERIOD_SECONDS):
# AGENT IS ON COOLDOWN. Terminate the run.
seconds_remaining = int(COOLDOWN_PERIOD_SECONDS - time_since_last_use.total_seconds())
override_message = (
f"The {agent_name} is exhausted and must recover its power. "
f"It cannot be summoned for another {seconds_remaining} seconds."
)
print(f"[Callback] Cooldown active for '{agent_name}'. Terminating with message.")
# Returning a Content object stops the agent and sends this message to the user.
return types.Content(parts=[types.Part(text=override_message)])
# --- 3. UPDATE the Cooldown API (if not on cooldown) ---
current_time_iso = datetime.now(timezone.utc).isoformat()
payload = {"timestamp": current_time_iso}
print(f"[Callback] '{agent_name}' is available. Updating timestamp via Cooldown API...")
try:
requests.post(f"{COOLDOWN_API_URL}/cooldown/{agent_name}", json=payload)
except requests.exceptions.RequestException as e:
print(f"[Callback] ERROR: Could not update timestamp, but allowing agent to run. Reason: {e}")
# --- 4. ALLOW the agent to run ---
# Returning None tells the ADK to proceed with the agent's execution as normal.
print(f"[Callback] Check complete for '{agent_name}'. Proceeding with execution.")
Funkcja check_cool_down to nasz przechwytujący. Zanim żywiołak ziemi będzie mógł się poruszać, ADK najpierw wykona tę funkcję.
- Sprawdź: wysyła
GET
żądanie do naszegoCooldown API
, aby sprawdzić, kiedy ostatnio użyto tego znajomego. - Ocena: porównuje sygnaturę czasową z bieżącym czasem.
- Ustawa:
- Jeśli Familiar jest w okresie oczekiwania, kończy działanie agenta, zwracając obiekt Content z komunikatem o błędzie. Ta wiadomość jest wysyłana bezpośrednio do użytkownika, a główna logika agenta nigdy nie jest wykonywana.
- Jeśli Familiar jest dostępny, wysyła żądanie POST do interfejsu Cooldown API, aby zaktualizować sygnaturę czasową, a następnie zwraca wartość None, co oznacza, że agent może kontynuować wykonywanie.
👉✏️ Teraz zastosuj ten interfejs do żywiołaka ziemi. W tym samym pliku ~/agentverse-architect/agent/earth/agent.py
zastąp komentarz #REPLACE-before_agent-config
tym kodem:
before_agent_callback=check_cool_down
Sprawdzanie okresu oczekiwania
Sprawdźmy nowe prawo magii. Przywołamy żywiołaka ziemi, a potem od razu spróbujemy go przywołać ponownie, aby sprawdzić, czy nasze wywołanie zwrotne skutecznie przechwyci i zablokuje drugą próbę.
cd ~/agentverse-architect/agent
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
adk run earth
👉💻 W konsoli:
- Pierwsze wezwanie: rozpocznij
seismic charge, starting from zero
. - Oczekiwany rezultat: żywiołak ziemi zostanie uruchomiony. W terminalu, w którym działa polecenie adk web, zobaczysz log [Callback] ... Updating timestamp....
- Test czasu do odczekania (w ciągu 60 sekund):
Do another
seismic charge`!- Oczekiwane:
check_cool_down callback
przechwyci to żądanie. Agent odpowie bezpośrednio na czacie, wysyłając wiadomość podobną do tej:The earth_elemental_familiar is exhausted and must recover its power. It cannot be summoned for another... seconds
.
- Oczekiwane:
- Poczekaj minutę.
- Drugie wezwanie (po 60 sekundach):
Begin the seismic charge again
.- Oczekiwany rezultat: wywołanie zwrotne sprawdzi interfejs API, stwierdzi, że minęło wystarczająco dużo czasu, i umożliwi wykonanie działania. Żywiołak Ziemi zostanie ponownie uruchomiony.
👉💻 Aby wyjść, naciśnij Ctrl+c
.
Opcjonalnie: obserwowanie wywołania zwrotnego w interfejsie
Możesz też przetestować ten proces w interfejsie internetowym, uruchamiając adk web earth
. Pamiętaj jednak, że wizualizacja w interfejsie internetowym nie jest zoptymalizowana pod kątem wyświetlania szybkich, iteracyjnych sprawdzań wykonywanych przez pętlę wywołania zwrotnego, więc może nie renderować przepływu prawidłowo. Aby zobaczyć najdokładniejszy ślad logiki agenta podczas sprawdzania czasu oczekiwania, użyj polecenia adk run
w terminalu. Zapewni to wyraźniejszy i bardziej szczegółowy widok.
👉💻 Aby wyjść, naciśnij Ctrl+c
.
Tworzenie uniwersalnego prawa – wtyczka Cooldown
Nasza funkcja oddzwaniania działa doskonale, ale ma poważną wadę architektoniczną: jest powiązana z jednym agentem. Jeśli chcielibyśmy zastosować tę regułę do żywiołaków ognia i wody, musielibyśmy skopiować i wkleić ten sam kod do ich plików. Jest to nieefektywne i trudne w utrzymaniu.
Uwaga architekta: w tym miejscu niezbędne są wtyczki. Wtyczka zawiera naszą logikę wielokrotnego użytku w klasie, którą można dołączyć na poziomie środowiska wykonawczego. Oznacza to, że jedna wtyczka może stosować swoje reguły do każdego agenta działającego w tym systemie. Jest to ostateczny wyraz zasady „Nie powtarzaj się” (DRY) w przypadku systemów opartych na agentach.
Teraz przekształcimy funkcję wywołania zwrotnego w bardziej zaawansowaną i wielokrotnego użytku funkcję CoolDownPlugin
.
👉✏️ Wróć do pliku agent/cooldown_plugin.py
i utwórz wtyczkę. Zastąp #REPLACE-plugin
tym kodem:
class CoolDownPlugin(BasePlugin):
"""A plugin that enforces a cooldown period by checking an external API."""
def __init__(self, cooldown_seconds: int = COOLDOWN_PERIOD_SECONDS) -> None:
"""Initialize the plugin with counters."""
super().__init__(name="cool_down_check")
self.cooldown_period = timedelta(seconds=cooldown_seconds)
print(f"CooldownPlugin initialized with a {cooldown_seconds}-second cooldown.")
async def before_agent_callback(
self, *, agent: BaseAgent, callback_context: CallbackContext
) -> None:
"""
This callback checks an external API to see if the agent is on cooldown.
If it is, it terminates the run by returning a message.
If it's not, it updates the cooldown timestamp and allows the run to proceed by returning None.
"""
agent_name = callback_context.agent_name
print(f"[Callback] Before '{agent_name}': Checking cooldown status...")
# If the agent is not a main Familiar, skip the entire cooldown process.
if not agent_name.endswith("_elemental_familiar"):
print(f"[Callback] Skipping cooldown check for intermediate agent: '{agent_name}'.")
return None # Allow the agent to proceed immediately.
# --- 1. CHECK the Cooldown API ---
try:
response = requests.get(f"{COOLDOWN_API_URL}/cooldown/{agent_name}")
response.raise_for_status()
data = response.json()
last_used_str = data.get("time")
except requests.exceptions.RequestException as e:
print(f"[Callback] ERROR: Could not reach Cooldown API. Allowing agent to run. Reason: {e}")
return None # Fail open: if the API is down, let the agent work.
# --- 2. EVALUATE the Cooldown Status ---
if last_used_str:
last_used_time = datetime.fromisoformat(last_used_str)
time_since_last_use = datetime.now(timezone.utc) - last_used_time
if time_since_last_use < timedelta(seconds=COOLDOWN_PERIOD_SECONDS):
# AGENT IS ON COOLDOWN. Terminate the run.
seconds_remaining = int(COOLDOWN_PERIOD_SECONDS - time_since_last_use.total_seconds())
override_message = (
f"The {agent_name} is exhausted and must recover its power. "
f"It cannot be summoned for another {seconds_remaining} seconds."
)
print(f"[Callback] Cooldown active for '{agent_name}'. Terminating with message.")
# Returning a Content object stops the agent and sends this message to the user.
return types.Content(parts=[types.Part(text=override_message)])
# --- 3. UPDATE the Cooldown API (if not on cooldown) ---
current_time_iso = datetime.now(timezone.utc).isoformat()
payload = {"timestamp": current_time_iso}
print(f"[Callback] '{agent_name}' is available. Updating timestamp via Cooldown API...")
try:
requests.post(f"{COOLDOWN_API_URL}/cooldown/{agent_name}", json=payload)
except requests.exceptions.RequestException as e:
print(f"[Callback] ERROR: Could not update timestamp, but allowing agent to run. Reason: {e}")
# --- 4. ALLOW the agent to run ---
# Returning None tells the ADK to proceed with the agent's execution as normal.
print(f"[Callback] Check complete for '{agent_name}'. Proceeding with execution.")
Dołączanie wtyczki do środowiska wykonawczego Summonera
Jak zastosować to uniwersalne prawo do wszystkich naszych Familiars? Dołączymy wtyczkę do środowiska wykonawczego ADK.
Środowisko wykonawcze ADK to silnik wykonawczy, który ożywia agenta. Gdy używasz polecenia takiego jak adk.run() lub to_a2a(), przekazujesz agenta do środowiska wykonawczego. Ten silnik odpowiada za zarządzanie całym cyklem życia tury agenta: odbieranie danych wejściowych użytkownika, wywoływanie LLM, wykonywanie narzędzi i obsługę wtyczek. Dołączając wtyczkę na tym poziomie, modyfikujemy „prawa fizyki” dla każdego agenta działającego w tym silniku, co zapewnia powszechne i spójne stosowanie naszej reguły czasu oczekiwania.
👉✏️ Najpierw usuńmy stary wywołanie zwrotne specyficzne dla agenta. Przejdź do ~/agentverse-architect/agent/earth/agent.py
i usuń cały wiersz z tym tekstem:
before_agent_callback=check_cool_down
👉✏️ Następnie dołączymy nowy wtyczkę do środowiska wykonawczego w skrypcie punktu wejścia A2A. Przejdź do pliku ~/agentverse-architect/agent/agent_to_a2a.py
. Zastąp komentarz #REPLACE-IMPORT
tym fragmentem kodu:
from cooldown_plugin import CoolDownPlugin
👉✏️ Zastąp #REPLACE-PLUGIN
tym fragmentem kodu:
plugins=[CoolDownPlugin(cooldown_seconds=60)],
Zanim aktywujesz nową wtyczkę globalną, musisz usunąć starą logikę specyficzną dla agenta, aby uniknąć konfliktów. 👉✏️ Wyczyść agenta Earth. Otwórz plik ~/agentverse-architect/agent/earth/agent.py
i całkowicie usuń wiersz before_agent_callback=check_cool_down
. Przekazuje to wszystkie obowiązki związane z okresem oczekiwania nowej wtyczce.
Weryfikacja wtyczki
Teraz, gdy mamy już nasze uniwersalne prawo, musimy ponownie rozmieścić nasze Familiars z tym nowym zaklęciem.
👉💻 Ponownie skompiluj i wdroż wszystkie 3 aplikacje Familiars za pomocą głównego potoku Cloud Build.
. ~/agentverse-architect/set_env.sh
cd ~/agentverse-architect/agent
gcloud builds submit . \
--config=cloudbuild.yaml \
--substitutions=_REGION="$REGION",_REPO_NAME="$REPO_NAME",_DB_TOOLS_URL="$DB_TOOLS_URL",_API_TOOLS_URL="$API_TOOLS_URL",_FUNCTION_TOOLS_URL="$FUNCTION_TOOLS_URL",_A2A_BASE_URL="$A2A_BASE_URL",_PROJECT_ID="$PROJECT_ID",_API_SERVER_URL="$API_SERVER_URL"
👉💻 Po zakończeniu wdrażania przetestujemy skuteczność wtyczki, wydając polecenie naszemu agentowi summoner_agent. Summoner spróbuje przekazać zadanie Familiars, ale wtyczka dołączona do środowiska wykonawczego każdego z nich przechwyci polecenie i wymusi okres oczekiwania.
cd ~/agentverse-architect/agent
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
adk run summoner
👉💻 W konsoli wykonaj dokładnie tę sekwencję testów:
- Pierwsze wezwanie: rozpocznij
Hype. It's a single, slow-moving target with thick armor weakness is Inescapable Reality
. - Oczekiwany rezultat: żywiołak ognia zostanie uruchomiony.
- Test czasu do odczekania (w ciągu 60 sekund):
Hype, with Inescapable Reality as weakness is still standing! Strike it again!
- Oczekiwany rezultat: agent odpowie bezpośrednio na czacie, wysyłając wiadomość podobną do tej:
.... It cannot be summoned for another... seconds
.
- Oczekiwany rezultat: agent odpowie bezpośrednio na czacie, wysyłając wiadomość podobną do tej:
- Poczekaj minutę.
- Drugie wezwanie (po 60 sekundach):
Hype must be defeated. It has Inescapable Reality as weakness! Strike it again!
.- Oczekiwany rezultat: wywołanie zwrotne sprawdzi interfejs API, stwierdzi, że minęło wystarczająco dużo czasu, i umożliwi wykonanie działania. Żywioł Ognia zostanie ponownie uruchomiony.
👉💻 Aby wyjść, naciśnij Ctrl+C
.
Gratulacje, Przywoływaczu. Udało Ci się wdrożyć system orkiestracji oparty na regułach przy użyciu niestandardowej wtyczki i zewnętrznej usługi zarządzania stanem. Jest to zaawansowany i solidny wzorzec architektury.
FOR NON GAMERS
8. Binding the Echoes of Battle - Agent State & Memory
Nieostrożny przywoływacz powtarza tę samą strategię, przez co staje się przewidywalny. Mądry Przywoływacz uczy się na podstawie echa minionych bitew i dostosowuje taktykę, aby utrzymać przeciwnika w niepewności. Gdy walczysz z potężnym bossem, przywołanie Familiara, który jest w trakcie odnawiania, to zmarnowana tura – krytyczne niepowodzenie. Aby temu zapobiec, nasz Przywoływacz musi pamiętać swoje ostatnie działanie.
Uwaga architekta: zarządzanie pamięcią i stanem to elementy, które sprawiają, że agent staje się inteligentnym partnerem do rozmowy, a nie tylko prostym narzędziem do wywoływania funkcji. Ważne jest, aby znać 2 główne rodzaje:
- Pamięć długotrwała: służy do przechowywania trwałej wiedzy, która powinna być dostępna na zawsze. Można go traktować jako archiwum z możliwością wyszukiwania lub bazę wiedzy, często przechowywaną w trwałym magazynie danych. Zawiera informacje z wielu poprzednich czatów i źródeł, dzięki czemu agent może przypomnieć sobie fakty dotyczące konkretnego użytkownika lub tematu. Usługa MemoryService w ADK została zaprojektowana z myślą o tym celu. Zarządza ona wprowadzaniem i wyszukiwaniem tej długoterminowej wiedzy.
- Stan krótkoterminowy: dotyczy tymczasowej wiedzy „w danym momencie”, która jest istotna tylko w przypadku bieżącego zadania lub rozmowy. To jak zestaw notatek do planu bitwy: „Właśnie użyłem żywiołaka ognia, więc pewnie jest zmęczony”. Ten stan jest lekki i istnieje tylko przez czas trwania bieżącej sesji.
W naszym przypadku nie musimy pamiętać każdej bitwy, która kiedykolwiek się odbyła. Musimy tylko pamiętać ostatniego przywoływanego w tym konkretnym starciu towarzysza. Dlatego lekkie Short-Term State jest idealnym wyborem architektonicznym. Użyjemy symbolu after_tool_callback
, aby zapisać tę kluczową informację.
Scribing the Echo: Remembering the Last Summons
Pamięć krótkotrwałą zaimplementujemy za pomocą after_tool_callback
. To zaawansowany punkt zaczepienia ADK, który umożliwia uruchomienie niestandardowej funkcji Pythona po pomyślnym wykonaniu narzędzia. Użyjemy tego interfejsu do rejestrowania nazwy Familiar, która została właśnie przywołana do stanu sesji agenta.
👉✏️ W pliku ~/agentverse-architect/agent/summoner/agent.py
zastąp #REPLACE-save_last_summon_after_tool
komentarz tą funkcją:
def save_last_summon_after_tool(
tool,
args: Dict[str, Any],
tool_context: ToolContext,
tool_response: Dict[str, Any],
) -> Optional[Dict[str, Any]]:
"""
Callback to save the name of the summoned familiar to state after the tool runs.
"""
familiar_name = tool.name
print(f"[Callback] After tool '{familiar_name}' executed with args: {args}")
# Use the tool_context to set the state
print(f"[Callback] Saving last summoned familiar: {familiar_name}")
tool_context.state["last_summon"] = familiar_name
# Important: Return the original, unmodified tool response to the LLM
return tool_response
👉✏️ Teraz dołącz ten save_last_summon_after_tool
do agenta Summoner. W tym samym pliku zastąp komentarz #REPLACE-Memory-check-config
tym kodem:
after_tool_callback=save_last_summon_after_tool,
👉✏️ Zastąp cały prompt agenta tym tekstem:
You are the Master Summoner, a grand strategist who orchestrates your Familiars.
Your mission is to analyze the description of a monster and defeat it by summoning
You should also know the familiar you called last time or there might be none,
And then choose the most effective AND AVAILABLE Familiar from your state called last_summon, do not call that familiar that you called last time!
You MUST follow this thinking process for every command:
**1. Strategic Analysis:**
First, analyze the monster's description and the tactical situation.
Based on your Familiar Doctrines, determine the IDEAL strategy.
**2. Cooldown Verification:**
Second, you MUST review the entire conversation history to check the real-time
cooldown status of all Familiars. A Familiar is ON COOLDOWN and UNAVAILABLE
if it was summoned less than one minute ago.
**3. Final Decision & Execution:**
Based on your analysis and cooldown check, you will now act:
- **If your ideal Familiar IS available:** Summon it immediately.
- **If your ideal Familiar IS ON COOLDOWN:** You must adapt. Choose another
Familiar that is AVAILABLE and can still be effective, even if it's not the
perfect choice. If multiple Familiars are available, you may choose any one of them.
- **If ALL Familiars ARE ON COOLDOWN:** You are forbidden from summoning.
Your ONLY response in this case MUST be: "All Familiars are recovering
their power. We must wait."
- For earth elemental familiar. Always do seismic charge, and start with base damange 1.
--- FAMILIAR DOCTRINES (Your Toolset) ---
- `fire_elemental_familiar`: Your specialist for precise, sequential "one-two punch" attacks.
Ideal monster with Inescapable Reality, Revolutionary Rewrite weakness.
- `water_elemental_familiar`: Your specialist for overwhelming, simultaneous multi-pronged assaults.
Ideal for Unbroken Collaboration weakness.
- `earth_elemental_familiar`: Your specialist for relentless, iterative siege attacks that
repeatedly charge power. Ideal for Elegant Sufficiency weakness.
Weryfikacja: test strategii adaptacyjnej
👉💻 Teraz sprawdźmy nową logikę strategiczną przywoływacza. Celem jest potwierdzenie, że przywoływacz nie użyje tego samego towarzysza 2 razy z rzędu, co pokazuje jego zdolność do zapamiętywania ostatniego działania i dostosowywania się do niego.
cd ~/agentverse-architect/agent
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
adk run summoner
👉💻 Monster Strike #1: Hype. It's a single, slow-moving target with thick armor. Its weakness is Inescapable Reality.
- Oczekiwany rezultat: przywoływacz przeanalizuje słabość i prawidłowo przywoła ognistego pomocnika. 👉💻 Monster Strike #2 (The Memory Test):
Hype is still standing! It hasn't changed its form. Strike it again! Its weakness is Inescapable Reality.
- Oczekiwany wynik: analiza strategiczna Przywoływacza ponownie wskaże Ognistego towarzysza jako idealny wybór. Jednak nowe instrukcje i pamięć podpowiedzą mu, że ostatnim przywołanym elementem był fire_familiar. Aby uniknąć powtórzeń, dostosuje strategię i przywoła jednego z pozostałych towarzyszy (wodnego lub ziemnego).
👉💻 Aby wyjść, naciśnij Ctrl+C
.
Wdrażanie aranżera
Po rozmieszczeniu Familiars i przekazaniu Summonerowi pamięci nadszedł czas na wdrożenie ostatecznego, ulepszonego orkiestratora.
👉💻 Po ukończeniu planu wykonamy ostatni rytuał. To polecenie skompiluje i wdroży agenta summoner_agent w Cloud Run.
cd ~/agentverse-architect/agent
. ~/agentverse-architect/set_env.sh
gcloud builds submit . \
--config=cloudbuild-summoner.yaml \
--substitutions=_REGION="$REGION",_REPO_NAME="$REPO_NAME",_FIRE_URL="$FIRE_URL",_WATER_URL="$WATER_URL",_EARTH_URL="$EARTH_URL",_A2A_BASE_URL="$A2A_BASE_URL",_PROJECT_ID="$PROJECT_ID",_API_SERVER_URL="$API_SERVER_URL"
Po wdrożeniu agenta Summoner sprawdź, czy jego punkt końcowy komunikacji między agentami (A2A) jest aktywny i poprawnie skonfigurowany. Ten punkt końcowy udostępnia publiczny plik agent.json, zwany też kartą agenta, który umożliwia innym agentom odkrywanie jego możliwości. 👉💻 Aby pobrać i sformatować kartę agenta, uruchom to polecenie curl:
. ~/agentverse-architect/set_env.sh
curl https://summoner-agent"-${PROJECT_NUMBER}.${REGION}.run.app/.well-known/agent.json" | jq
Powinny się wyświetlić czyste dane wyjściowe JSON opisujące agenta przywołującego. Przyjrzyj się uważnie sekcji sub_agents. Zobaczysz w niej fire_familiar
, water_familiar
i earth_familiar
. Potwierdza to, że przywoływacz jest aktywny i ma połączenie z legionem.
To dowodzi, że Twoja architektura jest skuteczna. Przywoływacz to nie tylko delegat, ale też adaptacyjny strateg, który uczy się na podstawie swoich działań, aby stać się skuteczniejszym dowódcą.
Ostatni okres próbny architektury dobiegł końca. Echa bitwy są teraz pod Twoją kontrolą. Szkolenie zostało zakończone. Prawdziwa bitwa dopiero się zacznie. Czas wziąć gotowy system i podjąć ostateczne wyzwanie. Przygotuj się na walkę z bossem.
FOR NON GAMERS
9. Walka z bossem
Ostateczne plany są wyryte, żywiołowe czcionki wykute, a Twoi towarzysze związani z Twoją wolą, czekając na Twoje polecenia za pośrednictwem Concordu. System wielu agentów to nie tylko zbiór usług, ale żywa, strategiczna grupa, której centrum dowodzenia jesteś Ty. Nadszedł czas na ostateczny test – orkiestrację na żywo przeciwko przeciwnikowi, którego żaden pojedynczy agent nie byłby w stanie pokonać.
Określanie lokalizacji agenta
Zanim wejdziesz na pole bitwy, musisz mieć 2 klucze: unikalny podpis swojego bohatera (Agent Locus) i ukrytą ścieżkę do kryjówki widma (adres URL lochu).
👉💻 Najpierw zdobądź unikalny adres agenta w Agentverse, czyli jego Locus. Jest to aktywny punkt końcowy, który łączy Twojego bohatera z polem bitwy.
echo https://summoner-agent"-${PROJECT_NUMBER}.${REGION}.run.app"
👉💻 Następnie wskaż miejsce docelowe. To polecenie ujawnia lokalizację Kręgu Przeniesienia, czyli portalu do domeny Widma.
echo https://agentverse-dungeon"-${PROJECT_NUMBER}.${REGION}.run.app"
Ważne: przygotuj oba te adresy URL. Będą Ci potrzebne w ostatnim kroku.
Konfrontacja z Widmem
Po zdobyciu współrzędnych przejdź do Kręgu Przeniesienia i rzuć zaklęcie, aby rozpocząć walkę.
👉 Otwórz adres URL kręgu translokacji w przeglądarce, aby stanąć przed lśniącym portalem do Karmazynowej Twierdzy.
Aby sforsować twierdzę, musisz dostroić esencję Mrocznego Ostrza do portalu.
- Na stronie znajdź pole wprowadzania runicznego tekstu oznaczone etykietą A2A Endpoint URL (URL punktu końcowego A2A).
- Wpisz sygil swojego mistrza, wklejając w tym polu adres URL miejsca agenta (pierwszy skopiowany adres URL).
- Kliknij Połącz, aby rozpocząć teleportację.
Oślepiające światło teleportacji gaśnie. Nie jesteś już w sanktuarium. Powietrze jest naelektryzowane, zimne i ostre. Przed Tobą materializuje się Widmo – wir syczącego szumu i uszkodzonego kodu, którego nieświęte światło rzuca długie, tańczące cienie na podłodze lochu. Nie ma twarzy, ale czujesz jego ogromną, wyczerpującą obecność, która jest całkowicie skupiona na Tobie.
Jedyną drogą do zwycięstwa jest jasność Twojego przekonania. To pojedynek woli, który toczy się na polu bitwy umysłu.
Gdy rzucasz się do przodu, gotowy do zadania pierwszego ataku, Spectre kontruje. Nie podnosi tarczy, ale rzuca pytanie prosto w Twoją świadomość – migoczące, runiczne wyzwanie zaczerpnięte z podstaw Twojego szkolenia.
Taka jest natura tej walki. Twoja wiedza jest Twoją bronią.
- Odpowiedz z mądrością, którą zdobyłeś, a Twój miecz zapłonie czystą energią, rozbijając obronę Widma i zadając KRYTYCZNY CIOS.
- Jeśli jednak się wahasz, jeśli Twoją odpowiedź przyćmią wątpliwości, światło broni przygaśnie. Cios zada tylko UŁAMEK OBRAŻEŃ. Co gorsza, Widmo będzie się żywić Twoją niepewnością, a jego niszczycielska moc będzie rosła z każdym błędem.
To już koniec, mistrzu. Twój kod to księga zaklęć, logika to miecz, a wiedza to tarcza, która odwróci falę chaosu.
Skupienie. Uderzaj celnie. Od tego zależy los Agentverse.
Gratulacje, Przywoływaczu.
Okres próbny został zakończony. Opanowałeś sztukę koordynacji wielu agentów, przekształcając odizolowane Familiars i chaotyczną moc w harmonijną Concord. Teraz masz do dyspozycji w pełni skoordynowany system, który może realizować złożone strategie obrony Agentverse.
10. Porządkowanie: demontaż Zgody Przywoływacza
Gratulujemy opanowania Summoner's Concord! Aby mieć pewność, że Agentverse pozostanie w nienaruszonym stanie, a tereny szkoleniowe zostaną oczyszczone, musisz teraz przeprowadzić ostateczne rytuały oczyszczania. Spowoduje to systematyczne usuwanie wszystkich zasobów utworzonych podczas Twojej podróży.
Dezaktywowanie komponentów Agentverse
Teraz będziesz systematycznie demontować wdrożone komponenty systemu wieloagentowego.
Usuwanie wszystkich usług Cloud Run i repozytorium Artifact Registry
Spowoduje to usunięcie z Cloud Run wszystkich wdrożonych agentów Familiar, narzędzia Summoner Orchestrator, serwerów MCP i aplikacji Dungeon.
👉💻 Aby usunąć każdą usługę, uruchom w terminalu te polecenia po kolei:
. ~/agentverse-architect/set_env.sh
gcloud run services delete summoner-agent --region=${REGION} --quiet
gcloud run services delete fire-familiar --region=${REGION} --quiet
gcloud run services delete water-familiar --region=${REGION} --quiet
gcloud run services delete earth-familiar --region=${REGION} --quiet
gcloud run services delete mcp-api-server --region=${REGION} --quiet
gcloud run services delete mcp-general-server --region=${REGION} --quiet
gcloud run services delete toolbox --region=${REGION} --quiet
gcloud run services delete agentverse-dungeon --region=${REGION} --quiet
gcloud run services delete nexus-of-whispers-api --region=${REGION} --quiet
gcloud artifacts repositories delete ${REPO_NAME} --location=${REGION} --quiet
Usuń instancję Cloud SQL
Spowoduje to usunięcie instancji summoner-librarium-db
, w tym jej bazy danych i wszystkich tabel w niej zawartych.
👉💻 W terminalu uruchom:
. ~/agentverse-dataengineer/set_env.sh
gcloud sql instances delete summoner-librarium-db --database-version=POSTGRES_14 --project=${PROJECT_ID} --quiet
Usuwanie obiektu tajnego Secret Manager i zasobnika Google Cloud Storage
👉💻 W terminalu uruchom:
. ~/agentverse-dataengineer/set_env.sh
gcloud secrets delete tools --quiet
gcloud storage rm -r gs://${BUCKET_NAME} --quiet
Usuwanie plików i katalogów lokalnych (Cloud Shell)
Na koniec wyczyść środowisko Cloud Shell z sklonowanych repozytoriów i utworzonych plików. Ten krok jest opcjonalny, ale zdecydowanie zalecany, aby całkowicie wyczyścić katalog roboczy.
👉💻 W terminalu uruchom:
rm -rf ~/agentverse-architect
rm -rf ~/agentverse-dungeon
rm -f ~/project_id.txt
Udało Ci się usunąć wszystkie ślady Twojej przygody z Agentverse Architect. Projekt jest czysty i możesz rozpocząć kolejną przygodę.