Jidoka: Memory
Capture conversation memory, retrieve it on the next turn, and choose whether memory is injected into the prompt or exposed as runtime context.
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 Memory Agent
defmodule LivebookDemo.Memory.Agent do
use Jidoka.Agent
agent do
id :livebook_memory_agent
end
defaults do
model :fast
instructions "You use relevant memory when it helps."
end
lifecycle do
memory do
mode :conversation
namespace {:context, :session}
capture :conversation
retrieve limit: 4
inject :context
end
end
end
LivebookDemo.Memory.Agent.memory()
Simulate Two Turns
The runtime callbacks let us prove capture and retrieval without calling a model.
runtime = LivebookDemo.Memory.Agent.runtime_module()
agent = runtime.new(id: "livebook-memory-runtime")
session = "memory-session-#{System.unique_integer([:positive])}"
{:ok, agent, _action} =
runtime.on_before_cmd(
agent,
{:ai_react_start,
%{
query: "Remember that my favorite color is blue.",
request_id: "req-memory-1",
tool_context: %{session: session}
}}
)
agent =
Jido.AI.Request.complete_request(
agent,
"req-memory-1",
"I will remember that your favorite color is blue."
)
{:ok, agent, []} =
runtime.on_after_cmd(agent, {:ai_react_start, %{request_id: "req-memory-1"}}, [])
{:ok, _agent, {:ai_react_start, params}} =
runtime.on_before_cmd(
agent,
{:ai_react_start,
%{
query: "What is my favorite color?",
request_id: "req-memory-2",
tool_context: %{session: session}
}}
)
memory = params.tool_context[:memory]
%{
namespace: memory.namespace,
record_count: length(memory.records),
public_context_keys: params.tool_context |> Map.keys() |> Enum.sort()
}
Render the retrieved records.
rows =
Enum.map(memory.records, fn record ->
%{
kind: record.kind,
text: record.text,
source: record.source
}
end)
Jidoka.Kino.table("Retrieved memory", rows)
Switching to inject :instructions would append a bounded Relevant memory:
section to the system prompt instead of exposing context.memory.
Optional Provider Turn
{:ok, pid} =
Jidoka.Kino.start_or_reuse("livebook-memory-agent", fn ->
LivebookDemo.Memory.Agent.start_link(id: "livebook-memory-agent")
end)
Jidoka.Kino.chat("Memory chat", fn ->
LivebookDemo.Memory.Agent.chat(pid, "Remember that my favorite snack is almonds.", context: %{session: session})
end)