Pure functional agents and OTP runtime for building autonomous multi-agent workflows in Elixir.
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 agentjido.xyz.
With Jido, your 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
end
{agent, directives} = MyAgent.cmd(agent, action)State changes are pure data transformations; side effects are described as directives and executed by an OTP runtime. You get deterministic agent logic, testability without processes, and a clear path to running those agents in production.
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.
| Package | Description |
|---|---|
| req_llm | HTTP client for LLM APIs |
| jido_action | Composable, validated actions with AI tool integration |
| jido_signal | CloudEvents-based message envelope and supporting utilities for routing and pub/sub messaging |
| jido | Core agent framework with state management, directives, and runtime |
| jido_ai | AI/LLM integration for agents |
| jido_coder | AI coding agent with file operations, git integration, and test execution |
For demos and examples of what you can build with the Jido Ecosystem, see https://agentjido.xyz.
OTP primitives are excellent. You can build agent systems with raw GenServer. But when building multiple cooperating agents, you'll reinvent:
| Raw OTP | Jido Formalizes |
|---|---|
| Ad-hoc message shapes per GenServer | Signals as standard envelope |
| Business logic mixed in callbacks | Actions as reusable command pattern |
| Implicit effects scattered in code | Directives as typed effect descriptions |
| Custom child tracking per server | Built-in parent/child hierarchy |
| Process exit = completion | State-based completion semantics |
Jido isn't "better GenServer" - it's a formalized agent pattern built on GenServer.
- Pure functional agent design inspired by Elm/Redux
cmd/2as the core operation: actions in, updated agent + directives out- Schema-validated state with NimbleOptions or Zoi
- Actions transform state; directives describe external effects
- Built-in directives: Emit, Spawn, SpawnAgent, StopChild, Schedule, Stop
- Protocol-based extensibility for custom directives
- GenServer-based AgentServer for production deployment
- Parent-child agent hierarchies with lifecycle management
- Signal routing with configurable strategies
- Instance-scoped supervision for multi-tenant deployments
- Reusable behavior modules that extend agents
- State isolation per skill with automatic schema merging
- Lifecycle hooks for initialization and signal handling
- Direct execution for simple workflows
- FSM (Finite State Machine) strategy for state-driven workflows
- Extensible strategy protocol for custom execution patterns
- Multi-agent workflows with configurable strategies
- Plan-based orchestration for complex workflows
- Extensible strategy protocol for custom execution patterns
Add jido to your list of dependencies in mix.exs:
def deps do
[
{:jido, "~> 2.0"}
]
endThen 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)defmodule MyApp.CounterAgent do
use Jido.Agent,
name: "counter",
description: "A simple counter agent",
schema: [
count: [type: :integer, default: 0]
]
enddefmodule 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# 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# Start the agent server
{:ok, pid} = MyApp.Jido.start_agent(MyApp.CounterAgent, id: "counter-1")
# Send signals to the running agent (synchronous)
{: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()The fundamental operation in Jido:
{agent, directives} = MyAgent.cmd(agent, action)Key invariants:
- The returned
agentis always complete - no "apply directives" step needed directivesdescribe external effects only - they never modify agent statecmd/2is a pure function - same inputs always produce same outputs
| Actions | Directives | State Operations |
|---|---|---|
| Describe state transformations | Describe external effects | Describe internal state changes |
Executed by cmd/2, update agent.state |
Bare structs emitted by agents | Applied by strategy layer |
| Never perform side effects | Runtime (AgentServer) interprets them | Never leave the strategy |
State operations are internal state transitions handled by the strategy layer during cmd/2. Unlike directives, they never reach the runtime.
| StateOp | Purpose |
|---|---|
SetState |
Deep merge attributes into state |
ReplaceState |
Replace state wholesale |
DeleteKeys |
Remove top-level keys |
SetPath |
Set value at nested path |
DeletePath |
Delete value at nested path |
| Directive | Purpose |
|---|---|
Emit |
Dispatch a signal via configured adapters |
Error |
Signal an error from cmd/2 |
Spawn |
Spawn a generic BEAM child process |
SpawnAgent |
Spawn a child Jido agent with hierarchy tracking |
StopChild |
Gracefully stop a tracked child agent |
Schedule |
Schedule a delayed message |
Stop |
Stop the agent process |
Start here:
- Quick Start - Build your first agent in 5 minutes
- Core Concepts - Understand the mental model
Guides:
- Building Agents - Agent definitions and state management
- Signals & Routing - Signal-based communication
- Agent Directives - Effect descriptions for the runtime
- Runtime and AgentServer - Process-based agent execution
- Skills - Composable capability bundles
- Strategies - Execution strategies (Direct, FSM)
Advanced:
- FSM Strategy Deep Dive - State machine workflows
- Testing Agents - Testing patterns and best practices
API Reference: hexdocs.pm/jido
- Elixir 1.17+
- Erlang/OTP 26+
mix testmix quality # Runs formatter, dialyzer, and credoWe welcome contributions! Please see our Contributing Guide for details on:
- Setting up your development environment
- Running tests and quality checks
- Submitting pull requests
- Code style guidelines
Copyright 2024-2025 Mike Hostetler
Licensed under the Apache License, Version 2.0. See LICENSE for details.
- Documentation: https://hexdocs.pm/jido
- GitHub: https://github.com/agentjido/jido
- AgentJido: https://agentjido.xyz
- Jido Workbench: https://github.com/agentjido/jido_workbench