Normandy.Coordination.HierarchicalCoordinator
(normandy v2.2.0)
View Source
Coordinates hierarchical multi-agent systems with manager-worker patterns.
The Hierarchical Coordinator implements a manager-worker pattern where a manager agent delegates tasks to worker agents and aggregates results.
execute/3 runs the manager twice, both times from the config the coordinator holds:
the aggregation call is a fresh conversation that does not include the planning call;
it gets the workers' results, each under its worker id.
Errors
{:error, {:manager_failed, exception}} when the planning call fails and
{:error, {:aggregation_failed, exception}} when the aggregation call does. The
exception is Normandy's own (Normandy.LLMError, Normandy.Schema.ValidationError,
...), the exception a bug raised (logged with its stacktrace, arities only), or a
:task_down Normandy.TurnError for an exit or a throw. No stacktrace is returned.
A failed worker does not fail the call: the manager is told about it.
Example
coordinator = HierarchicalCoordinator.new(
manager: manager_agent,
workers: [
%{id: "worker_1", agent: worker1},
%{id: "worker_2", agent: worker2}
],
delegation_strategy: :round_robin
)
{:ok, result} = HierarchicalCoordinator.execute(coordinator, "Analyze this dataset")
Summary
Functions
Adds a worker to the coordinator.
Executes the hierarchical coordination.
Executes with explicit task delegation.
Creates a new hierarchical coordinator.
Removes a worker from the coordinator.
Types
@type delegation_strategy() :: :round_robin | :broadcast | :conditional
@type t() :: %Normandy.Coordination.HierarchicalCoordinator{ delegation_strategy: delegation_strategy(), manager: struct(), workers: [%{id: String.t(), agent: struct()}] }
Functions
Adds a worker to the coordinator.
Example
coordinator = HierarchicalCoordinator.add_worker(
coordinator,
"new_worker",
new_agent
)
@spec execute(t(), term(), keyword()) :: {:ok, term()} | {:error, {:manager_failed | :aggregation_failed, Exception.t()}}
Executes the hierarchical coordination.
The manager agent analyzes the input and decides how to delegate work to worker agents.
Options
:max_concurrency(pos_integer/0) - Workers run at once. The default value is5.:manager_prompt(String.t/0) - A prompt put before the input the manager gets.
Example
{:ok, result} = HierarchicalCoordinator.execute(
coordinator,
input,
manager_prompt: "Break down this task for worker agents"
)
@spec execute_with_tasks(t(), [%{worker_id: String.t(), task: term()}], keyword()) :: {:ok, term()} | {:error, {:aggregation_failed, Exception.t()}}
Executes with explicit task delegation.
Bypasses manager's delegation planning and directly assigns tasks to workers.
Options
:max_concurrency(pos_integer/0) - Workers run at once. The default value is5.
Example
tasks = [
%{worker_id: "worker_1", task: "Research topic A"},
%{worker_id: "worker_2", task: "Research topic B"}
]
{:ok, result} = HierarchicalCoordinator.execute_with_tasks(
coordinator,
tasks
)
Creates a new hierarchical coordinator.
Options
:manager(term/0) - Required. The manager agent.:workers(a list of%{id: String.t(), agent: agent}maps) - Required. The workers, each%{id: String.t(), agent: agent}.:delegation_strategy- How the manager's plan is delegated. The default value is:round_robin.
Example
coordinator = HierarchicalCoordinator.new(
manager: manager_agent,
workers: [
%{id: "worker_1", agent: worker1},
%{id: "worker_2", agent: worker2}
],
delegation_strategy: :broadcast
)
Removes a worker from the coordinator.
Example
coordinator = HierarchicalCoordinator.remove_worker(coordinator, "worker_1")