Jido.AI (Jido AI v2.1.0)

View Source

AI integration layer for the Jido ecosystem.

Jido.AI provides a unified interface for AI interactions, built on ReqLLM and integrated with the Jido action framework.

Features

  • Model aliases for semantic model references
  • Lightweight app-configured LLM defaults
  • Thin ReqLLM generation facades
  • Action-based AI workflows
  • Splode-based error handling

Model Aliases

Use semantic model aliases instead of hardcoded model strings:

Jido.AI.resolve_model(:fast)      # => "provider:fast-model"
Jido.AI.resolve_model(:capable)   # => "provider:capable-model"

Configure custom aliases in your config:

config :jido_ai,
  model_aliases: %{
    fast: "provider:your-fast-model",
    capable: "provider:your-capable-model"
  }

A broad list of provider/model IDs is available at: https://llmdb.xyz

LLM Defaults

Configure small, role-based defaults for top-level generation helpers:

config :jido_ai,
  llm_defaults: %{
    text: %{model: :fast, temperature: 0.2, max_tokens: 1024},
    object: %{model: :thinking, temperature: 0.0, max_tokens: 1024},
    stream: %{model: :fast, temperature: 0.2, max_tokens: 1024}
  }

Then call the facade directly:

{:ok, response} = Jido.AI.generate_text("Summarize this in one sentence.")
{:ok, json} = Jido.AI.generate_object("Extract fields", schema)
{:ok, stream} = Jido.AI.stream_text("Stream this response")

Runtime Tool Management

Register and unregister tools dynamically with running agents:

# Register a new tool
{:ok, agent} = Jido.AI.register_tool(agent_pid, MyApp.Tools.Calculator)

# Unregister a tool by name
{:ok, agent} = Jido.AI.unregister_tool(agent_pid, "calculator")

# List registered tools
{:ok, tools} = Jido.AI.list_tools(agent_pid)

# Check if a tool is registered
{:ok, true} = Jido.AI.has_tool?(agent_pid, "calculator")

Tools must implement the Jido.Action behaviour (name/0, schema/0, run/2).

Summary

Functions

Convenience helper that returns extracted response text.

Returns the strategy config from an agent struct.

Returns the active context (conversation history) from the strategy state.

Checks if a specific tool is registered with an agent.

Lists all currently registered tools for an agent.

Returns configured LLM generation defaults merged with built-in defaults.

Returns defaults for a specific generation kind: :text, :object, or :stream.

Returns all configured model aliases merged with defaults.

Returns a stable human-readable label for a model input.

Registers a tool module with a running agent.

Resolves a model alias or passes through a direct ReqLLM model input.

Updates the base ReAct system prompt for a running agent.

Sets the system prompt directly on the agent's strategy config.

Unregisters a tool from a running agent by name.

Updates the active context entries (conversation messages) in the strategy state.

Types

llm_generation_opts()

@type llm_generation_opts() :: %{
  optional(:model) => model_input(),
  optional(:system_prompt) => String.t(),
  optional(:max_tokens) => non_neg_integer(),
  optional(:temperature) => number(),
  optional(:timeout) => pos_integer()
}

llm_kind()

@type llm_kind() :: :text | :object | :stream

model_alias()

@type model_alias() ::
  :fast
  | :capable
  | :thinking
  | :reasoning
  | :planning
  | :image
  | :embedding
  | atom()

model_input()

@type model_input() :: model_alias() | resolved_model_input()

model_spec()

@type model_spec() :: String.t()

resolved_model_input()

@type resolved_model_input() ::
  model_spec()
  | map()
  | {atom(), model_spec(), keyword()}
  | {atom(), keyword()}
  | %LLMDB.Model{
      aliases: term(),
      base_url: term(),
      capabilities: term(),
      cost: term(),
      deprecated: term(),
      extra: term(),
      family: term(),
      id: term(),
      knowledge: term(),
      last_updated: term(),
      lifecycle: term(),
      limits: term(),
      modalities: term(),
      model: term(),
      name: term(),
      pricing: term(),
      provider: term(),
      provider_model_id: term(),
      release_date: term(),
      retired: term(),
      tags: term()
    }

Functions

ask(input, opts \\ [])

@spec ask(
  term(),
  keyword()
) :: {:ok, String.t()} | {:error, term()}

Convenience helper that returns extracted response text.

generate_object(input, object_schema, opts \\ [])

@spec generate_object(term(), term(), keyword()) :: {:ok, term()} | {:error, term()}

Thin facade for ReqLLM.Generation.generate_object/4.

opts has the same behavior as generate_text/2.

generate_text(input, opts \\ [])

@spec generate_text(
  term(),
  keyword()
) :: {:ok, term()} | {:error, term()}

Thin facade for ReqLLM.Generation.generate_text/3.

opts supports:

  • :model - model alias or direct model spec
  • :system_prompt - optional system prompt
  • :max_tokens, :temperature, :timeout
  • Any other ReqLLM options (e.g. :tools, :tool_choice) as pass-through options

get_strategy_config(agent)

@spec get_strategy_config(Jido.Agent.t()) :: map()

Returns the strategy config from an agent struct.

Convenience for reading strategy config without reaching into internal state.

get_strategy_context(agent)

@spec get_strategy_context(Jido.Agent.t()) :: map() | nil

Returns the active context (conversation history) from the strategy state.

Prefers :run_context while a request is in flight, otherwise falls back to materialized :context. Returns nil if neither exists.

has_tool?(agent, tool_name)

@spec has_tool?(Jido.Agent.t() | GenServer.server(), String.t()) ::
  boolean() | {:ok, boolean()} | {:error, term()}

Checks if a specific tool is registered with an agent.

Can be called with either an agent struct or an agent server (PID/name).

Examples

# With agent struct
true = Jido.AI.has_tool?(agent, "calculator")

# With agent server
{:ok, true} = Jido.AI.has_tool?(agent_pid, "calculator")

inject(agent_server, content, opts \\ [])

@spec inject(GenServer.server(), String.t(), keyword()) ::
  {:ok, Jido.Agent.t()} | {:error, term()}

Compatibility wrapper for Jido.AI.Reasoning.ReAct.inject/3.

list_tools(agent)

@spec list_tools(Jido.Agent.t() | GenServer.server()) ::
  [module()] | {:ok, [module()]} | {:error, term()}

Lists all currently registered tools for an agent.

Can be called with either an agent struct or an agent server (PID/name).

Examples

# With agent struct
tools = Jido.AI.list_tools(agent)

# With agent server
{:ok, tools} = Jido.AI.list_tools(agent_pid)

llm_defaults()

@spec llm_defaults() :: %{required(llm_kind()) => llm_generation_opts()}

Returns configured LLM generation defaults merged with built-in defaults.

Configure under config :jido_ai, :llm_defaults.

llm_defaults(kind)

@spec llm_defaults(llm_kind()) :: llm_generation_opts()

Returns defaults for a specific generation kind: :text, :object, or :stream.

model_aliases()

@spec model_aliases() :: %{required(model_alias()) => model_spec()}

Returns all configured model aliases merged with defaults.

User overrides from config :jido_ai, :model_aliases are merged on top of built-in defaults.

Examples

iex> aliases = Jido.AI.model_aliases()
iex> is_binary(aliases[:fast])
true

model_label(model)

@spec model_label(model_input()) :: String.t()

Returns a stable human-readable label for a model input.

register_tool(agent_server, tool_module, opts \\ [])

@spec register_tool(GenServer.server(), module(), keyword()) ::
  {:ok, Jido.Agent.t()} | {:error, term()}

Registers a tool module with a running agent.

The tool must implement the Jido.Action behaviour (have name/0, schema/0, and run/2).

Options

  • :timeout - Call timeout in milliseconds (default: 5000)
  • :validate - Validate tool implements required callbacks (default: true)

Examples

{:ok, agent} = Jido.AI.register_tool(agent_pid, MyApp.Tools.Calculator)
{:error, :not_a_tool} = Jido.AI.register_tool(agent_pid, NotATool)

resolve_model(model)

@spec resolve_model(model_input()) :: resolved_model_input()

Resolves a model alias or passes through a direct ReqLLM model input.

Model aliases are atoms like :fast, :capable, :reasoning that map to full ReqLLM model specifications. Direct model inputs are passed through unchanged and may be strings, ReqLLM tuples, inline maps, or %LLMDB.Model{} structs.

Arguments

  • model - Either a model alias atom or a direct ReqLLM model input

Returns

A resolved ReqLLM model input.

Examples

iex> String.contains?(Jido.AI.resolve_model(:fast), ":")
true

iex> Jido.AI.resolve_model("openai:gpt-4")
"openai:gpt-4"

iex> Jido.AI.resolve_model({:openai, "gpt-4.1", []})
{:openai, "gpt-4.1", []}

Jido.AI.resolve_model(:unknown_alias)
# raises ArgumentError with unknown alias message

set_system_prompt(agent_server, prompt, opts \\ [])

@spec set_system_prompt(GenServer.server(), String.t(), keyword()) ::
  {:ok, Jido.Agent.t()} | {:error, term()}

Updates the base ReAct system prompt for a running agent.

Options

  • :timeout - Call timeout in milliseconds (default: 5000)

set_system_prompt_direct(agent, prompt)

@spec set_system_prompt_direct(Jido.Agent.t(), String.t()) :: Jido.Agent.t()

Sets the system prompt directly on the agent's strategy config.

This is the struct-level equivalent of set_system_prompt/3 — safe to call from within the agent process (e.g., on_before_cmd).

Also updates the system prompt in :context and :run_context if they exist, so resumed conversations pick up the new prompt.

steer(agent_server, content, opts \\ [])

@spec steer(GenServer.server(), String.t(), keyword()) ::
  {:ok, Jido.Agent.t()} | {:error, term()}

Compatibility wrapper for Jido.AI.Reasoning.ReAct.steer/3.

stream_text(input, opts \\ [])

@spec stream_text(
  term(),
  keyword()
) :: {:ok, term()} | {:error, term()}

Thin facade for ReqLLM.stream_text/3.

Returns ReqLLM stream response directly.

unregister_tool(agent_server, tool_name, opts \\ [])

@spec unregister_tool(GenServer.server(), String.t(), keyword()) ::
  {:ok, Jido.Agent.t()} | {:error, term()}

Unregisters a tool from a running agent by name.

Options

  • :timeout - Call timeout in milliseconds (default: 5000)

Examples

{:ok, agent} = Jido.AI.unregister_tool(agent_pid, "calculator")

update_context_entries(agent, entries)

@spec update_context_entries(Jido.Agent.t(), list()) :: Jido.Agent.t()

Updates the active context entries (conversation messages) in the strategy state.

If :run_context exists, it is treated as authoritative for the in-flight turn and updated in isolation. Otherwise, updates materialized :context.