Головна / Статті / Створіть багатоагентну систему ШІ за допомогою Gemini 3.1 + Google Cloud: Один бот ->

Створіть багатоагентну систему ШІ за допомогою Gemini 3.1 + Google Cloud: Один бот ->

Покрокова інструкція з створення багатоагентної системи ШІ з Gemini 3.1 + Google Cloud: один бот -> контракти, перевірки та готові блоки коду для команд, які використовують цю схему.

4117 слів

Наведені нижче примітки описують практичний підхід до створення багатоагентної системи ШІ за допомогою Gemini 3 та Google Cloud: від одного агента до оркестрованої інтелектуальності. Основна увага приділяється контрактам, перевіркам та місцям для вставки коду, а не мотиваційному опису.

Чому одного агента недостатньо

Під час роботи над етапом «Чому одного агента недостатньо» спочатку запишіть контракт: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність пізніших змін у коді. Запишіть час виконання та витрати на токени або запити поруч із функціональними результатами. Відомі заздалегідь витрати запобігають несподіваним рахункам під час переходу від демо-версії до спільних середовищ. Записуйте ідентифікатор запиту, ідентифікатор моделі та час затримки при кожному виклику. Без цих записів періодичні помилки постачальника виглядають як баги програми.

Проблема: монолітні запити не скалуються

Під час роботи над етапом The Problem Monolithic Prompts спочатку запишіть умови використання: необхідні дані вхіду, сигнал про успішне виконання та те, що відбувається у разі часткової невдачі. Такий перелік допомагає зберігати чесність пізніших змін у коді. Тримайте конфігурацію окремо від коду додатку. Файли середовища, сховища конфіденційних даних та флаги функцій мають знаходитися в одному місці, де оператори можуть їх перевіряти, не читаючи весь код. Записуйте ідентифікатор запиту, ідентифікатор моделі та час відгуку після кожного виклику. Без цих записів періодичні помилки постачальника виглядають як баги додатку.

Огляд архітектури

Під час роботи над етапом огляду архітектури спочатку запишіть умови взаємодії: необхідні вхідні дані, сигнал про успішне виконання та те, що відбувається у разі часткової невдачі. Такий перелік допомагає зберігати чесність пізніших змін у коді. Одночасно задокументуйте шлях успішного виконання та шлях відновлення. Повторні спроби, людський контроль та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої доробки. Зафіксуйте ідентифікатор запиту, ідентифікатор моделі та час затримки при кожному виклику. Без цих даних періодичні помилки постачальника виглядають як баги програмного забезпечення.

Крок 1: Налаштування набору засобів для розробки агента (30 хвилин)

Під час виконання етапу «Крок 1: Налаштування» спочатку запишіть умови контракту: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Такий перелік допоможе зберегти чесність пізніших змін у коді. Віддавайте перевагу невеликим, тестованим одиницям коду перед об’ємними скриптами. Якщо якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану послідовність операцій. Записуйте ідентифікатор запиту, ідентифікатор моделі та час виконання за кожен виклик. Без цих даних періодичні помилки постачальника можуть здаватися багами програми.

pip install google-adk google-generativeai google-cloud-firestore pydantic
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

Крок 2: Створення агента триажу (30 хвилин)

Під час виконання кроку 2 «Створення етапу» спочатку запишіть угоду: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність пізніших змін у коді. Розглядайте цей етап як угоду між вхідними даними та перевіреними результатами. Дайте назви елементам, визначте критерії успіху та не допускайте беззвучного часткового виконання. Записуйте ідентифікатор запиту, ідентифікатор моделі та час відгуку після кожного виклику. Без цих записів періодичні помилки постачальника виглядають як баги програми. Під час виконання кроку 2 «Створення етапу» спочатку запишіть угоду: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність пізніших змін у коді. Зберігайте конфігурацію окремо від коду програми. Файли середовища, сховища секретних даних та флаги функцій мають знаходитися в одному місці, де оператори можуть їх перевіряти, не читаючи весь код.

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

Крок 3: Створення агента досліджень (30 хвилин)

Етап створення у Кроці 3 найкраще функціонує, якщо його розглядати як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування дій перед розширенням обсягу роботи. Документуйте як успішний, так і відновлювальний сценарії разом. Повторні спроби, людський контроль та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої оптимізації. Закріпіть інтерпретатор та файл блокування залежностей перед тим, як пояснювати принцип роботи циклу. Розбіжності між ноутбуком та системою CI є найпоширенішою причиною безслідного збою під час демонстрацій API.

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

Крок 4: Створення агента дій (30 хвилин)

Крок 4 «Створення сцени» працює найкраще, якщо його розглядати як вимірювану поверхню. Запишіть один ідеальний приклад виконання, один випадок збою та примітку щодо скасування змін перед розширенням обсягу роботи. Віддавайте перевагу невеликим, тестованим одиницям перед об’ємними скриптами. Коли якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану послідовність дій. Закріпіть інтерпретатор та файл з параметрами залежностей перед тим, як пояснювати принцип роботи циклу. Різниця між параметрами ноутбука та середовища CI є найпоширенішою причиною прихованих збоїв у демонстраціях 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"
)

Крок 5: Створення агента QA (30 хвилин)

Етап 5 «Створення сцени» функціонує найкраще, якщо його розглядати як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Призначте назви для кожного елемента, визначте критерії успіху та не допускайте мовчазного часткового виконання завдань. Забезпечте фіксацію версії інтерпретатора та файлу з параметрами залежностей перед тим, як почнете використовувати цикли. Відмінності між ноутбуком та системою CI є найпоширенішою причиною мовчазних збоїв під час демонстрацій API. Етап 5 «Створення сцени» функціонує найкраще, якщо його розглядати як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Зберігайте конфігурацію окремо від коду програми. Файли середовища, бази зберігання секретних даних та флаги функцій мають знаходитися в одному місці, де оператори можуть їх перевіряти, не читаючи весь кодовий граф.

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

Крок 6: Оркестратор — об’єднання всього в єдине ціле (1 година)

На етапі Крок 6 «Оркестратор» необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись визначити прихований стан. Необхідно документувати як шлях успішного виконання, так і шлях відновлення. Повторні спроби, людський контроль та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої оптимізації. Необхідно розділити процес створення клієнта від циклу обробки повідомлень, щоб можна було замінювати постачальників без необхідності переписування машини станів розмови.

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

Запуск Оркестратора

На етапі запуску Orchestrator необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись здогадатися про прихований стан. Краще використовувати невеликі, перевірювані одиниці коду замість об’ємних скриптів. Коли крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану структуру обробки даних. Розділіть процес створення клієнта від циклу обробки повідомлень, щоб можна було замінювати постачальників без необхідності переписування машини станів розмови.

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

Крок 7: Розгортання у продакшн (30 хвилин)

Для кроку 7 «Розгортання на стадію» необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість знову виконати крок з відомої точки контролю, не намагаючись вгадати прихований стан. Розглядайте цю стадію як контракт між вхідними даними та перевіреними результатами. Позначте артефакти, визначте критерії успіху та не допускайте мовчазного часткового завершення. Відокремте створення клієнта від циклу обробки повідомлень, щоб можна було замінити постачальників без переписування машини станів розмови. Для кроку 7 «Розгортання на стадію» необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість знову виконати крок з відомої точки контролю, не намагаючись вгадати прихований стан. Зберігайте конфігурацію окремо від коду програми. Файли середовища, сховища секретів та флаги функцій мають знаходитися в одному місці, яке оператори можуть перевіряти, не читаючи весь граф структур.

Варіант А: Vertex AI Agent Engine (рекомендується)

Під час роботи з етапом Vertex AI за варіантом А спочатку запишіть умови функціонування: необхідні вхідні дані, сигнал про успішне виконання та наслідки часткової невдачі. Такий перелік допоможе зберегти чесність подальших змін у коді. Одночасно задокументуйте шлях успішного виконання та шлях відновлення. Повторні спроби, людський контроль та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої оптимізації. Фіксуйте ідентифікатор запиту, ідентифікатор моделі та час затримки при кожному виклику. Без цих даних періодичні помилки постачальника можуть здаватися багами програми.

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

Варіант Б: Cloud Run (власний контроль)

Під час роботи над етапом Cloud Run за варіантом B спочатку запишіть умови контракту: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Такий перелік допомагає зберігати чесність пізніших змін у коді. Віддавайте перевагу невеликим, тестованим одиницям коду перед об’ємними скриптами. Коли якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану послідовність операцій. Записуйте ідентифікатор запиту, ідентифікатор моделі та час відгуку після кожного виклику. Без цих даних періодичні помилки постачальника виглядають як баги програмного забезпечення.

# 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

Що вам обрати?

Під час роботи над етапом «Який варіант обрати», спочатку запишіть умови договору: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність пізніших змін у коді. Розглядайте цей етап як договір між вхідними даними та перевіреними результатами. Призначте назви елементам, визначте критерії успіху та не допускайте беззвучного часткового виконання завдань. Записуйте ідентифікатор запиту, ідентифікатор моделі та час виконання кожного виклику. Без цих записів періодичні помилки постачальника виглядають як баги програми. Під час роботи над етапом «Який варіант обрати», спочатку запишіть умови договору: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність пізніших змін у коді. Зберігайте конфігурацію окремо від коду програми. Файли середовища, сховища конфіденційних даних та флаги функцій мають знаходитися в одному місці, яке оператори можуть перевіряти, не читаючи весь код.

Крок 8: Постійні сеанси для багатоетапних розмов (30 хвилин)

Етап Крок 8 „Постійні сеанси“ працює найкраще, якщо його розглядати як вимірюваний показник. Збережіть один ідеальний запис розмови, один випадок збою та примітку про скасування дій перед розширенням обсягу. Документуйте як успішний, так і невдалий сценарії роботи. Повторні спроби, людський контроль та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої оптимізації. Забезпечте фіксацію версії інтерпретатора та файлу блокування залежностей перед початком виконання циклу. Різниця між версіями на ноутбуку та в середовищі CI є найпоширенішою причиною прихованих збоїв під час демонстрацій API.

Варіант А: Vertex AI Session Service (рекомендується разом з Agent Engine)

Етап Vertex AI варіанту A працює найкраще, якщо його розглядати як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування перед розширенням обсягу роботи. Віддавайте перевагу невеликим, тестованим одиницям перед складними скриптами. Коли якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану систему обробки даних. Фіксуйте версію інтерпретатора та файл з параметрами залежностей перед тим, як починати роботу з циклів. Розбіжності між ноутбуком та середовищем CI є найпоширенішою причиною прихованих збоїв у демонстраціях API.

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

Варіант B: Сервіс баз даних Session Service (для розгортання в Cloud Run)

Етап «Сесія бази даних Опції B» функціонує найкраще, коли його розглядають як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Позначте всі елементи, визначте критерії успіху та не допускайте мовчазного часткового виконання завдань. Забезпечте фіксацію версії інтерпретатора та файлу блокування залежностей перед початком використання циклів. Розбіжності між ноутбуком та системою CI є найпоширенішою причиною мовчазних збоїв під час демонстрацій API. Етап «Сесія бази даних Опції B» функціонує найкраще, коли його розглядають як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Зберігайте конфігурацію окремо від коду програми. Файли середовища, сховища конфіденційних даних та флаги функцій мають знаходитися в одному місці, де оператори можуть їх перевіряти, не читаючи весь код.

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

Як передається стан між агентами

На етапі «Як потоки даних переміщуються між станами» необхідно визначити вхідні дані, відповідальну особу за крок та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Необхідно документувати як шлях успішного виконання, так і шлях відновлення. Повторні спроби, людський контроль та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої оптимізації. Необхідно розділити процес створення клієнта від циклу обробки повідомлень, щоб можна було замінювати постачальників без необхідності переписування машини станів розмови.

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

Принципи проектування пам’яті

На етапі принципів проектування пам’яті необхідно визначити вхідні дані, відповідальну особу за крок та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Краще використовувати невеликі, перевірювані одиниці коду замість об’ємних скриптів. Коли крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану структуру обробки даних. Розділіть процес створення клієнта від циклу обробки повідомлень, щоб можна було замінювати постачальників без переписування машини станів розмови.

Коли багатоагентна система краща за одноагентну (і коли — ні)

Для етапу «Коли багатоагентна система перемагає одноагентну» необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Позначте всі елементи, визначте критерії успіху та не допускайте беззвучного часткового завершення. Відокремте процес створення клієнта від циклу обробки повідомлень, щоб можна було замінити постачальників без переписування машини станів розмови. Для етапу «Коли багатоагентна система перемагає одноагентну» необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Зберігайте конфігурацію поза кодом додатку. Файли середовища, сховища секретних даних та флаги функцій мають знаходитися в одному місці, яке оператори можуть перевіряти без змін.

Читання всього графа.

Поширені проблеми та рішення

Під час роботи над етапом «Поширені проблеми та рішення» спочатку запишіть умови контракту: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допоможе зберегти чесність подальших змін у коді. Одночасно задокументуйте шлях успішного виконання та шлях відновлення. Повторні спроби, людський контроль та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої доробки. Фіксуйте ідентифікатор запиту, ідентифікатор моделі та час затримки при кожному виклику. Без цих записів періодичні помилки постачальника виглядають як баги програми.

Очікувані показники продуктивності

Під час роботи над етапом очікуваних показників продуктивності спочатку запишіть умови контракту: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Такий перелік допомагає зберігати чесність пізніших змін у коді. Віддавайте перевагу невеликим, тестованим одиницям коду перед об’ємними скриптами. Коли якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану послідовність операцій. Записуйте ідентифікатор запиту, ідентифікатор моделі та час відгуку після кожного виклику. Без цих даних періодичні помилки постачальника виглядають як баги програмного забезпечення.

Приблизна місячна вартість (100 тис. складних запитів/міс.)

Під час роботи над етапом «Орієнтовна щомісячна вартість 100K» спочатку запишіть умови контракту: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність пізніших змін у коді. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Призначте назви елементам, визначте критерії успіху та не допускайте беззвучного часткового виконання завдань. Записуйте ідентифікатор запиту, ідентифікатор моделі та час відгуку після кожного виклику. Без цих записів періодичні помилки постачальника можуть здаватися багами програми. Під час роботи над етапом «Орієнтовна щомісячна вартість 100K» спочатку запишіть умови контракту: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність пізніших змін у коді. Зберігайте конфігурацію окремо від коду програми. Файли середовища, сховища секретних даних та флаги функцій мають знаходитися в одному місці, яке оператори можуть перевіряти, не читаючи весь код.

Що далі

Етап «Що далі» найкраще функціонує, якщо його розглядати як вимірювану поверхню. Зафіксуйте один ідеальний варіант виконання, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Документуйте як успішний, так і відновлювальний сценарії роботи разом. Повторні спроби, людський контроль та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої доробки. Забезпечте фіксацію версії інтерпретатора та файлу блокування залежностей перед початком використання циклів. Розбіжності між ноутбуком та середовищем CI є найпоширенішою причиною прихованих збоїв під час демонстрацій API.

Висновок

Етап висновків працює найкраще, якщо його розглядати як вимірювану поверхню. Зафіксуйте один ідеальний результат, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Віддавайте перевагу невеликим, тестованим одиницям перед складними скриптами. Коли якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану послідовність дій. Забезпечте фіксацію версії інтерпретатора та файлу блокування залежностей перед тим, як пояснювати принцип роботи циклу. Різниця між версіями на ноутбуку та в середовищі CI є найпоширенішою причиною безслідного збою під час демонстрацій API.

Чек-лист операцій

На етапі чек-листу операцій необхідно визначити вхідні дані, відповідальну особу за кожен крок та критерії завершення роботи перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не здогадуючись про прихований стан системи.

Записуйте час виконання та витрати на токени або запити поруч із функціональними результатами. Візуалізація витрат на ранньому етапі запобігає несподіваним рахункам під час переходу з демо-середовища у спільні.

Розділіть процес створення клієнта від циклу обробки повідомлень, щоб можна було змінювати постачальників без переписування машини станів розмови.

Створюйте контрольні точки після дорогих кроків. Функція відновлення не повинна знову стягувати плату за той самий виклик LLM, коли оператор перезапускає пізніший етап.

Фіксуйте версії залежностей та записуйте дайджест зображення, яке використовувалося під час демонстрації. Відтворюваність краща за індивідуальні знання.

Віддавайте перевагу малим, тестованим одиницям коду перед складними скриптами. Якщо якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану послідовність операцій.

Перш ніж запускати стек, заморозьте версії, створіть «золотий» запис для критичного шляху та підтвердьте кроки відкату. У спільних середовищах необхідні обмеження швидкості, перевірки прав на використання та чіткий власник для зміни секретів. Віддавайте перевагу надійності перед креативними одноразовими демонстраціями.

Примітка для dc0c111e30e7: не включайте ключі постачальника до репозиторію, встановіть ліміт токенів на сеанс та зберігайте записи поруч із фікстурами для оцінки, щоб подальша заміна моделей залишалася порівнянною.