Вызов инструментов: как это работает
Главная тема раздела: как модель «вызывает» написанные вами функции. Разбираем протокол по шагам.
Tool use (function calling) — механизм, при котором модель не выполняет действие сама, а сообщает вашему коду, какую функцию и с какими аргументами вызвать; код выполняет и возвращает результат модели.
Зачем это нужно
Модель не умеет ходить в вашу базу, узнавать погоду или отправлять письмо — у неё нет доступа к вашим системам и свежим данным. Но она умеет решить, что нужно вызвать функцию get_weather("Москва"), и попросить вас это сделать. Вы выполняете и отдаёте ответ — модель встраивает его в свой текст. Так LLM получает «руки».
Важно: модель НЕ выполняет код
Распространённое заблуждение — будто модель сама запускает ваши функции. Нет. Она лишь возвращает намерение: «вызови инструмент X с аргументами Y». Выполняет всегда ваш код. Это вы контролируете, что и как исполняется (важно для безопасности).
Цикл tool use — четыре шага
1. Запрос ─▶ вы шлёте сообщение + список доступных инструментов (tools)
2. tool_use ◀─ модель отвечает: "вызови get_weather с {city: 'Москва'}"
3. Выполнение ─ ВАШ код запускает get_weather('Москва') -> {temp: 7}
4. Результат ─▶ вы шлёте результат обратно; модель формулирует финальный ответ
Шаг 1: определяем инструменты
Инструмент — это имя, описание и JSON-схема входных параметров. Описание критично: по нему модель решает, когда инструмент применить.
{
"name": "get_weather",
"description": "Узнать текущую погоду в городе. Вызывай, когда спрашивают про погоду.",
"input_schema": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "Название города"}
},
"required": ["city"]
}
}
tools = [ { ... определение выше ... } ]
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=512,
tools=tools,
messages=[{"role": "user", "content": "Какая погода в Москве?"}],
)
print(response.stop_reason) # 'tool_use' — модель хочет вызвать инструмент
Шаг 2: что вернула модель
Если stop_reason == "tool_use", в content есть блок типа tool_use с именем, аргументами (input) и идентификатором (id).
{
"stop_reason": "tool_use",
"content": [
{"type": "text", "text": "Сейчас посмотрю."},
{"type": "tool_use", "id": "toolu_01", "name": "get_weather", "input": {"city": "Москва"}}
]
}
Шаги 3–4: выполняем и возвращаем результат
Вы запускаете свою функцию и отправляете результат обратно как сообщение с ролью user, где лежит блок tool_result с тем же tool_use_id. Модель использует результат и даёт финальный ответ.
messages = [
{"role": "user", "content": "Какая погода в Москве?"},
{"role": "assistant", "content": response.content}, # включая блок tool_use
{"role": "user", "content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01", # тот же id, что в tool_use
"content": "{\"temp\": 7}",
}
]},
]
final = client.messages.create(model="claude-opus-4-8", max_tokens=512, tools=tools, messages=messages)
# теперь final.content содержит текст вроде "В Москве сейчас 7°C."
Главное про id
Связка работает за счёт id: tool_result.tool_use_id должен совпадать с tool_use.id. По нему модель понимает, ответ на какой именно вызов вы прислали (вызовов может быть несколько).
Итог
- Tool use: модель просит вызвать функцию, выполняет её ваш код, результат возвращается модели.
- Цикл: запрос+tools →
tool_use→ выполнение →tool_result→ финальный ответ. - Связь вызова и результата — по совпадению
id/tool_use_id. - Модель сама код не запускает — это даёт вам контроль и безопасность.