Jido.Agent.Directive (Jido v2.0.0-rc.0)

View Source

Typed directive structs for Jido.Agent.

A directive is a pure description of an external effect for the runtime (e.g. Jido.AgentServer) to execute. Agents and strategies never interpret or execute directives; they only emit them.

Signal Integration

The Emit directive integrates with Jido.Signal and Jido.Signal.Dispatch:

  • %Emit{} - Dispatch a signal via configured adapters (pid, pubsub, bus, http, etc.)

Design

Directives are bare structs - no tuple wrappers. This enables:

  • Clean pattern matching on struct type
  • Protocol-based dispatch for extensibility
  • External packages can define custom directives

Core Directives

  • %Emit{} - Dispatch a signal via Jido.Signal.Dispatch
  • %Error{} - Signal an error (wraps Jido.Error.t())
  • %Spawn{} - Spawn a generic BEAM child process (fire-and-forget, no tracking)
  • %SpawnAgent{} - Spawn a child Jido agent with full hierarchy tracking
  • %StopChild{} - Request a tracked child agent to stop gracefully
  • %Schedule{} - Schedule a delayed message
  • %Stop{} - Stop the agent process (self)

Usage

alias Jido.Agent.Directive

# Emit a signal (runtime will dispatch via configured adapters)
%Directive.Emit{signal: my_signal}
%Directive.Emit{signal: my_signal, dispatch: {:pubsub, topic: "events"}}
%Directive.Emit{signal: my_signal, dispatch: {:pid, target: pid}}

# Schedule for later
%Directive.Schedule{delay_ms: 5000, message: :timeout}

Extensibility

External packages can define their own directive structs:

defmodule MyApp.Directive.CallLLM do
  defstruct [:model, :prompt, :tag]
end

The runtime dispatches on struct type, so no changes to core are needed.

Summary

Types

Built-in core directives.

t()

Any external directive struct (core or extension).

Functions

Creates a Cron directive for recurring scheduled execution.

Creates a CronCancel directive to stop a recurring job.

Creates an Emit directive.

Creates an Emit directive targeting the agent's parent.

Creates an Emit directive targeting a specific process by PID.

Creates an Error directive.

Creates a Schedule directive.

Creates a Spawn directive.

Creates a SpawnAgent directive for spawning child agents with hierarchy tracking.

Creates a Stop directive.

Creates a StopChild directive to gracefully stop a tracked child agent.

Types

core()

Built-in core directives.

t()

@type t() :: struct()

Any external directive struct (core or extension).

This is intentionally struct() so external packages can define their own directive structs without modifying this type.

Functions

cron(cron_expr, message, opts \\ [])

@spec cron(term(), term(), keyword()) :: Jido.Agent.Directive.Cron.t()

Creates a Cron directive for recurring scheduled execution.

Options

  • :job_id - Logical id for the job (for upsert/cancel)
  • :timezone - Timezone identifier

Examples

Directive.cron("* * * * *", tick_signal)
Directive.cron("@daily", cleanup_signal, job_id: :daily_cleanup)
Directive.cron("0 9 * * MON", weekly_signal, job_id: :monday_9am, timezone: "America/New_York")

cron_cancel(job_id)

@spec cron_cancel(term()) :: Jido.Agent.Directive.CronCancel.t()

Creates a CronCancel directive to stop a recurring job.

Examples

Directive.cron_cancel(:heartbeat)
Directive.cron_cancel(:daily_cleanup)

emit(signal, dispatch \\ nil)

@spec emit(term(), term()) :: Jido.Agent.Directive.Emit.t()

Creates an Emit directive.

Examples

Directive.emit(signal)
Directive.emit(signal, {:pubsub, topic: "events"})

emit_to_parent(agent, signal, extra_opts \\ [])

@spec emit_to_parent(struct(), term(), Keyword.t()) ::
  Jido.Agent.Directive.Emit.t() | nil

Creates an Emit directive targeting the agent's parent.

The agent's state must have a __parent__ field containing a ParentRef struct. This field is automatically populated when an agent is spawned via the SpawnAgent directive.

Returns nil if the agent has no parent. Use List.wrap/1 to safely handle the result when building directive lists.

Options

Same as emit_to_pid/3.

Examples

# In a child agent's action:
defmodule WorkDoneAction do
  use Jido.Action, name: "work.done", schema: []

  def run(_params, context) do
    reply = Signal.new!("worker.result", %{answer: 42}, source: "/worker")
    directive = Directive.emit_to_parent(context.agent, reply)
    {:ok, %{}, List.wrap(directive)}
  end
end

# With sync delivery
Directive.emit_to_parent(agent, signal, delivery_mode: :sync)

emit_to_pid(signal, pid, extra_opts \\ [])

@spec emit_to_pid(term(), pid(), Keyword.t()) :: Jido.Agent.Directive.Emit.t()

Creates an Emit directive targeting a specific process by PID.

This is a convenience for sending signals directly to another agent or process.

Options

All options are passed to the :pid dispatch adapter:

  • :delivery_mode - :async (default) or :sync
  • :timeout - Timeout for sync delivery (default: 5000)

Examples

Directive.emit_to_pid(signal, some_pid)
Directive.emit_to_pid(signal, worker_pid, delivery_mode: :sync)

error(error, context \\ nil)

@spec error(term(), atom() | nil) :: Jido.Agent.Directive.Error.t()

Creates an Error directive.

Examples

Directive.error(Jido.Error.validation_error("Invalid input"))
Directive.error(error, :normalize)

schedule(delay_ms, message)

Creates a Schedule directive.

Examples

Directive.schedule(5000, :timeout)
Directive.schedule(1000, {:check, ref})

spawn(child_spec, tag \\ nil)

@spec spawn(term(), term()) :: Jido.Agent.Directive.Spawn.t()

Creates a Spawn directive.

Examples

Directive.spawn({MyWorker, arg: value})
Directive.spawn(child_spec, :worker_1)

spawn_agent(agent, tag, options \\ [])

@spec spawn_agent(term(), term(), keyword()) :: Jido.Agent.Directive.SpawnAgent.t()

Creates a SpawnAgent directive for spawning child agents with hierarchy tracking.

Options

  • :opts - Additional options for the child AgentServer (map)
  • :meta - Metadata to pass to the child via parent reference (map)

Examples

Directive.spawn_agent(MyWorkerAgent, :worker_1)
Directive.spawn_agent(MyWorkerAgent, :processor, opts: %{initial_state: %{batch_size: 100}})
Directive.spawn_agent(MyWorkerAgent, :handler, meta: %{assigned_topic: "events"})

stop(reason \\ :normal)

@spec stop(term()) :: Jido.Agent.Directive.Stop.t()

Creates a Stop directive.

Examples

Directive.stop()
Directive.stop(:shutdown)

stop_child(tag, reason \\ :normal)

@spec stop_child(term(), term()) :: Jido.Agent.Directive.StopChild.t()

Creates a StopChild directive to gracefully stop a tracked child agent.

Examples

Directive.stop_child(:worker_1)
Directive.stop_child(:processor, :shutdown)