По умолчанию Claude может вызывать несколько инструментов в одном ответе. Эта страница описывает, как выполнять эти вызовы, как форматировать историю сообщений, чтобы параллелизм продолжал работать, и как отключить параллельное использование инструментов, когда это необходимо. Для потока с одним вызовом см. Обработка вызовов инструментов.
Когда Claude вызывает инструменты, ответ имеет stop_reason со значением tool_use и может содержать несколько блоков tool_use в одном ходе ассистента. Как выполнять эти вызовы — ваше решение. API не предписывает порядок выполнения: вы можете выполнять вызовы параллельно (Promise.all, asyncio.gather), последовательно в порядке их появления или в любой комбинации, которая подходит вашим инструментам.
Выбирайте стратегию в зависимости от того, что делают ваши инструменты. Независимые операции только для чтения обычно безопасно выполнять параллельно для снижения latency (задержки). Инструменты с побочными эффектами, общим состоянием или требованиями к порядку выполнения, возможно, лучше выполнять последовательно.
Какую бы стратегию вы ни использовали, возвращайте один 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."
}Следующий скрипт отправляет запрос, который должен вызвать параллельные вызовы инструментов, проверяет, что ответ их содержит, и форматирует результаты инструментов так, чтобы параллелизм продолжал работать. Запустите его с установленной переменной окружения 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-5", 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-5", 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-5",
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-5",
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?