Jido

Hex.pmHex DocsCILicenseWebsiteEcosystemDiscord

Jido is an autonomous agent framework for Elixir, built for workflows and multi-agent systems.

Define agents, connect them to actions, signals, and directives, and run them with supervision and fault tolerance built in.

The name "Jido" (自動) comes from the Japanese word meaning "automatic" or "automated", where 自 (ji) means "self" and 動 (dō) means "movement".

Learn more about Jido at jido.run.

Overview

Jido helps you build agent systems as ordinary Elixir and OTP software.

The purity boundary is the agent's decision logic: Jido keeps agent decisions and state transitions explicit, actions may be pure or effectful, and directives are for effects you want the runtime to own.

Use Jido when software needs to inspect context, choose among multiple steps, coordinate with other agents, and keep running reliably over time.

AI is optional. The core package gives you the agent architecture and runtime; companion packages such as jido_ai add model integration when you need it.

At the core, Jido agents are immutable data structures with a single command function:

defmodule MyAgent do
use Jido.Agent,
name: "my_agent",
description: "My custom agent",
schema: [
count: [type: :integer, default: 0]
]
end
{agent, directives} = MyAgent.cmd(agent, action)

State changes are explicit data transformations. If an action needs a result back immediately to continue reasoning or update state, it may perform that work itself. If the workflow has already decided on an outbound effect and wants the runtime or integration layer to own delivery, return a directive.

The Jido Ecosystem

Jido is the core package of the Jido ecosystem. The ecosystem is built around the core Jido Agent behavior and offer several opt-in packages to extend the core behavior.

PackageDescription
req_llmHTTP client for LLM APIs
jido_actionComposable, validated actions with AI tool integration
jido_signalCloudEvents-based message envelope and supporting utilities for routing and pub/sub messaging
jidoCore agent framework with state management, directives, and runtime
jido_aiAI/LLM integration for agents

For demos and examples of what you can build with the Jido Ecosystem, see https://jido.run. For the package map and support levels, see https://jido.run/ecosystem.

Why Jido?

OTP primitives are excellent. You can build agent systems with raw GenServer. But when building multiple cooperating agents, you'll reinvent:

Raw OTPJido Formalizes
Ad-hoc message shapes per GenServerSignals as standard envelope
Business logic mixed in callbacksActions as reusable command pattern
Implicit effects scattered in codeDirectives as typed effect descriptions
Custom child tracking per serverBuilt-in parent/child hierarchy
Process exit = completionState-based completion semantics

Jido isn't "better GenServer" - it's a formalized agent pattern built on GenServer.

Key Features

Immutable Agent Architecture

Directive-Based Effects

OTP Runtime Integration

Composable Plugins

Execution Strategies

Multi-Agent Orchestration

Installation

The fastest way to get started is with Igniter:

mix igniter.install jido

This automatically:

Generate an example agent to get started:

mix igniter.install jido --example

Manual Installation

Add jido to your list of dependencies in mix.exs:

def deps do
[
{:jido, "~> 2.0"}
]
end

Then define a Jido instance module and add it to your supervision tree:

# In lib/my_app/jido.ex
defmodule MyApp.Jido do
use Jido, otp_app: :my_app
end
# In config/config.exs
config :my_app, MyApp.Jido,
max_tasks: 1000,
agent_pools: []
# In your application.ex
children = [
MyApp.Jido
]
Supervisor.start_link(children, strategy: :one_for_one)

Quick Start

1. Define an Agent

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

2. Define an Action

defmodule MyApp.Actions.Increment do
use Jido.Action,
name: "increment",
description: "Increments the counter by a given amount",
schema: [
amount: [type: :integer, default: 1]
]
def run(params, context) do
current = context.state[:count] || 0
{:ok, %{count: current + params.amount}}
end
end

3. Execute Commands

# Create an agent
agent = MyApp.CounterAgent.new()
# Execute an action - returns updated agent + directives
{agent, directives} = MyApp.CounterAgent.cmd(agent, {MyApp.Actions.Increment, %{amount: 5}})
# Check the state
agent.state.count
# => 5

4. Run with AgentServer

# Start the agent server
{:ok, pid} = MyApp.Jido.start_agent(MyApp.CounterAgent, id: "counter-1")
# Send signals to the running agent (synchronous)
# Signal types must be declared in signal_routes
{:ok, agent} = Jido.AgentServer.call(pid, Jido.Signal.new!("increment", %{amount: 10}, source: "/user"))
# Look up the agent by ID
pid = MyApp.Jido.whereis("counter-1")
# List all running agents
agents = MyApp.Jido.list_agents()

Core Concepts

The cmd/2 Contract

The fundamental operation in Jido:

{agent, directives} = MyAgent.cmd(agent, action)

Key invariants:

Use this rule of thumb for side effects:

Actions vs Directives vs State Operations

ActionsDirectivesState Operations
Transform state, may perform side effectsDescribe runtime-owned effectsDescribe internal state changes
Executed by cmd/2, update agent.stateBare structs emitted by agentsApplied by strategy layer
Can call APIs, read files, query databasesRuntime (AgentServer) interprets themNever leave the strategy

State Operations (Jido.Agent.StateOp)

State operations are internal state transitions handled by the strategy layer during cmd/2. Unlike directives, they never reach the runtime.

StateOpPurpose
SetStateDeep merge attributes into state
ReplaceStateReplace state wholesale
DeleteKeysRemove top-level keys
SetPathSet value at nested path
DeletePathDelete value at nested path

Directive Types

DirectivePurpose
EmitDispatch a signal via configured adapters
ErrorSignal an error from cmd/2
SpawnSpawn a generic BEAM child process
SpawnAgentSpawn a tracked child Jido agent (restart: :transient by default)
StopChildGracefully stop and remove a tracked child agent
StartSensorStart or replace a tagged sensor runtime
StopSensorStop a tagged sensor runtime
ScheduleSchedule a delayed message
StopStop the agent process

Sensor runtimes started by StartSensor are tracked under {:sensor, tag} and are owner-monitored by default. Unexpected sensor exits emit jido.agent.sensor.exit back to the owning agent; controlled StopSensor shutdowns do not. Use link?: true only when a sensor should fail fast with its owning AgentServer.

Documentation

Start here:

Guides:

Advanced:

API Reference:hexdocs.pm/jido

FAQ

General Questions

Q: What is Jido and how does it differ from other agent frameworks?

A: Jido is an autonomous agent framework for Elixir, built for workflows and multi-agent systems. Key differentiators:

Compared to LangChain/CrewAI:

Q: What is the Agent/Action/Signal/Directive architecture?

A:

cmd/2 returns the updated agent plus directives. Directives never mutate agent state; the OTP runtime interprets them for runtime-owned external effects. Actions may still perform work such as API calls, file I/O, or database queries when that result is needed immediately by the action or state transition.

Q: Is AI required for Jido?

A: No! The core package (jido) provides agent architecture and runtime without AI. AI/LLM integration is optional via companion packages:

Use Jido when software needs to inspect context, choose steps, coordinate agents, and run reliably - AI is optional.

Q: What are the Jido ecosystem packages?

A:

PackageDescription
req_llmHTTP client for LLM APIs
jido_actionComposable, validated actions with AI tool integration
jido_signalCloudEvents-based message envelope and routing utilities
jidoCore agent framework with state management, directives, runtime
jido_aiAI/LLM integration for agents

Getting Started

Q: How do I install Jido?

A: Jido is available on Hex.pm:

def deps do
[
{:jido, "~> 2.0"}
]
end

See jido.run for demos and examples.

Q: How do I create an agent?

A:

defmodule MyAgent do
use Jido.Agent,
name: "my_agent",
description: "My custom agent",
schema: [
count: [type: :integer, default: 0]
]
end
{agent, directives} = MyAgent.cmd(agent, action)

See hexdocs.pm/jido for API reference.

Q: How do I run agents in production?

A: Use AgentServer (GenServer-based) for production deployment:

Features

Q: What directives are available?

A: Built-in directives:

External packages can also define custom directive structs. See Agent Directives for details.

Q: How do plugins work?

A: Composable plugins extend agents with:

See Plugins Guide for details.

Q: What execution strategies are available?

A:

See Strategies Guide and FSM Strategy Deep Dive.

Troubleshooting

Q: I'm getting GenServer timeout errors. What should I check?

A:

  1. Check action execution time
  2. Consider using worker pools for throughput (guides/worker-pools.md)
  3. Review supervision tree configuration

Q: My agents aren't receiving signals. What's wrong?

A:

  1. Check signal routing configuration
  2. Verify signal envelope format (CloudEvents)
  3. Review signal dispatch strategy

Help Resources

Development

Prerequisites

Running Tests

mix test

Quality Checks

mix quality # Runs formatter, dialyzer, and credo

Contributing

We welcome contributions! Please see our Contributing Guide for details on:

License

Copyright 2024-2025 Mike Hostetler

Licensed under the Apache License, Version 2.0. See LICENSE for details.