Search
Search docs, blog posts, and ecosystem packages with citations.
Enter a query to see grounded citations.
This is the staging site. Canonical host: stage.jido.run
We can't find the internet
Attempting to reconnect
Search docs, blog posts, and ecosystem packages with citations.
Diagnose agent issues with debug modes, event buffers, and structured diagnostics.
Mix.install([
{:jido, "~> 2.1"}
])
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)
Jido.start()
runtime = Jido.default_instance()
Define a minimal agent for the examples in this guide.
This guide runs entirely locally. No provider keys or network calls are required.
defmodule MyApp.CounterAgent do
use Jido.Agent,
name: "counter_agent",
schema: [
count: [type: :integer, default: 0],
status: [type: :atom, default: :idle]
]
end
Jido has three instance-wide debug levels that control logging verbosity and event capture across all agents in that instance.
| Level | Logging | Argument display | Debug events |
|---|---|---|---|
:off | Configured defaults | N/A | None |
:on | :debug | Keys only | Minimal |
:verbose | :trace | Full values | All |
Toggle the level at runtime with Jido.debug/1.
Jido.debug(:on)
Check the current level by calling Jido.debug/0.
Jido.debug()
When you need to see full argument values including sensitive fields, disable redaction.
Jido.debug(:on, redact: false)
Turn debug mode off when you are done investigating.
Jido.debug(:off)
Warning: Never leave
redact: falseenabled in production. It exposes sensitive values in log output.
Instance-level debug controls verbosity globally. Per-agent debug enables a ring buffer on a specific AgentServer process that records internal events as they happen.
Pass debug: true when starting the agent server.
{:ok, pid} = Jido.start_agent(
runtime,
MyApp.CounterAgent,
debug: true
)
Toggle debug mode on an already-running agent server.
:ok = Jido.AgentServer.set_debug(pid, true)
The ring buffer holds up to 500 events. When the buffer fills, the oldest events are dropped.
Retrieve events from the ring buffer with recent_events/2. Events arrive newest-first.
{:ok, events} = Jido.AgentServer.recent_events(pid, limit: 10)
Each event is a map with three keys.
%{
at: -576460734,
type: :signal_received,
data: %{signal_type: "counter.increment"}
}
The :at value is a monotonic timestamp in milliseconds. Use it for relative timing between events, not absolute wall-clock time.
| Type | Recorded when |
|---|---|
:signal_received | A signal arrives at the agent server |
:directive_started | A directive begins execution |
Pattern match on the event list to find specific issues.
{:ok, events} = Jido.AgentServer.recent_events(pid)
signals = Enum.filter(events, &(&1.type == :signal_received))
directives = Enum.filter(events, &(&1.type == :directive_started))
If debug mode is off, recent_events/2 returns {:error, :debug_not_enabled}.
Inspect the full debug configuration for an instance with Jido.Debug.status/1.
Jido.Debug.status(runtime)
This returns a map with the current level and all active overrides.
%{
level: :on,
overrides: %{
telemetry_log_level: :debug,
telemetry_log_args: :keys_only,
observe_log_level: :debug,
observe_debug_events: :minimal
}
}
The override keys control specific subsystems.
| Key | :on value | :verbose value | Controls |
|---|---|---|---|
telemetry_log_level | :debug | :trace | Logger level for telemetry events |
telemetry_log_args | :keys_only | :full | How action arguments appear in logs |
observe_log_level | :debug | :debug | Logger level for the observer |
observe_debug_events | :minimal | :all | Which debug events are emitted |
Named instances expose this as MyApp.Jido.debug_status/0.
When Jido.AgentServer.await_completion/2 times out, it returns a structured diagnostic map instead of a bare :timeout error.
{:error, {:timeout, diagnostic}} =
Jido.AgentServer.await_completion(pid, timeout: 5_000)
The diagnostic map contains five keys.
%{
hint: "Agent is idle but await_completion is blocking",
server_status: :idle,
queue_length: 0,
iteration: nil,
waited_ms: 5000
}
| Status | Queue | Meaning |
|---|---|---|
:idle | Empty | Agent finished processing but its state does not match the await condition |
:waiting | Any | Strategy is waiting for an external response (LLM call, HTTP request) |
:running | Non-empty | Agent is still processing directives |
An :idle timeout with an empty queue usually means the agent completed its work but did not set the expected status field. Check state.agent.state.status to see where it ended up.
Inspect a running agent directly without waiting for completion.
{:ok, state} = Jido.AgentServer.state(pid)
The return value is the full AgentServer.State struct. Access the agent’s domain state through state.agent.state.
state.agent.state.count
state.agent.state.status
For a higher-level view, use status/1 which returns a snapshot of the agent’s strategy state along with process metadata.
{:ok, agent_status} = Jido.AgentServer.status(pid)
agent_status.snapshot.status
Enable debug mode through application config so it activates automatically when the instance starts. This is useful for development environments where you always want verbose output.
Application.put_env(:my_app, MyApp.Jido, debug: true)
Set :verbose for maximum detail.
Application.put_env(:my_app, MyApp.Jido, debug: :verbose)
Jido calls Jido.Debug.maybe_enable_from_config/2 during instance initialization. The config value maps directly: true enables :on level, :verbose enables :verbose level, and any other value (or absence) keeps debug off.
Now that you can inspect agent internals, explore related operational topics.