Перейти к основному содержимому

Программный вызов инструментов

Продвинутый
What you'll learn
  • Понять, что на самом деле происходит, когда Claude вызывает ваш инструмент изнутри песочницы — и почему ваш инструмент по-прежнему выполняется на вашей собственной машине
  • Правильно включить это с помощью allowed_callers и знать, почему это не является границей безопасности
  • Знать реальные цифры: что это экономит, на каких рабочих нагрузках и где обходится вам дороже
  • Избегать пяти режимов отказа, которые приводят к 400-м ошибкам и TimeoutError в продакшене

Проблема, которую это решает

Классическое использование инструментов — это разговор. Claude запрашивает один вызов инструмента, вы отвечаете, весь результат попадает в контекстное окно, Claude читает его и запрашивает следующий. Двадцать поисков означают двадцать проходов инференса и двадцать сырых полезных нагрузок, навсегда оседающих в контексте.

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

Программный вызов инструментов инвертирует это. Claude пишет Python-скрипт, скрипт вызывает ваши инструменты в цикле, фильтрует результаты, и обратно к модели возвращается только то, что скрипт напечатал. Сырые данные вообще никогда не попадают в контекстное окно.

Что на самом деле происходит

Вот часть, которую почти все обзоры этой функции понимают неверно: ваш инструмент не выполняется внутри песочницы. Контейнер Anthropic не имеет доступа к вашей базе данных.

На самом деле происходит следующее: Python-код Claude приостанавливается на середине выполнения, API передаёт вызов обратно вам, и интерпретатор возобновляет работу, как только вы ответите:

Guided walkthrough1 of 5
  1. Он выполняется внутри контейнера code-execution. Ваши инструменты видны этому коду как асинхронные Python-функции — по одной на каждый инструмент, каждая принимает единственный словарь аргументов и возвращает строку.

Поскольку функции async, Claude может распараллеливаться с помощью asyncio.gather и обращаться к десяти инструментам одновременно — то, что классическое использование инструментов может лишь приблизительно эмулировать с помощью параллельных tool-блоков.

Как на самом деле выглядит сгенерированный код Claude

import json

rows = json.loads(await query_database({"sql": "<sql>"}))
top = sorted(rows, key=lambda r: r["revenue"], reverse=True)[:5]
print(f"Top 5 customers: {top}")

Обратите внимание на json.loads. Функция инструмента возвращает строку — буквальный текст tool_result, который вы отправляете обратно. Если в описании вашего инструмента не сказано "возвращает список строк как JSON-объекты", у Claude нет способа узнать, что можно десериализовать эту штуку, и он будет обрабатывать ваши данные как непрозрачный blob. Предложение о формате вывода в описании вашего инструмента перестаёт быть документацией и становится несущим кодом. Это единственная строка с наибольшим рычагом воздействия, которую вы напишете при принятии этой функции.

Как это включить

Одно поле у инструмента, который вы хотите вызывать из кода, плюс инструмент code-execution в запросе:

Включение программного вызова у инструмента

{
"name": "query_database",
"description": "Execute a SQL query against the sales database. Returns a list of rows as JSON objects.",
"input_schema": { "type": "object", "properties": { "sql": { "type": "string" } }, "required": ["sql"] },
"allowed_callers": ["code_execution_20260120"]
}

allowed_callers принимает три формы:

ЗначениеСмысл
["direct"]Классическое использование инструментов. Это значение по умолчанию, когда поле опущено.
["code_execution_20260120"]Claude направляется вызывать его только изнутри кода.
["direct", "code_execution_20260120"]И то, и другое. Документация советует против этого — выберите одно, чтобы Claude получал однозначный сигнал.

Каждый tool_use блок в ответе теперь несёт caller: либо {"type": "direct"}, либо code-execution caller, чей tool_id совпадает с server_tool_use блоком, запустившим скрипт. Именно так вы атрибутируете вызов скрипту, который его сделал.

Это не граница безопасности

Документация необычно откровенна в этом вопросе, и это стоит повторить, потому что легко предположить обратное: allowed_callers контролирует то, как инструмент представлен Claude. Это не жёсткая блокировка на уровне API. Claude настоятельно направляется соблюдать это — но ваш клиент всё равно должен быть готов получить прямой tool_use для любого инструмента, который он определяет, и вы не должны использовать это поле как механизм авторизации. Авторизация принадлежит вашему обработчику инструмента, где она всегда и была.

Цифры

Собственные заявленные цифры Anthropic, чтобы вы могли судить, стоит ли эта сложность того:

  • На сложных исследовательских задачах среднее использование упало с 43 588 до 27 297 токенов — сокращение на 37%.
  • На бенчмарках GIA точность выросла с 46,5% до 51,2%; на внутреннем поиске знаний — с 25,6% до 28,5%. Меньше токенов и лучшие ответы, потому что модель рассуждает над выводами вместо того, чтобы тонуть в сырых полезных нагрузках.
  • На бенчмарках агентного поиска (BrowseComp, DeepSearchQA) наложение программного вызова поверх базовых инструментов поиска улучшило производительность в среднем на 11% при использовании на 24% меньше входных токенов.
  • Латентность: оркестрация 20+ вызовов инструментов в одном блоке кода устраняет 19+ проходов инференса.

Форма выигрыша — это ключ. Это окупается, когда у вас есть 3+ зависимых вызова, цикл, фильтр или fan-out. Это ничего не окупает — и обходится вам в контейнер — когда Claude нужен ровно один вызов инструмента и он в любом случае хочет прочитать весь ответ.

Watch out
  • Claude Haiku 4.5 принимает новые типы инструментов, но НЕ поддерживает программный вызов инструментов или сохранение состояния REPL, от которого он зависит. Более новые версии там ведут себя молча как code_execution_20250825. Если вы маршрутизируете на Haiku ради стоимости, вы не получаете эту функцию — и не получите ошибку, сообщающую вам об этом.

Сколько это стоит

Программный вызов инструментов тарифицируется как code execution, а code execution тарифицируется по контейнер-часу, а не по вызову:

  • 1 550 бесплатных часов в месяц на организацию.
  • Сверх этого — $0,05 в час за контейнер.
  • Время выполнения имеет минимум 5 минут — двухсекундный скрипт всё равно тарифицируется как пять минут контейнера.
  • Если вы прикрепляете файлы к запросу, время выполнения тарифицируется, даже если инструмент никогда не вызывается, потому что файлы предзагружаются на контейнер в любом случае.
  • Это бесплатно, когда тот же запрос также использует web search или web fetch (web_search_20260209 / web_fetch_20260209 или новее).

Два следствия, которые стоит усвоить. Во-первых, порог в 5 минут означает, что много короткоживущих контейнеров — это дорогой паттерн; повторное использование одного контейнера на протяжении сессии — дешёвый. Во-вторых, эта функция не подходит для Zero Data Retention — если ZDR является контрактным требованием для вас, это жёсткая остановка, а не тюнинговая ручка.

Пять способов, которыми это ломается

Guided walkthrough1 of 5
  1. Когда есть незавершённые программные вызовы инструментов, ваше ответное сообщение должно содержать ТОЛЬКО tool_result блоки. Не текст плюс результаты инструментов. Не результаты инструментов, за которыми следует вежливое предложение. Только tool_result блоки.

Строки версий, расшифрованные

Все три версии code-execution общедоступны и не требуют beta-заголовка:

ВерсияЧто она добавляет
code_execution_20250825Базовая линия. Bash + Python + файловые операции. Поддерживается на каждой текущей модели.
code_execution_20260120Добавляет сохранение состояния REPL и программный вызов инструментов. Это та, что вам нужна.
code_execution_20260521Идентичный рантайм с 20260120. Единственное различие в том, что описание инструмента сообщает Claude о лимите wall-clock в 90 секунд на Python-ячейку, чтобы он мог бюджетировать долго выполняющиеся ячейки. Ячейка, которая превышает лимит, возвращает ненулевой return_code со статусом detection_timeout.

Последняя строка — это приятный элемент дизайна API, который стоит заметить: бамп версии, чья полная полезная нагрузка — это лучший промпт для модели. Обе строки взаимозаменяемы внутри allowed_callers, и ответы всегда тегируют caller как code_execution_20260120 независимо от того, что вы объявили.

Сам контейнер не имеет доступа в интернет — Claude не может pip install во время выполнения, поэтому вы получаете предустановленный набор библиотек (pandas, numpy, scipy, scikit-learn, statsmodels и им подобные) и ничего больше. Контейнеры чекпоинтятся примерно после пяти минут неактивности, восстанавливаются по ID и истекают через 30 дней после создания.

Когда к этому обращаться

Обращайтесь к программному вызову инструментов, когда модель используется как цикл и фильтр, а не как рассуждающий: пакетные поиски по N сущностям, ранняя терминация по достижении условия, условный выбор инструмента на основе промежуточного результата или свёртывание 200-КБ дампа логов до десяти строк, которые имеют значение.

Обращайтесь к Tool Search Tool вместо этого, когда ваша проблема в том, что определения поглощают ваш контекст до того, как сделан хотя бы один вызов — пометьте инструменты defer_loading: true, и Claude загрузит их по запросу. Эти два — дополнения, а не альтернативы: tool search находит правильный инструмент, программный вызов выполняет его дёшево. Если ваши определения инструментов превышают примерно 10K токенов, вам, вероятно, нужны оба.

А если вы упираетесь в это с другой стороны — агент, чей контекст тонет в результатах MCP-инструментов — начните с стоимости токенов MCP и Инжиниринга контекста, потому что самые дешёвые токены — это всё ещё те, которые вы никогда не отправляете.

Check yourself

0/5
  1. Где ваш инструмент на самом деле выполняется во время программного вызова инструмента?
  2. Можете ли вы полагаться на allowed_callers, чтобы предотвратить прямой вызов инструмента?
  3. Ваш агент маршрутизирует на Claude Haiku 4.5, чтобы сэкономить деньги, и передаёт code_execution_20260120. Что происходит?
  4. Когда есть незавершённый программный вызов инструмента, что может содержать ваше ответное сообщение?
  5. Двухсекундный скрипт выполняется в свежем контейнере. Сколько времени code-execution тарифицируется?
Нажмите Enter или пробел, чтобы перевернуть карточку. Используйте стрелки влево и вправо для перехода между карточками.Показан термин.
1 / 7

Источники и дальнейшее чтение