Зачем строить AI-агента вместо простого чат-бота

Чат-бот отвечает на вопрос и ждёт следующего. Агент — думает, планирует и действует самостоятельно: вызывает функции, обрабатывает результаты, уточняет данные и доводит задачу до конца без вашего участия.

Разница не в мощности модели, а в архитектуре: агент работает в цикле «наблюдение → мышление → действие», пока не достигнет цели или не исчерпает лимит шагов.

В апреле 2026 года Anthropic запустила Claude Agent SDK — официальный инструментарий для построения агентов на Python и TypeScript. Он даёт вам тот же механизм, на котором работает Claude Code, но полностью под вашим контролем. Именно его мы и разберём в этом туториале.

Агент — это не просто умный чат-бот. Это автономная программа, которая решает задачу, а не просто отвечает на вопрос.


Часть 1. Подготовка: модели, цены и настройка окружения

Выбор модели

Прежде чем писать код, выберите модель под задачу:

МодельInput ($/1M токенов)Output ($/1M токенов)Когда использовать
claude-haiku-4-5$1$5Быстрые задачи, высокий объём
claude-sonnet-4-6$3$15Балансирует скорость и качество
claude-opus-4-6$5$25Сложные многошаговые рассуждения

Для прототипа агента оптимален claude-sonnet-4-6 — он умный и не разорит бюджет. Опус подключайте только если Sonnet не справляется с логикой задачи.

💡 Экономия токенов
Используйте prompt caching — Anthropic даёт скидку до 90% на повторяющиеся части системного промпта. Для агента с длинными инструкциями это может сократить расходы в 5–10 раз.

Установка

# Python 3.10+ обязателен
pip install anthropic claude-agent-sdk
# Создайте файл .env в корне проекта
ANTHROPIC_API_KEY=sk-ant-...

Ключ получите на console.anthropic.com. Никогда не кладите его в код напрямую — только через переменные окружения.

⚠ Безопасность
Не коммитьте .env в git. Добавьте его в .gitignore прямо сейчас, до первого коммита.

Часть 2. Архитектура агента: как устроен агентный цикл

Прежде чем писать код — разберитесь, что происходит под капотом.


graph TD
    A[Задача пользователя] --> B[Агент: системный промпт + задача]
    B --> C{Claude думает}
    C -->|Нужен инструмент| D[Вызов tool]
    D --> E[Инструмент выполняется]
    E --> F[Результат → Claude]
    F --> C
    C -->|Ответ готов| G[Финальный ответ]
    G --> H[Пользователь]

Ключевые элементы:

  • Системный промпт — инструкции агента: кто он, что умеет, каким правилам следует.
  • Инструменты (tools) — Python-функции, которые Claude может вызывать: поиск в сети, работа с файлами, запросы к API.
  • Агентный цикл — бесконечный цикл, пока Claude не ответит без вызова инструментов.
  • История сообщений — контекст всего разговора, который SDK ведёт за вас.

В отличие от сырого Anthropic Python SDK, где вам пришлось бы реализовывать этот цикл вручную, Claude Agent SDK берёт оркестрацию на себя.


Часть 3. Первый агент: минимальный рабочий пример

Создадим агента, который умеет искать информацию и считать математику.

import asyncio
import os
from dotenv import load_dotenv
from claude_agent_sdk import ClaudeSDKClient, tool

load_dotenv()

# Определяем инструменты — простые async-функции

@tool("calculate", "Вычисляет математическое выражение", {"expression": str})
async def calculate(args: dict) -> dict:
    """Безопасное вычисление арифметики."""
    expression = args["expression"]
    # Только цифры и базовые операторы — никакого eval с произвольным кодом
    allowed = set("0123456789+-*/()., ")
    if not all(c in allowed for c in expression):
        return {"content": [{"type": "text", "text": "Недопустимые символы в выражении"}]}
    try:
        result = eval(expression)  # noqa: S307 — проверено выше
        return {"content": [{"type": "text", "text": str(result)}]}
    except Exception as e:
        return {"content": [{"type": "text", "text": f"Ошибка: {e}"}]}


@tool("get_current_date", "Возвращает текущую дату", {})
async def get_current_date(args: dict) -> dict:
    from datetime import datetime
    return {"content": [{"type": "text", "text": datetime.now().strftime("%Y-%m-%d")}]}


# Создаём клиент с системным промптом
client = ClaudeSDKClient(
    model="claude-sonnet-4-6",
    system_prompt="""Ты — умный ассистент с доступом к калькулятору и дате.
    Когда нужно что-то посчитать — используй инструмент calculate.
    Всегда отвечай на русском языке.""",
    tools=[calculate, get_current_date],
)


async def main():
    print("Агент запущен. Введите 'выход' для завершения.\n")
    while True:
        user_input = input("Вы: ").strip()
        if user_input.lower() in ("выход", "exit", "quit"):
            break

        print("Агент: ", end="", flush=True)
        async for message in client.query(user_input):
            if message.type == "text":
                print(message.text, end="", flush=True)
        print()  # Перевод строки после ответа


if __name__ == "__main__":
    asyncio.run(main())

Запустите и попробуйте: «Посчитай 1337 * 42» или «Какой сегодня день?» — агент вызовет нужный инструмент и вернёт ответ.

ℹ Почему async?
Claude Agent SDK построен на асинхронном Python (asyncio). Это позволяет стримить ответы токен за токеном и параллельно вызывать несколько инструментов. Если ваше приложение синхронное — используйте asyncio.run() как точку входа.

Часть 4. Реальный агент: работа с внешними API и файлами

Минимальный пример хорош для старта, но реальный агент обычно работает с внешними данными. Добавим инструменты для HTTP-запросов и работы с файлами.

import aiohttp
import aiofiles
from pathlib import Path

@tool(
    "fetch_url",
    "Загружает содержимое веб-страницы по URL",
    {"url": str, "max_chars": int}
)
async def fetch_url(args: dict) -> dict:
    url = args["url"]
    max_chars = args.get("max_chars", 2000)

    # Базовая защита от SSRF — блокируем внутренние адреса
    if any(blocked in url for blocked in ["localhost", "127.0.0.1", "0.0.0.0", "169.254"]):
        return {"content": [{"type": "text", "text": "Доступ к внутренним адресам запрещён"}]}

    try:
        async with aiohttp.ClientSession() as session:
            async with session.get(url, timeout=aiohttp.ClientTimeout(total=10)) as resp:
                text = await resp.text()
                return {"content": [{"type": "text", "text": text[:max_chars]}]}
    except Exception as e:
        return {"content": [{"type": "text", "text": f"Ошибка загрузки: {e}"}]}


@tool(
    "write_file",
    "Сохраняет текст в файл (только в папке ./output/)",
    {"filename": str, "content": str}
)
async def write_file(args: dict) -> dict:
    # Ограничиваем запись только в безопасную директорию
    output_dir = Path("./output")
    output_dir.mkdir(exist_ok=True)

    # Нормализуем путь и проверяем, что он внутри output/
    target = (output_dir / args["filename"]).resolve()
    if not str(target).startswith(str(output_dir.resolve())):
        return {"content": [{"type": "text", "text": "Запись за пределами output/ запрещена"}]}

    async with aiofiles.open(target, "w", encoding="utf-8") as f:
        await f.write(args["content"])

    return {"content": [{"type": "text", "text": f"Файл сохранён: {target}"}]}
⚠ Безопасность инструментов
Агент вызывает ваши инструменты автономно. Всегда валидируйте входные данные: проверяйте пути файлов через resolve(), ограничивайте URL-запросы, не допускайте произвольного выполнения кода. Инструмент без валидации — уязвимость.

Пример сессии с файловым агентом

Вы: Зайди на httpbin.org/json, извлеки данные и сохрани в файл result.json

Агент: [вызывает fetch_url → читает JSON → вызывает write_file]
Готово! Данные с httpbin.org/json сохранены в ./output/result.json

Часть 5. Архитектурные паттерны и масштабирование

Когда базовый агент работает, встают вопросы архитектуры. Вот проверенные паттерны:

Многоагентная система (оркестратор + исполнители)

# Оркестратор делегирует задачи специализированным агентам
orchestrator = ClaudeSDKClient(
    model="claude-opus-4-6",  # Сильная модель для планирования
    system_prompt="Ты менеджер. Декомпозируй задачу и вызывай специализированных агентов.",
    tools=[call_search_agent, call_writer_agent, call_analyst_agent],
)

# Исполнители используют более дешёвую модель
search_agent = ClaudeSDKClient(
    model="claude-haiku-4-5",  # Быстро и дёшево для поиска
    system_prompt="Ты специалист по поиску информации.",
    tools=[fetch_url, search_web],
)

Сравнение подходов к построению агентов

КритерийСырой Anthropic SDKClaude Agent SDKСторонние фреймворки
Контроль над цикломПолныйСреднийОграниченный
Скорость стартаМедленнаяБыстраяБыстрая
DebuggingПростоПростоСложно
ИнструментыСвоя реализацияВстроенные + кастомныеЗависит от фреймворка
СтабильностьВысокаяВысокаяВарьируется
Подходит дляСпецифических задачБольшинства проектовБыстрых прототипов
📝 Когда использовать что
Claude Agent SDK — выбор по умолчанию для новых проектов. Сырой SDK — если нужен нестандартный агентный цикл (например, с персистентностью в БД между вызовами). Сторонние фреймворки (LangChain, CrewAI) — только если нужны специфичные интеграции, которых нет в родном SDK.

Персистентность и долгосрочная память

Claude Agent SDK ведёт историю разговора внутри сессии, но не между запусками. Для долгосрочной памяти добавьте сохранение контекста:

import json
from pathlib import Path

def save_session(session_id: str, messages: list):
    path = Path(f"./sessions/{session_id}.json")
    path.parent.mkdir(exist_ok=True)
    path.write_text(json.dumps(messages, ensure_ascii=False, indent=2))

def load_session(session_id: str) -> list:
    path = Path(f"./sessions/{session_id}.json")
    if path.exists():
        return json.loads(path.read_text())
    return []

# При инициализации клиента передайте историю
client = ClaudeSDKClient(
    model="claude-sonnet-4-6",
    system_prompt="...",
    initial_messages=load_session("user_123"),
)

Заключение

Вы прошли путь от «что такое агент» до рабочего Python-кода с реальными инструментами. Ключевые выводы:

  1. Claude Agent SDK значительно упрощает построение агентов по сравнению с ручной реализацией агентного цикла.
  2. Безопасность инструментов — ваша ответственность. Валидируйте все входные данные, ограничивайте доступ к файловой системе и сети.
  3. Начинайте с claude-sonnet-4-6 — он покрывает 90% задач по разумной цене.
  4. Prompt caching может сократить расходы в 5–10 раз для агентов с длинными системными промптами.
  5. Многоагентные системы — следующий уровень: оркестратор на Opus, исполнители на Haiku.

Следующий шаг — добавьте реальные инструменты под вашу задачу: поиск по векторной базе (RAG), работу с почтой или интеграцию с вашим бизнес-API. Архитектура агента одинакова — меняются только инструменты.