Biuro wsparcia z pięcioma agentami na Gemini 3.1 i ADK: triaż, badania, działanie, kontrola jakości oraz system orkiestracji.
Stwórz system wsparcia klienta oparty na wielu agentach przy użyciu Google ADK i Gemini 3.1: przekazy zadaní poprzez wpisywanie tekstu, pętle korekty jakości, Agent Engine lub Cloud Run, sesje oraz koszty.
Załóżmy zamówienie, które poszło nie tak. Klient pisze, że dotarł niewłaściwy produkt, prosi o zwrot pieniędzy i chce również, aby ten właściwy został wysłany tego samego dnia. Za tym jednym zdaniem kryją się trzy zadania: weryfikacja zamówienia, obsługa zwrotu oraz szybka wysyłka zamiennika. Każde z nich wymaga własnych danych, własnej polityki i konkretnych działań. Samotny bot obsługi klienta z jednym długim poleceniem potrafi poradzić sobie z prostym pytaniem, ale ma trudności, gdy połączone są kilka zadań. Wtedy staje się powolny, podatny na błędy i niestabilny.
Rozwiązaniem jest projekt oparty na wielu agentach: kilku specjalistów, z których każdy odpowiada za określony etap procesu, a orkiestrator kieruje przepływem zadań. Poniżej przedstawiono przykład implementacji takiego rozwiązania w Google Cloud przy użyciu modeli Gemini 3.1 oraz narzędzia Google Agent Development Kit (ADK). Opisano w nim, jak określić role agentów z jasno zdefiniowanymi granicami, jak orkiestrator kieruje zadaniami, deleguje obowiązki i łączy wyniki, jak agenci przekazują sobie informacje o stanie, a także, co nie mniej ważne, kiedy pojedynczy agent pozostaje lepszym wyborem.
Co się dzieje, gdy używa się jednego długiego promptu
Wyobraźmy sobie agenta obsługi klienta, który zaczynał od prostych zadań i stopniowo nabywał nowych umiejętności: wyszukiwanie informacji w bazie wiedzy, łagodniejszy ton w rozmowach z niezadowolonymi klientami, możliwość samokontroli. Jego prompt systemowy rozrasta się do ponad 3000 tokenów, a każda dodatkowa informacja zakłóca już istniejącą strukturę. Pojawiają się cztery objawy:
- Przenikanie ograniczeń. Zasady zwrotów zaczynają obowiązywać również w przypadku pytań, które nie mają nic wspólnego ze zwrotami, więc proste zapytanie o produkt jest odpowiadane za pomocą logiki zwrotów.
- Rozproszone uwaga. Uwaga modelu jest skończona. Gdy jest rozdzielana między dziesiątki instrukcji, z których większość nie ma związku z aktualnym zapytaniem, każda z nich otrzymuje mniejszy nacisk.
- Niemal niemożliwa diagnostyka. Gdy odpowiedź jest błędna, nie jest jasne, która z wielu instrukcji jej spowodowała.
- Jedna ścieżka dla wszystkiego. Każde zapytanie przechodzi przez ten sam proces, niezależnie od jego trudności.
Rozdzielenie zadań pozwala każdemu modelowi przeznaczyć cały swój budżet uwagi na realizację konkretnego zadania. Myśli o polityce zwrotów tylko podczas obsługi zwrotów, a o tonie tylko podczas sprawdzania projektu.
ADK został zaprojektowany wokół tej koncepcji. Jego mechanizm AutoFlow zarządza przekazywaniem zadań między specjalistami: gdy orkiestrator ma podagentów, ADK dodaje narzędzie transfer_to_agent() i zapisuje opisy wszystkich dostępnych specjalistów w swoim kontekście. Dzięki temu orkiestrator wie, kto należy do jego zespołu i do czego nadaje się każdy członek.
Kształt systemu
Zamiast jednego promptu, centralny orkiestrator znajduje się nad zespołem wąsko specjalizowanych podagentów. Modele nie muszą być identyczne. Najlepszy analityk trafia tam, gdzie ważna jest ocena (orchestrowanie i sprawdzanie jakości), a najszybszy i najtańszy – tam, gdzie kluczowa jest szybkość (triage):
- Orkiestrator: planuje i deleguje zadania. Gemini 3.1 Pro. Jego narzędziami są specjalistyczni agenci.
- Agent do triage: analizuje emocje i intencje oraz kieruje zadania. Gemini 3.1 Flash-Lite, wspierany przez klasyfikatory NLP.
Gemini 2.5 Flash nadal stanowi dobry wybór dla procesów z jednym agentem. Jednak gdy decyzje o ścieżce działania są oparte na jakości rozumowania, seria Gemini 3.1 (dostępna od wczesnego 2026 roku) lepiej się sprawdza, szczególnie w rolach orkiestratora i agenta kontroli jakości.
Części z Google Cloud wykorzystane w tym rozwiązaniu:
- Modele Gemini 3.1 jako rdzeń rozumowania, dostosowane do używania narzędzi.
- Agent Development Kit jako framework obsługujący przenoszenie zadań za pośrednictwem AutoFlow.
- Vertex AI Agent Engine jako zarządzany środowisko wykonywania do wdrażania i skalowania agentów.
- Firestore jako wspólny stan sesji, w którym agenci czytają i zapisują pamięć rozmowy.
- Vertex AI Vector Search do wyszukiwania w bazie wiedzy.
Ustawianie ADK
ADK dostarcza niezbędne narzędzia, w tym wzorzec przekazywania, dzięki któremu jeden agent może skutecznie przenieść rozmowę do innego. Instalacja zajmuje zaledwie jedną linię kodu:
pip install google-adk google-generativeai google-cloud-firestore pydantic
Pydantic jest wymieniony wyraźnie, ponieważ ADK polega na nim do definiowania schematów danych wejściowych i wyjściowych agentów, a jego wskazanie zapewnia kompatybilność wersji.
Rozkład projektu wymaga wcześniejszego przemyślenia. Systemy wieloagentowe najczęściej zawodzą właśnie w tych miejscach: jeden agent wysyła refund_id jako liczbę całkowitą, podczas gdy inny oczekuje ciągu znaków. Prosty układ z wspólnymi schematami zapobiega tego typu błędom:
support_agents/
├── main.py # Entry point for Cloud Run
├── common/
│ ├── __init__.py
│ └── schemas.py # Shared Pydantic models (the "handshake")
├── agents/
│ ├── __init__.py
│ ├── orchestrator.py
│ ├── triage.py
│ ├── research.py
│ ├── action.py
│ └── qa.py
└── config.py # Environment & project IDs
Szpital stanowi odpowiedni przykład analogii. Orkiestratorem jest pielęgniarz zajmujący się triażem, agentem badawczym jest technik laboratoryjny, a agentem wykonawczym – chirurg. Żaden z nich nie rozmawia z pacjentem jednocześnie. Czytają i aktualizują kartę pacjenta, która w tym przypadku to Firestore, a schemas.py to format karty, co do którego wszyscy się zgadzają.
Agent triażu
Triaz pełni rolę kontroli ruchu lotniczego. Sam w sobie nic nie rozwiązuje, a jedynie upewnia się, że każda prośba trafia do odpowiedniego specjalisty z właściwym priorytetem.
Przekazywanie surowych ciągów znaków między agentami może prowadzić do błędów. Ścisłe schema w Pydantic oznacza, że orkiestrator otrzymuje zweryfikowany obiekt w Pythonie i nigdy nie musi analizować wolnego tekstu. Schema jest najważniejsze:
# common/schemas.py
from pydantic import BaseModel, Field
class TriageResult(BaseModel):
intents: list[str] = Field(description="List of detected customer goals")
urgency: str = Field(pattern="^(low|medium|high|critical)quot;)
sentiment: str = Field(description="Current emotional state of the user")
required_agents: list[str] = Field(
description="List of sub-agents needed (research, action, etc.)"
)
Następnie agent, który je wytwarza:
# agents/triage.py
from google.adk.agents import LlmAgent
from common.schemas import TriageResult
triage_agent = LlmAgent(
name="triage_agent",
model="gemini-3.1-flash-lite", # Fast and cheap for classification
instruction="""You are a triage specialist. Analyze the customer's
message and categorize it accurately.
Urgency rules:
- critical: Active outages or safety threats
- high: Frustrated users or financial issues > $100
- medium: Standard requests needing action
- low: General info/feedback
You must NOT attempt to solve the problem. Only classify it.""",
output_schema=TriageResult, # Force structured JSON output
output_key="triage_data"
)
Cztery kryteria projektowe są istotne w tej definicji:
- Jedno zadanie. Agent nigdy nie odpowiada na pytania ani nie podejmuje działań, tylko klasyfikuje. Dzięki temu prompt jest krótki, a dokładność wysoka.
- Ustrukturyzowany wynik.
output_schemawymusza poprawny JSON zgodny zTriageResult, a ADK automatycznie weryfikuje go za pomocą Pydantic. - Kilka intencji jednocześnie. Ponieważ
intentsto lista ciągów znaków, wiadomość prosząca o aktualizację adresu oraz sprawdzenie najnowszego rachunku działa poprawnie, podczas gdy klasyfikator z jedną etykietą by zawiodł. - Przekaz stanu.
output_key="triage_data"zapisuje wynik w stanie sesji, dzięki czemu orkiestrator odczytuje go zsession.state['triage_data'].
Agent badawczy
Agent badawczy to osoba prowadząca dochodzenie. Pobiera surowe dane z Firestore oraz z procesu pobierania, a następnie przekształca je w uporządkowany raport przeznaczony dla agenta działającego. Schemat tego raportu stanowi umowę pomiędzy tymi dwoma rolami:
# common/schemas.py (add to existing file)
class ResearchBrief(BaseModel):
order_status: str = Field(description="Current order state")
customer_tier: str = Field(description="e.g. Gold, Standard")
applicable_policy: str = Field(description="Relevant policy text")
can_refund: bool = Field(description="Whether a refund is allowed")
reasoning: str = Field(description="Why this conclusion was reached")
Następnie przychodzą narzędzia oraz definicja agenta:
# agents/research.py
from google.adk.agents import LlmAgent
from google.cloud import firestore
from common.schemas import ResearchBrief
db = firestore.Client()
def lookup_order(order_id: str) -> dict:
"""Fetch real-time shipping status and line items for an order ID."""
doc = db.collection('orders').document(order_id).get()
if doc.exists:
return doc.to_dict()
return {"error": f"Order {order_id} not found"}
def lookup_customer(customer_id: str) -> dict:
"""Retrieve customer profile, tier, and interaction history."""
doc = db.collection('customers').document(customer_id).get()
if doc.exists:
return doc.to_dict()
return {"error": f"Customer {customer_id} not found"}
def search_knowledge_base(query: str) -> list:
"""Search product docs and company policies via RAG pipeline."""
# Uses the RAG pipeline from our previous article
from rag_pipeline import pipeline
result = pipeline.query(query, top_k=5)
return result['sources']
research_agent = LlmAgent(
name="research_agent",
model="gemini-3.1-flash",
instruction="""You are a research specialist.
1. Extract identifiers (Order ID, Customer ID) from the triage data.
2. Use tools to gather order history and relevant company policies.
3. If policy info is missing, use search_knowledge_base.
CRITICAL: Do not answer the customer. Output a formal ResearchBrief.""",
tools=[lookup_order, lookup_customer, search_knowledge_base],
output_schema=ResearchBrief,
output_key="research_brief"
)
Kraj podróżuje bez dodatkowego kodu. Gdy agent badawczy się uruchamia, ADK wprowadza do swojego kontekstu triage_data z poprzedniego kroku, dzięki czemu od razu wie, że musi sprawdzić zamówienie nr 12345, ponieważ triage zidentyfikowało taki cel. Każdy agent buduje na pracy poprzedniego i nic nie jest wykonywane dwukrotnie. Mała wskazówka z praktyki: ADK automatycznie otacza zwykłe funkcje obiektami FunctionTool, ale ich wyraźne otoczenie za pomocą from google.adk.tools import FunctionTool zapewnia lepsze śledzenie opóźnień oraz rejestrację użycia tokenów w Vertex AI Agent Engine.
Agent działania
Tylko ten specjalista ma dostęp do zapisu w API biznesowych. Ponieważ wykonywa on operacje o wysokim stopniu ryzyka, stosuje się wobec niego ścisłe schematy oraz wyraźne zasady bezpieczeństwa. Schemat wyników najpierw:
# common/schemas.py (add to existing file)
class ActionSummary(BaseModel):
actions_taken: list[str] = Field(description="List of actions executed")
refund_id: str | None = Field(default=None, description="Refund ID if issued")
escalated: bool = Field(default=False)
escalation_reason: str | None = Field(default=None)
Następnie sam agent, który wymaga potwierdzenia od człowieka przy operacjach o wysokiej wartości:
# agents/action.py
from google.adk.agents import LlmAgent
from google.adk.tools import FunctionTool
from common.schemas import ResearchBrief, ActionSummary
def process_refund(order_id: str, amount: float, reason: str) -> dict:
"""Process a financial refund. Required: valid order_id and amount."""
# In production: call your payment API
return {
"status": "processed",
"refund_id": f"REF-{order_id}",
"amount": amount
}
def create_replacement_order(
order_id: str,
item_id: str,
shipping_speed: str
) -> dict:
"""Create a replacement order with specified shipping speed."""
# In production: call your order management API
return {
"status": "created",
"new_order_id": f"REPL-{order_id}",
"estimated_delivery": "2 business days"
}
def escalate_to_human(reason: str, priority: str) -> dict:
"""Escalate to a human agent with full context."""
return {
"status": "escalated",
"queue": "priority" if priority == "high" else "standard"
}
# Wrap refund tool with human confirmation for high-value transactions
refund_tool = FunctionTool(
func=process_refund,
require_confirmation=True # Pauses for human approval before executing
)
action_agent = LlmAgent(
name="action_agent",
model="gemini-3.1-flash",
instruction="""You are an action specialist.
Review the 'research_brief' in the session state.
CRITICAL RULES:
1. Only refund if 'can_refund' is True in the research brief
2. If amount > $500, you MUST use escalate_to_human
3. You must call tools for every action — do not just tell the user
it happened
4. If information is missing from the brief, escalate""",
tools=[refund_tool, create_replacement_order, escalate_to_human],
input_schema=ResearchBrief, # Only sees research data, not raw chat
output_schema=ActionSummary,
output_key="action_result"
)
Twoje ustawienia zapewniają największy poziom bezpieczeństwa. Funkcja require_confirmation istnieje dlatego, że system produkcyjny rzadko pozwala agentowi na dokonanie zwrotu pieniędzy wyłącznie na podstawie instrukcji zawartych w zapytaniu. Proces potwierdzenia narzędzia ADK wstrzymuje wykonywanie działań, dopóki ktoś go nie zatwierdzi, a system koordynacyjny wykazuje status „czekające”, który można przekierować na panel sterowania pracowników. Ustawienie input_schema jest istotne, ponieważ bez niego agent widzi całą rozmowę, w tym przestarzałe informacje. Ograniczenie wprowadzanych danych do formatu ResearchBrief zapobiega dostawaniu się przestarzałego kontekstu i gwarantuje, że decyzje opierają się na najnowszych danych.
Należy również zauważyć, że escalate_to_human to celowa zasada biznesowa, a nie stan awarii. System koordynacyjny może dokładnie zobaczyć, dlaczego agent przestał działać, i przesłać zgłoszenie osobie z pełnym opisem badania dołączonym do wiadomości.
Agent QA
QA to ostatnia bariera. Oprócz sprawdzania sformułowań, porównuje to, co zrobił agent działający, z tym, co stanowiło treść briefu badawczego, tak aby działanie odpowiadało wiedzy.
Ta funkcja działa na Gemini 3.1 Pro, ponieważ musi mieć w pamięci cały stan rozmowy i wykrywać subtelne sprzeczności – zadania, w których wersja Pro konsekwentnie przewyższa Flasha. ADK umożliwia jej również użycie trybu myślenia w celu głębszej autorefleksji przed zatwierdzeniem odpowiedzi. Schemat przeglądu:
# common/schemas.py (add to existing file)
class QAReview(BaseModel):
is_approved: bool = Field(description="True if the response meets all criteria")
feedback: str = Field(description="Specific corrections if not approved")
final_text: str = Field(description="The customer-facing message")
A konfiguracja agenta:
# agents/qa.py
from google.adk.agents import LlmAgent
from google.adk.planners import BuiltInPlanner
from google.genai.types import ThinkingConfig
from common.schemas import QAReview
qa_agent = LlmAgent(
name="qa_agent",
model="gemini-3.1-pro",
instruction="""You are a senior QA auditor. Compare the 'action_result'
against the 'research_brief' in the session state.
CRITICAL CHECKS:
1. Did the Action Agent refund the EXACT amount listed in the brief?
2. Does the response cite the policy found during research?
3. Is the tone empathetic but professional?
4. Are ALL intents from the triage classification addressed?
5. No unauthorized promises, discounts, or policy exceptions
If any check fails, set is_approved to False with specific feedback.""",
output_schema=QAReview,
output_key="qa_review",
# MEDIUM for routine QA; switch to HIGH for edge cases or audits
planner=BuiltInPlanner(
thinking_config=ThinkingConfig(thinking_level="MEDIUM")
)
)
Odrzucenie nie kończy procesu. Gdy qa_review.is_approved ma wartość fałszywą, orkiestrator odczytuje pole feedback i przekazuje dane z konkretnymi korektami z powrotem do agenta działającego lub badawczego. To właśnie ten cykl korekt odróżnia agenta produkcyjnego od skryptu demonstracyjnego. Proces jest ograniczony do dwóch cykli korekt, po których sprawa trafia do osoby.
Orkiestrator
Orkiestrator ani nie prowadzi badań, ani nie podejmuje działań. Zarządza stanem i zapewnia, że specjaliści działają w rozsądnej kolejności. Na podstawie sub_agents AutoFlow ADK dodaje narzędzie transfer_to_agent(), a LLM orkiestratora wybiera następnego specjalistę na podstawie swoich instrukcji oraz aktualnego stanu sesji:
# agents/orchestrator.py
from google.adk.agents import LlmAgent
from agents.triage import triage_agent
from agents.research import research_agent
from agents.action import action_agent
from agents.qa import qa_agent
orchestrator = LlmAgent(
name="support_orchestrator",
model="gemini-3.1-pro", # Best reasoning for delegation decisions
instruction="""You are the lead coordinator of a customer support team.
Use the following specialists in order:
1. triage_agent: to classify the intent and urgency
2. research_agent: to gather order data and relevant policies
3. action_agent: to execute the required operations
4. qa_agent: to verify the final response
Special cases:
- If triage classifies as 'critical': bypass the chain and escalate
- If QA returns is_approved=False: re-route to the responsible agent
with the feedback (maximum 2 revision cycles, then escalate)
- If any agent fails: escalate to human with full context
You must never respond to the customer directly.
Always route through the specialist pipeline.""",
sub_agents=[triage_agent, research_agent, action_agent, qa_agent]
)
Rozpoczęcie działania
ADK uruchamia agenty za pośrednictwem Runnera, który wstrzymuje wykonywanie, gdy agent używa jakiegoś narzędzia, a następnie ponownie uruchamia agenta po otrzymaniu wyniku:
# main.py
from google.adk.runners import Runner
from google.adk.sessions import InMemorySessionService
from agents.orchestrator import orchestrator
APP_NAME = "customer_support"
USER_ID = "system"
# For production, replace with a Firestore-backed session service
session_service = InMemorySessionService()
runner = Runner(
agent=orchestrator,
app_name=APP_NAME,
session_service=session_service
)
async def handle_customer_message(customer_id: str, message: str):
"""
Entry point for customer messages.
"""
session_id = f"support-{customer_id}"
# Ensure session exists
session = await session_service.get_session(
app_name=APP_NAME, user_id=USER_ID, session_id=session_id
)
if not session:
session = await session_service.create_session(
app_name=APP_NAME, user_id=USER_ID, session_id=session_id
)
# run_async yields events as agents execute
final_response = None
async for event in runner.run_async(
user_id=USER_ID,
session_id=session_id,
new_message=message
):
if event.is_final_response():
final_response = event
return {
"response": final_response.content.parts[0].text if final_response else None,
"session_id": session_id
}
Dlaczego nie zadzwonić bezpośrednio do agentów? Runner kontroluje cały proces. Przechowuje sesje, śledzi aktywnego agenta, przetwarza wywołania narzędzi i rejestruje każdy krok. Ponieważ każdy agent zapisuje swoje wyniki pod kluczem output_key, Runner gwarantuje, że informacje potrzebne agentowi wykonawczemu będą dostępne w odpowiednim momencie, bez konieczności ręcznego pisania dodatkowych elementów. Możliwość śledzenia działań jest również wbudowana: każde wywołanie agenta, użycie narzędzia oraz przekazanie danych są rejestrowane jako wydarzenia, co rozwiązuje problemy z debugowaniem wspomniane wcześniej. Gdy coś pójdzie nie tak, ślady pokazują, który agent podjął jaką decyzję i dlaczego.
Drogi wdrożenia
Istnieją dwa sposoby jego wdrożenia. Vertex AI Agent Engine oferuje zarządzany środowisko działania, w którym prawie nic nie trzeba konfigurować, natomiast Cloud Run zapewnia pełną kontrolę nad kontenerem.
Agent Engine
To opcja wymagająca niewielkiej konserwacji, zalecana dla większości rozwiązań opartych na ADK. Należy ustawić dwie zmienne:
PROJECT_ID=your-project-id
LOCATION_ID=us-central1
Następnie zainstaluj za pomocą jednego polecenia:
adk deploy agent_engine \
--project=$PROJECT_ID \
--region=$LOCATION_ID \
--display_name="Customer Support Team" \
support_agents
Agent Engine zajmuje się skalowaniem, przechowywaniem sesji oraz rejestracją śladów działań z uwzględnieniem agentów. Nie ma żadnego pliku Dockerfile, kodu sesji ani infrastruktury, którą trzeba byłoby obsługiwać.
Cloud Run
Wybierz tę opcję, gdy potrzebne są własne biblioteki systemowe, określone rozwiązania sieciowe, takie jak VPC Service Controls, lub komponenty inne niż ADK. Przykład używa Quart zamiast Flask. Składnia jest niemal identyczna, ale Quart obsługuje async/await w sposób natywny, co pozwala uniknąć antypaternu asyncio.run(), polegającego na uruchamianiu nowego pętla zdarzeń dla każdej prośby:
# server.py
from quart import Quart, request, jsonify
from main import handle_customer_message
app = Quart(__name__)
@app.route("/support", methods=["POST"])
async def support():
data = await request.get_json()
# No asyncio.run needed — Quart handles the event loop
result = await handle_customer_message(
data["customer_id"],
data["message"]
)
return jsonify(result)
@app.route("/health", methods=["GET"])
async def health():
return jsonify({"status": "healthy"})
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8080)
Definicja kontenera:
# Dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8080
CMD ["python", "server.py"]
A polecenie deploy:
gcloud run deploy support-agents \
--source . \
--region us-central1 \
--memory 4Gi \
--cpu 2 \
--allow-unauthenticated
Krótko mówiąc, Cloud Run wymaga umiarkowanego wysiłku w zakresie konfiguracji (Dockerfile i API), wymaga ręcznego zarządzania stanem za pomocą Firestore lub Redis, loguje dane do standardowego Cloud Logging i nadaje się do używania z niestandardowymi środowiskami wykonawczymi oraz frameworkami. Agent Engine wymaga tylko jednego polecenia, ma wbudowane sesje, generuje ślady specyficzne dla agenta i nadaje się do agentów typu ADK, które muszą szybko skalować.
Zachowywanie ciągłości rozmów
Przykład orkiestratora wykorzystywał InMemorySessionService, który nadaje się do testowania, ale traci wszystko po ponownym uruchomieniu procesu. W środowisku produkcyjnym potrzebna jest usługa trwała. ADK oferuje dwie takie usługi.
Z Agent Engine sesje są obsługiwane automatycznie za pośrednictwem usługi sesji Vertex AI:
# config.py
from google.adk.sessions import VertexAiSessionService
session_service = VertexAiSessionService(
project="your-project-id",
location="us-central1",
agent_engine_id="your-agent-engine-id" # From adk deploy output
)
Agent Engine również podsumowuje długie historie i sam oczyszcza zaległości, więc nie jest potrzebny żaden kod Firestore.
Dla Cloud Run DatabaseSessionService działa z backendem PostgreSQL lub SQLite:
# config.py
from google.adk.sessions import DatabaseSessionService
# PostgreSQL for production
session_service = DatabaseSessionService(
db_url="postgresql+asyncpg://user:pass@host:5432/agents"
)
# Or SQLite for development
session_service = DatabaseSessionService(
db_url="sqlite+aiosqlite:///sessions.db"
)
Tworzy swoje tabele przy pierwszym uruchomieniu. Umieść je w Runnerze, a stan sesji przetrwa restarty.
Jak stan przechodzi między agentami
Nie są potrzebne ręczne wywołania get() i set(). output_key każdego agenta automatycznie zapisuje dane do stanu sesji, a późniejsze agenty odczytują je stamtąd:
triage_agent (output_key="triage_data")
↓ writes to session.state["triage_data"]
research_agent (reads triage_data, output_key="research_brief")
↓ writes to session.state["research_brief"]
action_agent (input_schema=ResearchBrief, output_key="action_result")
↓ writes to session.state["action_result"]
qa_agent (reads action_result + research_brief, output_key="qa_review")
Runner przechowuje cały ten stan w dowolnym skonfigurowanym backendzie – czy to Firestore, PostgreSQL, czy Agent Engine.
Trzy nawyki pomagają utrzymać pamięć w dobrym stanie:
- Streszczaj. Przechowuj skondensowane wyniki zamiast surowych odpowiedzi API, aby okno kontekstowe nie wypełniało się zbędnymi danymi.
- Wygaszaj sesje. Sesje powinny mieć czas trwania od 24 do 48 godzin, co sprawia, że baza danych pozostaje mała i bezpieczniejsza.
- Ochroniaj dane osobowe. Surowe dane osobowe, takie jak numery identyfikacyjne lub hasła, nie powinny znajdować się w wspólnym stanie; należy je zasłaniać przed zapisaniem do sesji.
Kiedy jeden agent nadal jest lepszym rozwiązaniem
Rozwiązanie oparte na wielu agentach nie jest automatycznie lepsze. Praktyczny sposób na podjęcie decyzji:
- Proste FAQ lub sprawdzenie stanu: jeden agent. Najniższa latencja i koszt, nie wymaga skomplikowanych rozumowań.
- wzbogacanie danych za pomocą trzech do pięciu zapytań: jeden agent. Jedno wezwanie LLM wystarcza do podstawowego używania narzędzi.
- Pracy w środowiskach regulowanych: wielu agentów. Izolacja oddziela logikę działań od danych wprowadzanych przez użytkownika, co ogranicza możliwość wstrzykiwania złośliwego kodu.
- niejednoznaczne kierowanie zapytaniami: wielu agentów. Specjalny agent do triażu, który specjalizuje się w mapowaniu intencji użytkownika, zmniejsza problemy związane z ograniczeniami.
- działania o dużym znaczeniu wartościowym powyżej 500 dolarów: wielu agentów. Umożliwia podwójną weryfikację przez agenta QA przed wykonaniem jakiejkolwiek operacji API.
- wymagania audytowe: wielu agentów. Dane wejściowe i wyjściowe każdego agenta są rejestrowane oddzielnie.
Zasada ogólna: gdy prompt dla pojedynczego agenta osiąga 3000 tokenów – to moment, w którym pojawiają się problemy z ograniczeniami i rozcieńczenie uwagi – albo gdy różne etapy procesu wymagają różnych narzędzi, nadszedł czas na podział.
Częste pułapki
- Agent, który robi wszystko. Wydajność spada, gdy jeden agent posiada dziesięć lub więcej narzędzi, ponieważ modele zaczynają poświęcać czas na wybór narzędzia zamiast na zrozumienie żądania. Podziel agenta według funkcji: agent potrzebujący narzędzi do zwrotów pieniędzy, wysyłki i obsługi prawnej staje się trzema specjalistami.
- Niekontrolowany kontekst. Jeśli każdy agent widzi całą rozmowę składającą się z dziesięciu kroków, koszty tokenów gwałtownie rosną. Skompresuj stan, aby proces triażu przekazywał tylko zidentyfikowaną intencję, a nie całą rozmowę.
input_schema i output_schema bez nakładających się obowiązków.ParallelAgent w ADK umożliwia równoległe wykonywanie zadań, a jednoczesne przeprowadzanie badań i kontrol compliance może skrócić łączne opóźnienie o 30 do 40%.Czego można się po nim spodziewać
Systemy wieloagentowe oferują większą niezawodność przy złożonych zadaniach, ale kosztem wyższych opóźnień. Opublikowane testy i doświadczenia branżowe wskazują na następujące zalety:
- Dokładność przy złożonych zadaniach. Podział problemów wieloetapowych na skoncentrowane podzadania zazwyczaj daje lepsze wyniki niż użycie monolitycznych instrukcji, a dokumentacja ADK wskazuje na wyższe wskaźniki ukończenia zadań, gdy agenci mają wąskie zakresy obowiązków.
- Zawarte awarie. Gdy jeden komponent przestaje działać, szkody pozostają w obrębie danego agenta i nie psują całej odpowiedzi.
- Możliwość audytu. Odrębne logi dla każdego agenta ułatwiają debugowanie oraz sprawdzanie zgodności z wytycznymi.
Koszty są równie rzeczywiste:
- Latencja. Pełny proces z udziałem pięciu agentów trwa około 3 do 8 sekund, podczas gdy jeden agent potrzebuje od 1 do 2 sekund. Głównym wąskim gardłem są sekwencyjne wywołania.
thinking_level="HIGH") może dodać około 20 tysięcy tokenów, które są naliczane według stawki 12 dolarów za milion tokenów wyjściowych. Jedna szczegółowa weryfikacja jakości kosztuje zatem około 0,24 dolara tylko za przetwarzanie myśli. Używaj ustawienia HIGH wybiórczo, ponieważ większość weryfikacji jakości sprawdza się przy ustawieniu MEDIUM.Dla przybliżonego miesięcznego rachunku za 100 000 złożonych zapytań:
- Orchestrator routing w Gemini 3.1 Pro: około 80 dolarów
- Triage w Flash-Lite: około 20 dolarów
- Badania nad Flash: około 40 dolarów
- Działania z użyciem Flash: około 40 dolarów
- QA z modelem MEDIUM w wersji Pro: około 100 dolarów
- Cloud Run z 2 vCPU i 2 GiB pamięci: około 120 dolarów
- Seanse PostgreSQL: około 30 dolarów
- Vector Search, używany w konfiguracji z jednym agentem: około 100 dolarów
- Łącznie: około 530 dolarów miesięcznie
Prawdziwym czynnikiem wpływającym na koszty jest mieszanie modeli. Tylko około 30% zapytań (orchestrator i QA) obciąża cennik wersji Pro, natomiast pozostałe są przetwarzane za pomocą Flash lub Flash-Lite po cenie od jednej ósmej do jednej pięćdziesiątej ceny za token. Koszt jednostkowy za złożoną interakcję wynosi mniej więcej pół centa. Te dane pochodzą z opublikowanych cen Google Cloud, a rzeczywiste rachunki zmieniają się w zależności od złożoności zapytań, poziomu rozumowania agenta oraz głębokości jego działań.
Kolejność wdrażania
Rozsądna sekwencja polega na rozpoczęciu od jednego agenta, dostosowaniu jego logiki, wzbogaceniu jej za pomocą funkcji wyszukiwania informacji, a dopiero wtedy, gdy komenda systemowa stanie się zbyt długa lub zadania zbyt zróżnicowane, by jeden model mógł je skutecznie obsłużyć, na podziale go na specjalistów. Każda warstwa opiera się na tej poniżej.
Moment mikrosług dla agentów
Projektowanie z udziałem wielu agentów nie sprawia, że sztuczna inteligencja staje się bardziej skomplikowana. Sprawia natomiast, że złożone procesy pracy stają się przewidywalne, podobnie jak mikrosługi zastąpiły monolity: jedna komenda przekształca się w zespół rozproszonych elementów, z których każdy wykonuje jedną funkcję. Prośba o to, by jeden agent jednocześnie sortował informacje, prowadził badania, działał i sprawdzał wyniki, jest jak prośba o to, by jedna osoba pełniła rolę recepcjonisty, głównego analityka, technika i audytora naraz. To działa w firmie z jedną osobą, ale zawodzi w dużym przedsiębiorstwie.
Daj każdemu agentowi konkretne zadanie, specjalistyczne narzędzia oraz wspólną warstwę pamięci – w rezultacie uzyskamy dokładne wyniki, ponieważ precyzyjne instrukcje zmniejszają błędy przy wykonywaniu niepowiązanych zadań; możliwość debugowania, gdyż problematyczny specjalista jest widoczny; oraz niskie koszty, gdyż działanie pięciu agentów na Gemini 3.1 kosztuje około pół centa za złożoną interakcję, co stanowi znacznie mniej niż minutę czasu poświęconego przez ludzkiego agenta.
Konstrukcja ta ma również potencjał rozwoju. Dzięki protokolowi Agent-to-Agent (A2A), otwartemu standardowi zarządzanemu przez Linux Foundation, taki system mógłby w przyszłości negocjować z agentami uruchamianymi przez dostawców lub partnerów – na przykład agent obsługi klienta mógłby bezpośrednio rozmawiać z agentem firmy kurierskiej w celu rozwiązania problemu zagubionej przesyłki, bez udziału człowieka.
Na razie rada jest prosta: najpierw stwórz jeden agent, a następnie go rozdziel, gdy instrukcje staną się zbyt długie lub zadania zbyt różnorodne.
Powiązane materiały
- Paralelne agenty LangGraph, które recenzują pull requests za pomocą webhooków FastAPI — Jak webhook, kolejka Redis i cztery agenty LangGraph przekształcają pull request w uszeregowaną, strukturyzowaną recenzję AI w ciągu około 30 sekund, przy użyciu ngrok do testów lokalnych.
- Claude Agent SDK kontra OpenAI Agents SDK kontra Google ADK: jeden agent, trzy wersje — Ten sam agent do tworzenia etykiet żywieniowych zbudowany przy użyciu Claude Agent SDK, OpenAI Agents SDK i Google ADK, z wyraźnym przedstawieniem tego, co każdy zestaw obsługuje, a co nadal musisz zbudować sam.