Код-ревью Senior Агенты и вызов инструментов обновлено

Код-ревью: агент аналитики с SQL-инструментом

Вопрос

Агент отвечает менеджерам на вопросы о продажах, выполняя SQL по базе компании. Найдите проблемы в коде цикла агента.

TOOLS = [{
    "name": "run_sql",
    "description": "Выполняет любой SQL",
    "parameters": {"type": "object", "properties": {"query": {"type": "string"}}},
}]

def ask(question, user):
    history = [{"role": "system", "content": f"Ты аналитик. Пользователь: {user.name}, роль {user.role}"},
               {"role": "user", "content": question}]
    while True:
        resp = llm.chat(history, tools=TOOLS)
        if not resp.tool_calls:
            return resp.text
        for call in resp.tool_calls:
            rows = db_admin.execute(call.args["query"])
            history.append({"role": "tool", "content": json.dumps(rows)})

Коротко

Главное: модель получила неограниченные права в базе, и защита держится на промпте. Правильная схема: роль только на чтение с доступом к витринам, ограничения строк по правам пользователя в базе, таймауты и лимиты строк, лимит шагов агента и обработка ошибок с возвратом их модели.

Что должен найти ревьюер

  1. Безопасностьстрока 3
    Универсальный инструмент «любой SQL»: модель может выполнить UPDATE, DELETE или DROP. Нужны узкие инструменты или хотя бы только SELECT по разрешённым представлениям.
  2. Безопасностьстрока 15
    Запросы идут под админским подключением. Нужна отдельная роль только на чтение, с доступом к витринам, а не к сырым таблицам с персональными данными.
  3. Безопасностьстрока 8
    Права пользователя описаны только в промпте. Ограничение по роли (например, менеджер видит только свой регион) должно применяться в базе: row-level security или параметры в коде.
  4. Ошибкастрока 10
    while True без лимита шагов, токенов и времени: агент может зациклиться и тратить деньги бесконечно.
  5. Производительностьстрока 16
    Результат запроса целиком в историю: тысячи строк раздуют контекст и стоимость. Нужен лимит строк и агрегаты.
  6. Ошибкастрока 15
    Нет обработки ошибок SQL и таймаута: исключение уронит весь запрос, а долгий запрос повесит агента. Ошибку надо вернуть модели текстом, запрос ограничить statement_timeout.
  7. Ошибкастрока 16
    Сообщение tool без идентификатора вызова: при нескольких вызовах модель не поймёт, какой результат к какому вызову относится. Большинство API требует tool_call_id.

Разбор

Главное: модель получила неограниченные права в базе, и защита держится на промпте. Правильная схема: роль только на чтение с доступом к витринам, ограничения строк по правам пользователя в базе, таймауты и лимиты строк, лимит шагов агента и обработка ошибок с возвратом их модели. Для типовых вопросов ещё лучше заранее подготовленные параметризованные запросы как отдельные инструменты.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.