Отметим: когда вашему сервису нужен AI-агент, который не просто отвечает на вопросы, а выполняет действия: ищет в базах, создаёт тикеты, бронирует переговорные. Обычный чат-бот с LLM тут не справится — нужна интеграция инструментов (tool use). Claude Agent SDK от Anthropic даёт готовый паттерн для таких агентов. Мы используем его в продакшене, и расскажем, как это работает.
Почему именно Claude Agent SDK?
Прямая интеграция через anthropic Python-клиент даёт контроль над каждым шагом. В отличие от LangChain, здесь нет лишних абстракций: вы сами определяете инструменты в формате Anthropic, пишете диспетчер вызовов и управляете историей. Для агентов с 3–5 инструментами это быстрее и легче. Плюс — нативная поддержка параллельных tool calls и streaming.
Что входит в работу?
| Этап | Что получаете |
|---|---|
| Проектирование | Архитектура агента, схема инструментов, матрица ошибок |
| Реализация | Полный код агента с tool use, streaming, логированием |
| Интеграция | Развёртывание в вашей среде (Docker, Kubernetes) |
| Документация | README с описанием всех инструментов и примеров |
| Обучение | Воркшоп для команды (4 часа) |
| Поддержка | 2 недели инцидент-менеджмента после запуска |
Как работает агентный цикл?
Агентный цикл — это последовательность: пользователь → модель → вызов инструмента → результат → модель. Claude Agent SDK автоматизирует этот цикл. Модель решает, какой инструмент вызвать и с какими параметрами. Диспетчер execute_tool выполняет вызов и возвращает результат. История сообщений хранит все взаимодействия, включая результаты инструментов.
Прямая интеграция через Anthropic API
import anthropic
import json
client = anthropic.Anthropic()
# Определение инструментов в формате Anthropic
tools = [
{
"name": "search_database",
"description": "Поиск информации в корпоративной базе данных",
"input_schema": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "Поисковый запрос"},
"table": {"type": "string", "enum": ["products", "orders", "customers"]},
"limit": {"type": "integer", "default": 10},
},
"required": ["query"],
},
},
{
"name": "create_ticket",
"description": "Создать тикет в системе поддержки",
"input_schema": {
"type": "object",
"properties": {
"title": {"type": "string"},
"description": {"type": "string"},
"priority": {"type": "string", "enum": ["low", "medium", "high", "critical"]},
"customer_id": {"type": "string"},
},
"required": ["title", "description", "customer_id"],
},
},
]
def execute_tool(tool_name: str, tool_input: dict) -> str:
"""Диспетчер вызовов инструментов"""
handlers = {
"search_database": lambda i: db.search(**i),
"create_ticket": lambda i: helpdesk.create(**i),
}
handler = handlers.get(tool_name)
if not handler:
return f"Unknown tool: {tool_name}"
try:
result = handler(tool_input)
return json.dumps(result, ensure_ascii=False)
except Exception as e:
return f"Error: {e}"
def run_agent(user_message: str, system_prompt: str = None) -> str:
"""Агентный цикл с tool use"""
messages = [{"role": "user", "content": user_message}]
for iteration in range(10):
response = client.messages.create(
model="claude-opus-4-5",
max_tokens=4096,
system=system_prompt or "Ты — полезный ассистент с доступом к корпоративным инструментам.",
tools=tools,
messages=messages,
)
# Добавляем ответ модели в историю
messages.append({"role": "assistant", "content": response.content})
# Проверяем причину остановки
if response.stop_reason == "end_turn":
# Модель завершила работу — возвращаем текстовый ответ
text_blocks = [b.text for b in response.content if b.type == "text"]
return "\n".join(text_blocks)
if response.stop_reason == "tool_use":
# Обрабатываем вызовы инструментов
tool_results = []
for block in response.content:
if block.type == "tool_use":
result = execute_tool(block.name, block.input)
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": result,
})
# Добавляем результаты инструментов
messages.append({"role": "user", "content": tool_results})
return "Достигнут лимит итераций"
Как работают параллельные tool calls?
def run_agent_with_parallel_tools(user_message: str) -> str:
"""Claude может вызывать несколько инструментов за один ход"""
messages = [{"role": "user", "content": user_message}]
while True:
response = client.messages.create(
model="claude-opus-4-5",
max_tokens=4096,
tools=tools,
messages=messages,
)
messages.append({"role": "assistant", "content": response.content})
if response.stop_reason == "end_turn":
return next((b.text for b in response.content if b.type == "text"), "")
# Все tool_use блоки в одном ответе — выполняем параллельно
tool_use_blocks = [b for b in response.content if b.type == "tool_use"]
if not tool_use_blocks:
break
import asyncio
async def execute_parallel():
tasks = [
asyncio.to_thread(execute_tool, block.name, block.input)
for block in tool_use_blocks
]
return await asyncio.gather(*tasks)
results = asyncio.run(execute_parallel())
tool_results = [
{
"type": "tool_result",
"tool_use_id": block.id,
"content": result,
}
for block, result in zip(tool_use_blocks, results)
]
messages.append({"role": "user", "content": tool_results})
return ""
Streaming агент для низкой задержки
def run_streaming_agent(user_message: str):
"""Агент со стримингом текста"""
messages = [{"role": "user", "content": user_message}]
while True:
collected_content = []
tool_use_id = None
tool_name = None
tool_input_parts = []
with client.messages.stream(
model="claude-opus-4-5",
max_tokens=4096,
tools=tools,
messages=messages,
) as stream:
for event in stream:
if hasattr(event, "type"):
if event.type == "content_block_start":
if event.content_block.type == "tool_use":
tool_use_id = event.content_block.id
tool_name = event.content_block.name
elif event.type == "content_block_delta":
if hasattr(event.delta, "text"):
print(event.delta.text, end="", flush=True)
collected_content.append({"type": "text_delta", "text": event.delta.text})
elif hasattr(event.delta, "partial_json"):
tool_input_parts.append(event.delta.partial_json)
final_message = stream.get_final_message()
messages.append({"role": "assistant", "content": final_message.content})
if final_message.stop_reason == "end_turn":
break
if tool_use_id:
full_tool_input = json.loads("".join(tool_input_parts))
result = execute_tool(tool_name, full_tool_input)
messages.append({
"role": "user",
"content": [{"type": "tool_result", "tool_use_id": tool_use_id, "content": result}],
})
Computer Use (бета) — управление компьютером
# Claude Computer Use — управление компьютером через скриншоты
computer_use_tools = [
{"type": "computer_20241022", "name": "computer", "display_width_px": 1920, "display_height_px": 1080},
{"type": "bash_20241022", "name": "bash"},
{"type": "text_editor_20241022", "name": "str_replace_editor"},
]
response = client.messages.create(
model="claude-opus-4-5", # Поддерживает computer use
max_tokens=4096,
tools=computer_use_tools,
messages=[{"role": "user", "content": "Открой браузер, перейди на company.ru, найди раздел 'Контакты' и скопируй телефон."}],
betas=["computer-use-2024-10-22"],
)
Практический кейс: интеграция Claude в корпоративный портал
Из нашей практики: клиенту требовался AI-ассистент в корпоративный портал на Python/FastAPI без внешних фреймворков. Мы выбрали прямой Anthropic API, так как LangChain оказался избыточным для задачи с 5 инструментами. Инструменты включали: search_knowledge_base (векторный поиск по документам), get_employee_info (HR), create_it_ticket (ServiceDesk), get_meeting_rooms (бронирование), get_company_policies (нормативы). Результат: время внедрения 2 недели (против 4 с LangChain), кодовая база 450 строк, latency первого токена на 80 мс ниже. Заказчик сэкономил более 300 000 рублей на разработке — эти средства перенаправили на дополнительную функциональность.
| Инструмент | Назначение | Частота вызова (в день) |
|---|---|---|
| search_knowledge_base | Поиск по документам | 1500+ |
| get_employee_info | Данные сотрудника | 800+ |
| create_it_ticket | Создание заявки в ServiceDesk | 300+ |
| get_meeting_rooms | Бронирование переговорных | 200+ |
| get_company_policies | Нормативные документы | 100+ |
Типичные ошибки при интеграции
- Неправильно спроектированные схемы инструментов (неоднозначные описания) — агент путается. В документации Anthropic рекомендуется использовать явные исключающие примеры в описании поля.
- Отсутствие обработки ошибок
execute_tool— агент зависает в цикле. - Игнорирование лимита итераций — утечка токенов.
- Неверный choice модели для Computer Use (нужна
claude-opus-4-5).
Подробнее о настройке инструментов читайте в официальном репозитории Anthropic SDK.
Сроки и как заказать
| Этап | Срок |
|---|---|
| Базовый агент с 3–5 инструментами | 3–5 дней |
| Streaming + production error handling | 3–5 дней |
| Computer Use интеграция | 1–2 недели |
| Интеграция в web-приложение | 1 неделя |
Мониторинг и контроль расходов на токены
В production важно отслеживать стоимость каждого агентного вызова. Claude API возвращает usage с количеством токенов на вход и выход в каждом ответе. Мы встраиваем счётчик в run_agent:
def run_agent_tracked(user_message: str) -> dict:
total_input_tokens = 0
total_output_tokens = 0
iterations = 0
messages = [{"role": "user", "content": user_message}]
while iterations < 10:
response = client.messages.create(
model="claude-opus-4-5",
max_tokens=4096,
tools=tools,
messages=messages,
)
total_input_tokens += response.usage.input_tokens
total_output_tokens += response.usage.output_tokens
iterations += 1
# ... обработка tool use ...
if response.stop_reason == "end_turn":
break
return {
"result": "...",
"tokens_in": total_input_tokens,
"tokens_out": total_output_tokens,
"iterations": iterations,
}
Средний агентный сеанс с 3 вызовами инструментов потребляет 2000–5000 input-токенов и 500–1500 output. Логируем эти данные в Prometheus и строим дашборды по стоимости на пользователя, на сценарий и на день. Это позволяет быстро выявить аномально длинные цепочки и оптимизировать промпты.
Дополнительная оптимизация: кэширование через prompt_caching (заголовок anthropic-beta: prompt-caching-2024-07-31) снижает стоимость повторяющихся системных промптов на 90%. Для инструментов с редкими описаниями (>1024 токенов) кэширование применяется автоматически и экономит до 40% токенов на многоходовых диалогах. Итоговая экономия на токенах при 10 000 агентных вызовов в день — существенная статья бюджета, которую стоит закладывать в архитектуру с первого дня.
Получите консультацию инженера — оценим ваш проект за 1 день. Опыт интеграции Claude Agent SDK подтверждён десятками успешных проектов. Свяжитесь с нами: мы поможем выбрать архитектуру и подготовить техническое задание.







