Sagents.AgentSupervisor (Sagents v0.8.0-rc.2)

Copy Markdown

Custom supervisor for managing an Agent and its supporting infrastructure.

AgentSupervisor coordinates the lifecycle of:

  • AgentServer - Agent execution and state management
  • SubAgentsDynamicSupervisor - Dynamic supervisor for spawning sub-agents

Supervision Strategy

Uses :rest_for_one strategy to ensure crash resilience:

  • If AgentServer crashes, SubAgentsDynamicSupervisor restarts
  • SubAgentsDynamicSupervisor crashes only affect itself

Filesystem Integration

Filesystems are now managed independently via FileSystemSupervisor. Agents reference filesystems through the filesystem_scope field in the Agent struct. See Sagents.FileSystem for filesystem lifecycle management.

Configuration

Accepts a keyword list with:

  • :agent - The Agent struct (required)
  • :initial_state - Initial State for AgentServer (optional)
  • :pubsub - PubSub configuration as {module(), atom()} tuple or nil (optional, default: nil)
  • :shutdown_delay - Delay in milliseconds to allow the supervisor to gracefully stop all children (optional, default: 5000)
  • :conversation_id - Optional conversation identifier for message persistence (optional, default: nil)
  • :agent_persistence - Module implementing Sagents.AgentPersistence (optional, default: nil)
  • :display_message_persistence - Module implementing Sagents.DisplayMessagePersistence (optional, default: nil)

Examples

# Minimal configuration
{:ok, agent} = Agent.new(
  agent_id: "my-agent",
  model: model,
  base_system_prompt: "You are a helpful assistant."
)

{:ok, sup_pid} = AgentSupervisor.start_link(agent: agent)

# With initial state and PubSub
initial_state = State.new!(%{
  messages: [Message.new_user!("Hello!")]
})

{:ok, sup_pid} = AgentSupervisor.start_link(
  agent: agent,
  initial_state: initial_state,
  pubsub: {Phoenix.PubSub, :my_app_pubsub}
)

# With external filesystem
# Start filesystem separately
{:ok, config} = FileSystemConfig.new(%{
  scope_key: {:user, 123},
  base_directory: "Memories",
  persistence_module: Sagents.FileSystem.Persistence.Disk,
  storage_opts: [path: "/data/users/123"]
})
{:ok, _fs_pid} = FileSystem.ensure_filesystem({:user, 123}, [config])

# Create agent with filesystem reference
{:ok, agent} = Agent.new(%{
  agent_id: "my-agent",
  model: model,
  filesystem_scope: {:user, 123}
})

{:ok, sup_pid} = AgentSupervisor.start_link(agent: agent)

Summary

Functions

Returns a specification to start this module under a supervisor.

Get the name of the AgentSupervisor process for a specific agent.

Get the PID of an AgentSupervisor by agent_id.

Start the AgentSupervisor.

Start the AgentSupervisor and wait for the AgentServer to be ready.

Stop the AgentSupervisor.

Functions

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

get_name(agent_id)

@spec get_name(String.t()) :: GenServer.name()

Get the name of the AgentSupervisor process for a specific agent.

Examples

name = AgentSupervisor.get_name("my-agent-1")
AgentSupervisor.stop(name)

get_pid(agent_id)

@spec get_pid(String.t()) :: {:ok, pid()} | {:error, :not_found}

Get the PID of an AgentSupervisor by agent_id.

Examples

{:ok, pid} = AgentSupervisor.get_pid("my-agent-1")
{:error, :not_found} = AgentSupervisor.get_pid("non-existent")

start_link(config)

@spec start_link(keyword()) :: Supervisor.on_start()

Start the AgentSupervisor.

Options

  • :agent - The Agent struct (required)
  • :initial_state - Initial State for AgentServer (optional)
  • :pubsub - PubSub configuration as {module(), atom()} tuple or nil (optional, default: nil). Used only for Phoenix.Presence presence_diff wiring; per-agent events are delivered directly to subscriber pids via Sagents.Publisher.
  • :inactivity_timeout - Timeout in milliseconds for automatic shutdown (optional, default: 300_000 - 5 minutes) Set to nil or :infinity to disable automatic shutdown
  • :name - Supervisor name registration (optional)
  • :shutdown_delay - Delay in milliseconds to allow the supervisor to gracefully stop all children (optional, default: 5000)
  • :conversation_id - Optional conversation identifier for message persistence (optional, default: nil)
  • :agent_persistence - Module implementing Sagents.AgentPersistence (optional, default: nil)
  • :display_message_persistence - Module implementing Sagents.DisplayMessagePersistence (optional, default: nil)

Examples

{:ok, sup_pid} = AgentSupervisor.start_link(
  agent: agent,
  pubsub: {Phoenix.PubSub, :my_app_pubsub}
)

{:ok, sup_pid} = AgentSupervisor.start_link(
  agent: agent,
  name: AgentSupervisor.get_name("agent-123")
)

# With custom inactivity timeout
{:ok, sup_pid} = AgentSupervisor.start_link(
  agent: agent,
  inactivity_timeout: 600_000  # 10 minutes
)

# Disable automatic shutdown
{:ok, sup_pid} = AgentSupervisor.start_link(
  agent: agent,
  inactivity_timeout: nil
)

stop(agent_id, timeout \\ 5000)

@spec stop(String.t(), timeout()) :: :ok | {:error, :not_found}

Stop the AgentSupervisor.

Examples

AgentSupervisor.stop("my-agent-1")
AgentSupervisor.stop("my-agent-1", 10_000) # 10 second timeout