Search
Search docs, blog posts, and ecosystem packages with citations.
Enter a query to see grounded citations.
We can't find the internet
Attempting to reconnect
Search docs, blog posts, and ecosystem packages with citations.
Add LLM reasoning to a Jido agent with jido_ai, configure a provider, and run your first AI-enhanced command.
This notebook is self-contained: install the dependencies, configure a provider key, start the default Jido runtime, and send one prompt through an AI agent. If you already completed Your first agent, still run this notebook top to bottom because it defines its own module.
Mix.install([
{:jido, "~> 2.1"},
{:jido_ai, "~> 2.0"},
{:req_llm, "~> 1.7"}
])
Logger.configure(level: :warning)
# Livebook imports can execute generated docs as doctests.
# Disable compiler docs until the current Jido Hex release drops the invalid signal_types/0 example.
Code.put_compiler_option(:docs, false)
In Livebook, store OPENAI_API_KEY as a secret. Livebook exposes that secret as LB_OPENAI_API_KEY inside the notebook, so this cell checks both names.
openai_key = System.get_env("LB_OPENAI_API_KEY") || System.get_env("OPENAI_API_KEY")
configured? =
if is_binary(openai_key) do
ReqLLM.put_key(:openai_api_key, openai_key)
true
else
IO.puts("Set OPENAI_API_KEY or LB_OPENAI_API_KEY before running the request cell.")
false
end
use Jido.AI.Agent keeps the module declarative: describe the agent, choose a model, and provide a system prompt. This first example does not use tools, so the only new capability is the LLM call.
defmodule MyAgentApp.Greeter do
use Jido.AI.Agent,
name: "greeter",
description: "Generates a friendly greeting",
tools: [],
model: :fast,
system_prompt: """
You are a friendly greeter.
Generate a short, warm welcome message.
One or two sentences maximum.
"""
end
model: :fast uses the default fast model alias from jido_ai. You can swap in a provider-specific string later, but the alias keeps the tutorial portable.
Jido.start/0 is the notebook-friendly runtime helper. It is safe to call more than once, so rerunning this cell does not force you to restart the notebook. Jido.start_agent/3 then starts your agent inside that runtime.
{:ok, _} = Jido.start()
runtime = Jido.default_instance()
agent_id = "greeter-demo-#{System.unique_integer([:positive])}"
{:ok, pid} = Jido.start_agent(runtime, MyAgentApp.Greeter, id: agent_id)
Send one prompt with ask_sync/3. The return value is {:ok, text} on success or {:error, reason} if the provider call fails.
greeting =
if configured? do
MyAgentApp.Greeter.ask_sync(
pid,
"Say hello to someone just getting started with Jido.",
timeout: 30_000
)
else
{:skip, :no_openai_key}
end
IO.inspect(greeting, label: "Greeting")
case greeting do
{:ok, text} ->
IO.puts(text)
{:error, reason} ->
IO.puts("Greeting failed: #{inspect(reason)}")
{:skip, :no_openai_key} ->
IO.puts("Skipped request. Set OPENAI_API_KEY or LB_OPENAI_API_KEY to run it.")
end
Show the success path first, then inspect the runtime state. Jido.AgentServer.status/1 gives you the current snapshot for the running agent process.
snapshot =
case Jido.AgentServer.status(pid) do
{:ok, status} ->
%{
done?: status.snapshot.done?,
result: status.snapshot.result,
model: status.snapshot.details[:model]
}
other ->
other
end
IO.inspect(snapshot, label: "Snapshot")
Jido.start/0 started the default runtime used for scripts and Livebook. Jido.start_agent/3 started MyAgentApp.Greeter as a supervised agent process. ask_sync/3 combined the system prompt and your message, then sent the request through req_llm. Jido.AgentServer.status/1 exposed the resulting snapshot so you could inspect the completed request. The agent module stays free of provider-specific HTTP code. The runtime handles request execution, while your module stays focused on behavior.
Keep the agent module the same, add the dependencies to mix.exs, configure the provider key in config/runtime.exs, and supervise a use Jido module in your application:
defmodule MyAgentApp.Jido do
use Jido, otp_app: :my_agent_app
end
children = [
{MyAgentApp.Jido, name: MyAgentApp.Jido}
]
Then start agents against that named runtime:
{:ok, pid} = Jido.start_agent(MyAgentApp.Jido, MyAgentApp.Greeter, id: "greeter-1")
MyAgentApp.Greeter.ask_sync(pid, "Say hello to the production app.", timeout: 30_000)