Интеграция Anthropic Tool Use (Function Calling) в приложение
Представьте: CRM-менеджер тратит 20–30 минут на сбор истории сделок, последних контактов и открытых задач перед встречей. При 50 менеджерах это 1000 часов в месяц, уходящих на рутину. Tool Use от Anthropic превращает Claude в ассистента, который за секунды выполняет поиск в CRM, отправляет email и создаёт задачи — без риска SQL-инъекций или доступа к коду. Клод не выполняет код, а возвращает структурированный JSON с именем инструмента и аргументами. Ваше приложение делает настоящую работу и возвращает результат. Это основа агентов, работающих с реальными данными.
Наши инженеры имеют более 5 лет коммерческой разработки AI-решений и 50+ успешных проектов с RAG и Function Calling. Мы гарантируем production-ready код с логированием, ретраями и мониторингом. Обратитесь к нам — внедрим Tool Use за 3 дня.
Какие проблемы решает Tool Use?
Без Tool Use модель ограничена генерацией текста. Чтобы получить данные из базы, нужно либо дать ей прямой доступ к SQL (опасно), либо вручную парсить её ответы и выполнять код. Tool Use решает обе проблемы:
- Безопасность: модель возвращает только JSON, приложение контролирует выполнение.
- Надёжность: JSON Schema задаёт формат аргументов, уменьшая ошибки.
- Производительность: параллельные вызовы инструментов сокращают время ответа агента в 2–3 раза.
Дополнительно Tool Use снижает число галлюцинаций модели при работе с фактологическими данными — она опирается на реальные результаты выполнения, а не на свой внутренний knowledge cutoff.
Базовый цикл Tool Use
import anthropic
import json
from typing import Any
client = anthropic.Anthropic()
# Определение инструментов
TOOLS = [
{
"name": "search_database",
"description": "Поиск клиентов в CRM по параметрам",
"input_schema": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "Поисковый запрос"},
"limit": {"type": "integer", "description": "Количество результатов", "default": 10},
"status": {
"type": "string",
"enum": ["active", "churned", "trial"],
"description": "Фильтр по статусу"
}
},
"required": ["query"]
}
},
{
"name": "send_email",
"description": "Отправить email клиенту",
"input_schema": {
"type": "object",
"properties": {
"to": {"type": "string"},
"subject": {"type": "string"},
"body": {"type": "string"},
},
"required": ["to", "subject", "body"]
}
}
]
# Диспетчер инструментов
def execute_tool(tool_name: str, tool_input: dict) -> Any:
if tool_name == "search_database":
return search_crm(**tool_input)
elif tool_name == "send_email":
return send_email_via_smtp(**tool_input)
raise ValueError(f"Unknown tool: {tool_name}")
def run_agent(user_message: str) -> str:
"""Полный agentic loop с tool use"""
messages = [{"role": "user", "content": user_message}]
while True:
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=4096,
tools=TOOLS,
messages=messages,
)
# Нет вызовов инструментов — возвращаем финальный ответ
if response.stop_reason == "end_turn":
for block in response.content:
if hasattr(block, "text"):
return block.text
return ""
# Обрабатываем tool_use блоки
tool_results = []
for block in response.content:
if block.type == "tool_use":
print(f"Calling tool: {block.name}({block.input})")
result = execute_tool(block.name, block.input)
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": json.dumps(result, ensure_ascii=False),
})
messages.append({"role": "assistant", "content": response.content})
messages.append({"role": "user", "content": tool_results})
Почему стоит использовать параллельные вызовы?
Выполнение нескольких инструментов одновременно ускоряет агента. Когда модель возвращает несколько tool_use блоков в одном ответе, запустите их параллельно через asyncio. Это сокращает общее время до максимума среди всех инструментов. При трёх независимых инструментах со временем выполнения 0.5, 1.2 и 0.8 секунды синхронный подход займёт 2.5 секунды, асинхронный — 1.2 секунды. Выигрыш в 2-3 раза.
import asyncio
async def execute_tool_async(tool_name: str, tool_input: dict) -> tuple[str, Any]:
"""Асинхронное выполнение инструмента"""
result = await asyncio.to_thread(execute_tool, tool_name, tool_input)
return tool_name, result
async def run_agent_async(user_message: str) -> str:
messages = [{"role": "user", "content": user_message}]
while True:
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=4096,
tools=TOOLS,
messages=messages,
)
if response.stop_reason == "end_turn":
return next((b.text for b in response.content if hasattr(b, "text")), "")
# Выполняем все инструменты параллельно
tool_use_blocks = [b for b in response.content if b.type == "tool_use"]
results = await asyncio.gather(*[
execute_tool_async(b.name, b.input)
for b in tool_use_blocks
])
tool_results = [
{
"type": "tool_result",
"tool_use_id": block.id,
"content": json.dumps(result, ensure_ascii=False),
}
for block, (_, result) in zip(tool_use_blocks, results)
]
messages.append({"role": "assistant", "content": response.content})
messages.append({"role": "user", "content": tool_results})
Сравнение синхронного и асинхронного циклов
| Характеристика | Синхронный цикл | Асинхронный цикл |
|---|---|---|
| Выполнение инструментов | Последовательно один за другим | Параллельно, все сразу |
| Задержка при N инструментах | Сумма времён N | Максимальное время одного инструмента |
| Сложность кода | Низкая | Средняя (asyncio) |
| Когда использовать | Инструменты зависят друг от друга | Инструменты независимы |
Как принудительно вызвать инструмент?
# tool_choice="required" — Claude обязан вызвать хотя бы один инструмент
# tool_choice={"type": "tool", "name": "..."} — вызвать конкретный
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=1024,
tools=TOOLS,
tool_choice={"type": "tool", "name": "search_database"},
messages=[{"role": "user", "content": "Найди клиентов с trial статусом"}],
)
Принудительный вызов полезен, когда нужно гарантировать выполнение критичного действия — например, создать задачу или отправить уведомление. При этом модель может вернуть результат вызова без дополнительного текста.
Как обрабатывать ошибки инструментов?
Ошибки — неотъемлемая часть продакшена. Никогда не завершайте диалог при сбое выполнения. Вместо этого передайте описание ошибки обратно модели: она сможет выбрать другой инструмент или запросить уточнение. Пошаговый подход:
- Оберните вызов инструмента в try-except.
- При успехе добавьте результат в
tool_resultsсtype: "tool_result". - При исключении добавьте блок с
is_error: Trueи текстом ошибки. - Отправьте tool_results модели и продолжите цикл.
# Передавайте ошибки обратно в модель — она адаптирует поведение
try:
result = execute_tool(block.name, block.input)
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": json.dumps(result),
})
except Exception as e:
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": f"Error: {str(e)}",
"is_error": True, # Модель знает об ошибке и может скорректировать
})
Пример полного ответа с ошибкой:
{
"type": "tool_result",
"tool_use_id": "toolu_abc123",
"content": "Error: Connection timeout to database",
"is_error": true
}
Модель Claude, получив такой результат, может предложить повторить попытку или использовать другой инструмент.
Практический кейс: CRM-ассистент
Из нашей практики: один из клиентов — крупная розничная сеть с отделом продаж из 50 менеджеров. На подготовку к встрече с клиентом уходило 20–30 минут: нужно было собрать историю сделок, последние контакты, открытые задачи. Мы развернули ассистента на Claude с инструментами:
-
get_customer_info— профиль клиента -
get_deal_history— история сделок -
get_recent_activities— последние действия -
create_task— создать задачу -
get_calendar— свободные слоты
Результат: подготовка к встрече — 2 минуты через диалог с ассистентом. Экономия времени составила 28 минут на встречу. При средней зарплате менеджера $30/час это даёт экономию $14 за встречу, а при 10 встречах в день — $140 ежедневно. Окупаемость проекта — 3 месяца за счёт экономии времени senior-менеджеров. Дополнительно снизилось число ошибок ввода данных на 75% — инструменты работают строго по схемам.
Что входит в работу
| Этап | Содержание | Ориентировочный срок |
|---|---|---|
| Анализ | Определение схем инструментов под бизнес-логику, согласование JSON Schema | 1 день |
| Разработка | Реализация диспетчера инструментов с типизацией, настройка параллельного выполнения через asyncio | 2-3 дня |
| Тестирование | Обработка ошибок и ретраи с передачей фидбека модели, unit-тесты | 1 день |
| Документация | Описание развертывания и поддержки, обучение команды (до 3 часов) | 1 день |
Сроки
- Базовый tool use loop с 2–3 инструментами: 2–3 дня
- Параллельные вызовы + обработка ошибок: 1–2 дня
- Production-ready с логированием и retry: 1 неделя
Получите консультацию по интеграции — мы оценим ваш проект за 1 день и предложим оптимальную архитектуру. Наши сертифицированные ML-инженеры имеют опыт работы с OpenAI, Claude, Gemini и open-source моделями. Пишите — обсудим ваш сценарий.







