«Programmatic tool calling» (программный вызов инструментов) позволяет Claude писать код, который программно вызывает ваши инструменты внутри контейнера выполнения кода, вместо того чтобы требовать обращения к модели для каждого вызова инструмента. Это снижает «latency» (задержку) для рабочих процессов с несколькими инструментами и уменьшает расход токенов, позволяя Claude фильтровать или обрабатывать данные до того, как они попадут в «context window» (контекстное окно) модели. На агентных поисковых бенчмарках, таких как BrowseComp и DeepSearchQA, которые проверяют многошаговое веб-исследование и сложный поиск информации, добавление программного вызова инструментов поверх базовых поисковых инструментов улучшило результаты в среднем на 11% при использовании на 24% меньше входных токенов (см. Improved web search with dynamic filtering).
Рассмотрим проверку соблюдения бюджета для 20 сотрудников: традиционный подход требует 20 отдельных обращений к модели, попутно загружая в контекст тысячи строк расходов. При программном вызове инструментов один скрипт выполняет все 20 запросов, фильтрует результаты и возвращает только тех сотрудников, которые превысили свои лимиты, сокращая объём данных, над которыми Claude нужно рассуждать, с сотен килобайт до нескольких строк.
Программный вызов инструментов требует code_execution_20260120 или более поздней версии, которая поддерживается на следующих моделях:
| Модель |
|---|
| Claude Fable 5 () |
| Claude Mythos 5 () |
| Claude Opus 5 () |
| Claude Opus 4.8 () |
| Claude Opus 4.7 () |
| Claude Opus 4.6 () |
| Claude Sonnet 5 () |
| Claude Sonnet 4.6 () |
| Claude Opus 4.5 () |
| Claude Sonnet 4.5 () |
Полную матрицу версий инструмента выполнения кода см. в таблице совместимости моделей инструмента выполнения кода. Программный вызов инструментов доступен в Claude API, Claude Platform on AWS и Microsoft Foundry. В Microsoft Foundry для программного вызова инструментов требуется развёртывание Hosted on Anthropic. В настоящее время он недоступен в Amazon Bedrock и Google Cloud.
Вот пример, в котором Claude программно несколько раз запрашивает базу данных и агрегирует результаты. Добавление allowed_callers: ["code_execution_20260120"] в определение инструмента — это то, что делает этот инструмент вызываемым из выполнения кода (см. Поле allowed_callers):
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-5",
max_tokens=4096,
messages=[
{
"role": "user",
"content": "Query sales data for the West, East, and Central regions, then tell me which region had the highest revenue",
}
],
tools=[
{"type": "code_execution_20260120", "name": "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", "description": "SQL query to execute"}
},
"required": ["sql"],
},
"allowed_callers": ["code_execution_20260120"],
},
],
)
print(response)Ответ останавливается с stop_reason: "tool_use", идентификатором container и блоком tool_use для query_database, поле caller которого идентифицирует запуск выполнения кода, вызвавший его. Верните результат, как показано в шаге 3 примера рабочего процесса, чтобы код мог завершиться.
Когда вы настраиваете инструмент так, чтобы его можно было вызывать из выполнения кода, и Claude определяет, что этот инструмент нужен:
tool_useЭтот подход особенно полезен для:
allowed_callersПоле allowed_callers указывает, какие контексты могут вызывать инструмент:
{
"name": "query_database",
"description": "Execute a SQL query against the database",
"input_schema": {
// ...
},
"allowed_callers": ["code_execution_20260120"]
}Возможные значения:
["direct"] — Claude направляется вызывать этот инструмент напрямую (по умолчанию, если опущено)["code_execution_20260120"] — Claude направляется вызывать этот инструмент только из выполнения кода["direct", "code_execution_20260120"] — Claude может вызывать этот инструмент напрямую или из выполнения кодаИ "code_execution_20260120", и "code_execution_20260521" принимаются в allowed_callers и взаимозаменяемы: запрос, использующий любую из версий инструмента выполнения кода, удовлетворяет инструментам, в которых указан любой из этих вызывающих. Блоки ответа всегда помечают вызывающего как code_execution_20260120 независимо от того, какую версию объявил запрос.
caller в ответахКаждый блок использования инструмента включает поле caller, указывающее, как он был вызван:
Прямой вызов (традиционное использование инструментов):
{
"type": "tool_use",
"id": "toolu_abc123",
"name": "query_database",
"input": { "sql": "<sql>" },
"caller": { "type": "direct" }
}Программный вызов:
{
"type": "tool_use",
"id": "toolu_xyz789",
"name": "query_database",
"input": { "sql": "<sql>" },
"caller": {
"type": "code_execution_20260120",
"tool_id": "srvtoolu_abc123"
}
}tool_id — это id блока server_tool_use выполнения кода, который совершил вызов, поэтому вы можете сопоставить каждый программный tool_use с запуском выполнения кода, который его породил.
Программный вызов инструментов использует те же контейнеры, что и выполнение кода:
container вместе с временной меткой expires_atexpires_at сообщает, сколько времени осталось у контейнера. Простаивающие контейнеры в настоящее время освобождаются примерно через 5 минут, и ни один контейнер нельзя использовать повторно более чем через 30 дней после его создания.Вот как работает полный процесс программного вызова инструментов:
Отправьте запрос с выполнением кода и инструментом, допускающим программный вызов. Чтобы включить программный вызов, добавьте поле allowed_callers в определение инструмента.
Форма запроса идентична примеру из раздела Быстрый старт: включите code_execution в список инструментов, добавьте allowed_callers: ["code_execution_20260120"] к любому инструменту, который вы хотите, чтобы Claude вызывал из кода, и отправьте пользовательское сообщение. Остальные шаги этого рабочего процесса используют пользовательское сообщение "Query customer purchase history from the last quarter and identify our top 5 customers by revenue".
Claude пишет код, который вызывает ваш инструмент. API приостанавливается и возвращает:
{
"role": "assistant",
"content": [
{
"type": "text",
"text": "I'll query the purchase history and analyze the results."
},
{
"type": "server_tool_use",
"id": "srvtoolu_abc123",
"name": "code_execution",
"input": {
"code": "import json\n\nrows = json.loads(await query_database({'sql': '<sql>'}))\ntop_customers = sorted(rows, key=lambda x: x['revenue'], reverse=True)[:5]\nprint(f'Top 5 customers: {top_customers}')"
}
},
{
"type": "tool_use",
"id": "toolu_def456",
"name": "query_database",
"input": { "sql": "<sql>" },
"caller": {
"type": "code_execution_20260120",
"tool_id": "srvtoolu_abc123"
}
}
],
"container": {
"id": "container_xyz789",
"expires_at": "2026-01-20T14:30:00Z"
},
"stop_reason": "tool_use"
}Отправьте полную историю разговора плюс результат инструмента. В этом запросе важны три детали:
tool_result. См. Ограничения форматирования сообщений.container из приостановленного ответа. API отклоняет продолжение, в котором есть ожидающие программные вызовы инструментов, но нет идентификатора контейнера.tools, что и в исходном запросе. Инструмент выполнения кода должен по-прежнему присутствовать, чтобы приостановленный код возобновился, а инструменты, которые вы отправляете в этом запросе, — это определения, которые Claude и выполняющийся код могут использовать до конца хода.response = client.messages.create(
model="claude-opus-5",
max_tokens=4096,
container="container_xyz789", # Reuse the container
messages=[
{
"role": "user",
"content": "Query customer purchase history from the last quarter and identify our top 5 customers by revenue",
},
{
"role": "assistant",
"content": [
{
"type": "text",
"text": "I'll query the purchase history and analyze the results.",
},
{
"type": "server_tool_use",
"id": "srvtoolu_abc123",
"name": "code_execution",
"input": {"code": "..."},
},
{
"type": "tool_use",
"id": "toolu_def456",
"name": "query_database",
"input": {"sql": "<sql>"},
"caller": {
"type": "code_execution_20260120",
"tool_id": "srvtoolu_abc123",
},
},
],
},
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_def456",
"content": '[{"customer_id": "C1", "revenue": 45000}, {"customer_id": "C2", "revenue": 38000}, ...]',
}
],
},
],
# Тот же массив tools, что и в исходном запросе
tools=[
{"type": "code_execution_20260120", "name": "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", "description": "SQL query to execute"}
},
"required": ["sql"],
},
"allowed_callers": ["code_execution_20260120"],
},
],
)
print(response)Код продолжает с того места, где он приостановился, и обрабатывает ваш результат. Каждый ответ-продолжение либо снова приостанавливается с новыми программными блоками tool_use, либо завершает выполнение кода и позволяет Claude продолжить ход (шаг 5). Проверяйте stop_reason и caller каждого блока tool_use, чтобы различить эти два случая: ответ, который приостанавливается в ожидании вас, имеет stop_reason: "tool_use" и блок tool_use, в caller которого указана версия выполнения кода, и вы повторяете шаг 3 с tool_result для каждого ожидающего программного вызова в одном пользовательском сообщении.
Когда выполнение кода завершается, Claude предоставляет итоговый ответ:
{
"content": [
{
"type": "code_execution_tool_result",
"tool_use_id": "srvtoolu_abc123",
"content": {
"type": "code_execution_result",
"stdout": "Top 5 customers: [{'customer_id': 'C1', 'revenue': 45000}, {'customer_id': 'C2', 'revenue': 38000}, {'customer_id': 'C5', 'revenue': 32000}, {'customer_id': 'C8', 'revenue': 28500}, {'customer_id': 'C3', 'revenue': 24000}]",
"stderr": "",
"return_code": 0,
"content": []
}
},
{
"type": "text",
"text": "I've analyzed the purchase history from last quarter. Your top 5 customers generated $167,500 in total revenue, with Customer C1 leading at $45,000."
}
],
"stop_reason": "end_turn"
}Claude может писать код, который эффективно обрабатывает несколько элементов:
regions = ["West", "East", "Central", "North", "South"]
results = {}
for region in regions:
rows = json.loads(await query_database({"sql": f"<sql for {region}>"}))
results[region] = sum(row["revenue"] for row in rows)
# Программная обработка результатов
top_region = max(results.items(), key=lambda x: x[1])
print(f"Top region: {top_region[0]} with ${top_region[1]:,} in revenue")Этот паттерн:
Claude может прекратить обработку, как только критерии успеха выполнены:
endpoints = ["us-east", "eu-west", "apac"]
for endpoint in endpoints:
status = await check_health({"endpoint": endpoint})
if status == "healthy":
print(f"Found healthy endpoint: {endpoint}")
break # Stop early, don't check remainingpath = "/tmp/example.txt"
file_info = json.loads(await get_file_info({"path": path}))
if file_info["size"] < 10000:
content = await read_full_file({"path": path})
else:
content = await read_file_summary({"path": path})
print(content)server_id = "srv-01"
log_text = await fetch_logs({"server_id": server_id})
errors = [line for line in log_text.splitlines() if "ERROR" in line]
print(f"Found {len(errors)} errors")
for error in errors[-10:]: # Only return last 10 errors
print(error)Когда выполнение кода вызывает инструмент:
{
"type": "tool_use",
"id": "toolu_abc123",
"name": "query_database",
"input": { "sql": "<sql>" },
"caller": {
"type": "code_execution_20260120",
"tool_id": "srvtoolu_xyz789"
}
}Ваш результат инструмента передаётся обратно выполняющемуся коду:
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_abc123",
"content": "[{\"customer_id\": \"C1\", \"revenue\": 45000, \"orders\": 23}, {\"customer_id\": \"C2\", \"revenue\": 38000, \"orders\": 18}, ...]"
}
]
}Когда все вызовы инструментов удовлетворены и код завершается:
{
"type": "code_execution_tool_result",
"tool_use_id": "srvtoolu_xyz789",
"content": {
"type": "code_execution_result",
"stdout": "Analysis complete. Top 5 customers identified from 847 total records.",
"stderr": "",
"return_code": 0,
"content": []
}
}| Ошибка | Где появляется | Описание | Решение |
|---|---|---|---|
invalid_tool_input | error_code в блоке ошибки code_execution_tool_result в ответе | Инструменту выполнения кода были переданы недопустимые параметры | См. ошибки инструмента выполнения кода |
invalid_request_error (для tool_choice) | Ответ с ошибкой HTTP 400 | tool_choice указывает инструмент, allowed_callers которого не включает "direct" | Либо добавьте "direct" в allowed_callers этого инструмента, либо удалите инструмент из tool_choice и позвольте Claude вызывать его из кода |
Если результат вашего инструмента не поступает в течение примерно 4 минут, ожидающий вызов вызывает TimeoutError внутри выполняющегося кода Claude. Claude видит ошибку в stderr и обычно повторяет вызов:
{
"type": "code_execution_tool_result",
"tool_use_id": "srvtoolu_abc123",
"content": {
"type": "code_execution_result",
"stdout": "",
"stderr": "TimeoutError: Calling tool ['query_database'] timed out (no response after 270s).",
"return_code": 0,
"content": []
}
}Чтобы предотвратить тайм-ауты:
expires_at в ответахЕсли ваш инструмент возвращает ошибку:
{
"type": "tool_result",
"tool_use_id": "toolu_abc123",
"content": "Error: Query timeout - table lock exceeded 30 seconds"
}Код Claude получает эту ошибку и может обработать её соответствующим образом.
strict: true не поддерживаются при программном вызовеtool_choicedisable_parallel_tool_use: true не поддерживается при программном вызовеПользовательские инструменты, input_schema которых содержит рекурсивный $ref (цикл ссылок, например схема, ссылающаяся на саму себя), нельзя включить для программного вызова. Включение версии инструмента выполнения кода в allowed_callers для такого инструмента приводит к сбою запроса с ошибкой 400 invalid_request_error, сообщение которой содержит Circular $ref detected. Та же схема принимается для прямого вызова инструмента.
Чтобы обойти это, сделайте одно из следующего:
allowed_callers (или установив его в ["direct"]). Другие инструменты в том же запросе по-прежнему могут использовать программный вызов.description самого внутреннего уровня, либо замените рекурсивное свойство простым {"type": "object"}, description которого объясняет ожидаемую форму.Следующие инструменты нельзя вызывать программно:
computer_toolset_20260801 и browser_toolset_20260801), поле allowed_callers которых принимает только "direct"При ответе на программные вызовы инструментов действуют строгие требования к форматированию:
Ответы только с результатами инструментов: если есть ожидающие программные вызовы инструментов, ждущие результатов, ваше ответное сообщение должно содержать только блоки tool_result. Вы не можете включать какой-либо текстовый контент, даже после результатов инструментов.
Недопустимо — нельзя включать текст при ответе на программные вызовы инструментов:
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01",
"content": "[{\"customer_id\": \"C1\", \"revenue\": 45000}]"
},
{ "type": "text", "text": "What should I do next?" }
]
}Допустимо — только результаты инструментов при ответе на программные вызовы инструментов:
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01",
"content": "[{\"customer_id\": \"C1\", \"revenue\": 45000}]"
}
]
}Это ограничение применяется только при ответе на программные вызовы инструментов (из выполнения кода). Для обычных клиентских вызовов инструментов вы можете включать текстовый контент после результатов инструментов.
Только текстовое содержимое результата инструмента: content каждого tool_result, отвечающего на программный вызов, должен быть строкой или блоками text. Изображения, документы и другие типы блоков контента отклоняются.
Программные вызовы инструментов подчиняются тем же «rate limits» (ограничениям скорости), что и обычные вызовы инструментов. Каждый вызов инструмента из выполнения кода считается отдельным вызовом.
При реализации пользовательских инструментов, которые будут вызываться программно:
Программный вызов инструментов сокращает расход токенов тремя способами:
Например, прямой вызов 10 инструментов расходует примерно в 10 раз больше токенов, чем их программный вызов с возвратом сводки.
Во внутренних оценках Anthropic на продакшн-модели Claude:
tools которых содержит от 10 до 49 определений инструментов, показывают типичную экономию токенов от 20% до 40% при включённом программном вызове инструментов.Фактическая экономия зависит от формы рабочей нагрузки. См. Когда использовать программный вызов.
Программный вызов инструментов использует те же цены, что и выполнение кода. Подробности см. в разделе цены на выполнение кода.
Программный вызов инструментов обменивает небольшие фиксированные накладные расходы (запуск контейнера, генерация скрипта) на большую экономию токенов результатов инструментов и обращений к модели. Окупается ли этот обмен, зависит от формы рабочей нагрузки.
Хорошо подходит:
Плохо подходит:
Если вы не уверены, измерьте тарифицируемые входные токены с allowed_callers и без него на репрезентативной выборке вашего трафика, прежде чем включать его широко.
invalid_request_error при установке tool_choice
tool_choice не может указывать инструмент, в allowed_callers которого отсутствует "direct". Либо добавьте "direct" в allowed_callers этого инструмента, либо удалите инструмент из tool_choice и позвольте Claude вызывать его из кода.Истечение срока контейнера
expires_at приостановленного ответа. Код Claude перестаёт ждать результата примерно через 4 минуты, а простаивающие контейнеры в настоящее время освобождаются примерно через 5 минут.Результат инструмента разобран неправильно
caller, чтобы подтвердить программный вызовClaude обучен на больших объёмах кода, поэтому представление инструментов в виде вызываемых функций Python позволяет ему использовать эту сильную сторону:
Программный вызов инструментов — это обобщаемый паттерн, который также можно реализовать на собственной инфраструктуре. Вот как соотносятся подходы:
Предоставьте Claude инструмент выполнения кода и опишите, какие функции доступны в этой среде. Когда Claude вызывает инструмент с кодом, ваше приложение выполняет его локально там, где определены эти функции.
Преимущества:
Недостатки:
Используйте, когда: ваше приложение может безопасно выполнять произвольный код, вам нужна минимальная реализация, а управляемое предложение Anthropic не соответствует вашим потребностям.
Тот же подход с точки зрения Claude, но код выполняется в изолированном контейнере с ограничениями безопасности (например, без исходящего сетевого трафика). Если вашим инструментам требуются внешние ресурсы, вам понадобится протокол для выполнения вызовов инструментов вне песочницы.
Преимущества:
Недостатки:
Используйте, когда: безопасность критически важна, а управляемое решение Anthropic не соответствует вашим требованиям.
Программный вызов инструментов от Anthropic — это управляемая версия изолированного выполнения со специализированной средой Python, настроенной для Claude. Anthropic берёт на себя управление контейнерами, выполнение кода и безопасную коммуникацию при вызове инструментов.
Преимущества:
Рассмотрите использование управляемого решения Anthropic, если вы используете Claude API, Claude Platform on AWS или Microsoft Foundry. В Microsoft Foundry для программного вызова инструментов требуется развёртывание Hosted on Anthropic.
Программный вызов инструментов построен на инфраструктуре выполнения кода и использует те же контейнеры-песочницы. Данные контейнера, включая артефакты выполнения и выводы, хранятся до 30 дней.
О соответствии требованиям ZDR для всех функций см. API и хранение данных.
Передавайте входные данные инструментов потоком без буферизации JSON на стороне сервера для приложений, чувствительных к задержке.
Запускайте код на Python и bash в изолированном контейнере для анализа данных, генерации файлов и итеративной работы над решениями.
Подключите Claude к внешним инструментам и API. Узнайте, где выполняются инструменты, когда Claude их вызывает и какой инструмент подходит для вашей задачи.
Задавайте схемы инструментов, пишите эффективные описания и управляйте тем, когда Claude вызывает ваши инструменты.
Was this page helpful?