По умолчанию Claude может вызывать несколько инструментов в одном ответе. На этой странице описано, как выполнять такие вызовы, как форматировать историю сообщений, чтобы параллелизм продолжал работать, и как отключить параллельное использование инструментов, когда это необходимо. Для потока с одиночным вызовом см. Обработка вызовов инструментов.
Когда Claude вызывает инструменты, ответ содержит stop_reason со значением tool_use и может включать несколько блоков tool_use в одном ходе ассистента. Как выполнять эти вызовы — решать вам. API не предписывает порядок выполнения: вы можете запускать вызовы конкурентно (Promise.all, asyncio.gather), последовательно в порядке их появления или в любой комбинации, подходящей для ваших инструментов.
Выбирайте стратегию исходя из того, что делают ваши инструменты. Независимые операции только для чтения обычно безопасно выполнять параллельно для снижения задержки. Инструменты с побочными эффектами, общим состоянием или требованиями к порядку выполнения, возможно, лучше запускать последовательно.
Какую бы стратегию вы ни использовали, возвращайте один tool_result для каждого блока tool_use — все вместе в следующем сообщении пользователя. Сопоставляйте каждый результат с его вызовом через tool_use_id и размещайте все блоки tool_result перед любым текстовым содержимым в этом сообщении. Полные правила форматирования см. в разделе Обработка вызовов инструментов. Если вы решили не выполнять конкретный вызов (например, потому что вы запускали пакет последовательно и более ранний вызов завершился с ошибкой), всё равно верните для него tool_result с is_error: true и кратким объяснением.
{
"type": "tool_result",
"tool_use_id": "toolu_02",
"is_error": true,
"content": "Not executed: the preceding write_file call failed."
}Используйте Tool Runner для большинства приложений: Tool Runner в SDK обрабатывает ответы с несколькими вызовами инструментов и форматирует результаты за вас, так что вам не нужно писать эту обработку самостоятельно. Используйте ручной подход, описанный на этой странице, когда вам нужен прямой контроль над выполнением вызовов — например, пользовательская пакетная обработка, упорядочивание или обработка ошибок.
Следующий скрипт отправляет запрос, который должен вызвать параллельные вызовы инструментов, проверяет, что ответ их содержит, и форматирует результаты инструментов так, чтобы параллелизм продолжал работать. Запустите его с установленной переменной окружения ANTHROPIC_API_KEY:
client = Anthropic()
# Определяем инструменты
tools = [
{
"name": "get_weather",
"description": "Get the current weather in a given location",
"input_schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA",
}
},
"required": ["location"],
},
},
{
"name": "get_time",
"description": "Get the current time in a given timezone",
"input_schema": {
"type": "object",
"properties": {
"timezone": {
"type": "string",
"description": "The timezone, e.g. America/New_York",
}
},
"required": ["timezone"],
},
},
]
# Тестовый диалог с параллельными вызовами инструментов
messages = [
{
"role": "user",
"content": "What's the weather in SF and NYC, and what time is it there?",
}
]
# Выполняем первоначальный запрос
print("Requesting parallel tool calls...")
response = client.messages.create(
model="claude-opus-4-8", max_tokens=1024, messages=messages, tools=tools
)
# Проверяем наличие параллельных вызовов инструментов
tool_uses = [block for block in response.content if block.type == "tool_use"]
print(f"\n✓ Claude made {len(tool_uses)} tool calls")
if len(tool_uses) > 1:
print("✓ Parallel tool calls detected!")
for tool in tool_uses:
print(f" - {tool.name}: {tool.input}")
else:
print("✗ No parallel tool calls detected")
# Имитируем выполнение инструментов и правильно форматируем результаты
tool_results = []
for tool_use in tool_uses:
if tool_use.name == "get_weather":
if "San Francisco" in str(tool_use.input):
result = "San Francisco: 68°F, partly cloudy"
else:
result = "New York: 45°F, clear skies"
else: # get_time
if "Los_Angeles" in str(tool_use.input):
result = "2:30 PM PST"
else:
result = "5:30 PM EST"
tool_results.append(
{"type": "tool_result", "tool_use_id": tool_use.id, "content": result}
)
# Продолжаем диалог с результатами инструментов
messages.extend(
[
{"role": "assistant", "content": response.content},
{"role": "user", "content": tool_results}, # All results in one message!
]
)
# Получаем окончательный ответ
print("\nGetting final response...")
final_response = client.messages.create(
model="claude-opus-4-8", max_tokens=1024, messages=messages, tools=tools
)
final_text = next(
block.text for block in final_response.content if block.type == "text"
)
print(f"\nClaude's response:\n{final_text}")
# Проверяем форматирование
print("\n--- Verification ---")
print(f"✓ Tool results sent in single user message: {len(tool_results)} results")
print("✓ No text before tool results in content array")
print("✓ Conversation formatted correctly for future parallel tool use")Итоговые строки в конце повторяют два правила форматирования, которые обеспечивают работу параллелизма: все результаты инструментов возвращаются в одном сообщении пользователя, и никакое текстовое содержимое не появляется перед результатами инструментов в этом сообщении.
Модели Claude 4 по умолчанию выполняют параллельные вызовы инструментов, когда запрос выигрывает от использования нескольких инструментов. Для всех моделей вы можете повысить вероятность параллельных вызовов инструментов с помощью целенаправленных подсказок:
Параллельное использование инструментов включено по умолчанию. Чтобы отключить его, установите disable_parallel_tool_use: true внутри объекта tool_choice. Это не параметр верхнего уровня запроса. Эффект зависит от типа tool_choice.
Когда тип tool_choice — auto (по умолчанию), установка disable_parallel_tool_use: true означает, что Claude вызывает не более одного инструмента за ответ. Claude по-прежнему может ответить обычным текстом, не вызывая никакого инструмента. Выделенные строки — единственное отличие от стандартного запроса с использованием инструментов:
client = Anthropic()
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=1024,
tools=[
{
"name": "get_weather",
"description": "Get the current weather in a given location",
"input_schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA",
}
},
"required": ["location"],
},
}
],
tool_choice={"type": "auto", "disable_parallel_tool_use": True},
messages=[
{
"role": "user",
"content": "What is the weather in San Francisco and New York?",
}
],
)
print(response.content)Когда тип tool_choice — any или tool, установка disable_parallel_tool_use: true означает, что Claude вызывает ровно один инструмент. В следующем примере используется any. То же поле работает и с tool:
client = Anthropic()
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=1024,
tools=[
{
"name": "get_weather",
"description": "Get the current weather in a given location",
"input_schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA",
}
},
"required": ["location"],
},
}
],
tool_choice={"type": "any", "disable_parallel_tool_use": True},
messages=[
{
"role": "user",
"content": "What is the weather in San Francisco and New York?",
}
],
)
print(response.content)Если Claude не выполняет параллельные вызовы инструментов, когда это ожидается, проверьте следующие распространённые проблемы:
1. Неправильное форматирование результатов инструментов
Самая распространённая проблема — неправильное форматирование результатов инструментов в истории диалога. Это «учит» Claude избегать параллельных вызовов.
Конкретно для параллельного использования инструментов:
// Wrong: separate user messages reduce parallel tool use
[
{"role": "assistant", "content": [tool_use_1, tool_use_2]},
{"role": "user", "content": [tool_result_1]},
{"role": "user", "content": [tool_result_2]} // Separate message
]
// Correct: one user message with all results maintains parallel tool use
[
{"role": "assistant", "content": [tool_use_1, tool_use_2]},
{"role": "user", "content": [tool_result_1, tool_result_2]} // Single message
]Другие правила форматирования см. в разделе Обработка вызовов инструментов.
2. Слабые подсказки
Подсказок по умолчанию может быть недостаточно. Используйте более сильную системную подсказку из раздела Максимизация параллельного использования инструментов.
3. Измерение параллельного использования инструментов
Чтобы убедиться, что параллельные вызовы инструментов работают:
messages = [] # Message objects returned by client.messages.create across your run
tool_call_messages = [
msg for msg in messages if any(block.type == "tool_use" for block in msg.content)
]
total_tool_calls = sum(
len([block for block in msg.content if block.type == "tool_use"])
for msg in tool_call_messages
)
avg_tools_per_message = (
total_tool_calls / len(tool_call_messages) if tool_call_messages else 0.0
)
print(f"Average tools per message: {avg_tools_per_message}")
# Должно быть > 1.0, если параллельные вызовы работают4. Вызовы в пакете кажутся зависящими друг от друга
Порядок выполнения — ваш выбор. Если ваши инструменты имеют зависимости по порядку, последовательное выполнение пакета с остановкой на первой ошибке — допустимая стратегия: возвращайте is_error: true для любого вызова, который вы не выполнили. Если вы выполняете вызовы параллельно и вызов завершается с ошибкой, потому что его предварительное условие не было выполнено, верните is_error: true с естественным сообщением об ошибке. Claude повторит вызов на следующем ходе. Чтобы уменьшить появление зависимых вызовов вместе, добавьте это в вашу системную подсказку: «Only batch tool calls that are independent of each other.»
Используйте абстракцию Tool Runner из SDK для автоматической обработки агентного цикла, обёртывания ошибок и типобезопасности.
Разбирайте блоки tool_use, форматируйте ответы tool_result и обрабатывайте ошибки с помощью is_error.
Задавайте схемы инструментов, пишите эффективные описания и управляйте тем, когда Claude вызывает ваши инструменты.
Was this page helpful?