Packages
claude_code
0.13.1
0.36.5
0.36.4
0.36.3
0.36.2
0.36.1
0.36.0
0.35.0
0.34.0
0.33.1
0.32.2
0.32.0
0.31.0
0.30.0
0.29.0
0.28.0
0.27.0
0.26.0
0.25.0
0.24.0
0.23.0
0.22.0
0.21.0
0.20.0
0.19.0
0.18.0
0.17.0
0.16.0
0.15.0
0.14.0
0.13.3
0.13.2
0.13.1
0.13.0
0.12.0
0.11.0
0.10.0
0.9.0
0.8.1
0.8.0
0.7.0
0.6.0
0.5.0
0.4.0
0.3.0
0.2.0
0.1.0
Claude Agent SDK for Elixir – Build AI agents with Claude Code
Current section
Files
Jump to
Current section
Files
lib/claude_code/supervisor.ex
defmodule ClaudeCode.Supervisor do
@moduledoc """
Supervisor for managing multiple ClaudeCode sessions.
This supervisor allows you to start and manage multiple named Claude sessions
in your application's supervision tree, providing fault tolerance and automatic
restart capabilities.
## Examples
### Basic usage with predefined sessions
children = [
{ClaudeCode.Supervisor, [
[name: :code_reviewer, api_key: api_key, system_prompt: "You are an expert code reviewer"],
[name: :test_writer, api_key: api_key, system_prompt: "You write comprehensive tests"]
]}
]
Supervisor.start_link(children, strategy: :one_for_one)
### Using global names for distributed access
children = [
{ClaudeCode.Supervisor, [
[name: {:global, :main_assistant}, api_key: api_key],
[name: {:via, Registry, {MyApp.Registry, :helper}}, api_key: api_key]
]}
]
### Dynamic session management
# Start the supervisor without initial sessions
{:ok, supervisor} = ClaudeCode.Supervisor.start_link([])
# Add sessions dynamically
ClaudeCode.Supervisor.start_session(supervisor, [
name: :dynamic_session,
api_key: api_key,
system_prompt: "Dynamic helper"
])
# Remove sessions when no longer needed
ClaudeCode.Supervisor.terminate_session(supervisor, :dynamic_session)
## Session Access
Once supervised, sessions can be accessed by name from anywhere in your application:
# Query a supervised session
{:ok, response} = ClaudeCode.query(:code_reviewer, "Review this function")
# Stream from a supervised session
:test_writer
|> ClaudeCode.query_stream("Write tests for UserController")
|> Stream.each(&IO.inspect/1)
|> Stream.run()
## Fault Tolerance
If a session crashes, the supervisor will automatically restart it:
- Session state is lost but the process name is preserved
- Conversation history is cleared on restart
- Other sessions continue running unaffected
## Configuration
Sessions inherit application configuration and can override specific options:
# config/config.exs
config :claude_code,
model: "opus",
timeout: 300_000
# Supervisor sessions automatically use app config
{ClaudeCode.Supervisor, [
[name: :assistant, api_key: api_key], # Uses app config defaults
[name: :writer, api_key: api_key, model: "sonnet"] # Overrides model
]}
"""
use Supervisor
@doc """
Starts the ClaudeCode supervisor.
## Arguments
- `sessions` - List of session configurations. Each session config is a keyword list
of options passed to `ClaudeCode.Session.start_link/1`.
## Options
- `:name` - Name for the supervisor process (optional)
- `:strategy` - Supervision strategy (defaults to `:one_for_one`)
- `:max_restarts` - Maximum restarts allowed (defaults to `3`)
- `:max_seconds` - Time window for max restarts (defaults to `5`)
## Examples
# Start with predefined sessions
{:ok, sup} = ClaudeCode.Supervisor.start_link([
[name: :assistant, api_key: "sk-ant-..."],
[name: :reviewer, api_key: "sk-ant-...", system_prompt: "Review code"]
])
# Start empty supervisor for dynamic management
{:ok, sup} = ClaudeCode.Supervisor.start_link([])
# Start with custom supervisor options
{:ok, sup} = ClaudeCode.Supervisor.start_link(
[
[name: :assistant, api_key: "sk-ant-..."]
],
name: MyApp.ClaudeSupervisor,
max_restarts: 5,
max_seconds: 10
)
"""
def start_link(sessions, opts \\ []) do
{supervisor_opts, _session_opts} = extract_supervisor_options(opts)
supervisor_name = supervisor_opts[:name]
case supervisor_name do
nil ->
Supervisor.start_link(__MODULE__, {sessions, supervisor_opts})
name ->
Supervisor.start_link(__MODULE__, {sessions, supervisor_opts}, name: name)
end
end
@doc """
Dynamically starts a new session under the supervisor.
## Arguments
- `supervisor` - PID or name of the ClaudeCode.Supervisor
- `session_config` - Keyword list of session options
## Examples
ClaudeCode.Supervisor.start_session(supervisor, [
name: :new_assistant,
api_key: api_key,
system_prompt: "You are helpful"
])
# With custom child ID
ClaudeCode.Supervisor.start_session(supervisor, [
name: :temp_session,
api_key: api_key
], id: :my_temp_session)
"""
def start_session(supervisor, session_config, opts \\ []) do
child_id = opts[:id] || session_config[:name] || make_ref()
child_spec = %{
id: child_id,
start: {ClaudeCode.Session, :start_link, [session_config]},
restart: :permanent,
shutdown: 5000,
type: :worker
}
Supervisor.start_child(supervisor, child_spec)
end
@doc """
Terminates a session managed by the supervisor.
## Arguments
- `supervisor` - PID or name of the ClaudeCode.Supervisor
- `session_id` - Child ID or session name
## Examples
ClaudeCode.Supervisor.terminate_session(supervisor, :old_session)
"""
def terminate_session(supervisor, session_id) do
Supervisor.terminate_child(supervisor, session_id)
Supervisor.delete_child(supervisor, session_id)
end
@doc """
Lists all sessions currently managed by the supervisor.
Returns a list of `{child_id, child_pid, type, modules}` tuples.
## Examples
sessions = ClaudeCode.Supervisor.list_sessions(supervisor)
#=> [{:assistant, #PID<0.123.0>, :worker, [ClaudeCode.Session]}]
"""
def list_sessions(supervisor) do
Supervisor.which_children(supervisor)
end
@doc """
Gets the count of sessions managed by the supervisor.
## Examples
count = ClaudeCode.Supervisor.count_sessions(supervisor)
#=> 3
"""
def count_sessions(supervisor) do
supervisor
|> Supervisor.count_children()
|> Map.get(:active, 0)
end
@doc """
Restarts a specific session.
This will terminate the current session process and start a new one with the same configuration.
Note that conversation history will be lost.
## Examples
:ok = ClaudeCode.Supervisor.restart_session(supervisor, :assistant)
"""
def restart_session(supervisor, session_id) do
case Supervisor.restart_child(supervisor, session_id) do
{:ok, _child} -> :ok
{:ok, _child, _info} -> :ok
{:error, reason} -> {:error, reason}
end
end
# Supervisor Callbacks
@impl true
def init({sessions, supervisor_opts}) do
# Extract supervision strategy options
strategy = supervisor_opts[:strategy] || :one_for_one
max_restarts = supervisor_opts[:max_restarts] || 3
max_seconds = supervisor_opts[:max_seconds] || 5
# Build child specifications
children = Enum.map(sessions, &build_child_spec/1)
Supervisor.init(children,
strategy: strategy,
max_restarts: max_restarts,
max_seconds: max_seconds
)
end
# Private Functions
defp extract_supervisor_options(opts) do
supervisor_keys = [:name, :strategy, :max_restarts, :max_seconds]
{supervisor_opts, _session_opts} = Keyword.split(opts, supervisor_keys)
{supervisor_opts, []}
end
defp build_child_spec(session_config) do
# Use session name as child ID, fallback to unique reference
child_id = session_config[:name] || make_ref()
%{
id: child_id,
start: {ClaudeCode.Session, :start_link, [session_config]},
restart: :permanent,
shutdown: 5000,
type: :worker
}
end
end