Інтеграція 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 зменшує ризик помилок введення у 4 рази порівняно з ручним введенням даних.
Базовий цикл Tool Use
Повний код agentic loop
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 хвилини через діалог з асистентом. Це у 10 разів швидше, ніж ручний збір даних. Економія часу склала 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 тиждень
Вартість базової інтеграції — від $5000, включаючи документацію та навчання команди.
Отримайте консультацію з інтеграції — ми оцінимо ваш проєкт за 1 день і запропонуємо оптимальну архітектуру. Наші сертифіковані ML-інженери мають досвід роботи з OpenAI, Claude, Gemini та open-source моделями. Команда має понад 5 років на ринку, 5+ років досвіду в AI та 50+ реалізованих проєктів. Пишіть — обговоримо ваш сценарій.







