AI-агенты и автоматизация Собрать руками

Как собрать агента с tool-calling

Tool-calling — это сердце современного AI-агента. В этом гайде вы соберёте рабочий агент «руками», пройдя путь от концепции до отладки и evals.

Что такое tool-calling и зачем он нужен

Tool-calling — это механизм, при котором LLM не просто генерирует текст, а формирует структурированный запрос к внешнему инструменту (API, функции, скрипту). Это превращает LLM из «разговорного интерфейса» в автономного исполнителя. Без tool-calling агент не может взаимодействовать с реальными системами: базами данных, CRM, платёжными шлюзами и т.д.

Цикл мышления агента с tool-calling

flowchart TD
    A[Пользователь] -->|Запрос| B[Контекст + Инструкция]
    B --> C[LLM: Планирование]
    C --> D{Нужен ли инструмент?}
    D -->|Да| E[Генерация tool_call]
    D -->|Нет| F[Генерация ответа]
    E --> G[Исполнение инструмента]
    G --> H[Результат инструмента]
    H --> I[LLM: Синтез ответа]
    I --> J[Ответ пользователю]
    F --> J

Минимальный пример: Python + OpenAI

Пример агента, который умеет получать текущее время через инструмент:

import openai

# 1. Инструмент (реальная функция)
def get_current_time():
    from datetime import datetime
    return datetime.now().isoformat()

# 2. Описание инструмента для LLM
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_current_time",
            "description": "Возвращает текущее время в ISO формате",
            "parameters": {"type": "object", "properties": {}}
        }
    }
]

# 3. Цикл агента
messages = [{"role": "user", "content": "Сколько сейчас времени?"}]

response = openai.chat.completions.create(
    model="gpt-4o-mini",
    messages=messages,
    tools=tools,
    tool_choice="auto"
)

choice = response.choices[0]
if choice.message.tool_calls:
    # 4. Исполнение инструмента
    tool_call = choice.message.tool_calls[0]
    if tool_call.function.name == "get_current_time":
        result = get_current_time()
        messages.append(choice.message)
        messages.append({
            "role": "tool",
            "tool_call_id": tool_call.id,
            "content": result
        })
        # 5. Финальный ответ
        final = openai.chat.completions.create(
            model="gpt-4o-mini",
            messages=messages
        )
        print(final.choices[0].message.content)
else:
    print(choice.message.content)

Типичные ошибки при сборке

  • Нет валидации tool_call — агент вызывает несуществующий инструмент или с неверными параметрами. Решение: всегда проверять `tool_call.function.name` и `arguments` перед исполнением.
  • Циклические вызовы — агент бесконечно вызывает один и тот же инструмент. Решение: лимитировать число tool-calls в сессии (например, max_steps=5).
  • Утечка контекста — результаты инструментов попадают в публичный лог. Решение: фильтровать `tool_call` и `tool` сообщения перед сохранением.
  • Отсутствие fallback — при ошибке инструмента агент «зависает». Решение: возвращать структурированную ошибку (например, `{"error": "DB_TIMEOUT", "retry_after": 30}`).

Пример: агент-помощник в CRM

Сценарий: пользователь просит «найти клиента по email и показать последнюю сделку».

  • Инструменты: `find_customer(email)`, `get_last_deal(customer_id)`
  • Контекст: инструкция + история диалога + описание инструментов
  • Лог агента:
    [user] "Найди клиента ivan@company.ru и покажи последнюю сделку"
    [agent] → tool_call: find_customer(email="ivan@company.ru")
    [tool] → {"id": "c123", "name": "Иван Петров"}
    [agent] → tool_call: get_last_deal(customer_id="c123")
    [tool] → {"deal": "SaaS Pro", "amount": 15000, "date": "2025-04-10"}
    [agent] → "У клиента Ивана Петрова последняя сделка: SaaS Pro (15 000 ₽, 10 апреля)"

Чеклист перед запуском в прод

  • [ ] Все tool_call обрабатываются в `try/except` с fallback-сообщением
  • [ ] Лимит шагов (max_steps) задан и логируется
  • [ ] Инструменты не возвращают чувствительные данные (пароли, токены)
  • [ ] Аудит: сохраняется `tool_call.id`, `name`, `status`, `duration_ms`
  • [ ] Тесты: есть evals с синтетическими инструментами (mocked)
  • [ ] Human review: для критичных инструментов (например, списание средств) включён ручной апрув

Следующий шаг

После освоения базового tool-calling — переходите к тестированию агента и оркестрации шагов. В реальном проекте вы будете комбинировать tool-calling с памятью, ретраями и fallback-логикой — это создаёт устойчивые агентные системы.