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

Через месяц он получил оффер. Сам скрипт отработал 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 openaiAPI-ключ 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: практика с первого дня, тысячи задач, попробовать можно бесплатно.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ