Собираем агента целиком и что дальше

Соберём всё пройденное в одного работающего агента и наметим, куда двигаться дальше.

Простой агент = цель + реестр инструментов + модель (здесь — заглушка) + ReAct-цикл с парсером + предохранитель (лимит шагов). Всё это вы уже знаете по отдельности — осталось собрать.

Что собираем

Задача агенту: «Сколько часов в неделе?» Чтобы решить, агент должен сначала узнать число часов в сутках (инструмент-справочник), затем умножить на 7 (калькулятор). Это многошаговая задача с двумя инструментами — то, ради чего и нужен агент.

Собираем компоненты из всего курса:

  • Инструменты (раздел 2): lookup и calc в реестре.
  • Модель (заглушка, раздел 1): ведёт себя по ReAct в зависимости от истории.
  • Парсер и цикл (раздел 3): извлекают действие/финал, крутят цикл.
  • История (раздел 4): память хода решения.
  • Лимит шагов (раздел 3): предохранитель.

Полный агент

import re

# 1) Инструменты (раздел 2)
def calc(expr):
    return str(eval(expr))

def lookup(key):
    kb = {"часов в сутках": "24", "дней в неделе": "7"}
    return kb.get(key.lower().strip(), "не найдено")

TOOLS = {"calc": calc, "lookup": lookup}

# 2) Модель-заглушка в формате ReAct (раздел 1, 3)
def llm(history):
    text = "\n".join(history)
    if "Observation: 24" not in text and "Action: calc" not in text:
        return ("Thought: сначала узнаю, сколько часов в сутках.\n"
                "Action: lookup[часов в сутках]")
    if "Observation: 24" in text and "Action: calc" not in text:
        return ("Thought: в сутках 24 часа, умножу на 7 дней.\n"
                "Action: calc[24 * 7]")
    if "Observation: 168" in text:
        return "Thought: получилось 168.\nFinal Answer: в неделе 168 часов"
    return "Final Answer: не удалось"

# 3) Парсер (раздел 3)
def parse(text):
    f = re.search(r"Final Answer:\s*(.*)", text)
    if f:
        return ("final", f.group(1).strip())
    a = re.search(r"Action:\s*(\w+)\[(.*?)\]", text)
    if a:
        return ("action", a.group(1), a.group(2))
    return ("unknown", text)

# 4) Цикл с лимитом шагов (раздел 3, 4)
def run_agent(question, max_steps=5):
    history = [f"Question: {question}"]
    for step in range(1, max_steps + 1):
        block = llm(history)
        history.append(block)
        print(f"[шаг {step}]")
        for line in block.splitlines():
            print("  " + line)
        kind, *rest = parse(block)
        if kind == "final":
            return rest[0]
        if kind == "action":
            name, arg = rest
            obs = TOOLS.get(name, lambda x: "нет инструмента")(arg)
            history.append(f"Observation: {obs}")
            print(f"  Observation: {obs}")
    return "лимит шагов исчерпан"

answer = run_agent("Сколько часов в неделе?")
print("=== ОТВЕТ АГЕНТА ===")
print(answer)

Вывод:

[шаг 1]
  Thought: сначала узнаю, сколько часов в сутках.
  Action: lookup[часов в сутках]
  Observation: 24
[шаг 2]
  Thought: в сутках 24 часа, умножу на 7 дней.
  Action: calc[24 * 7]
  Observation: 168
[шаг 3]
  Thought: получилось 168.
  Final Answer: в неделе 168 часов
=== ОТВЕТ АГЕНТА ===
в неделе 168 часов

Это полноценный агент в миниатюре: он рассуждает, выбирает инструменты, наблюдает результаты, комбинирует их и сам решает, когда закончить. Замените llm на настоящую модель с тем же форматом промпта — и получите рабочего ReAct-агента. Вся остальная инфраструктура останется неизменной.

Путь от прототипа к продакшну

Чтобы этот прототип стал боевым, добавьте по порядку:

  1. Настоящую модель и function calling вместо ручного парсинга (уроки 6.1–6.2).
  2. Реальные инструменты с обработкой ошибок (раздел 2).
  3. Память: обрезку истории, при нужде — долгосрочную/RAG (раздел 4).
  4. Защиты: гардрейлы, лимиты, человек-в-цикле, песочница (урок 6.3).
  5. Оценку: набор тестовых задач и success rate (урок 6.4).

Что дальше изучать

  • RAG — долгосрочная память и работа с базой знаний для агента.
  • Фреймворки — LangGraph для сложных циклов, CrewAI/AutoGen для команд.
  • Function calling и MCP на практике — надёжное и переносимое подключение инструментов.
  • Свой проект — лучший способ закрепить: возьмите узкую задачу с 2–3 инструментами и доведите агента до рабочего состояния.

Итог

  • Полный простой агент собирается из пройденного: цель, инструменты, модель, ReAct-цикл, лимит шагов.
  • Прототип превращается в продакшн добавлением настоящей модели, реальных инструментов, памяти, защит и оценки.
  • Дальше — RAG, фреймворки, function calling/MCP и собственный проект на узкой задаче.
Проверьте себя
1. Из каких частей собран простой агент в финальном примере?
AТолько модель и промпт
BЦель, реестр инструментов, модель (заглушка), ReAct-цикл с парсером и лимит шагов
CВекторная база и эмбеддинги
DНесколько агентов и оркестратор
2. Что нужно сделать, чтобы прототип-агент стал работать с настоящей моделью?
AПереписать весь цикл и парсер заново
BЗаменить заглушку llm на реальную модель с тем же форматом промпта — остальная инфраструктура не меняется
CУдалить инструменты
DОтказаться от истории
3. Какой шаг разумно сделать первым при переводе прототипа в продакшн?
AСразу собрать мультиагентную систему
BПодключить настоящую модель с function calling и реальные инструменты с обработкой ошибок
CУбрать все лимиты шагов
DОтключить оценку качества
Поддержать проект