В конце 2023 года один мой знакомый написал скрипт. Простой Python, 80 строк. Скрипт каждое утро заходил на три сайта с вакансиями, собирал позиции под его профиль, сравнивал с его резюме и присылал в Telegram список с пометками: «хорошо подходишь», «нужно подтянуть вот это», «не трать время».

Как создать AI-агента: пошаговое руководство - 1

Через месяц он получил оффер. Сам скрипт отработал 29 дней и нашёл ту самую вакансию, которую он вряд ли бы заметил вручную.

Я тогда подумал: вот это агент. Не в смысле шпион. В смысле — программа, которая действует сама, по цепочке, с инструментами в руках. Без того, чтобы ты сидел рядом и нажимал кнопки.

С тех пор AI-агенты из лабораторной экзотики превратились в рабочий инструмент. Cursor пишет код за тебя. Devin закрывает задачи в GitHub. Компании строят на агентах целые продукты — и нанимают людей, которые умеют их создавать.

В этой статье разберём, как агент устроен изнутри, и напишем своего с нуля. Рабочий код, понятные объяснения. И в конце — кое-что важное про то, почему большинство первых агентов ломаются в самый неподходящий момент.

Чат-бот и AI-агент: в чём разница

Сначала о терминологии, потому что путаница тут постоянная — и она реально мешает понять, что строить.

Представь: тебе нужно найти три вакансии Python-разработчика, проверить каждую на соответствие твоим навыкам и написать под каждую отдельное сопроводительное письмо.

Ты открываешь ChatGPT и пишешь: «Найди три вакансии Python-разработчика в Берлине». Он скажет, что не имеет доступа в интернет. Или, что хуже, что-то придумает. Ты идёшь на сайт, копируешь вакансию, вставляешь обратно в чат, просишь письмо. Потом снова. Потом снова. Ты — оператор при чат-боте.

Чат-бот знает и отвечает. Агент получает задачу — и делает.

AI-агент с теми же инструментами сам зайдёт на сайты с вакансиями, найдёт подходящие, проанализирует их и напишет три письма. Ты в это время пьёшь кофе.

Разница не в умности модели. Разница в архитектуре.

Чат-ботAI-агент
Что получаетВопросЗадачу
Что возвращаетОтветРезультат действий
ИнструментыНетПоиск, код, файлы, API — всё что напишешь
ПамятьТолько текущий диалогМожет накапливать между сессиями
Следующий шагДелает пользовательРешает сам агент
Пример«Объясни что такое Docker»«Найди три вакансии DevOps, проверь требования, составь план подготовки»

Из чего состоит агент: четыре блока

Любой AI-агент — и простой скрипт на 100 строк, и сложная корпоративная система — собирается из одних и тех же частей. Представь менеджера проекта в маленькой команде: это поможет.

LLM — мозг. GPT-4o, Claude, Gemini — не принципиально. Это менеджер: он не копает сам, но знает, кому позвонить и что попросить. Модель не умеет запускать код или ходить в интернет — она умеет только рассуждать и давать инструкции. Всю «магию» делает архитектура вокруг неё.

Tools — руки. Инструменты — это функции, которые ты пишешь сам. Поиск в интернете, запуск кода, чтение файлов, отправка письма — это подрядчики менеджера: каждый умеет одно, но делает хорошо. LLM не вызывает их напрямую — он говорит «хочу вызвать функцию X с аргументом Y», твой код это читает и вызывает.

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

Петля — оркестратор. Главный цикл: получили задачу → спросили LLM → LLM сказал вызвать инструмент → вызвали → результат отдали обратно → LLM решил что дальше. Повторяется, пока задача не выполнена.

Всё. Больше ничего нет. Из этих четырёх блоков строится и скрипт на 80 строк, который нашёл моему знакомому работу, и Devin.

Пишем агента: рабочий код

Берём Python — самый доступный язык для этой задачи. Одна библиотека:

pip install openai

API-ключ OpenAI — на platform.openai.com. Есть стартовый кредит.

Наш агент умеет две вещи: искать информацию и считать. Это звучит скромно — но именно из таких примитивов строятся серьёзные системы.

Шаг 1. Описываем инструменты

Инструменты передаются модели как JSON-схемы. LLM читает описания и понимает, что умеет делать. Обрати внимание на поле description — это не комментарий для тебя, это инструкция для модели. Чем точнее опишешь — тем умнее будет выбор инструмента.

from openai import OpenAI
import json

client = OpenAI(api_key="YOUR_API_KEY")

tools = [
    {
        "type": "function",
        "function": {
            "name": "search_web",
            "description": "Ищет актуальную информацию в интернете. Используй когда нужны свежие данные, которых может не быть в обучающей выборке.",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {
                        "type": "string",
                        "description": "Поисковый запрос на русском или английском"
                    }
                },
                "required": ["query"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "calculate",
            "description": "Вычисляет математическое выражение. Используй для точных расчётов — LLM плохо считает в уме.",
            "parameters": {
                "type": "object",
                "properties": {
                    "expression": {
                        "type": "string",
                        "description": "Математическое выражение, например: '112000 * 1.3'"
                    }
                },
                "required": ["expression"]
            }
        }
    }
]

Шаг 2. Пишем функции-инструменты

def search_web(query: str) -> str:
    # В реальном агенте здесь — запрос к Tavily API или SerpAPI.
    # Для примера — заглушка с реальными данными.
    results = {
        "python developer salary 2026": "Медианная зарплата Python-разработчика в США — $112 000. Диапазон $98k–$188k.",
        "go developer salary": "Go-разработчики в США зарабатывают $120k–$175k. Высокий спрос в cloud и DevOps.",
    }
    for key in results:
        if key.lower() in query.lower():
            return results[key]
    return f"По запросу '{query}': данные получены, информация актуальна на 2026 год."


def calculate(expression: str) -> str:
    try:
        # В продакшне используй ast.literal_eval или библиотеку numexpr
        result = eval(expression)
        return f"Результат вычисления {expression} = {result}"
    except Exception as e:
        return f"Ошибка: {e}"

Шаг 3. Петля агента

Вот сердце всего — цикл, который превращает скрипт в агента:

def run_agent(user_task: str):
    print(f"\n Задача: {user_task}")
    print("─" * 50)

    messages = [
        {
            "role": "system",
            "content": (
                "Ты полезный AI-агент. У тебя есть инструменты: поиск и калькулятор. "
                "Используй поиск для актуальных данных. Используй калькулятор для точных вычислений. "
                "Отвечай только после того, как получил все нужные данные."
            )
        },
        {"role": "user", "content": user_task}
    ]

    step = 1

    while True:
        response = client.chat.completions.create(
            model="gpt-4o",
            messages=messages,
            tools=tools,
            tool_choice="auto"  # LLM сам решает: вызвать инструмент или ответить
        )

        message = response.choices[0].message

        # LLM хочет вызвать инструмент
        if message.tool_calls:
            messages.append(message)

            for tool_call in message.tool_calls:
                fn_name = tool_call.function.name
                fn_args = json.loads(tool_call.function.arguments)

                print(f"\n  Шаг {step}: вызываю {fn_name}")
                print(f"   Аргументы: {fn_args}")

                if fn_name == "search_web":
                    result = search_web(**fn_args)
                elif fn_name == "calculate":
                    result = calculate(**fn_args)
                else:
                    result = f"Инструмент '{fn_name}' не найден"

                print(f"   Результат: {result}")
                step += 1

                # Возвращаем результат обратно в LLM
                messages.append({
                    "role": "tool",
                    "tool_call_id": tool_call.id,
                    "content": result
                })

        # LLM готов дать финальный ответ
        else:
            print(f"\n Ответ агента:\n{message.content}")
            return message.content


# Запускаем
run_agent("Сколько в год будет стоить нанять Python-разработчика, если платить медианную зарплату с учётом всех налогов?")

Что происходит при запуске

Задача: Сколько в год будет стоить нанять Python-разработчика?
──────────────────────────────────────────────────

  Шаг 1: вызываю search_web
   Аргументы: {'query': 'python developer salary 2026'}
   Результат: Медианная зарплата Python-разработчика — $112 000.

  Шаг 2: вызываю calculate
   Аргументы: {'expression': '112000 * 1.3'}
   Результат: Результат вычисления 112000 * 1.3 = 145600.0

 Ответ агента:
Медианная зарплата Python-разработчика в США — $112 000 в год.
С учётом налогов и взносов (~30%) реальная стоимость для
работодателя составит около $145 600 в год.

Агент сам решил: сначала нужны данные — поиск. Потом нужно посчитать — калькулятор. Мы не говорили ему делать именно это. Он решил самостоятельно.

Вот за это люди и восхищаются агентами. Не за то, что они умные — за то, что они действуют.

Почему это работает: механика function calling

Самый частый вопрос после первого запуска: «Подожди, а как LLM вообще вызывает функцию? Он что, запускает Python?»

Нет. Вот что происходит на самом деле.

Когда модель решает, что нужен инструмент, она возвращает не текст, а структурированный JSON:

{
  "name": "search_web",
  "arguments": "{\"query\": \"python developer salary 2026\"}"
}

Твой код читает этот JSON, вызывает нужную Python-функцию, берёт результат и отправляет обратно в модель как новое сообщение. Модель продолжает думать уже с этой информацией.

LLM не знает, как работает поиск. Он знает только описание инструмента — и решает, нужен ли он в данной ситуации.

Это принципиально важно понять: ты контролируешь инструменты, LLM контролирует логику. Хочешь научить агента отправлять письма — напиши функцию send_email и добавь её в список. Хочешь, чтобы агент мог работать с базой данных — напиши query_database. Возможности ограничены только тем, что умеет Python.

Частые грабли — читай до того, как запустишь

Это самый важный раздел статьи. Все ошибки ниже — классические, каждый первый на них наступает. Лучше наступить сейчас, читая текст, чем в два часа ночи, глядя в консоль.

Бесконечная петля. Если инструмент постоянно возвращает мусор или ошибку, агент будет вызывать его снова и снова — и тратить деньги на каждый запрос к API. Добавь лимит шагов прямо в петлю:

if step > 10:
    print("Достигнут лимит шагов")
    break

Это не хак, это обязательная защита.

Галлюцинации аргументов. LLM может передать в функцию аргумент не того типа или с опечаткой. Функция calculate получит строку «сто двадцать» вместо «120» и упадёт. Всегда валидируй входные данные и оборачивай функции в try/except.

Нет tool_call_id. Когда возвращаешь результат инструмента, tool_call_id обязателен — иначе модель не поймёт, ответ на какой именно вызов ты вернул. Это самая частая ошибка у новичков, она не бросается в глаза в трейсбеке, и дебажить её неприятно.

Дорогие петли. Каждый шаг — это запрос к API, а каждый запрос стоит денег. Агент, который делает 30 шагов ради простой задачи — это дыра в бюджете. Чем точнее и конкретнее description у инструмента, тем реже модель вызывает лишнее.

Плохой system prompt. Агент — это не просто код, это ещё и инструкция в system. Если написать «ты полезный ассистент» — получишь непредсказуемое поведение. Пиши конкретно: что агент должен делать, когда использовать каждый инструмент, в каком формате отвечать.

Куда расти дальше

Базовый агент готов. Это не игрушка — это рабочая архитектура, от которой строятся серьёзные продукты.

Реальные инструменты. Замени заглушку поиска на Tavily API или SerpAPI — буквально 10 строк кода. Добавь send_email, read_file, query_database. Тот самый скрипт из начала статьи — это агент с инструментом поиска вакансий и инструментом сравнения с резюме. 80 строк, нашёл работу.

Долгосрочная память. Сейчас агент забывает всё между запусками — как Гай Пирс в «Помни». Добавь векторную базу (Chroma, Pinecone) — и агент начнёт накапливать контекст, помнить прошлые разговоры, становиться полезнее со временем.

Несколько агентов. Один агент-оркестратор делегирует задачи специализированным: один ищет, другой анализирует, третий пишет отчёты. Именно так устроены Devin, AutoGPT и серьёзные корпоративные AI-продукты. Архитектура — та же самая, просто масштаб больше.

Сложность растёт линейно. Принципы — не меняются.

Часто задаваемые вопросы

Что такое AI-агент простыми словами?

AI-агент — это программа, которая получает задачу и выполняет её самостоятельно, шаг за шагом, используя инструменты: поиск, запуск кода, работу с файлами и API. В отличие от чат-бота, который просто отвечает на вопросы, агент действует и возвращает результат, а не текст.

Чем AI-агент отличается от ChatGPT?

ChatGPT — это чат-бот: он отвечает на вопросы в рамках диалога. AI-агент построен поверх таких же языковых моделей (GPT-4o, Claude и др.), но дополнен инструментами и петлёй выполнения задач. ChatGPT не может сам зайти на сайт, запустить код или отправить письмо — агент может.

На каком языке лучше писать AI-агентов?

Python — стандарт де-факто. Библиотека openai, фреймворки LangChain и LlamaIndex, инструменты для работы с векторными базами (Chroma, Pinecone) — всё это нативно под Python. Для продакшн-систем с высокой нагрузкой используют Go или TypeScript, но для старта и прототипов Python — очевидный выбор.

Что такое function calling в OpenAI API?

Механизм, который позволяет LLM «вызывать» внешние функции. На самом деле модель не запускает код — она возвращает структурированный JSON с названием функции и аргументами. Твой код читает этот JSON, вызывает нужную функцию и возвращает результат обратно в модель. Именно на этом механизме строятся все AI-агенты с инструментами.

Сколько стоит запустить AI-агента через OpenAI API?

Зависит от модели и количества шагов. GPT-4o: ~$2.50 за 1 млн входящих токенов, ~$10 за 1 млн исходящих. Простой агент на 3–5 шагов обходится в доли цента за запрос. Дорого становится только при плохо написанных петлях, которые делают десятки лишних вызовов — именно поэтому важно ставить лимит шагов.

Какие фреймворки используют для создания AI-агентов?

Самые популярные: LangChain (универсальный, большая экосистема), LlamaIndex (фокус на работе с данными и RAG), AutoGen от Microsoft (мультиагентные системы), CrewAI (агенты с ролями). Для простых задач фреймворк не нужен — достаточно openai SDK, как в этой статье.

Хочешь разобраться в Python глубже — написать не только агентов, но и нормальный бэкенд, работать с API и базами данных, понять всё, что у агентов под капотом — на JavaRush есть курс по Python: практика с первого дня, тысячи задач, попробовать можно бесплатно.

javarush.com/courses/python