Программный вызов инструментов позволяет Claude писать код, который вызывает ваши инструменты программно внутри контейнера code execution (выполнения кода), вместо того чтобы требовать обращения к модели для каждого вызова инструмента. Это снижает задержку для рабочих процессов с несколькими инструментами и уменьшает потребление токенов, позволяя Claude фильтровать или обрабатывать данные до того, как они попадут в контекстное окно модели. В бенчмарках агентного поиска, таких как BrowseComp и DeepSearchQA, которые тестируют многоэтапное веб-исследование и сложный поиск информации, добавление программного вызова инструментов поверх базовых инструментов поиска улучшило производительность в среднем на 11% при использовании на 24% меньше входных токенов (см. Improved web search with dynamic filtering).
Рассмотрим проверку соблюдения бюджета для 20 сотрудников: традиционный подход требует 20 отдельных обращений к модели, попутно загружая в контекст тысячи строк расходов. С программным вызовом инструментов один скрипт выполняет все 20 запросов, фильтрует результаты и возвращает только сотрудников, превысивших свои лимиты, сокращая объём данных, над которыми Claude нужно рассуждать, с сотен килобайт до нескольких строк.
Для более глубокого понимания затрат на инференс и контекст, которые решает программный вызов инструментов, см. Advanced tool use.
Эта функция требует включения инструмента выполнения кода.
Эта функция не подпадает под действие политики Zero Data Retention (ZDR). Данные хранятся в соответствии со стандартной политикой хранения данных для этой функции.
Программный вызов инструментов требует code_execution_20260120 или более поздней версии, которая поддерживается в следующих моделях:
| Модель |
|---|
| Claude Fable 5 (claude-fable-5) |
| Claude Mythos 5 (claude-mythos-5) |
| Claude Opus 4.8 (claude-opus-4-8) |
| Claude Opus 4.7 (claude-opus-4-7) |
| Claude Opus 4.6 (claude-opus-4-6) |
| Claude Sonnet 5 (claude-sonnet-5) |
| Claude Sonnet 4.6 (claude-sonnet-4-6) |
| Claude Opus 4.5 (claude-opus-4-5-20251101) |
| Claude Sonnet 4.5 (claude-sonnet-4-5-20250929) |
Полную матрицу версий инструмента выполнения кода см. в таблице совместимости моделей с инструментом выполнения кода. Программный вызов инструментов доступен в Claude API, Claude Platform on AWS и Microsoft Foundry. В Microsoft Foundry программный вызов инструментов требует развёртывания Hosted on Anthropic. В настоящее время он недоступен в Amazon Bedrock или Google Cloud.
Вот пример, в котором Claude программно запрашивает базу данных несколько раз и агрегирует результаты:
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-4-8",
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Этот подход особенно полезен для:
Инструменты, допускающие вызов из выполнения кода, предоставляются коду Claude как асинхронные функции Python, поэтому Claude может запускать их параллельно с помощью asyncio.gather. Каждая функция принимает один словарь аргументов и возвращает строку: текст tool_result, который вы отправляете обратно. Код Claude ожидает эти функции с помощью await верхнего уровня и разбирает результаты, которые ему нужны как структурированные данные, например rows = json.loads(await query_database({"sql": "<sql>"})).
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 независимо от того, какая версия была объявлена в запросе.
Выбирайте либо ["direct"], либо ["code_execution_20260120"] для каждого инструмента, а не включайте оба, так как это даёт Claude более чёткое указание, как лучше использовать инструмент.
allowed_callers управляет тем, как инструмент представляется Claude, и проверяется относительно tool_choice, но это не жёсткая блокировка прямого вызова на уровне API. Claude настоятельно направляется на соблюдение этого параметра, но ваш клиент всё равно должен быть готов обработать прямой tool_use для любого определённого им инструмента. Не полагайтесь на allowed_callers как на границу безопасности.
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 дней после его создания.Пока код Claude ожидает результата программного вызова инструмента, ожидающий вызов завершается по тайм-ауту примерно через 4 минуты и вызывает TimeoutError внутри кода. Возвращайте каждый результат инструмента задолго до временной метки expires_at в приостановленном ответе. См. Истечение срока контейнера во время вызова инструмента.
Вот как работает полный поток программного вызова инструментов:
Отправьте запрос с выполнением кода и инструментом, который допускает программный вызов. Чтобы включить программный вызов, добавьте поле allowed_callers в определение вашего инструмента.
Предоставьте подробные описания формата вывода вашего инструмента в описании инструмента. Если вы укажете, что инструмент возвращает JSON, Claude попытается десериализовать и обработать результат в коде. Чем больше деталей вы предоставите о схеме вывода, тем лучше Claude сможет обработать ответ программно.
Форма запроса идентична примеру из раздела Быстрый старт: включите 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-4-8",
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=[
{"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 объясняет ожидаемую форму.Следующие инструменты не могут быть вызваны программно:
При ответе на программные вызовы инструментов существуют строгие требования к форматированию:
Ответы только с результатами инструментов: если есть ожидающие программные вызовы инструментов, ожидающие результатов, ваше ответное сообщение должно содержать только блоки 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. Блоки изображений, документов и других типов контента отклоняются.
Программные вызовы инструментов подчиняются тем же ограничениям скорости, что и обычные вызовы инструментов. Каждый вызов инструмента из выполнения кода считается отдельным вызовом.
При реализации пользовательских инструментов, которые будут вызываться программно:
Программный вызов инструментов снижает потребление токенов тремя способами:
Например, прямой вызов 10 инструментов использует примерно в 10 раз больше токенов, чем их программный вызов с возвратом сводки.
Во внутренних оценках Anthropic на производственной модели Claude:
tools содержит от 10 до 49 определений инструментов, показывают типичную экономию токенов от 20% до 40% при включённом программном вызове инструментов.Фактическая экономия варьируется в зависимости от формы рабочей нагрузки. См. Когда использовать программный вызов.
Программный вызов инструментов использует ту же тарификацию, что и выполнение кода. Подробности см. в разделе цены на выполнение кода.
Подсчёт токенов для программных вызовов инструментов: результаты инструментов от программных вызовов не учитываются в вашем использовании входных/выходных токенов. Учитываются только финальный результат выполнения кода и ответ Claude.
Программный вызов инструментов обменивает небольшие фиксированные накладные расходы (запуск контейнера, генерация скрипта) на большую экономию токенов результатов инструментов и обращений к модели. Окупается ли этот обмен, зависит от формы рабочей нагрузки.
Хорошо подходит:
Плохо подходит:
Если вы не уверены, измерьте тарифицируемые входные токены с 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?