The easy on-ramp to LLM agents in Elixir.
Jidoka is a small, opinionated harness over Jido and Jido.AI. It gives you a developer-friendly DSL focused on the common LLM-agent use cases, without asking you to learn signals, directives, state operations, strategy internals, or request plumbing on day one.
If you have looked at the broader Jido ecosystem and felt it was a lot to absorb just to ship one agent, Jidoka is for you.
Beta status: Jidoka is in beta. We are actively refining, trimming, and reshaping the package before a stable release. APIs, behaviors, and feature boundaries can change without notice while this work continues.
The Jido ecosystem is powerful, but powerful is not the same as approachable. Jidoka is the opinionated layer that:
- starts with a single agent module and a
chat/3call - grows progressively when you actually need tools, memory, compaction, structured output, workflows, subagents, or handoffs
- hides Jido's lower-level surface until you choose to opt in
You can stay on the easy path indefinitely, or drop down into Jido directly when your application needs it. Jidoka does not get in the way.
- A tiny DSL.
use Jidoka.Agent, name it, give it instructions, you have an agent. - Fast time-to-first-agent. Define, start, and chat in under thirty lines.
- Progressive opt-in. Tools, structured output, memory, compaction, characters, workflows, subagents, handoffs, MCP, web access, plugins, hooks, and guardrails are all available, but none are required.
defmodule MyApp.AssistantAgent do
use Jidoka.Agent
agent do
id :assistant_agent
end
defaults do
model :fast
instructions "You are a concise assistant. Answer directly."
end
endStart it and chat:
{:ok, pid} = MyApp.AssistantAgent.start_link(id: "assistant-1")
{:ok, reply} =
MyApp.AssistantAgent.chat(pid, "Write one sentence about why Elixir works well for agents.")That is a complete Jidoka agent. Only agent.id and defaults.instructions
are required. Everything else is optional.
You can also load the same conceptual agent from a JSON or YAML spec at runtime. See Two equal authoring paths below.
Jidoka agents are OTP processes owned by the shared Jidoka.Runtime
supervisor. Your application chooses the lifetime: one request, one user
session, one long-lived application worker, or one first-class Jidoka schedule.
session =
Jidoka.Session.new!(
agent: MyApp.AssistantAgent,
id: "support-123",
context: %{actor: current_user}
)
{:ok, reply} =
Jidoka.chat(session, "Help me triage this support ticket.")Jidoka.Session is a plain descriptor for stable conversation identity and
runtime context. It is not a process or persistence layer. For UI-facing agents,
use an AgentView adapter to project visible messages, async turns, streaming
state, and final result mapping.
If you need an application-owned Jido instance instead of the shared
Jidoka.Runtime, start the generated runtime_module/0 under your own
use Jido, otp_app: :my_app runtime and keep calling Jidoka.chat/3.
For event-level streaming, keep the same API and opt in per turn:
{:ok, stream} = Jidoka.chat(session, "Draft a reply.", stream: true)
for event <- stream do
if delta = Jidoka.Chat.Stream.text_delta(event), do: IO.write(delta)
end
{:ok, final_reply} = Jidoka.Chat.Stream.await(stream)See Running Agents, Sessions, AgentView, Schedules, Phoenix LiveView, and Graduating To Jido.
For classification, extraction, and routing tasks, put the response shape on the agent. Jidoka asks the model for JSON, parses it, validates it with Zoi, and hands you back a typed map.
defmodule MyApp.TicketClassifier do
use Jidoka.Agent
agent do
id :ticket_classifier
output do
schema Zoi.object(%{
category: Zoi.enum([:billing, :technical, :account]),
confidence: Zoi.float(),
summary: Zoi.string()
})
end
end
defaults do
model :fast
instructions "Classify support tickets for routing."
end
end{:ok, pid} = MyApp.TicketClassifier.start_link(id: "ticket-classifier-1")
{:ok, ticket} =
MyApp.TicketClassifier.chat(pid, "I was double charged for my last invoice.")
# ticket =>
# %{category: :billing, confidence: 0.92, summary: "Customer reports a duplicate invoice charge."}Validation retries and repair behavior are configurable. See Structured Output and Errors for the details.
Tools are how an agent does deterministic application work: lookups, math, API calls, anything that should not be the model's job to imagine.
defmodule MyApp.Tools.AddNumbers do
use Jidoka.Tool,
description: "Adds two integers.",
schema: Zoi.object(%{a: Zoi.integer(), b: Zoi.integer()})
@impl true
def run(%{a: a, b: b}, _context) do
{:ok, %{sum: a + b}}
end
end
defmodule MyApp.MathAgent do
use Jidoka.Agent
agent do
id :math_agent
end
defaults do
model :fast
instructions "Use tools when they help. Keep the final answer short."
end
capabilities do
tool MyApp.Tools.AddNumbers
end
endThe model can now call add_numbers mid-turn. See Tools for
the full tool API, plus the per-capability guides for
Ash Resources, MCP,
Web Access, Skills, and
Plugins.
Jidoka grows with you. The capabilities below are all optional and individually
documented under guides/.
- Context schemas: declare a Zoi schema on
the agent and have per-turn
context:validated before the model is called. - Memory: opt-in conversation memory built on
jido_memory, with simple namespace and capture/retrieve options. - Compaction: opt-in summary compaction for long sessions, trimming only provider-facing messages while preserving the original thread.
- Characters: structured persona data for voice, tone, and identity, rendered into the prompt before instructions.
- Structured output: Zoi-validated final answers with retries and optional repair.
- Schedules: cron-based scheduled agent turns and
workflow runs through
Jidoka.Schedule.Manager.
- Workflows: deterministic, app-owned multi-step
processes via
use Jidoka.Workflow. - Subagents: specialist agents exposed to a parent agent as tools, for one-turn delegation.
- Handoffs: transfer ownership of future turns in a conversation to another agent.
- Imported agents: load agents from JSON or YAML at runtime through explicit allowlist registries.
- MCP tools: sync external tools through
jido_mcp. - Web access: constrained, read-only public web search and page reads.
- Plugins: deeper extension points that contribute tools and runtime behavior.
- Ash resources: expose generated
AshJidoactions as model-callable tools.
- Hooks and guardrails: turn-scoped callbacks and input/output/tool validation.
- Structured errors:
Jidoka.format_error/1turns any runtime failure into a user-safe string. See Errors. - Inspection:
Jidoka.inspect_agent/1,Jidoka.inspect_request/1, andJidoka.inspect_workflow/1expose stable views of definitions and runs.Jidoka.inspect_compaction/1shows the latest context summary snapshot. - Tracing: first-class run traces through
Jidoka.Traceand Livebook helpers. - Testing: provider-free contract, tool, guardrail, structured output, and workflow tests, plus opt-in live evals. See Testing Agents.
Recommended reading order:
- Getting Started
- Agents
- Models
- Instructions
- Context
- Structured Output
- Running Agents
- Sessions
- Schedules
- AgentView
- Tools (then see Capabilities for the rest)
- Subagents, Workflows, Handoffs
- Memory
- Compaction
- Imported Agents
- Errors, Inspection, and Testing Agents
- Examples
- Phoenix LiveView
- Graduating To Jido
- Production
The full guide index is at guides/overview.md.
Jidoka has two ways to describe the same conceptual agent. They are peers, not a primary and a fallback.
use Jidoka.Agent is the recommended path for Elixir developers. You get
compile-time validation, formatter support, and source-aware errors.
defmodule MyApp.AssistantAgent do
use Jidoka.Agent
agent do
id :assistant_agent
end
defaults do
model :fast
instructions "You are a concise assistant."
end
endFor teams that want portable specs, or want to author agents without writing Elixir, Jidoka supports a constrained runtime import path:
json = ~S"""
{
"agent": { "id": "json_agent" },
"defaults": {
"model": "fast",
"instructions": "You are a concise assistant."
}
}
"""
{:ok, agent} = Jidoka.import_agent(json)
{:ok, pid} = Jidoka.start_agent(agent, id: "json-agent")
{:ok, reply} = Jidoka.chat(pid, "Say hello.")YAML works the same way with format: :yaml. Tools, plugins, hooks,
guardrails, characters, workflows, and handoffs are resolved through explicit
available_* allowlist registries so imported agents stay safe.
See Imported Agents for the full constrained schema.
Jidoka beta releases are distributed through Hex:
def deps do
[
{:jidoka, "~> 1.0.0-beta.1"}
]
endDuring beta development, you can also pin a specific Git commit:
def deps do
[
{:jidoka,
git: "https://github.com/agentjido/jidoka.git",
ref: "COMMIT_SHA"}
]
endFor local development against a checkout:
def deps do
[
{:jidoka, path: "../jidoka"}
]
endThen:
mix deps.getThe README examples use Anthropic through ReqLLM/Jido.AI:
export ANTHROPIC_API_KEY=sk-ant-...In this repo, .env is also loaded automatically through dotenvy. Shell
environment variables win over .env.
Jidoka owns a small alias layer under config :jidoka, :model_aliases. The
default :fast alias maps to anthropic:claude-haiku-4-5. You can also pass
direct model strings ("anthropic:claude-haiku-4-5") or inline maps wherever
model is accepted.
Jidoka is currently beta. The core authoring surface (agents, tools, workflows, imports, structured output, tracing, structured errors, examples, and the Phoenix LiveView consumer) is ready for early adopters, but small breaking changes are still possible before stable 1.0. See ROADMAP.md for the current state.
mix jidoka chat --dry-run
mix jidoka imported --dry-run
mix jidoka workflow --dry-run
mix jidoka orchestrator --dry-runDrop --dry-run to run a demo against a configured provider:
mix jidoka chat -- "Use one sentence to explain what Jidoka is."The examples/ directory contains focused, runnable demos for chat, structured
output, tools, workflows, orchestration, support, and more. Each canonical
example also supports --verify to exercise its tool and output contracts
without calling a provider:
mix jidoka lead_qualification --verifyFrom this directory:
mix deps.get
mix compile
mix test
mix formatmix quality runs formatting, compiler warnings, Credo, Dialyzer, and
documentation coverage.
dev/jidoka_consumer/ is a Phoenix LiveView fixture that integrates a Jidoka
chat agent, an Ash-backed ticket resource, subagents, workflows, and handoffs.
Boot it on port 4002:
cd dev/jidoka_consumer
mix deps.get
PORT=4002 mix phx.serverSee Phoenix LiveView for the integration walk-through.
Apache-2.0. See LICENSE.