Галоўная / Артыкулы

Падтрымкава служба з пяцьма агентамі на базе Gemini 3.1 і ADK: сортаванне задач, дакледжэння, выконанне дзеянь, пераконтроль якасці і кераванне працэсамі.

Створыце сістэму падтрымкі кліянта з калькуляцыяй колькох агентаў за дапамою Google ADK і Gemini 3.1: перэдача задач у пісьмовы фармат, ціклы корэкцыі якасці, Agent Engine або Cloud Run, сесіі і вітраты.

Выдавец: REACTAPP.TOP19 хв чытання4349 слоў

Крыніцы: Building a Multi-Agent AI System with Gemini 3 and Google Cloud: From Single Agent to Orchestrated Intelligence

Уявіце замовлення, якое пайшло не так. Кліент пасля отрымання товару напісвае, што прыбыў не той артыкул, прасіць про вярненне грошаў і таксама хочаць, каб правільны артыкул быў адправлены там жа дзень. За гэтым адным рэчэннем крыюцца тры заведамення: пераканацься ў правільнасці замовлення, апрацуе вярненне і якнайшыльней адправіць замену. Кожна з іх выклікае патрэбныя даны, сваю політыку і власныя дзеяння. Адзін бот для падтрымкі з адным вялікім запітам можа распрацаваць простыя запытанні, але часта сталкаецца з труднасцямі, калі разам выконваюцца калькі заведамення. У такім разе ў яго працэсе з’яўляюцца сповольнення, нестабільнасць і вялікая колькасць памылак.

Рашэннем являецца дызайн на адзэльных агентах: калькі спецыялістаў, кожны з яых адпавядае за адзін элемент працы, а оркестратор керуе прабачаннем заданняў. Далей паказана, як стварыць такую сістэму на Google Cloud з выкарыстоўваннем модэляў Gemini 3.1 і кіту для разработкі агентаў Google (ADK). У гэтым матэрыяле расказваецца пра тое, як візначыць ролі агентаў з чысткімі межамі, як оркестратор керуе прабачаннем, давае заведаменні і асамблюе рэзультаты, як агенты перадаюць адзін другаму інфармацыю, і, што не менш важна, калі адзін агент застаецца лепшым выборам.

Што выходзіць з-пад контролю з аднім вялікім запітам

Уявіце сабе агента падтрымкі, які пачаў з малага і постаўляў адну за адной новыя можлівасці: пошук інфармацыі ў базе знанняў, болей добры тон паўстання з незадоволенымі кліентамі, можлівасць самапераканання. Яго сістэмны запіт вырастае да 3 000 токенаў, і кожны новы элемент паўтарае абараняецца з чымось, ўжо ўсёткі ў сістэме. Праявляюцца чатыры сімптамы:

  • Занадта шырокія абмежэннія. Правіла варыць пачынаюць дапраўляцца да запытанняў, якія не маюць нічынага з вароцем, таму просты запыт пра продукт адпавядаецца за дапамою логікі варыць.
  • Слабэе ўвага. Увага мадэлі ёсць скончанай. Калі яна распадаецца между дзесяткамі інструкцый, большасць з яых неякіснае да данаго запытання, кожная з іх атрымле меншую вагу.
  • Немагчымая дыяганастыка. Калі адпаведзь бяроза, незрозумела, якая з многіх інструкцый стала прычыной гэтага.
  • Одна схема для усяго. Кожны запыт праходзіць праз той самы працэс, незалежна ад яго складносці.

Раздзелэнне працы дазволяе кожной модэлі выкорыстоўваць усю сваю квоту на увагу для выканання задачы, якая ёй дадзена. Яна думае пра правіла варыць толькі пад час апрацоўкі запытанняў пра варуць, а пра тон — толькі пад час перагляду чэрнавіка.

ADK створаны на адміністрацыю гэтай ідэяй. Яго механізм AutoFlow керуе перадачай задач між спецыялістамі: калі у оркестрабірача ёсць падагенты, ADK додае інструмент transfer_to_agent() і запісвае апісанні кожнага доступнага спецыяліста ў свой кантэкст. Такім чынам оркестрабірач ведае, хто ў яго командзе і чаму кожны з учаснікаў падходзіць для певных задач.

Форма сістэмы

Уместо аднаго запіту центральны оркестрабірач керуе наборам вузькаясправных падагентаў. Мадэлі не павінны быць ідэентычныя. Найсільнейшы аналізатор выконвае задачы, дэткі важная ўхвалка рашэнняў (оркестрацыя і перагляд якосці), а найшвэйшы і найдэшавейшы — тыя, дэткі важная швальце (трыаж):

  • Оркестрабірач: плануе і давае заведаменні. Gemini 3.1 Pro. Яго інструменты — спецыялістскія агенты.
  • Агент для трыажу: чытае настроены і намеры і направляе задачы. Gemini 3.1 Flash-Lite, падтрымваны класіфікаторамі NLP.
  • Агент даследжэння: збірае факты і кантэкст. Gemini 3.1 Flash, з алгорытмам даследжэння Vertex і API CRM.
  • Агент дзеяння: адконанае транзакцыі, такія як вярненне грошаў і абнаўленні. Gemini 3.1 Flash, з API для кантролю замовэнняў і платэжаў.
  • Агент кантролю якосці: пераканальвае факты і супашчывасць з правіламі. Gemini 3.1 Pro, з базай знанняў пра правілы.
  • Gemini 2.5 Flash застаецца хорашым інструментам для працы з адным агентам. Аднак калі для прыняцьбы рашэнняў аб маршрутацыі важліва якосць разумовых выводаў, лінейка Gemini 3.1 (доступная з пачатку 2026 года) падходзіць лепшая, ў тым часе як для ролей оркестрацыі і кантролю якосці.

    Інструменты Google Cloud, якія былі выкарыстаны:

    • Мадэлі Gemini 3.1 як ядро для разумовых выводаў, налаштаваныя для вікорыстоўвання з інструментамі.
    • Agent Development Kit як фрэймворк, які керуе перадачай заданняў праз AutoFlow.
    • Vertex AI Agent Engine як кераваны рэнтайм для развяроцелі і масштабавання агентаў.
    • Firestore як спяльны стан сэсіі, дзе агенты чытаюць і запішваюць памяць размовы.
    • Vertex AI Vector Search для пошуку ў базе знанняў.

    Настройка ADK

    ADK забезпечвае неабходную структуру, укладаючы ў сябе шаблон перадачы, праз які агент можа эфектываўна перадаць вызов іншаму агенту. Інсталляцыя выконваецца за адну лінію:

    pip install google-adk google-generativeai google-cloud-firestore pydantic
    

    Pydantic указана якраз там, колькі хто ADK выкарыстоўвае яе для схем вводу і выходу дадзенняў агентаў, а ўказванне яе назвы дапамагае падтрымваць сумяжнасць версій.

    Структура праекта трэба продумаць з самага пачатку. Сістэмы з кальком агентаў часта выключваюцца самэль у местах з’ўязку: адны агенты надаюць refund_id у вачынку, тады калі іншыя чакаюць строку. Плоская структура з спадзяльнымі схемамі запобегае такім багам:

    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
    

    Больніца — граматычны аналаг. Архітэктар процэса — медбрат, які выконвае трыаж, агент дакларацій — лабораторны тэхнік, а агент дзеяння — хірург. Ніхто з іх не размаўляе з паціентам адразу. Яны чытаюць і актуалізуюць картку паціента, якая тут выступае як Firestore, а schemas.py — гэта фармат карткі, пра які всі дагадваюцца.

    Агент трыажу

    Трыаж выступае як контроль небявыходу. Ён сам не рашае нічога, а толькі стараецца, каб кожны запіт потрапіў да правільнага спецыяліста з належным прыорытэтом.

    Перадача необработаных стрынгоў між агентамі можа спрычыніць проблемы. Строгая схема Pydantic значыць, што архітэктар процэса отрымае пераверыты об’ект на Python і ніколі не патрабуе парсаваць вольны тэкст. Схема ў першую чаргу:

    # 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.)"
        )
    

    Потым агент, які ўтварае яго:

    # 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"
    )
    

    У гэтым апісаванні важлівы чатыры выбора дызайну:

    • Адна задача. Агент ніколі не адпавядае на запытанні і не выконвае дзеяння, толькі класыфікуе. Гэта дапамагае заліць запыт короткім і падняць точнасць.
    • Структураваны выхід. output_schema прымушвае выдаць правільны JSON, які падходзіць TriageResult, а ADK автаматычна пераканае яго за дапомогою Pydantic.
    • Калькі намероў адразу. Пакалі intents — гэта спіс строк, то паведамленне, якое прасіць апдэйтаваць адрэс і таксама пераканаць найновейшы рахунок, працюе, тады калі класыфікатор з аднам маркерам не справіцца.
    • Перадача стану. output_key="triage_data" зберагае рэзультат у стане сесіі, таму оркестратор чытае яго з session.state['triage_data'].

    Дзяржавны агент

    Агент даследжэння — гэта следавальнік. Ён запоўнюе первычныя даны з Firestore і канвэю адзыскві, пасля чаго структуруе іх у адформаваны кароткі звярнення для агента дзеяння. Схема гэтага звярнення ёсць угода між гэтымі двума ролямі:

    # 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")
    

    Далей йду яго інструменты і адзынак агента:

    # 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"
    )
    

    Стэйт практыкуецца без дадзейнага коду. Калі запускаецца агент для даследавання, ADK вводзіць triage_data з пярэднего крока ў свой кантэкст, таму я он вялікі час знае, што павінен шукаты запыт №12345, адколі функцыя трыажу выявіла такую мету. Кожны агент будуе на рэзультатах пярэднега, і нічога не выконваецца два разы. Адна маленькая практычная падказка: ADK аўтаматычна пераключае простыя функцыі ў об’екты FunctionTool, але якшае выкарыстоўванне from google.adk.tools import FunctionTool дапамагае лепшая сочыць за затрымкамі і логаваць вікорыстоўванне токенам у Vertex AI Agent Engine.

    Агент дзеяння

    Толькі гэты спецыяліст мае права на зберагчэнне дадзеных у бізнес-API. Адколі ён выконвае крытычна важлівыя операцыі, яму надаюцца строгія схемы і чысткія правіла. Спачатку — схема выходных дадзеных:

    # 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)
    

    Потым сам агент, які выкарыстоўваецца для запіту на палявенне чалавека ў разы працы з операцыямі высокай вартасі:

    # 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"
    )
    

    Два настройкі правяць большайшай часткай безпекі. require_confirmation існуе таму, што прыметны сістэмы рэдка калі дазваляюць агенту выдаць вярненне толькі на адказ на запіт. Працэс парадактавання інструментам ADK зупіняе выконанне пакуль чалавек не схваліць яго, а оркестрайтар бачыць статус „в очакванні“, які можа перадаць на панель керування спецавістам. input_schema мае значэнне, таму што без яго агент бачыць усю розмову, включаючы застарэлыя пункты. Обмежэнне вводу толькі ResearchBrief запобегае прасачэнню застарэлага кантэксту і дапамагае прымкнуць рашэнні да найсвежэйшых дадзенняў.

    Таксама зважайце, што escalate_to_human — цэлая бізнес-правіл, а не стан абякання. Оркестрайтар можа точна бачыць, чаму агент зупініўся, і перадаць запіт чалавеку з усім дакументам ResearchBrief.

    Агент QA

    QA — гэта апошнія стадыя. Перакантрачыўшы тэкст, ён парабягае дзеяння агента з тым, што было запісана ў інструкцыях даследжэння, каб практычныя дзеяння супадалі з ведамасцю.

    Гэтая функцыя працуе на Gemini 3.1 Pro, адколькі яй трэба памяцаць усю становішча размовы і выявляць тонкія суперасункі, у задачах, дзе версія Pro стабільна перамагае Flash. ADK таксама дазволяе ёй выкорыстоўваць рэжым раздумаў для глэбокага самапрааналізу пры затверджэнні адпаведзі. Схема перагляду:

    # 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")
    

    А таксама настройкі агента:

    # 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")
        )
    )
    

    Адзыявленне не завершае працэс. Калі qa_review.is_approved мае значэнне false, оркестрайтар чытае поле feedback і перадае задачу з конкрэтнымі паследніцамі назад агенту, які выкарыстоўваецца для дзейства або даследжэння. Саме гэты цыкл паследніц ўжо розлічвае агента для практычнага выкарыстоўвання ад дэмавога скрыпта. Ён обмежаны двумя цыкламі праверкі, пасля чаго задача пераходзіць да чалавека.

    Оркестрайтар

    Оркестрайтар ні даследжвае, ні выкарыстоўваецца для дзейства. Ён керуе станам і стараецца, каб спецыялісты працавалі у логічнай парады. На адной з версый ADK's AutoFlow, калі ёсць sub_agents, дадаўся інструмент transfer_to_agent(), а LLM оркестрайтара выбірае наступнага спецыяліста на адной з падказак і на адваротнае застосоўваючы стан тэкушчай сесіі:

    # 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]
    )
    

    Яго запуск

    ADK выкананяе агентаў праз Runner, які павяршвае выкананне калі агент запускае інструмент, а потым зноў пачынае выкананне агента, калі рэзультат вяртаецца:

    # 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
        }
    

    Чаму бы не звоніць агентам безпосерэдня? Runner контролюе ўсю працэзную цягласць. Ён зберагае сесіі, сочыць за актываўным агентам, обрабоцвае запыты да інструментаў і фіксуе кожны крок. Паколькі кожны агент запісвае свой выхад пад output_key, Runner гарантуе, што інформацыя для доследжэння будзе ў належным стане, калі яй патрабуе агент дзейства, без неабяжнай ручной наладкі. Возможнасць трэасабельнасці таксама ёсць без дапамогі дадатковых зусілляў: кожны запыт агента, выкарыстоўванне інструмента і перадача заданняя фіксуюцца як адпаведныы запіс, што дапамагае рашыць проблемы з дэбагаваннем, якія выйшлі раней. Калі ўтвараецца проблема, этыя запісы паказваюць, калькі агент прыняў якое рашэнне і чаму.

    Шляхі развёртвання

    Існуе два спосабы ўпроваджэння. Vertex AI Agent Engine праслугвае кераваным сервісам, які практычна не выкарыстоўваецца ў керуванні, тады як Cloud Run дае паўны контроль над кантэйнерам.

    Agent Engine

    Гэта спосаб з мінімальным адтрыманням, рэкамендаваны для большасці настаўленняў, створаных на базе ADK. Неабяжна задаць два зменнікі:

    PROJECT_ID=your-project-id
    LOCATION_ID=us-central1
    

    Потым запускайце за адзінам камандам:

    adk deploy agent_engine \
      --project=$PROJECT_ID \
      --region=$LOCATION_ID \
      --display_name="Customer Support Team" \
      support_agents
    

    Agent Engine адмініструе масштабаванне, зберэжэння сесій і логаванне падзейкаў з урахоўваннем стану агента. Не трэба Dockerfile, коду сесій і інфраструктуры для адпаведнага керування.

    Cloud Run

    Выберыце гэты варыянт, калі патрэбны спецыяльныя бібліятэкі сістэмы, певныя сеткавыя функцыі, такія як VPC Service Controls, або компоненты, не належачыя да ADK. У прыкладзе вікорыстоўваецца Quart заместо Flask. Сінтаксіс практычна ідэнтычны, але Quart натыўна падтрымляе async/await, чыгуча адхоўваючыся ад паслабленага падходу asyncio.run(), калі для кожнага запіту ствараецца новы цыкл падзейкаў:

    # 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)
    

    Апісаведчэнне кантэйнера:

    # 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"]
    

    І команды для розплівання:

    gcloud run deploy support-agents \
      --source . \
      --region us-central1 \
      --memory 4Gi \
      --cpu 2 \
      --allow-unauthenticated
    

    Короткая версія: Cloud Run вімагае сярэдняго рывня зусіль для наластановкі (Dockerfile і API), потрэбуе ручного керування станом за допомогою Firestore або Redis, логуе даныя до стандартного Cloud Logging і підходыць для кастомніх часовіх механізмів. Agent Engine вікорыстовуе одын командній параметр, мае вбудовані сесіі, створуе даныя для агентаў і підходыць для швідкоі масшалування.

    Зберэжэння довгостроковіх розмов

    Прыклад організатора вікорыстовуе InMemorySessionService, што підходыць для тэстування, але все втрачаецца пасля перэзавантажэння працэсу. У продуктывній серэдовіці потрыбен стабільній сервіс. ADK пропонуе два варыанты.

    # 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 таксама ствараяе аптаты з дужа дзялегіх історыяў і сама чыстае за сабой, таму не патрабуецца коду Firestore.

    Для Cloud Run DatabaseSessionService працуе з адміністрацыяй на базе PostgreSQL або 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"
    )
    

    У першы час запуску ён стварае своія таблы. Калі яго пераключыць у рэжым Runner, стан сесіі застаецца пасля перзапуску.

    Як стан пераходзіць межы агентам

    Не трэба ручных вызоваў get() і set(). output_key кожнага агента автаматычна запісвае даныя у стан сесіі, а пазней іншыя агенты чытаюць іх з таму:

    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 сохраняе ўсё гэта стан у тым бэкендзе, які настроўаны, будзь то Firestore, PostgreSQL чы Agent Engine.

    Тры прыкметы дапамагаюць падтрымаць здаровую памяць:

    • Падсумавайце. Храніце сконцентраваныя рэзультаты заместо неасоблівых адпаведзей API, інакш паветрак кантэкста заполніцца зайвымі данымі.
    • Заканчвайце тэрмін сесый. Сесыі, якія падтрымваюцца, должны маць тэрмін жыцця 24–48 гадоў, што дапамагае заліць базу дадзеных маленькай і бяспечней.
    • Захоўвайце прыватныя даны. Неасоблівыя персональныя даны, такія як номеры нацыянальных айдэнтайвоў чы паролі, не маюць месца ў спяльнам стане, таму іх трэба маскаваць пры запісе ў сесыю.

    Калі аднам агенту все ўсё ж лепей

    Мнагія агенты не ўсега яе вышэйшы варыянт. Практычны спосаб выбору:

    • Простая адміністрацыя FAQ або перагляд статусу: адзін агент. Найменшы час адказу і вартасць, не трэба складных расчынэнняў.
    • Узбагачэнне дадзеных за дапамою трохі-пяці пошукоў: адзін агент. Одна вызовка LLM дастаткова для базовага выкарыстоўвання інструментаў.
    • Рэгулюемыя працэсы: кальколька агентаў. Ізоляцыя дзеянняў дазволяе аддзеліць логіку дзеянняў ад уводу корыстніка, чым скарочвае рызык втрымкі спрамптаў.
    • Неодназначнае направленне дзеянняў: кальколька агентаў. Спецыяльны агент для сортавання, які спецыялізуецца на адпрацоўцы намеру, скарочвае парадкі, якія вынікаюць з неодназначнасці.
    • Дзеяння з вялікімі рызыкамі, калі сума прыбліжна перавышае 500 долераў: кальколька агентаў. Гэта дазволяе агенту QA адразу пераканацца ў правільнасці пры выкананні будзь-каго API-запыту.
    • Трэбаванні до аўдыту: кальколька агентаў. Увод і выходы кожнага агента фіксуюцца окрэма.

    Адміністратыўны прыем: калі запрос для адного агента доходзіць да 3 000 токенаў — гэта момент, калі пачынаецца перанасылка абмежэнняў і розбліжэнне увагі, альбо калі разныя часткі робочага працэсу патрабуюць разных інструментоў, настав час яго раздзеліць.

    Пашчэрбныя моменты

    • Агент, які робіць усё. Рэзультаты працы падупаюць, калі адны агент мае дзесяць чы больш інструментоў, таму што мадэлі пачынаюць вітрачаць зусілля на выбір інструмента замест на розумеўць запіту. Раздзеліце яго па можлівасцях: агент, якому трэбны інструменты для вярнення грошаў, доставкі і юрыдычных пытанняў, стане трохма спецыялістамі.
    • Неконтрольваны кантэкст. Якшчо кожны агент бачыць усю чат-розмову з дзесяці крокаў, вартасць токенаў стрэлкамі расце. Сконцентруйце стан, каб трыаж пасылаў толькі выявленую мету, а не всю розмову.
  • Бесканцэскія перадачы. Агент А надае даныя агенту Б, які зноў надае іх А, так што токены спалююцца ў кругу. Неабходна задаць максымальны лічылак перадач; два цыклу прымаюцца як оптымальны тэрмін для пераходу да людзя.
  • Нечыстыя межы. Два агенты беруцься за аднаковая задача, або задача застаецца між ямі. Неабходна чыткая вакуумацыя input_schema і output_schema без перакрыцэння адпаведных обавязкаў.
  • Ігнараванне затрымкі. У секвэнцыйным пайплайне затрымка становіцца 4–6 секунд, тады як у аднаго агента — 1–2 секунды. ParallelAgent ADK дазволяе аднойчасна выканаць незалежныя задачы, і аднойчасныя доследжэння і пераконтрольнае адпрацоўванне можа зменшыць загальную затрымку на 30–40%.
  • Што можна спакоўвацца ад гэтага

    Сістэмы з калькольнай канцэларыяй праграмаваюць затрымку зарады надзеянняй на надзейнасць у складных задачах. Опублікованыя тэсты і практычны дазнаўленні промышленасці адзначаюць такія якосты:

    • Точна праца з складнымі задачамі. Разбіўка багатоэтапных проблем на конкрэтныя падзаданні зазвычай дае лепшыя рэзультаты, чым вікорыстанне монолітных запітоў, а даследжэння ADK паказваюць вышэйшыя практычныя показнікі, калі агенты маюць чыста вялікі круг обавянэнняў.
    • Контрольліваныя абыекты. Калі зламваецца адны з компонентаў, ушкоджэння застаецца толькі ў тым агенце і не пашкоджае всю адпаведзь.
    • Магчымасць аўдыту. Аддзельныя лог-файлы для кожнага агента спрыяюць простаму адлучэнню бягаў і перакананню ў ўсасненні правілаў.

    Косты таксама ёсць рэальнымі:

    • Затрымкі. Працэс з удзелам пяці агентаў займае прыблізна 3–8 секунд, тады як для аднаго агента — 1–2 секунды. Галоўным бутылчыным горлам являюцца последовныя вызовы.
  • Выкорыстанне API. Пяць агентоў (аднага оркестрабіста і чатырох спецялістав) коштаюць прыблізна чатыры-пяць разоў больш, чым аднаго агента за кожны запіт, хоча сумешанне модэляў дапамагае контролюваць гэты расход. Ранжаванне за дапамогою Flash-Lite коштае 0,25 долара за мільйон токэнаў вхідных дадзеных, а версія Pro за 2 долара за мільйон прызначаная для оркестрацыі і пераконтроўвання якасці, што дазволяе утрымаць сумарны расход за адну взаімадзею пад адным цэнтам.
  • Токэны для раздумаў. Рэжым расшырэнага раздумвання у версіі Pro (thinking_level="HIGH") можа дадаць прыблізна 20 тысяч токэнаў, за якія бераецца плата за 12 долароў за мільйон токэнаў выходных дадзеных. Такім чынам, адна глыбока пераконтроўвання якасці коштае прыблізна 0,24 долара толькі на раздумвання. Вярніцеся да рэжыму HIGH толькі у спецыяльных случаях, адколі для большасці пераконтроўваннях якасці падходзіць рэжым MEDIUM.
  • Складнасць. Ёсць больш элементаў, якія трэба сочыць. Гэта корыстна для складных рабочых працэсаў, але занадта сложна для простых.
  • Для апрыксіматывнага месячнага рachunkу за 100 000 складных запытоў:

    • Рутаванне аранжэтара на Gemini 3.1 Pro: прыблізна $80
    • Трыяж на Flash-Lite: прыблізна $20
    • Даследжэння на Flash: прыблізна $40
    • Дзеянне на Flash: прыблізна $40
    • Перакантролька з MEDIUM thinking на Pro: прыблізна $100
    • Cloud Run з 2 vCPU і 2 GiB: прыблізна $120
    • Сесіі PostgreSQL: прыблізна $30
    • Vector Search, выкорыстоўваны з адна-агентным наладжэнням: прыблізна $100
    • Аб’ём: прыблізна $530 на месцы

    Спалучэнне модэляў — гэта справжняе рычага для кантролю віткоў. Толькі адносна 30% вызоў (аранжэтар і перакантролька) парадкаваюцца за цэнамі Pro, тады як рэшта выконваюцца на Flash або Flash-Lite за цэнамі, якія станавяць ад восьмай да п’ятдэсятай часткі цены за токен. Аб’ёмная вартасць адной складнай інтэрацыі станавяе прыблізна паў цента. Гэтыя цыфры апынуліся на падставе опублікованых цэнаў Google Cloud, а рэальныя сумы змінююцца залежна ад складносці запытання, рэвэлю цыклу размышлення і глубіны вызоў агента.

    Парадакт адыябрацыі

    Розумным падчынам ёсць пачаць з адного агента, налаштаваць яго логіку, падкрэпляць яго данымі з базы інформацый, а раздзеляць на спецялістаў толькі тады, калі запіт сістэмы стане занадта дзьвялым або задачы будуць занадта разнародныя, каб аднаму модэлю было можна ўпэўненна іх адрабатваць. Кожны слой будуе на тым, што знаходзіцца ніжэй.

    Момент мікросервісаў для агентаў

    Дызайн з калькамі агентаў не робіць ШЫ болей складным. Ён робіць сложныя рабочыя працэсы прагнозаванымі, так сама як мікросервісы заменілі моноліт: адны запіт стае распадзеленым наборам частак, кожная з якіх выпаловае адну задачу. Калі прасіць адного агента адразу трыяжыраваць, дзерабатваць даныя, дзеяць і аўдытаваць, гэта як прасіць адну люст карбавацца рэцыпшанткай, галоўным аналітыкам, тэхнікам і аўдытаром адночасна. Гэта можа працаваць у компаніі з аднаго чалавека, але не ў вялікай корпорацыі.

    Дадзіце кожнам агенту чыткую задачу, спецыялізаваныя інструменты і спольную шару памяці, і рэзультат будзе точным — адколі чыткія запіты зменшаюць паклонення пад час віканання некалякучых задач; сістэму лёгка будзе дыягнаставаць, адколі проблемы спецыяліста ёсць віднымі; і гэта дэшэўа — адколі запуск пяціх агентоў на Gemini 3.1 коштае апоўну паў цента за кожную складную взаімадзею, што значна меньш за хвіліну часу людзкага агента.

    Дыяграма таксама мае простор для развіцця. За дапамогою протаколу Agent-to-Agent (A2A), адкрытага стандарту, кіраванага Linux Foundation, такая сістэма згодна будзе можаць весты пераговоры з агентамі, якія працуюць у вендораў чыста партнероў, напрыклад, калі агент падтрымкі будзе спрачывацца безпосерэдна з агентам развознай компаніі, каб рашыць проблему з загубленай паказкой, без удзеле людзя.

    Наразе парада простая: спачатку створыце аднаго агента, а потым дэкомпозуйце ўзел, калі запіты стануць занадта дужымі чыста задачы — занадто разнароднымі.