Как навести порядок в хаосе микросервисов с помощью Jido

22 May, 2026

Знакомая история: вы начинаете проект на Elixir, радуетесь мощи OTP и легкости создания процессов. Но проходит полгода, и ваш проект превращается в зоопарк из сотен GenServer-ов. У каждого свои форматы сообщений, свои способы обработки ошибок и хитровыдуманные схемы отслеживания дочерних процессов. В какой-то момент вы понимаете, что в пятый раз переписываете один и тот же код для маршрутизации сигналов или управления жизненным циклом агента.

Именно эту проблему пытается решить Jido. Это не просто очередная библиотека, а попытка формализовать паттерн автономных агентов в Elixir, сохранив при этом все преимущества функционального программирования.

Hex.pm Hex Docs CI License Coverage Status

Что такое Jido и зачем оно в Elixir

Название Jido (自動) переводится с японского как «автоматический». По сути, это фреймворк для создания автономных агентов. Если GenServer дает нам примитив для управления состоянием, то Jido накладывает на него структуру.

Главная фишка здесь в разделении чистой логики и побочных эффектов. В Jido агент — это неизменяемая структура данных. Вы вызываете функцию cmd/2, передаете туда текущее состояние и команду, а на выходе получаете обновленного агента и список «директив». Директивы — это просто описание того, что нужно сделать: отправить письмо, запустить другой процесс или сохранить данные. Сама функция cmd/2 остается чистой, что делает тестирование агентов элементарным делом. Вам не нужно запускать процессы и ждать ответов в тестах, достаточно проверить возвращаемую структуру.

Реклама

Как это выглядит на практике

Давайте посмотрим на классический пример с простым счетчиком. Сначала опишем действие (Action):

defmodule MyApp.Actions.Increment do
  use Jido.Action,
    name: "increment",
    schema: [amount: [type: :integer, default: 1]]

  def run(params, context) do
    current = context.state[:count] || 0
    {:ok, %{count: current + params.amount}}
  end
end

Теперь создадим самого агента:

defmodule MyApp.CounterAgent do
  use Jido.Agent,
    name: "counter",
    schema: [count: [type: :integer, default: 0]],
    signal_routes: [{"increment", MyApp.Actions.Increment}]
end

Использование в чистом функциональном стиле выглядит так:

agent = MyApp.CounterAgent.new()
{agent, directives} = MyApp.CounterAgent.cmd(agent, {MyApp.Actions.Increment, %{amount: 5}})
# agent.state.count теперь равен 5

Почему бы не использовать обычный GenServer

Этот вопрос возникает первым. Автор проекта Mike Hostetler приводит наглядное сравнение. В сыром OTP вам приходится каждый раз заново изобретать форму сообщений, мешать бизнес-логику с колбэками GenServer и вручную следить за иерархией процессов.

Jido предлагает стандарт:

  • Сигналы (на базе CloudEvents) вместо произвольных сообщений.
  • Действия (Actions) как переиспользуемые паттерны команд.
  • Директивы вместо разбросанных по коду send или Repo.insert.
  • Встроенная иерархия «родитель-ребенок» для агентов.

Это напоминает переход от голого SQL к полноценной ORM или от манипуляций с DOM к реактивным фреймворкам. Вы теряете в «свободе» делать всё как угодно, но выигрываете в предсказуемости и скорости разработки.

Экосистема и возможности

Jido — это не монолит. Проект разбит на несколько пакетов, которые можно подключать по мере необходимости. Например, jido_ai добавляет интеграцию с LLM, превращая ваших агентов в умных помощников, способных использовать инструменты. jido_signal отвечает за маршрутизацию сообщений, а jido_action позволяет создавать валидируемые и композируемые действия.

Интересна концепция State Operations. Это внутренние операции над состоянием (SetState, DeleteKeys, SetPath), которые применяются внутри cmd/2. Они позволяют глубоко модифицировать состояние агента, не превращая код в мешанину из put_in и update_in.

Для продакшена предусмотрен AgentServer. Это обертка над GenServer, которая умеет исполнять те самые директивы, управлять жизненным циклом и даже восстанавливать агентов после перезагрузки (через механизмы гибернации и «оттаивания» состояния).

Кому стоит попробовать Jido

Если вы пишете простое CRUD-приложение, Jido, скорее всего, будет избыточным. Но проект станет спасением, если вы строите:

  1. Системы со сложными рабочими процессами (Workflows), где много промежуточных состояний.
  2. Многоагентные системы, где сущности должны активно общаться друг с другом.
  3. Приложения, интегрированные с ИИ, где нужно четко контролировать, какие действия разрешено выполнять модели.

Проект еще достаточно молодой (версия 2.0 вышла недавно), но архитектурно он выглядит очень зрелым. Он берет идеи из Elm и Redux и переносит их на благодатную почву Elixir/OTP. Если вам надоело отлаживать гонки состояний в своих процессах, Jido — отличный повод пересмотреть свой подход к архитектуре.

Начать проще всего через установщик Igniter: mix igniter.install jido. Он сам создаст нужные модули и пропишет их в дерево супервизии, так что можно будет сразу перейти к экспериментам.