defmodule AgentSea.Crew do @moduledoc """ A crew of agents that collaborate on a task DAG. Starting a crew boots a supervision subtree (a `Task.Supervisor`, a `DynamicSupervisor` of agents, and a coordinator). Tasks are added, then `kickoff/1` runs them — dispatching ready tasks to agents via the configured delegation strategy, running independent tasks concurrently, and unlocking dependents as results arrive. ## Example spec = %AgentSea.Crew.Spec{ name: :research_crew, strategy: AgentSea.Crew.Delegation.BestMatch, agents: [researcher_config, writer_config] } {:ok, _sup} = AgentSea.Crew.start_link(spec) AgentSea.Crew.add_task(:research_crew, description: "Research X", required_capabilities: ["research"]) {:ok, result} = AgentSea.Crew.kickoff(:research_crew) """ defmodule Spec do @moduledoc "Declarative crew configuration." @enforce_keys [:name, :agents] defstruct [ :name, :agents, strategy: AgentSea.Crew.Delegation.BestMatch, delegation_ctx: %{} ] @type t :: %__MODULE__{ name: term(), agents: [AgentSea.Agent.Config.t()], strategy: module(), delegation_ctx: map() } end @doc "Start a crew supervision subtree from a `Spec`." def start_link(%Spec{} = spec), do: AgentSea.Crew.Supervisor.start_link(spec) @doc false def child_spec(%Spec{name: name} = spec) do %{id: {:crew, name}, start: {__MODULE__, :start_link, [spec]}, type: :supervisor} end @doc "Add a task to the crew (only while idle). Accepts `AgentSea.Crew.Task.new/1` attrs." defdelegate add_task(crew, attrs), to: AgentSea.Crew.Coordinator @doc "Run the crew to completion; returns `{:ok, result}` with results & failures." defdelegate kickoff(crew), to: AgentSea.Crew.Coordinator @doc "Current crew status: `:idle | :running | :paused | :completed | :aborted`." defdelegate status(crew), to: AgentSea.Crew.Coordinator @doc "Pause dispatching (in-flight tasks finish). Only while `:running`." defdelegate pause(crew), to: AgentSea.Crew.Coordinator @doc "Resume dispatching after a pause. Only while `:paused`." defdelegate resume(crew), to: AgentSea.Crew.Coordinator @doc "Abort: cancel in-flight tasks; the kickoff caller gets `{:error, :aborted}`." defdelegate abort(crew), to: AgentSea.Crew.Coordinator end