Powered by AppSignal & Oban Pro

Jidoka: Errors, Inspection, And Debugging

04_errors_inspection_debugging.livemd

Jidoka: Errors, Inspection, And Debugging

Run in Livebook

Learn the diagnostic loop: inspect what Jidoka compiled, trigger a structured error, format it for a user, and capture a concise runtime trace.

Setup

Mix.install(
  [
    {:jidoka, git: "https://github.com/mikehostetler/jidoka.git", ref: "924a486f3c1b7e7a943cb3d5ceee0de65f158467"},
    {:kino, "~> 0.19.0"}
  ],
  config: [
    jidoka: [
      model_aliases: %{fast: "anthropic:claude-haiku-4-5"}
    ]
  ]
)
Jidoka.Kino.setup()

Define A Small Agent

defmodule LivebookDemo.Diagnostics.Tools.AddNumbers do
  use Jidoka.Tool,
    name: "diagnostic_add_numbers",
    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

defmodule LivebookDemo.Diagnostics.Agent do
  use Jidoka.Agent

  agent do
    id :livebook_diagnostic_agent

    schema Zoi.object(%{
      tenant: Zoi.string() |> Zoi.default("demo"),
      session: Zoi.string() |> Zoi.optional()
    })
  end

  defaults do
    model :fast
    instructions "You are a concise diagnostic assistant."
  end

  capabilities do
    tool LivebookDemo.Diagnostics.Tools.AddNumbers
  end
end

Inspect the compiled surface before making any model calls.

{:ok, definition} = Jidoka.inspect_agent(LivebookDemo.Diagnostics.Agent)

Map.take(definition, [
  :kind,
  :id,
  :model,
  :context,
  :tool_names,
  :plugins,
  :memory,
  :guardrails
])

Format Failures

Context validation happens before the provider call, so this cell runs without an API key.

{:ok, pid} =
  Jidoka.Kino.start_or_reuse("livebook-diagnostic-agent", fn ->
    LivebookDemo.Diagnostics.Agent.start_link(id: "livebook-diagnostic-agent")
  end)

{:error, error} =
  LivebookDemo.Diagnostics.Agent.chat(pid, "Hello", context: %{tenant: 123})

%{
  error_struct: error,
  user_text: Jidoka.format_error(error)
}

Jidoka errors stay structured, so you can render them however your application needs.

rows = [
  %{
    case: "bad context type",
    message: Jidoka.format_error(Jidoka.Error.invalid_context(:expected_map, value: [1, 2]))
  },
  %{
    case: "missing actor",
    message: Jidoka.format_error(Jidoka.Error.missing_context(:actor))
  },
  %{
    case: "execution failure",
    message: Jidoka.format_error(Jidoka.Error.execution_error("Tool failed."))
  }
]

Jidoka.Kino.table("Formatted error examples", rows)

Trace A Turn

Jidoka.Kino.chat/3 renders a compact trace table and returns plain response text. Without ANTHROPIC_API_KEY, it returns a friendly missing-provider error before calling the provider.

Jidoka.Kino.chat("Diagnostic chat", fn ->
  LivebookDemo.Diagnostics.Agent.chat(pid, "Use one sentence to describe Jidoka debugging.")
end)

Inspect the running agent when you need the latest runtime state.

{:ok, running} = Jidoka.inspect_agent(pid)

Map.take(running, [:kind, :id, :runtime_module, :last_request_id, :definition])