AI Agents Guide

Practical patterns for building autonomous agents

Архитектура агентов

AI-агент — это система, где LLM в цикле принимает решения, выполняет действия и получает обратную связь. Ниже — четыре основных паттерна, которые лежат в основе большинства продакшн-агентов.

ReAct Reasoning + Acting

Агент чередует размышление (Thought) и действие (Action), получая наблюдения (Observation) после каждого шага. Самый распространённый паттерн — используется в ChatGPT, Claude, большинстве чат-агентов.

┌─────────────────────────────────────────────────────────┐ │ ReAct Loop │ │ │ │ Запрос ──► Thought ──► Action ──► Observation ──┐ │ │ ▲ │ │ │ └──────────────────────────────────┘ │ │ │ │ Repeat until: ответ найден или лимит итераций │ └─────────────────────────────────────────────────────────┘ Пример одной итерации: Thought: "Нужно найти текущую цену BTC" Action: search_web("BTC price USD") Observe: "BTC = $67,432 (CoinGecko, 5 min ago)" Thought: "Цена получена, могу ответить" Action: final_answer("Текущая цена BTC: $67,432")

Когда использовать: задачи с неизвестным числом шагов, исследовательские запросы, работа с инструментами. Минус: может зациклиться — нужен лимит итераций.

Plan-and-Execute Планирование

Сначала агент создаёт полный план из шагов, затем выполняет каждый шаг последовательно. План может обновляться по ходу выполнения (re-planning).

┌──────────────────────────────────────────────────────────────┐ │ Plan-and-Execute │ │ │ │ Запрос ──► Planner LLM ──► [Step1, Step2, Step3, ...] │ │ │ │ │ ▼ │ │ Executor ──► Step 1 ──► Result 1 │ │ ──► Step 2 ──► Result 2 │ │ ──► Step 3 ──► Result 3 │ │ │ │ │ ▼ │ │ Re-plan? ──yes──► Planner (update plan) │ │ │ │ │ no │ │ ▼ │ │ Final Answer │ └──────────────────────────────────────────────────────────────┘

Когда использовать: сложные многошаговые задачи (написание кода, исследования, рефакторинг). Плюс: структурированность, легче отлаживать. Минус: overhead на планирование, плохо для простых задач.

Multi-agent Systems Несколько агентов

Несколько специализированных агентов работают вместе, каждый с собственным system prompt, набором инструментов и ответственностью. Координация через supervisor или прямое общение.

┌──────────────┐ │ Supervisor │ │ (Router) │ └──────┬───────┘ │ ┌────────────┼────────────┐ ▼ ▼ ▼ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ Coder │ │ Reviewer │ │ Searcher │ │ Agent │ │ Agent │ │ Agent │ │ │ │ │ │ │ │ tools: │ │ tools: │ │ tools: │ │ - edit │ │ - read │ │ - web │ │ - run │ │ - lint │ │ - docs │ └──────────┘ └──────────┘ └──────────┘

Когда использовать: сложные задачи, требующие разных компетенций (разработка + ревью + тестирование). Плюс: разделение ответственности, лучше масштабируется. Минус: сложнее отлаживать, overhead на координацию.

Tool-use Pattern Function Calling

Простейший агентный паттерн: LLM решает, какой инструмент вызвать, получает результат и формирует ответ. Основа для всех остальных паттернов.

┌──────────────────────────────────────────────────────┐ │ Tool-use Loop │ │ │ │ User ──► LLM ──► "Нужен tool X с args Y" │ │ │ │ │ ▼ │ │ Execute tool(Y) │ │ │ │ │ ▼ │ │ Result Z │ │ │ │ │ ▼ │ │ LLM ──► Response to User │ │ (или ещё один tool call) │ └──────────────────────────────────────────────────────┘ Ключевое: LLM НЕ выполняет tool — только генерирует JSON с именем и аргументами. Runtime выполняет и возвращает результат.

Ключевой принцип: LLM генерирует структурированный запрос на вызов инструмента — runtime выполняет вызов и возвращает результат. LLM никогда не выполняет код напрямую.

Фреймворки

Сравнение основных фреймворков для построения AI-агентов. Выбор зависит от задачи, языка и уровня контроля.

Фреймворк Язык Сложность Лучше для Модели
Claude Agent SDK Python Низкая Быстрый старт, tool use, guardrails Claude
LangGraph Python, TS Средняя Сложные графы, state machines, persistence Любые
CrewAI Python Низкая Multi-agent с ролями, быстрый прототип Любые
AutoGen Python Средняя Conversational agents, code execution Любые

Claude Agent SDK Anthropic

Официальный SDK от Anthropic для создания агентов на базе Claude. Минимальный boilerplate, встроенные guardrails и handoffs между агентами.

python — claude agent sdk
import anthropic from agents import Agent, Runner, function_tool @function_tool def get_weather(city: str) -> str: """Получить текущую погоду в городе.""" return f"В {city} сейчас +22, солнечно" agent = Agent( name="Weather Assistant", instructions="Ты помощник по погоде. Отвечай кратко.", tools=[get_weather], ) result = Runner.run_sync(agent, "Какая погода в Москве?") print(result.final_output)

Handoffs — ключевая фича: агент может передать управление другому агенту. Это позволяет строить multi-agent системы декларативно.

LangChain / LangGraph Граф состояний

LangGraph — расширение LangChain для построения агентов как графов состояний. Поддержка циклов, условных переходов, persistence, human-in-the-loop.

python — langgraph react agent
from langgraph.prebuilt import create_react_agent from langchain_anthropic import ChatAnthropic from langchain_core.tools import tool @tool def search_docs(query: str) -> str: """Поиск по базе знаний.""" return f"Результат для: {query}" llm = ChatAnthropic(model="claude-sonnet-4-20250514") agent = create_react_agent(llm, [search_docs]) # Запуск с потоковой передачей for chunk in agent.stream( {"messages": [{"role": "user", "content": "Найди инфо о VLESS"}]} ): print(chunk)

Когда выбрать: нужен полный контроль над графом выполнения, persistence состояния между сессиями, поддержка множества LLM-провайдеров.

CrewAI Роли и задачи

Фреймворк для multi-agent систем с фокусом на ролях. Каждый агент — это роль (researcher, writer, reviewer) с чёткими задачами.

python — crewai
from crewai import Agent, Task, Crew researcher = Agent( role="Researcher", goal="Найти актуальную информацию по теме", backstory="Ты опытный аналитик данных", tools=[search_tool], ) writer = Agent( role="Writer", goal="Написать понятную статью", backstory="Ты технический писатель", ) task1 = Task(description="Исследуй тему AI-агентов", agent=researcher) task2 = Task(description="Напиши статью по результатам", agent=writer) crew = Crew(agents=[researcher, writer], tasks=[task1, task2]) result = crew.kickoff()

AutoGen Microsoft

Фреймворк от Microsoft для conversational multi-agent систем. Агенты общаются друг с другом в чат-формате. Встроенная поддержка code execution.

python — autogen
from autogen import AssistantAgent, UserProxyAgent assistant = AssistantAgent( name="assistant", llm_config={"model": "claude-sonnet-4-20250514"}, ) # UserProxy может выполнять код локально user_proxy = UserProxyAgent( name="user", code_execution_config={"work_dir": "workspace"}, ) user_proxy.initiate_chat( assistant, message="Напиши скрипт для парсинга CSV", )

Когда выбрать: задачи с генерацией и выполнением кода, исследовательские сценарии с несколькими итерациями диалога.

Промпт-инжиниринг для агентов

Промпт агента — это не просто текст запроса. Это операционная система агента: роль, правила, ограничения, формат вывода. Качество промпта определяет 80% поведения агента.

System Prompt Structure

Хорошо структурированный system prompt содержит 5 блоков. Порядок важен — модели уделяют больше внимания началу и концу промпта.

system prompt — структура
# 1. РОЛЬ — кто агент и что делает Ты — AI-ассистент для DevOps-инженеров. Твоя задача: помогать с настройкой серверов и деплоем. # 2. КОНТЕКСТ — что агент знает Ты работаешь с Ubuntu 22.04 серверами. Стек: Docker, Nginx, PostgreSQL, Python. # 3. ИНСТРУКЦИИ — как действовать - Всегда проверяй статус сервиса перед изменением конфига - Создавай бэкап перед любым деструктивным действием - Объясняй каждую команду перед выполнением # 4. ОГРАНИЧЕНИЯ — чего НЕ делать - Никогда не удаляй данные без подтверждения - Не используй rm -rf без явного пути - Не раскрывай credentials в логах # 5. ФОРМАТ ВЫВОДА — как отвечать Отвечай в формате: 1. Диагноз проблемы (1-2 предложения) 2. План действий (нумерованный список) 3. Команды для выполнения (code blocks)
Tip

Используй XML-теги для разделения секций в system prompt — это помогает модели чётко разграничивать контекст. Claude особенно хорошо работает с тегами <role>, <rules>, <output_format>.

Tool Descriptions Best Practices

Описание инструмента — это промпт для модели. От его качества зависит, правильно ли модель выберет tool и передаст аргументы.

Хорошо

search_database: Поиск по базе данных клиентов. Принимает SQL-подобный запрос. Возвращает до 10 результатов в JSON. Используй для: поиск клиента по имени, email, ID заказа.

Плохо

search: Ищет данные. (Непонятно: что ищет, где ищет, какой формат, когда использовать?)

python — правильное описание tool
@tool def execute_sql(query: str, read_only: bool = True) -> str: """Выполнить SQL-запрос к production базе данных. Args: query: SQL-запрос. Поддерживается PostgreSQL синтаксис. Для безопасности используй параметризованные запросы. read_only: Если True (по умолчанию), только SELECT-запросы. Установи False для INSERT/UPDATE/DELETE. Returns: JSON-массив строк. Максимум 100 строк. При ошибке возвращает {"error": "описание"}. Когда использовать: - Поиск данных клиентов, заказов, транзакций - Аналитические запросы (COUNT, SUM, AVG) - НЕ используй для DDL-операций (CREATE, DROP, ALTER) """

Chain-of-Thought CoT

Явная инструкция модели «думать вслух» перед ответом. Критично для сложных задач с multi-step reasoning.

prompt — chain-of-thought
# Вариант 1: Явная инструкция Перед ответом продумай решение пошагово в теге <thinking>. Проанализируй все варианты, выбери лучший, затем ответь. # Вариант 2: Structured CoT для агента Для каждого действия выведи: 1. ANALYSIS: Что я знаю и чего не знаю 2. PLAN: Какие шаги нужны 3. ACTION: Какой tool вызвать и почему 4. EVALUATE: Достаточно ли информации для ответа # Вариант 3: Extended thinking (Claude) # Используй budget_tokens для контроля "глубины" размышлений response = client.messages.create( model="claude-sonnet-4-20250514", thinking={ "type": "enabled", "budget_tokens": 5000 }, ... )
Важно

Chain-of-thought увеличивает расход токенов. Для простых tool-use задач (вызов API, поиск) он не нужен. Включай CoT только для задач с неочевидной логикой.

Few-shot Examples

Примеры — лучший способ показать модели формат и стиль ответа. Для агентов — показываем примеры корректного использования инструментов.

prompt — few-shot для tool use
# В system prompt: Примеры правильного использования инструментов: User: "Какой баланс у клиента Иванов?" Мысль: Нужно найти клиента по фамилии, затем запросить баланс. Tool call: search_customer(name="Иванов") Result: {"id": 42, "name": "Иванов И.И."} Tool call: get_balance(customer_id=42) Result: {"balance": 15230.50, "currency": "RUB"} Answer: "Баланс клиента Иванов И.И.: 15 230,50 руб." User: "Удали заказ #789" Мысль: Деструктивная операция — нужно подтверждение. Answer: "Для удаления заказа #789 требуется подтверждение. Вы уверены? Это действие необратимо."
Tip

Включай примеры отказа и запроса подтверждения. Это учит модель не выполнять опасные действия автоматически.

Tool Use

Инструменты (tools) — это способ дать агенту возможность взаимодействовать с внешним миром: базы данных, API, файловая система, браузер. Два основных подхода: Function Calling (встроен в API) и MCP (универсальный протокол).

Function Calling OpenAI / Anthropic

Модель получает описание доступных функций и возвращает структурированный JSON с именем функции и аргументами. Runtime выполняет вызов и передаёт результат обратно.

Anthropic формат (Claude)

python — anthropic tool use
import anthropic client = anthropic.Anthropic() # Определение инструментов tools = [ { "name": "get_weather", "description": "Получить текущую погоду в указанном городе. " "Возвращает температуру в Цельсиях и описание.", "input_schema": { "type": "object", "properties": { "city": { "type": "string", "description": "Название города (например: Москва)" } }, "required": ["city"] } } ] # Цикл агента messages = [{"role": "user", "content": "Погода в Москве?"}] while True: response = client.messages.create( model="claude-sonnet-4-20250514", max_tokens=1024, tools=tools, messages=messages, ) # Если модель хочет вызвать tool if response.stop_reason == "tool_use": tool_block = next( b for b in response.content if b.type == "tool_use" ) result = execute_tool(tool_block.name, tool_block.input) messages.append({"role": "assistant", "content": response.content}) messages.append({ "role": "user", "content": [{ "type": "tool_result", "tool_use_id": tool_block.id, "content": result, }] }) else: break # Финальный ответ

TypeScript вариант

typescript — anthropic tool use
import Anthropic from "@anthropic-ai/sdk"; const client = new Anthropic(); const tools: Anthropic.Tool[] = [{ name: "get_weather", description: "Получить погоду в городе", input_schema: { type: "object" as const, properties: { city: { type: "string", description: "Город" } }, required: ["city"], }, }]; const response = await client.messages.create({ model: "claude-sonnet-4-20250514", max_tokens: 1024, tools, messages: [{ role: "user", content: "Погода в Москве?" }], });

MCP Model Context Protocol

MCP — открытый стандарт от Anthropic для подключения инструментов к LLM. Единый протокол вместо кастомных интеграций. Работает как USB — подключил сервер, и все его tools доступны.

┌──────────┐ stdio/SSE ┌──────────────┐ │ MCP │ ◄────────────────► │ MCP Server │ │ Client │ JSON-RPC │ │ │ (Claude, │ │ - tools │ │ IDE, │ │ - resources │ │ Agent) │ │ - prompts │ └──────────┘ └──────┬───────┘ │ ▼ ┌──────────────┐ │ Datasource │ │ (DB, API, │ │ Files...) │ └──────────────┘
python — mcp server
from mcp.server.fastmcp import FastMCP mcp = FastMCP("my-tools") @mcp.tool() def query_database(sql: str) -> str: """Выполнить SELECT-запрос к базе данных. Только чтение — INSERT/UPDATE/DELETE запрещены. """ # Валидация и выполнение if not sql.strip().upper().startswith("SELECT"): raise ValueError("Только SELECT-запросы") return execute_query(sql) @mcp.resource("config://app") def get_config() -> str: """Конфигурация приложения.""" return load_config() mcp.run() # Запускает stdio transport
typescript — mcp server
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; const server = new McpServer({ name: "my-tools", version: "1.0.0", }); server.tool( "search_files", "Поиск файлов по glob-паттерну в проекте", { pattern: z.string().describe("Glob pattern, e.g. **/*.ts") }, async ({ pattern }) => { const files = await glob(pattern); return { content: [{ type: "text", text: files.join("\n") }], }; } );
Tip

MCP поддерживает три типа данных: tools (агент вызывает), resources (агент читает, как файл), prompts (шаблоны промптов). Для агентов tools — самое важное.

Практические примеры Tool Definitions

Паттерны, которые работают в продакшне. Ключ — чёткие описания, enum для ограниченных значений, примеры в description.

json — tool definitions
[ { "name": "create_jira_ticket", "description": "Создать задачу в Jira. Используй для: баг-репортов, " "feature requests, tech debt. НЕ используй для: " "эпиков, sub-tasks (для них есть отдельные tools).", "input_schema": { "type": "object", "properties": { "project": { "type": "string", "enum": ["BACKEND", "FRONTEND", "INFRA", "DATA"], "description": "Проект в Jira" }, "issue_type": { "type": "string", "enum": ["Bug", "Task", "Story"], "description": "Bug — дефект, Task — техническая задача, " "Story — пользовательская история" }, "summary": { "type": "string", "description": "Краткое название (до 100 символов)" }, "description": { "type": "string", "description": "Полное описание в Markdown" }, "priority": { "type": "string", "enum": ["Critical", "High", "Medium", "Low"], "default": "Medium" } }, "required": ["project", "issue_type", "summary"] } } ]

Паттерны надёжности

Агент в продакшне должен быть предсказуемым и устойчивым. LLM могут галлюцинировать, API могут падать, контекст может переполниться. Вот паттерны, которые решают эти проблемы.

Retry with Exponential Backoff

API-вызовы и tool calls могут проваливаться. Повторные попытки с экспоненциальной задержкой — базовый паттерн надёжности.

python — retry pattern
import time import random def retry_with_backoff( func, max_retries: int = 3, base_delay: float = 1.0, max_delay: float = 60.0, ): """Retry с exponential backoff + jitter.""" for attempt in range(max_retries + 1): try: return func() except (RateLimitError, APITimeoutError) as e: if attempt == max_retries: raise delay = min( base_delay * (2 ** attempt) + random.uniform(0, 1), max_delay ) print(f"Attempt {attempt + 1} failed: {e}. Retry in {delay:.1f}s") time.sleep(delay) # Использование с Anthropic SDK (встроенный retry) client = anthropic.Anthropic( max_retries=3, # Встроенный retry для 429 и 5xx )

Guardrails / Validation

Guardrails — это проверки до и после каждого действия агента. Они предотвращают опасные операции и валидируют output.

python — guardrails
# 1. Input guardrail — проверка перед вызовом tool def validate_tool_call(tool_name: str, args: dict) -> bool: """Проверка безопасности tool call.""" # Запрет деструктивных операций без подтверждения destructive = ["delete_user", "drop_table", "send_email"] if tool_name in destructive: raise NeedsApproval(f"Действие {tool_name} требует подтверждения") # SQL injection protection if tool_name == "execute_sql": sql = args.get("query", "").upper() if any(kw in sql for kw in ["DROP", "DELETE", "TRUNCATE"]): raise ForbiddenAction("DDL/DML запрещены") return True # 2. Output guardrail — проверка ответа агента def validate_output(response: str) -> str: """Проверка output на PII, prompt injection и т.д.""" import re # Проверка на утечку данных if re.search(r'\b\d{16}\b', response): # номер карты raise PIILeakError("Обнаружен номер карты в ответе") return response # 3. Claude Agent SDK — встроенные guardrails from agents import Agent, InputGuardrail, GuardrailFunctionOutput async def check_injection(ctx, agent, input): # LLM-based guardrail — быстрая модель проверяет input result = await Runner.run(injection_detector, input) return GuardrailFunctionOutput( output_info=result, tripwire_triggered=result.is_injection, ) agent = Agent( input_guardrails=[InputGuardrail(guardrail_function=check_injection)], )

Human-in-the-Loop

Агент запрашивает подтверждение человека для критических действий. Три уровня автономности:

Full Auto

Агент выполняет все действия без подтверждения. Подходит для read-only операций и задач с низким риском.

Approve & Continue

Агент показывает план и ждёт OK/Cancel. Подходит для мутирующих операций (отправка email, изменение данных).

Step-by-Step

Подтверждение на каждое действие. Для критических систем (финансы, медицина, production deploy).

Approve & Continue: Agent: "Мой план: 1. Найти пользователя по email 2. Обновить его тариф на Premium 3. Отправить уведомление на email Выполнить? [Y/n]" Human: "Y" Agent: → выполняет все шаги → сообщает результат

Error Recovery

Агент должен уметь восстанавливаться после ошибок, а не падать. Ключевые стратегии:

python — error recovery
def agent_loop(messages, tools, max_errors=3): """Цикл агента с обработкой ошибок.""" consecutive_errors = 0 while consecutive_errors < max_errors: response = call_llm(messages, tools) if response.stop_reason == "tool_use": tool_call = extract_tool_call(response) try: result = execute_tool(tool_call) consecutive_errors = 0 # Сброс счётчика # Передаём результат обратно messages.append(tool_result(result)) except ToolNotFoundError as e: # Стратегия 1: Сообщить модели об ошибке messages.append(tool_error( f"Tool '{tool_call.name}' не найден. " f"Доступные tools: {list_tools()}" )) consecutive_errors += 1 except ToolExecutionError as e: # Стратегия 2: Дать контекст для исправления messages.append(tool_error( f"Ошибка выполнения: {e}. " f"Попробуй другой подход или другие аргументы." )) consecutive_errors += 1 except NeedsApproval: # Стратегия 3: Эскалация к человеку if get_human_approval(tool_call): result = execute_tool(tool_call, bypass_guard=True) messages.append(tool_result(result)) else: messages.append(tool_error("Действие отклонено.")) else: return response # Финальный ответ raise AgentStuckError("Слишком много последовательных ошибок")

Context Window Management

LLM имеют ограниченное context window. Для длинных сессий агента нужна стратегия управления контекстом.

Sliding Window

Сохраняем последние N сообщений. System prompt + последние сообщения. Простое решение, теряется ранний контекст.

Summarization

Периодически суммируем историю в краткое описание. Вставляем summary в начало контекста. Сохраняет ключевую информацию.

RAG-based

Сохраняем всю историю в vector store. При каждом запросе извлекаем релевантные фрагменты. Лучшее решение для длинных сессий.

python — context management
def manage_context( messages: list, max_tokens: int = 100_000, strategy: str = "summarize", ) -> list: """Управление context window.""" current_tokens = count_tokens(messages) if current_tokens <= max_tokens: return messages if strategy == "sliding": # Оставляем system + последние сообщения system = messages[0] return [system] + messages[-20:] elif strategy == "summarize": # Суммируем старые сообщения system = messages[0] old_msgs = messages[1:-10] recent = messages[-10:] summary = call_llm([{ "role": "user", "content": f"Суммируй ключевые факты из диалога:\n" f"{format_messages(old_msgs)}" }]) return [ system, {"role": "user", "content": f"[Краткое содержание]: {summary}"}, *recent, ]
Tip

Для tool results — сохраняйте только summary результата, а не полный output. Ответ API на 10KB можно сжать до 200 байт с ключевыми данными. Это экономит до 80% контекста.

Оркестрация

Когда одного агента недостаточно — нужна оркестрация нескольких. Три основных паттерна координации.

Supervisor Pattern Самый популярный

Один «главный» агент (supervisor) решает, какому подчинённому агенту делегировать задачу. Supervisor видит все результаты и принимает финальное решение.

Запрос пользователя │ ▼ ┌─────────────────┐ │ Supervisor │ │ │ │ "Это вопрос │ │ про код → │ │ делегирую │ │ Coder Agent" │ └────────┬────────┘ │ ┌───────────┼───────────┐ ▼ ▼ ▼ ┌────────────┐ ┌────────┐ ┌──────────┐ │ Coder │ │ Search │ │ Analyst │ │ │ │ │ │ │ │ tools: │ │ tools: │ │ tools: │ │ - write │ │ - web │ │ - sql │ │ - run_test │ │ - docs │ │ - chart │ └─────┬──────┘ └────────┘ └──────────┘ │ ▼ Result → Supervisor → User
python — supervisor (claude agent sdk)
from agents import Agent, Runner coder = Agent( name="Coder", instructions="Ты пишешь и отлаживаешь Python-код.", tools=[write_file, run_tests], ) searcher = Agent( name="Searcher", instructions="Ты ищешь информацию в интернете и документации.", tools=[web_search, read_docs], ) # Supervisor использует handoffs для делегирования supervisor = Agent( name="Supervisor", instructions="""Ты координатор команды. Анализируй запрос и передай его подходящему агенту: - Coder: написание/исправление кода - Searcher: поиск информации Если задача требует обоих — начни с Searcher, затем Coder.""", handoffs=[coder, searcher], ) result = Runner.run_sync(supervisor, "Напиши парсер RSS на Python")

Pipeline Pattern Последовательный

Агенты работают последовательно, как конвейер. Выход одного — вход следующего. Подходит для задач с чётким порядком этапов.

Pipeline: Генерация статьи Запрос ──► [Research Agent] ──► факты и данные │ ▼ [Writer Agent] ──► черновик │ ▼ [Editor Agent] ──► финальный текст │ ▼ Результат Каждый агент имеет свой system prompt, tools и специализацию. Output передаётся как input следующему агенту.
python — pipeline
async def content_pipeline(topic: str) -> str: """Pipeline: Research → Write → Edit.""" # Этап 1: Исследование research = await Runner.run( research_agent, f"Собери ключевые факты по теме: {topic}", ) # Этап 2: Написание (получает результат research) draft = await Runner.run( writer_agent, f"Напиши статью на основе этих данных:\n" f"{research.final_output}", ) # Этап 3: Редактура (получает черновик) final = await Runner.run( editor_agent, f"Отредактируй статью. Исправь стиль, факты, структуру:\n" f"{draft.final_output}", ) return final.final_output

Debate / Consensus Параллельный

Несколько агентов решают одну задачу независимо, затем результаты сравниваются или обсуждаются. Повышает качество за счёт разных «точек зрения».

Debate: Code Review ┌── Security Agent ──► "SQL injection в строке 42" │ Pull Request ─────┼── Performance Agent ──► "O(n²) в цикле, строка 78" │ └── Style Agent ──► "Нарушение naming convention" │ ▼ ┌─────────────────┐ │ Aggregator │ │ │ │ Объединяет │ │ все замечания, │ │ убирает │ │ дубликаты, │ │ приоритизирует │ └────────┬────────┘ │ ▼ Финальный Code Review
python — debate pattern
import asyncio async def parallel_review(code: str) -> str: """Параллельный code review тремя агентами.""" # Запускаем агентов параллельно security, performance, style = await asyncio.gather( Runner.run(security_agent, f"Проверь безопасность:\n{code}"), Runner.run(perf_agent, f"Проверь производительность:\n{code}"), Runner.run(style_agent, f"Проверь стиль кода:\n{code}"), ) # Агрегатор объединяет результаты combined = await Runner.run( aggregator_agent, f"""Объедини результаты code review: Security: {security.final_output} Performance: {performance.final_output} Style: {style.final_output} Убери дубликаты, отсортируй по критичности.""", ) return combined.final_output
Tip

Debate pattern особенно полезен для задач, где важна полнота (code review, risk analysis, research). Параллельный запуск не увеличивает latency, но увеличивает стоимость пропорционально числу агентов.