Гайд · TNWS AI

Как связать шаги CrewAI Flow через @start и @listen

4 мин—

Детерминированный CrewAI Flow из двух шагов: @start, @listen, передача результата, точный ожидаемый вывод и тест порядка выполнения.

Задача и применимость

Актуальный поисковый запрос: «как связать шаги CrewAI Flow start listen». Создать прозрачный двухшаговый workflow без вызова LLM: старт возвращает учебный код, listener превращает его в готовое сообщение. В CrewAI Flow @start() обозначает точку входа, а @listen(method) запускает зависимый метод после события и передаёт его результат. Это удобнее автономного агента, когда маршрут заранее известен и должен быть аудируемым. Материал сверён 26 сентября 2026 года с официальной документацией CrewAI 1.15.22. Примеры предназначены для Python 3.10+; закрепите версию пакета, потому что сигнатуры и поведение развиваются. Все коды, статусы и даты в примерах вымышлены.

Пошаговая настройка

  1. Унаследуйте класс от Flow.
  2. Пометьте первый метод @start() и верните детерминированное значение.
  3. Пометьте второй @listen(first_method) и примите результат аргументом.
  4. Вызовите kickoff и проверьте порядок событий и финальную строку.

Перед запуском установите CrewAI по официальной инструкции. Для примеров с агентом задайте CREWAI_MODEL и учётные данные провайдера через переменные среды; доступность модели зависит от вашего аккаунта. Flow-примеры не требуют LLM и должны сначала проходить как детерминированные тесты. Не включайте действующие ключи и реальные клиентские данные в исходник или prompt.

Готовый шаблон

from crewai.flow.flow import Flow, listen, start

class StatusFlow(Flow):
    @start()
    def load_code(self):
        return "R-7"

    @listen(load_code)
    def format_status(self, code):
        message = f"Статус {code}: готово"
        print(message)
        return message

flow = StatusFlow()
result = flow.kickoff()
assert result == "Статус R-7: готово"

Конкретный вход и ожидаемый результат

Стартовый шаг возвращает R-7; listener получает именно эту строку. Ожидаемый результат kickoff — «Статус R-7: готово». Здесь слово «готово» является частью вымышленного теста, а не получено из внешней системы. В рабочем процессе статус должен приходить из проверенного API на отдельном шаге.

Как фактически проверить

Добавьте список событий и записывайте имя метода при входе. Ожидаемый порядок: load_code, затем format_status. Замените возврат старта на A-204 и убедитесь, что listener не содержит захардкоженный R-7. Если маршрут полностью предсказуем, не добавляйте агента ради генерации той же шаблонной строки.

Проверяйте не только итоговую строку, но и путь исполнения: входные данные, вызванный метод или Task, промежуточный результат и финальное преобразование. Успешный Python-процесс не доказывает правильность фактов LLM. Для агентных сценариев сделайте не менее трёх прогонов фиксированной модели и укажите долю прохождения критериев, а не выбирайте лучший ответ вручную.

Критерии приёмки

  1. Python-код проходит синтаксическую проверку, а зависимости и версия зафиксированы.
  2. Положительный пример даёт заранее описанный результат без новых фактов.
  3. Отрицательный пример завершается явным отказом либо контролируемой веткой.
  4. Ни один шаг не получает больше данных или полномочий, чем требуется задаче.
  5. После обновления CrewAI или модели тот же набор выполняется повторно.

Протокол воспроизводимости

Сохраните дату, версию CrewAI, версию Python, идентификатор модели для agent-примеров и обезличенный вход. Для Flow зафиксируйте порядок событий и финальный state; для Task — TaskOutput, число попыток и результат guardrail. Не записывайте секреты, системные prompts и персональные данные без необходимости. Если ошибка плавающая, классифицируйте её как неверный маршрут, неверный аргумент, исключение Python или неподтверждённую генерацию — эти случаи исправляются по-разному.

Регрессионный набор

Не ограничивайтесь одним удачным примером. Добавьте стандартный вход, отсутствующее обязательное поле, похожий идентификатор, пустую строку и слишком длинное значение. Для каждого заранее укажите ожидаемое событие, состояние и финальный результат. В агентных задачах отдельно оценивайте правильность фактов и соблюдение формата; красивый текст не компенсирует неверный код. В Flow проверяйте, какой метод действительно вызван и сколько раз: одинаковая финальная строка может скрыть ошибочный маршрут. При изменении модели не переносите прежние показатели автоматически. При изменении схемы state предусмотрите миграцию сохранённых записей. Ошибка одного теста должна блокировать автоматическое внешнее действие, но не обязана останавливать независимые процессы системы. После исправления обязательно повторите весь набор, а не только упавший случай. Такой набор превращает статью в повторяемую инструкцию, а не в демонстрацию единственного счастливого пути.

Типичные ошибки и чего не делать

  • Не ставьте @start и @listen на один метод.
  • Не обращайтесь к случайной глобальной переменной вместо результата события.
  • Не добавляйте LLM в детерминированное форматирование без причины.

Не увеличивайте retries, max_iter или таймаут после каждой ошибки автоматически. Ограничение останавливает цикл, но не исправляет отсутствующий факт или плохую схему. Не выполняйте платежи, удаление, публикацию и другие необратимые действия только на основании текста модели. Добавляйте детерминированную проверку и, где требуется, человеческое подтверждение.

FAQ

Что запускается первым?

Метод с @start().

Как listener получает результат?

Через аргумент метода, вызванного после источника события.

Нужен ли LLM?

Нет, Flow может состоять из обычных детерминированных методов.

Официальные источники

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

Что запускается первым?

Метод с @start().

Как listener получает результат?

Через аргумент метода, вызванного после источника события.

Нужен ли LLM?

Нет, Flow может состоять из обычных детерминированных методов.

Читайте также

Комментарии

Пока тихо. Скажите первое слово