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
end

Use 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.results

Both 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)
end

resume/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.messages

Use 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.id

Handle 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)}
end

error_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

NeedUse
Build spec from dataagent/1
Import JSON/YAMLimport/2
Export JSON/YAMLexport/2
Compile runtime planplan/1
Final textchat/3
Full turn resultturn/3
Async UI requestchat_async/3
Event streamstream/2
Await async resultawait/2
Multi-turn statesession/2 or session/3
Continue a paused turnresume/2
Start hosted processstart_agent/2
Stop hosted processstop_agent/2
Lookup hosted processwhereis/2
Prompt/tool preflightpreflight/3
Human-readable inspectioninspect/2
Data projectionproject/1
Format error stringformat_error/1
Error map for logs/UIerror_to_map/1
Current handoff ownerhandoff/1
Clear handoff ownerreset_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