Skip to content

SubAgentSpec

SubAgentSpec — specification for a named sub-agent.

SubAgentSpec

Bases: BaseModel

Specification for a named sub-agent in a multi-agent system.

Each SubAgentSpec entry registers a fully-built LLMAgent under a human-readable name. The name serves as the registry key on the parent coordinator and as the enum value the coordinator's UseSubAgentTool presents to the LLM for dispatch.

Attributes:

Name Type Description
name str

Unique registry key for this sub-agent. Appears as an enum value in UseSubAgentTool's dispatch schema — must be human-readable and stable.

description str

Short routing signal shown to the coordinator LLM in the <available_subagents> catalog. Should describe capability, not implementation.

agent LLMAgent

The fully-built sub-agent. Held as a live object; Pydantic's arbitrary_types_allowed is required for this field.

max_steps int | None

Optional cap on the number of steps the sub-agent may take per dispatch. Passed to agent.run() to bound runaway executions. None uses the agent's own default.

skills_scopes list[SkillScope] | None

Optional scopes to scan for skills on this sub-agent's dispatches. Passed to agent.run(). None uses the agent's own default ([USER, PROJECT]).

explicit_only_skills set[str] | None

Optional skill names to exclude from this sub-agent's model catalog on dispatch. Passed to agent.run(). None uses the agent's own default (no exclusions).

Source code in src/llm_agents_from_scratch/subagents/spec.py
class SubAgentSpec(BaseModel):
    """Specification for a named sub-agent in a multi-agent system.

    Each ``SubAgentSpec`` entry registers a fully-built ``LLMAgent`` under a
    human-readable name. The name serves as the registry key on the parent
    coordinator and as the enum value the coordinator's ``UseSubAgentTool``
    presents to the LLM for dispatch.

    Attributes:
        name: Unique registry key for this sub-agent. Appears as an enum
            value in ``UseSubAgentTool``'s dispatch schema — must be
            human-readable and stable.
        description: Short routing signal shown to the coordinator LLM in
            the ``<available_subagents>`` catalog. Should describe capability,
            not implementation.
        agent: The fully-built sub-agent. Held as a live object; Pydantic's
            ``arbitrary_types_allowed`` is required for this field.
        max_steps: Optional cap on the number of steps the sub-agent may
            take per dispatch. Passed to ``agent.run()`` to bound runaway
            executions. ``None`` uses the agent's own default.
        skills_scopes: Optional scopes to scan for skills on this
            sub-agent's dispatches. Passed to ``agent.run()``. ``None``
            uses the agent's own default (``[USER, PROJECT]``).
        explicit_only_skills: Optional skill names to exclude from this
            sub-agent's model catalog on dispatch. Passed to
            ``agent.run()``. ``None`` uses the agent's own default (no
            exclusions).
    """

    model_config = ConfigDict(arbitrary_types_allowed=True)

    name: str = Field(
        description=(
            "Unique registry key for this sub-agent. Appears as an enum "
            "value in UseSubAgentTool's dispatch schema."
        ),
    )
    description: str = Field(
        description=(
            "Routing signal shown to the coordinator LLM in the "
            "<available_subagents> catalog."
        ),
    )
    agent: LLMAgent = Field(
        description="The fully-built sub-agent to dispatch tasks to.",
    )
    max_steps: int | None = Field(
        default=None,
        description=(
            "Optional cap on sub-agent steps per dispatch. "
            "None uses the agent's own default."
        ),
    )
    skills_scopes: list[SkillScope] | None = Field(
        default=None,
        description=(
            "Optional scopes to scan for skills on this sub-agent's "
            "dispatches. None uses the agent's own default."
        ),
    )
    explicit_only_skills: set[str] | None = Field(
        default=None,
        description=(
            "Optional skill names to exclude from this sub-agent's model "
            "catalog on dispatch. None uses the agent's own default."
        ),
    )

    def catalog(self) -> str:
        """Return XML entry for this spec in the sub-agents catalog."""
        return CATALOG_SPEC_TEMPLATE.format(
            name=self.name,
            description=self.description,
        )

catalog

catalog()

Return XML entry for this spec in the sub-agents catalog.

Source code in src/llm_agents_from_scratch/subagents/spec.py
def catalog(self) -> str:
    """Return XML entry for this spec in the sub-agents catalog."""
    return CATALOG_SPEC_TEMPLATE.format(
        name=self.name,
        description=self.description,
    )