Jidoka: Phoenix LiveView Consumer Boundary
Jidoka does not need to render Phoenix components. The reusable boundary is a
Jidoka.Session plus an AgentView: the session names the conversation and
runtime context, while AgentView projects the runtime state a LiveView can
render.
Setup
Mix.install(
[
{:jidoka, git: "https://github.com/agentjido/jidoka.git", branch: "main"},
{:kino, "~> 0.19.0"}
],
config: [
jidoka: [
model_aliases: %{fast: "anthropic:claude-haiku-4-5"}
]
]
)
Jidoka.Kino.setup()
Define An AgentView
defmodule LivebookDemo.AgentView.SupportAgent do
use Jidoka.Agent
agent do
id :livebook_agent_view_support
schema Zoi.object(%{
channel: Zoi.string() |> Zoi.default("livebook"),
session: Zoi.string()
})
end
defaults do
model :fast
instructions "You are a support assistant."
end
end
defmodule LivebookDemo.AgentView.SupportView do
use Jidoka.AgentView
end
Project Runtime State
session =
Jidoka.Session.new!(
agent: LivebookDemo.AgentView.SupportAgent,
id: "onboarding-demo",
context: %{channel: "livebook", actor: %{id: "user-1"}}
)
{:ok, pid} = LivebookDemo.AgentView.SupportView.start_agent(session)
{:ok, view} = LivebookDemo.AgentView.SupportView.snapshot(pid, session)
Map.take(view, [
:agent_id,
:conversation_id,
:runtime_context,
:visible_messages,
:streaming_message,
:status
])
A LiveView can optimistically append the user’s message before the async agent turn completes.
pending = LivebookDemo.AgentView.SupportView.before_turn(view, "My invoice is confusing.")
Map.take(pending, [:status, :visible_messages, :streaming_message])
The lower-level projection remains available for debugging.
{:ok, projection} = Jidoka.Agent.View.snapshot(pid)
projection
|> Map.take([:visible_messages, :streaming_message, :llm_context, :events])
Optional Provider Turn
Jidoka.Kino.chat("AgentView-backed chat", fn ->
Jidoka.chat(session, "Explain the AgentView boundary in one sentence.")
end)