jeevesagent.architecture.supervisor
===================================

.. py:module:: jeevesagent.architecture.supervisor

.. autoapi-nested-parse::

   Supervisor: workers + a ``delegate`` tool injected into the loop.

   Anthropic Multi-Agent Research System (2026 internal report) +
   Anthropic Agent Teams (Feb 2026). The 2026 production consensus:
   **hierarchical Supervisor is the multi-agent pattern that earns its
   cost in production.** Anthropic reports +90.2% on their MA research
   benchmark vs single-agent baseline.

   Pattern
   -------

   The supervisor itself runs an architecture (default
   :class:`ReAct`). Its tool host is augmented with one extra tool:
   ``delegate(worker, instructions)``. When the supervising model
   calls ``delegate``, the named worker :class:`Agent` runs to
   completion with the supervisor's instructions and returns its final
   answer as the tool result.

   Because :class:`ReAct`'s tool dispatch is already parallel
   (:func:`anyio.create_task_group` over all tool calls in a turn),
   **the supervisor gets parallel delegation for free** — emit two
   ``delegate`` calls in one turn and both workers run concurrently.

   Replay correctness
   ------------------
   Each ``delegate`` call is wrapped by ``runtime.step`` at the
   parent's tool dispatch layer (see ReAct), so the worker's full
   :class:`RunResult.output` is journaled in the parent's session.
   Replays return the cached worker output without re-running the
   worker. The worker is itself an :class:`Agent` and uses a
   collision-free session id (parent + worker name + a fresh ULID)
   when it does run.

   Composition
   -----------
   * Workers can be any architecture themselves (DeepAgent worker for
     research, ActorCritic worker for code, plain Agent for simple
     specialists).
   * Workers can be supervisors (nested teams).
   * Wrap Supervisor in Reflexion for cross-session learning of which
     worker handles which intent best.



Attributes
----------

.. autoapisummary::

   jeevesagent.architecture.supervisor.DEFAULT_SUPERVISOR_TEMPLATE


Classes
-------

.. autoapisummary::

   jeevesagent.architecture.supervisor.Supervisor


Module Contents
---------------

.. py:class:: Supervisor(*, workers: dict[str, jeevesagent.agent.api.Agent], base: jeevesagent.architecture.base.Architecture | None = None, instructions_template: str | None = None, delegate_tool_name: str = 'delegate', forward_tool_name: str = 'forward_message')

   Coordinator + workers, glued by a ``delegate`` tool.

   The supervisor's base architecture (default :class:`ReAct`) sees
   a fresh ``delegate(worker, instructions)`` tool that routes calls
   to the named worker :class:`Agent`. Worker outputs come back as
   tool results just like any other tool call.

   Constructor
   -----------
   * ``workers``: dict mapping role-names to fully-built
     :class:`Agent` instances. Names must be valid identifiers
     (the model emits them as the ``worker`` argument).
   * ``base``: the architecture the supervisor itself runs.
     Default :class:`ReAct`. Wrap inside :class:`Reflexion` to
     learn delegation patterns across runs.
   * ``instructions_template``: format string with
     ``{worker_descriptions}``. Default teaches the supervisor
     to delegate effectively. The agent's own ``instructions``
     are *prepended* (so domain context survives).
   * ``delegate_tool_name``: defaults to ``"delegate"``. Customize
     to avoid clashes with user-defined tools that happen to have
     the same name.
   * ``forward_tool_name``: defaults to ``"forward_message"``. The
     supervisor calls this with a worker name to return that
     worker's last output VERBATIM as the supervisor's final
     response. Skips a synthesis round-trip — the
     `langchain.com/blog/benchmarking-multi-agent-architectures`_
     benchmark showed +50% quality on tasks where the supervisor
     would otherwise paraphrase a worker's output.


   .. py:method:: add_worker(name: str, agent: jeevesagent.agent.api.Agent) -> None

      Register a worker between runs.

      Safe to call between :meth:`Agent.run` invocations on the
      agent that owns this supervisor; the new worker becomes
      available for ``delegate(name, ...)`` on the next run.
      Calling mid-run is undefined — the supervisor's prompt is
      composed at run start.



   .. py:method:: declared_workers() -> dict[str, jeevesagent.agent.api.Agent]


   .. py:method:: remove_worker(name: str) -> jeevesagent.agent.api.Agent | None

      Unregister a worker by name. Returns the removed Agent
      if it was registered, ``None`` otherwise. Same lifecycle
      rules as :meth:`add_worker`.



   .. py:method:: run(session: jeevesagent.architecture.base.AgentSession, deps: jeevesagent.architecture.base.Dependencies, prompt: str) -> collections.abc.AsyncIterator[jeevesagent.core.types.Event]
      :async:



   .. py:attribute:: name
      :value: 'supervisor'



.. py:data:: DEFAULT_SUPERVISOR_TEMPLATE
   :value: Multiline-String

   .. raw:: html

      <details><summary>Show Value</summary>

   .. code-block:: python

      """You are a supervisor coordinating specialist worker agents.
      
      For each task you receive:
      1. Decide which workers are needed.
      2. Call `delegate(worker, instructions)` to invoke a specialist.
      3. Each worker runs independently and returns its final answer.
      4. Either synthesize worker outputs into a unified response, OR
         call `forward_message(worker)` if a single worker's output IS
         already the final answer the user wants. Forwarding skips a
         paraphrase round-trip: the worker's output is returned verbatim
         as YOUR final response. End your turn immediately after a
         forward_message call.
      
      You can delegate multiple workers in a single turn — they will run
      in parallel. Be specific in the ``instructions`` you pass; workers
      do NOT see the user's original message, only what you write.
      
      Available workers:
      {worker_descriptions}
      """

   .. raw:: html

      </details>



