Use the Jidoka module from application code. It builds, runs, inspects, and
resumes agents.
Build
Use the DSL for normal agent modules:
defmodule MyApp.Assistant do
use Jidoka.Agent
agent :assistant do
model "openai:gpt-4o-mini"
instructions "Answer clearly and briefly."
end
endUse agent/1 when an agent comes from runtime data:
{:ok, spec} =
Jidoka.agent(
id: "assistant",
model: "openai:gpt-4o-mini",
instructions: "Answer clearly and briefly."
)Use import/2 for JSON or YAML strings:
{:ok, spec} =
Jidoka.import("""
agent:
id: assistant
model: openai:gpt-4o-mini
instructions: Answer clearly and briefly.
""")Use export/2 when you need portable agent data:
{:ok, yaml} = Jidoka.export(MyApp.Assistant, format: :yaml)Use plan/1 when you want the executable turn data before running:
{:ok, plan} = Jidoka.plan(MyApp.Assistant)Reserve agent!/1 and plan!/1 for boot paths and tests where invalid data
should raise.
Run
Use chat/3 for product code that only needs text:
{:ok, text} = Jidoka.chat(MyApp.Assistant, "Draft a short status update.")Use turn/3 when you need the full result:
{:ok, result} =
Jidoka.turn(MyApp.Assistant, "Draft a short status update.")
result.content
result.events
result.journal.resultsBoth functions accept a DSL module, Agent.Spec, Turn.Plan, process id, pid,
or session where appropriate.
Stream For UI
Use chat_async/3 when a UI needs to start work now and collect events while
the turn runs:
{:ok, request} =
Jidoka.chat_async(MyApp.Assistant, "Write a two paragraph summary.",
stream: true
)
stream = Jidoka.stream(request)
for event <- stream do
if delta = Jidoka.Stream.text_delta(event) do
IO.write(delta)
end
end
{:ok, text} = Jidoka.await(request)stream/2 yields Jidoka.Event values. await/2 returns the same normalized
shape as chat/3.
Keep State
Use sessions for multi-turn conversations:
{:ok, session} = Jidoka.session(MyApp.Assistant, "conversation-123")
{:ok, session, text} =
Jidoka.chat(session, "Remember that my account is A1001.")
{:ok, session, text} =
Jidoka.chat(session, "Which account did I mention?")Use session/3 when passing a store or runtime options:
{:ok, session} =
Jidoka.session(MyApp.Assistant, "conversation-123",
store: {Jidoka.Harness.Store.InMemory, pid: store_pid}
)Resume
When a control pauses a turn, turn/3 returns a snapshot:
case Jidoka.turn(MyApp.RefundAgent, "Refund order A1001") do
{:ok, result} ->
result.content
{:hibernate, snapshot} ->
review = snapshot.metadata["pending_review"]
approval = Jidoka.Review.Response.approve(review)
Jidoka.resume(snapshot, approval: approval)
endresume/2 accepts a snapshot struct, snapshot map, or serialized snapshot
string.
Host In A Process
Use process hosting when the application wants a long-lived, addressable agent:
{:ok, _pid} = Jidoka.start_agent(MyApp.Assistant, id: "assistant-1")
{:ok, text} = Jidoka.chat("assistant-1", "Are you running?")
pid = Jidoka.whereis("assistant-1")
:ok = Jidoka.stop_agent("assistant-1")Hosted agents run as Jido.AgentServer processes. Turns still use the same
runtime.
Inspect
Use preflight/3 for prompt and tool wiring:
{:ok, preflight} = Jidoka.preflight(MyApp.Assistant, "What can you do?")
preflight.prompt.messagesUse inspect/2 for a readable compiled view:
Jidoka.inspect(MyApp.Assistant)Use project/1 for data maps in tests, traces, and UI projections:
projection = Jidoka.project(MyApp.Assistant.spec())
projection.idHandle Errors
Use the error helpers at application boundaries:
case Jidoka.chat(MyApp.Assistant, "Hello") do
{:ok, text} ->
text
{:error, reason} ->
Logger.warning(Jidoka.format_error(reason))
{:error, Jidoka.error_to_map(reason)}
enderror_to_map/1 sanitizes likely credential fields.
Handoffs
Handoffs are routing state. They tell your application which agent should own future turns for a conversation:
Jidoka.handoff("conversation-123")
#=> nil or %{agent_id: "...", ...}
:ok = Jidoka.reset_handoff("conversation-123")Handoff operations happen inside turns. These helpers only read or clear the owner state.
Function Picker
| Need | Use |
|---|---|
| Build spec from data | agent/1 |
| Import JSON/YAML | import/2 |
| Export JSON/YAML | export/2 |
| Compile runtime plan | plan/1 |
| Final text | chat/3 |
| Full turn result | turn/3 |
| Async UI request | chat_async/3 |
| Event stream | stream/2 |
| Await async result | await/2 |
| Multi-turn state | session/2 or session/3 |
| Continue a paused turn | resume/2 |
| Start hosted process | start_agent/2 |
| Stop hosted process | stop_agent/2 |
| Lookup hosted process | whereis/2 |
| Prompt/tool preflight | preflight/3 |
| Human-readable inspection | inspect/2 |
| Data projection | project/1 |
| Format error string | format_error/1 |
| Error map for logs/UI | error_to_map/1 |
| Current handoff owner | handoff/1 |
| Clear handoff owner | reset_handoff/1 |
Testing
Use real providers in product guides and demos. In tests, inject fake capabilities:
llm = fn _intent, _journal ->
{:ok, %{type: :final, content: "ok"}}
end
assert {:ok, "ok"} = Jidoka.chat(MyApp.Assistant, "ping", llm: llm)See Testing And Evals for operation capabilities, golden tests, and integration tests.
Next
- Getting Started - build and run the first agent.
- Core Concepts - the data model behind the facade.
- Configuration - default model, generation, loop, and timeout settings.
- Sessions And Stores - durable conversations.
- Streaming - event streams for UI.