Sagents.Persistence.Hooks behaviour (Sagents v0.8.0-rc.2)

Copy Markdown

Optional behavior for hooking into agent state persistence events.

Implement this behavior to automatically save state at key points in the agent lifecycle without explicit calls.

Usage

Define a module implementing this behavior:

defmodule MyApp.Conversations.Hooks do
  @behaviour Sagents.Persistence.Hooks

  @impl true
  def after_message_received(conversation_id, message) do
    MyApp.Conversations.append_display_message(conversation_id, message)
  end

  @impl true
  def after_agent_response(conversation_id, agent_state) do
    MyApp.Conversations.save_agent_state(conversation_id, agent_state)
  end

  @impl true
  def after_status_change(conversation_id, status, data) do
    # Optional: track status changes
    :ok
  end
end

Then configure it in your application:

# config/config.exs
config :sagents, :persistence,
  adapter: MyApp.Conversations,
  hooks: MyApp.Conversations.Hooks,
  auto_save: true

Hook Callbacks

All callbacks are optional. If a callback is not defined, the hook will be skipped silently.

Error Handling

Hook callbacks should return :ok or {:ok, term()} on success. Errors will be logged but won't interrupt the agent execution.

Summary

Callbacks

Called after the agent produces a response.

Called after a user message is received.

Called when the agent status changes.

Functions

Check if hooks are enabled.

Get the configured hooks module.

Invoke a hook callback if hooks are configured.

Callbacks

after_agent_response(conversation_id, agent_state)

(optional)
@callback after_agent_response(conversation_id :: binary(), agent_state :: map()) ::
  :ok | {:ok, term()} | {:error, term()}

Called after the agent produces a response.

This is typically used to:

  • Save the agent's response message to display messages
  • Save the updated agent state

Parameters

  • conversation_id - The conversation identifier
  • agent_state - The complete agent state (map with string keys from export_state/1)

Returns

:ok or {:ok, term()} on success. Errors are logged but don't interrupt execution.

after_message_received(conversation_id, message)

(optional)
@callback after_message_received(conversation_id :: binary(), message :: term()) ::
  :ok | {:ok, term()} | {:error, term()}

Called after a user message is received.

This is typically used to save the user's message to the display messages table.

Parameters

  • conversation_id - The conversation identifier
  • message - The message struct

Returns

:ok or {:ok, term()} on success. Errors are logged but don't interrupt execution.

after_status_change(conversation_id, status, data)

(optional)
@callback after_status_change(
  conversation_id :: binary(),
  status :: atom(),
  data :: term()
) :: :ok | {:ok, term()} | {:error, term()}

Called when the agent status changes.

This can be used to track agent lifecycle events like:

  • :idle - Ready for work
  • :running - Executing
  • :interrupted - Awaiting human decision
  • :completed - Execution finished
  • :error - Execution failed

Parameters

  • conversation_id - The conversation identifier
  • status - The new status (:idle, :running, :interrupted, :completed, :error)
  • data - Additional data (interrupt_data for :interrupted, error for :error, state for :completed)

Returns

:ok or {:ok, term()} on success. Errors are logged but don't interrupt execution.

Functions

enabled?()

Check if hooks are enabled.

Returns true if a hooks module is configured, false otherwise.

get_hooks_module()

Get the configured hooks module.

Returns the module or nil if not configured.

invoke(callback_name, args)

Invoke a hook callback if hooks are configured.

This is a convenience function for the framework to call hooks without requiring the hooks module to be defined.

Examples

# In AgentServer
Sagents.Persistence.Hooks.invoke(:after_message_received, [conversation_id, message])