Чат-бот · ИИ-агент · Python · API 5 ноября 2026 · 10 мин чтения · Команда IRI

Как создать чат-бота и ИИ-агента
рабочий код и цена

Чат-бот и агент с инструментами на Python: запущенный код, настоящий вывод, токены и цена, частые ошибки и как не навредить агентом.

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

Честная оговорка: код шёл через OpenAI-совместимый API-агрегатор на моделях GPT-6 Luna и DeepSeek V4.1 Flash, а не через IRI Gateway. Адрес Gateway ниже взят из документации, на его ключе мы этот код не запускали.

Чем чат-бот отличается от агента

Чат-ботИИ-агент
Что делаетОтвечает текстомВызывает ваши функции и отвечает по их результату
Запросов к модели на одну просьбуОдинНесколько, в нашем примере 2–3
Главный рискНеверный ответНеверное действие
Когда братьВопросы по правилам и документамНужно что-то узнать в системе или сделать

Начинайте с чат-бота и переходите к агенту, только когда боту нужны действия. Если ответы должны опираться на большой набор документов, посмотрите, какой слой нужен для RAG и агентов.

Что нужно заранее

  • Python 3 и библиотека: pip install openai. Мы запускали с версией 2.29.0.
  • API-ключ. Для Gateway его выпускают в кабинете, шаги — на странице начала работы.
  • Адрес и ключ в переменных окружения, а не в коде:
# Linux и macOS
export API_KEY="ваш_ключ"
export API_BASE="https://api-ru.agi-iri.ru/v1/"

# Windows PowerShell
$env:API_KEY="ваш_ключ"
$env:API_BASE="https://api-ru.agi-iri.ru/v1/"

Если вы раньше не работали с такими API, начните со статьи об OpenAI-совместимом API.

Шаг 1. Чат-бот на Python

Сохраните как bot.py. Инструкция в начале задаёт правила, а история отправляется с каждым запросом: так бот помнит разговор.

import os
from openai import OpenAI

client = OpenAI(api_key=os.environ["API_KEY"], base_url=os.environ["API_BASE"])
MODEL = os.environ.get("MODEL", "gpt-6-luna")

messages = [{
    "role": "system",
    "content": "Ты помощник интернет-магазина. Доставка 3 дня, возврат 14 дней. "
               "Если ответа нет в этих правилах, скажи, что передашь вопрос менеджеру.",
}]

while True:
    question = input("Вы: ").strip()
    if not question:
        break
    messages.append({"role": "user", "content": question})
    messages = messages[:1] + messages[-20:]  # система и последние 20 реплик
    reply = client.chat.completions.create(model=MODEL, messages=messages)
    text = reply.choices[0].message.content
    messages.append({"role": "assistant", "content": text})
    print("Бот:", text)
    print("Токены:", reply.usage.prompt_tokens, "+", reply.usage.completion_tokens)

Запуск: python bot.py. Вот настоящий разговор на GPT-6 Luna:

Вы: Сколько идёт доставка?
Бот: Доставка занимает 3 дня.
Токены: 113 + 11
Вы: А можно вернуть товар через месяц?
Бот: По правилам магазина возврат возможен в течение 14 дней, поэтому через месяц оформить его нельзя.
Токены: 174 + 25
Вы: Какая погода на Марсе?
Бот: Я передам ваш вопрос менеджеру.
Токены: 250 + 12

Обратите внимание на вход: 113, затем 174, затем 250 токенов. Это история разговора, и она растёт с каждой репликой. Поэтому код оставляет только последние 20 реплик. DeepSeek V4.1 Flash ответил так же по существу, с 98, 156 и 237 токенами на входе.

Шаг 2. Как создать ИИ-агента с инструментами

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

import json
import os
import sys
from openai import OpenAI

client = OpenAI(api_key=os.environ["API_KEY"], base_url=os.environ["API_BASE"])
MODEL = os.environ.get("MODEL", "gpt-6-luna")
MAX_STEPS = 8

ORDERS = {"1001": {"status": "в пути", "days_left": 2}, "1002": {"status": "доставлен", "days_left": 0}}
TICKETS = []


def get_order(order_id):
    return ORDERS.get(order_id, {"error": "заказ не найден"})


def create_ticket(order_id, text):
    TICKETS.append({"order_id": order_id, "text": text})
    return {"ticket": len(TICKETS)}


FUNCTIONS = {"get_order": get_order, "create_ticket": create_ticket}
TOOLS = [
    {"type": "function", "function": {
        "name": "get_order", "description": "Узнать статус заказа по номеру",
        "parameters": {"type": "object", "properties": {"order_id": {"type": "string"}}, "required": ["order_id"]},
    }},
    {"type": "function", "function": {
        "name": "create_ticket", "description": "Создать обращение менеджеру",
        "parameters": {"type": "object", "properties": {"order_id": {"type": "string"}, "text": {"type": "string"}}, "required": ["order_id", "text"]},
    }},
]


def run(task):
    messages = [
        {"role": "system", "content": "Ты агент поддержки. Сначала узнай статус заказа инструментом. Не выдумывай данные. Обращение создавай, только если об этом просят."},
        {"role": "user", "content": task},
    ]
    spent = [0, 0]
    for step in range(1, MAX_STEPS + 1):
        reply = client.chat.completions.create(model=MODEL, messages=messages, tools=TOOLS)
        spent[0] += reply.usage.prompt_tokens
        spent[1] += reply.usage.completion_tokens
        message = reply.choices[0].message
        messages.append(message)
        if not message.tool_calls:
            return message.content, step, spent
        for call in message.tool_calls:
            args = json.loads(call.function.arguments)
            result = FUNCTIONS[call.function.name](**args)
            print("Шаг", step, call.function.name, args, "->", result)
            messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps(result, ensure_ascii=False)})
    return "Остановлено: превышен лимит шагов", MAX_STEPS, spent


answer, steps, spent = run(sys.argv[1])
print("Ответ:", answer)
print("Шагов:", steps, "токены:", spent[0], "+", spent[1], "обращения:", TICKETS)

Настоящий запуск на GPT-6 Luna, три разные просьбы:

$ python agent.py "Где мой заказ 1001?"
Шаг 1 get_order {'order_id': '1001'} -> {'status': 'в пути', 'days_left': 2}
Ответ: Заказ **1001** в пути. Ожидается через **2 дня**.
Шагов: 2 токены: 323 + 55 обращения: []

$ python agent.py "Заказ 1002 пришёл разбитым, создайте обращение менеджеру"
Шаг 1 get_order {'order_id': '1002'} -> {'status': 'доставлен', 'days_left': 0}
Шаг 2 create_ticket {'order_id': '1002', 'text': 'Заказ пришёл разбитым. Просьба рассмотреть ситуацию и помочь с решением.'} -> {'ticket': 1}
Ответ: По заказу №1002 статус: **доставлен**. Обращение менеджеру создано, номер обращения: **1**.
Шагов: 3 токены: 596 + 157 обращения: [{'order_id': '1002', 'text': 'Заказ пришёл разбитым. Просьба рассмотреть ситуацию и помочь с решением.'}]

$ python agent.py "Где заказ 9999?"
Шаг 1 get_order {'order_id': '9999'} -> {'error': 'заказ не найден'}
Ответ: Заказ **9999** не найден. Проверьте номер заказа — возможно, в нём есть ошибка.
Шагов: 2 токены: 316 + 58 обращения: []

Все три просьбы агент выполнил как задумано: создал обращение только там, где о нём просили, и не выдумал несуществующий заказ. DeepSeek V4.1 Flash прошёл те же три случая. Это маленькая проверка, а не гарантия поведения в настоящей работе.

Важная оговорка про Luna. В документации OpenAI написано, что в Chat Completions функции у этой модели работают только с reasoning_effort="none", а для инструментов рекомендован Responses API. У нас код сработал без этого параметра, но мы запускали его не напрямую у OpenAI и не через Gateway. На части маршрутов Gateway сам отключает рассуждения для такого запроса, на остальных это не проверено. Если на вашем маршруте запрос с инструментами вернёт ошибку, передайте этот параметр или возьмите другую модель.

Как не навредить агентом

  • Ограничьте шаги. В примере MAX_STEPS = 8: иначе ошибка в логике может гонять запросы и тратить деньги.
  • Разделите чтение и действия. Узнать статус безопасно, а вернуть деньги или удалить запись должен подтверждать человек.
  • Проверяйте аргументы в своём коде. Модель может передать неожиданное значение. В настоящем продукте добавьте проверку прав и обработку ошибок вокруг json.loads и вызова функции: в примере их нет ради краткости.
  • Не доверяйте тексту из внешних источников. Письмо или страница могут содержать чужие указания для модели, поэтому такие данные не должны открывать опасные действия.
  • Пишите журнал. Сохраняйте каждый вызов и результат: без этого ошибку агента не разобрать.

Сколько это стоит

Это настоящие токены из запусков выше и текущие цены Gateway. На DeepSeek просьба с обращением заняла 722 + 229 токенов. Сам код на Gateway мы не запускали, поэтому считайте это оценкой.

ЗапросМодель и токены1 000 таких запросов
Вопрос в чат-бот, третья репликаLuna, 250 + 122,21 ₽
Агент: статус заказаLuna, 323 + 553,53 ₽
Агент: статус и обращениеLuna, 596 + 1577,48 ₽
Агент: статус и обращениеDeepSeek, 722 + 22910,43 ₽

Цены Gateway указаны для API-ключа из кабинета на 13 ноября 2026 года. У старых ключей и тарифов цена может отличаться, актуальная — в таблице цен.

В настоящем продукте инструкция, история и данные намного больше, поэтому счёт будет выше. Посчитать свой случай можно в калькуляторе стоимости ИИ-продукта. Выбрать модель помогут каталог и разборы GPT-6.1 Sol и Claude Sonnet 5.5.

Частые ошибки и как их исправить

Что видитеПричинаЧто сделать
401, ключ не принятКлюч неверный или удалёнПроверьте ключ в кабинете и переменную API_KEY
402На балансе нет средствПополните баланс или возьмите бесплатный уровень: MODEL=iri-zero
400 или 403, модель неизвестна или недоступна ключуНеверное имя модели или нет доступаСверьте имя с каталогом
429Превышен лимит ключаПовторите с паузой или поднимите лимит в кабинете
Бот выдумывает ответыНет правила, что делать при незнанииНапишите в инструкции, куда передавать такие вопросы, и проверьте на вопросах вне темы
Счёт растёт с длиной разговораВся история уходит с каждым запросомОграничьте историю, как в примере

Коды ошибок Gateway перечислены в документации. Повторять имеет смысл запросы с кодами 429 и 503, остальные нужно исправлять.

Как проверить результат

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

Что делать дальше

  1. Соберите 20–30 настоящих вопросов и ожидаемых ответов.
  2. Прогоняйте их после каждого изменения инструкции и при смене модели.
  3. Запишите токены за неделю и посчитайте бюджет.
  4. Только потом выпускайте бота к людям, начиная с малой доли обращений.

Если своей команды нет, подрядчика можно поискать в каталоге компаний.

Частые вопросы

Можно ли создать чат-бота бесплатно?

Да, для проверки подойдёт бесплатная модель Gateway, но при исчерпании её ёмкости запросы будут отклоняться. Мы запускали пример на платных моделях, поэтому на бесплатной проверьте его сами, особенно вызов инструментов.

Нужно ли уметь программировать?

Для примеров из статьи нужны основы Python. Без кода простого бота собирают на конструкторе, цены — в расчёте стоимости.

Какую модель взять для начала?

Начните с недорогой, на которой пример работает, и проверьте её на своих вопросах. На более дорогую переходите, когда видите конкретные ошибки.

Как подключить бота к Telegram или сайту?

Замените input() и print() на получение и отправку сообщений канала, а историю храните отдельно для каждого пользователя. Логика запроса к модели остаётся той же. Этот шаг мы здесь не запускали.

Чем агент опаснее бота?

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

Подключить LLM API для команды?

Запросите счёт на р/с: после оплаты — ключ, баланс и каталог моделей в одном endpoint.

Чат-ботИИ-агентPythonAPI