К курсу

Цикл агента

Один шаг цикла агентаПрактика: один шаг циклаЦикл в кодеПрактика: цикл в кодеОстановка и повторыПрактика: остановка и повторыЧто решает только кодПрактика: что решает код

Надёжность в проде

Таймаут и ключ идемпотентностиПрактика: таймаут и ключ идемпотентностиСказал «готово», а ничего не произошлоПрактика: ложный успехУстойчивый агент: checkpoint и продолжениеПрактика: устойчивый агент

Устройство агентов

Workflow или агентПрактика: workflow или агентReAct и plan-and-executeПрактика: ReAct и plan-and-executePlan-and-SolveПрактика: Plan-and-SolveReflexionПрактика: ReflexionОдин агент или ройПрактика: один агент или рой

Контекст и стоимость

Почему растёт счёт за агентаПрактика: токены и кэшКонтекст-инженерияПрактика: управление окномПамять агентаПрактика: что агент хранит

Инструменты и протоколы

MCPПрактика: MCPОписания инструментов и инъекцииПрактика: описания инструментов и инъекцииКод вместо набора инструментовПрактика: код вместо набора инструментовНавыки агента и A2AПрактика: навыки агента и A2A

Фреймворки

LangGraph или обычный циклПрактика: LangGraph или обычный циклAgent SDK: что вы покупаетеПрактика: agent SDK

Агенты для кода

Агент для кода по спецификацииПрактика: агент для кода по спецификации
←→ENВойти
Агенты › ФреймворкиDeep dive

Agent SDK: что вы покупаете

Опирается наLangGraph или обычный цикл

Этот блок раскладывает инструменты вокруг цикла агента по тому, что каждый берёт на себя, и показывает, чего за вас не делает ни один из них.

Northwind хочет агента-сортировщика, который передаёт дела о возвратах специалисту. Один инженер предлагает OpenAI Agents SDK, другой Claude Agent SDK, третий FastMCP. Спорят они о трёх разных вещах.

Телефонистка на коммутаторе

До сих пор на звонки коллеги вы отвечали сами. Теперь представьте, что наняли телефонистку. Она читает вслух блокнот, выполняет просьбы из утверждённого вами списка, переводит звонки в другие отделы и записывает каждый разговор. Список и правила о том, что можно делать, остаются вашими, а решена ли проблема покупателя, она не знает. Она знает только, что разговор закончился.

Agent SDK — это такая телефонистка. Проследим за одним tool call и посмотрим, какой продукт где стоит.

Путь одного tool call. SDK цикла и библиотеки MCP работают в разных его точках, поэтому в проекте могут быть и те и другие.
Путь одного tool call. SDK цикла и библиотеки MCP работают в разных его точках, поэтому в проекте могут быть и те и другие.

Инструмент

Слой

Что берёт на себя

OpenAI Agents SDK

Цикл в вашем процессе

Ходы, запуск инструментов, handoff, guardrail, сессии, трейсинг

Claude Agent SDK

Harness: библиотека, которая запускает бинарник Claude Code

Цикл плюс встроенные инструменты для файлов и shell, разрешения, хуки, сессии

Google ADK, Vercel AI SDK

Цикл в вашем процессе, как в первой строке

Цикл и управление контекстом, у каждого через свой API

FastMCP

Сервер и клиент MCP

Схема из вашей функции, валидация, транспорт, авторизация

mcp-use

Агент и клиент поверх MCP

MCPClient и MCPAgent, которому нужна модель из LangChain

Термины ещё не устоялись. В документации LangChain Agents SDK назван фреймворком, а Claude Agent SDK — harness, хотя в Agents SDK теперь тоже есть sandbox-агенты с настоящим рабочим окружением.

Прежний цикл, переданный SDK

Вот агент Northwind на OpenAI Agents SDK. Мы запускали этот код на версии 0.24.0 с моделью-заглушкой.

async def over_limit(ctx, params, call_id) -> bool:
    return params["amount_cents"] > 20000

@function_tool(needs_approval=over_limit)
def issue_refund(ctx: RunContextWrapper[Session], order_id: str,
                 amount_cents: int) -> str:
    """Refund part or all of an order."""
    return refunds.issue(ctx.context.customer_id, order_id, amount_cents)

refunds_agent = Agent(name="Refunds", instructions=REFUND_RULES,
                      tools=[issue_refund])
triage = Agent(name="Triage", instructions=TRIAGE_RULES,
               handoffs=[refunds_agent])

result = await Runner.run(triage, "Order 4417 arrived broken",
                          context=session, max_turns=8)

Runner.run — это ваш цикл for. Он вызывает модель, запускает инструменты и дописывает результаты. По умолчанию max_turns равен 10, а при превышении выбрасывается MaxTurnsExceeded, который ваш код должен поймать или передать в error_handlers.

Схема берётся из сигнатуры. SDK читает аннотации типов и docstring. Первый параметр с типом RunContextWrapper он в схему не включает, поэтому личность покупателя по-прежнему приходит из вашей сессии и модель её задать не может.

Docstring читает модель, так что относитесь к нему как к промпту. FastMCP делает то же самое на стороне сервера. Вот настоящая запись tools/list с сервера FastMCP 4.1.7, с сокращениями:

{
  "name": "lookup_order",
  "description": "Look up one order. Use the number the customer gave, digits only.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "order_id": {
        "type": "string"
      }
    },
    "required": [
      "order_id"
    ]
  }
}

Пауза — это сохранённая строка. Когда over_limit вернул True, прогон останавливается, а в result.interruptions лежит этот вызов. Вы сохраняете result.to_state().to_string(), потом загружаете через await RunState.from_string(triage, saved, context_override=session), вызываете state.approve(...) и запускаете снова. Когда мы убрали context_override, продолженный инструмент упал при чтении покупателя. SDK записал предупреждение в лог, но до нашего кода исключение не дошло, модель просто получила An error occurred while running the tool. Please try again.

У Claude Agent SDK другая форма, потому что у него есть собственные руки. Он подходит для задачи вроде починки упавшего теста в репозитории Northwind, а для чата с покупателем подходит хуже.

options = ClaudeAgentOptions(
    allowed_tools=["Read", "Glob", "Grep", "Bash(pytest *)"],
    permission_mode="acceptEdits",
    max_turns=30,
    max_budget_usd=2.0,
)
async for message in query(prompt="Fix the failing tests in refunds/",
                           options=options):
    if isinstance(message, ResultMessage):
        print(message.subtype, message.total_cost_usd)

Действовать ему позволяют allowed_tools и permission_mode: в режиме по умолчанию вызов инструмента, которому нужно одобрение, отклоняется, если его не покрывает правило и вы не дали callback. На версии 0.2.180 мы убрали эти два параметра и запустили тот же промпт. Edit был отклонён, файл не изменился, а подтип результата всё равно оказался success. Отклонённые вызовы перечислены в permission_denials.

Без ограничений он работает, пока Claude не закончит сам. При достижении max_turns у результата будет подтип error_max_turns, при достижении max_budget_usd — error_max_budget_usd, а query() после такого результата выбрасывает исключение.

Перевести или посоветоваться

По телефону можно перевести покупателя в отдел возвратов, и дальше он говорит с ними. А можно попросить его подождать, самому спросить отдел возвратов и вернуться с ответом.

Handoff меняет того, кто говорит с покупателем. Агент-инструмент оставляет главным менеджера.
Handoff меняет того, кто говорит с покупателем. Агент-инструмент оставляет главным менеджера.

Handoff выбирайте, когда специалист должен отвечать сам, а промпты должны оставаться узкими. Agent.as_tool() выбирайте, когда итоговый ответ должен принадлежать одному агенту или нужно объединить нескольких специалистов.

Где на самом деле работают проверки

Guardrail звучит как проверка всего подряд. В Agents SDK каждый вид запускается в определённых точках.

Где работает каждый вид guardrail в цепочке из сортировщика и возвратов. В нашем прогоне input guardrail у Refunds не сработал ни разу.
Где работает каждый вид guardrail в цепочке из сортировщика и возвратов. В нашем прогоне input guardrail у Refunds не сработал ни разу.

Input guardrail по умолчанию идёт параллельно с агентом, поэтому агент мог уже вызвать инструменты к моменту, когда guardrail остановит прогон. Чтобы сначала проверять, поставьте run_in_parallel=False. Tool guardrail не покрывает handoff и инструменты на стороне OpenAI вроде WebSearchTool. При needs_approval input guardrail инструмента по умолчанию запускается уже после одобрения.

По умолчанию OpenAI Agents SDK и Claude Agent SDK завершают цикл, когда модель отвечает без tool call. В документации OpenAI написано, что цикл идёт, пока задача не выполнена ("continues until the task is complete"), но правило для финального вывода там такое: текст без tool call. Что возврат состоялся, никто не подтвердил, как и показывал блок о ложном успехе.

Чем вы платите

Anthropic ещё в 2024 году предупреждала: слои фреймворка могут скрывать промпты и ответы и усложнять отладку. OpenAI сама проводит границу в документации: берите Responses API напрямую, если хотите владеть циклом или задача короткая и сводится к ответу модели, и SDK, если хотите отдать рантайму ходы, инструменты, guardrail, handoff или сессии.

Вы также берёте на себя темп релизов. За 12 месяцев до 10 ноября 2026 на PyPI вышло 84 релиза openai-agents, всё ещё в ветке 0.x, 144 релиза claude-agent-sdk и 74 релиза fastmcp, считая патчи, а у fastmcp ещё и 19 предварительных версий. Фиксируйте версии и читайте changelog перед обновлением.

Вывод

Глубже

OpenAI Agents SDK: OverviewПримитивы и раздел о том, когда брать Responses API напрямую.OpenAI Agents SDK: GuardrailsГраницы в цепочке агентов, режимы выполнения и что пропускают tool guardrail.Claude Agent SDK: How the agent loop worksХоды, сообщения и ограничения, которые останавливают прогон.FastMCP: WelcomeЧто фреймворк выводит из функции. Цифры о популярности там от самого проекта.
‹ Назад
Предложить улучшениеНашёл ошибку