Skip to Content

Team

from loomflow.team import Team

Team builds a multi-agent setup in one call: give it the member agents, and it returns a regular Agent (the coordinator, or the entry point) whose architecture is the matching multi-agent strategy. Use it for single-level teams; it mirrors the builders other frameworks have (create_supervisor, Crew, GroupChatManager).

For the conceptual page see Team facade.

Team is a namespace class: you don’t construct it, and every method is a class-level builder.


Shared parameters

Every builder takes the same coordinator settings as Agent(...), as flat keyword arguments, and forwards them to the Agent it builds:

instructions, model, memory, runtime, budget, permissions, hooks, tools, telemetry, audit_log, max_turns, auto_consolidate, skills, workspace, living_plan, run_until, stop_hooks, max_stop_hook_iterations, prompt_caching, tool_result_summarizer, tool_result_summary_threshold, persist_tool_transcripts, tool_transcript_max_bytes, snip_window, auto_compact_at_tokens, auto_compact_summariser, auto_compact_keep_recent_turns, retry_policy, auto_extract, approval_handler, secrets, response_tone, effort, strict_effort.

The knobs that live on Tuning for a plain Agent (retry_policy, secrets, stop_hooks and so on) are passed flat here; the builder packs them into a Tuning for you. See the Agent reference for what each one does.

Every builder also takes persistent_subagents: bool = True. With it on, each member keeps one stable session across delegations, handoffs or rounds, and across separate run() calls, so members remember earlier work. Set it to False to give each call a fresh conversation.

Member sessions are kept per user: each user_id gets its own stable session of each member (anonymous runs share one), so a shared team never replays one user’s work into another’s run. Member ids are derived from the role and instructions, the same in every process, so a team rebuilt after a restart finds its members’ memory and, on a durable runtime, resumes a crashed run without repeating their side effects.

The signatures below list only each builder’s own parameters.


Team.supervisor

@classmethod def supervisor( cls, workers: dict[str, Agent], *, instructions: str = "", # ...shared parameters... instructions_template: str | None = None, delegate_tool_name: str = "delegate", forward_tool_name: str = "forward_message", persistent_subagents: bool = True, allow_spawn: bool = False, max_spawned: int = 5, spawn_template: Agent | None = None, ) -> Agent: ...

Returns an Agent whose architecture is Supervisor(workers=..., ...).

ParameterDefaultNote
workersrequiredRole-name → Agent mapping.
instructions""Coordinator system prompt (prepended to the supervisor template).
instructions_template / delegate_tool_name / forward_tool_nameSupervisor’s defaultsForwarded to the architecture.
allow_spawn / max_spawned / spawn_templateFalse / 5 / NoneLet the coordinator create temporary workers during a run. See Supervisor.
team = Team.supervisor( workers={"researcher": researcher, "writer": writer}, instructions="manage the pipeline", model="claude-opus-4-7", ) result = await team.run("write me a blog post")

Team.swarm

@classmethod def swarm( cls, agents: dict[str, Agent | Handoff], entry_agent: str, *, instructions: str = "", # ...shared parameters... max_handoffs: int = 8, detect_cycles: bool = True, pass_full_history: bool = True, handoff_tool_name: str = "handoff", persistent_subagents: bool = True, ) -> Agent: ...

Returns an Agent whose architecture is Swarm(agents=..., entry_agent=..., ...).

team = Team.swarm( agents={"triage": triage, "billing": billing, "tech": tech}, entry_agent="triage", model="claude-opus-4-7", )

Team.router

@classmethod def router( cls, routes: list[RouterRoute], *, instructions: str = "", # ...shared parameters... fallback_route: str | None = None, require_confidence_above: float = 0.0, classifier_prompt: str | None = None, decider: Any | None = None, persistent_subagents: bool = True, conversation_scope: str = "per_route", ) -> Agent: ...

Returns an Agent whose architecture is Router(routes=..., ...).

team = Team.router( routes=[ RouterRoute(name="billing", agent=billing, description="..."), RouterRoute(name="tech", agent=tech, description="..."), ], instructions="customer support entry point", model="claude-haiku-4-5", )

Team.debate

@classmethod def debate( cls, debaters: list[Agent], *, judge: Agent | None = None, instructions: str = "", # ...shared parameters... rounds: int = 2, convergence_check: bool = True, convergence_similarity: float = 0.85, debater_instructions: str | None = None, judge_instructions: str | None = None, persistent_subagents: bool = True, ) -> Agent: ...

Returns an Agent whose architecture is MultiAgentDebate(debaters=..., judge=..., ...).

team = Team.debate( debaters=[optimist, skeptic, analyst], judge=cio, rounds=2, convergence_similarity=0.85, model="claude-opus-4-7", )

Team.actor_critic

@classmethod def actor_critic( cls, actor: Agent, critic: Agent, *, instructions: str = "", # ...shared parameters... max_rounds: int = 3, approval_threshold: float = 0.9, critique_template: str | None = None, refine_template: str | None = None, persistent_subagents: bool = True, ) -> Agent: ...

Returns an Agent whose architecture is ActorCritic(actor=..., critic=..., ...).

team = Team.actor_critic( actor=Agent("Generate", model="claude-opus-4-7"), critic=Agent("Critique", model="gpt-4o"), max_rounds=3, approval_threshold=0.9, model="claude-opus-4-7", )

Team.blackboard

@classmethod def blackboard( cls, agents: dict[str, Agent], *, coordinator: Agent | None = None, decider: Agent | None = None, instructions: str = "", # ...shared parameters... max_rounds: int = 10, coordinator_instructions: str | None = None, decider_instructions: str | None = None, persistent_subagents: bool = True, ) -> Agent: ...

Returns an Agent whose architecture is BlackboardArchitecture(agents=..., coordinator=..., decider=..., ...).

team = Team.blackboard( agents={"hypothesis": h, "evidence": e, "critic": c}, coordinator=coord, decider=decider, model="claude-opus-4-7", )

Why explicit kwargs (not **kwargs)?

Each Team builder spells out every coordinator kwarg plus the architecture-specific ones rather than forwarding through **kwargs. It is more verbose, but Pylance / Pyright / mypy can then show the full parameter list with types, defaults and docstrings on hover.


When to skip Team and use Agent(architecture=...)

The Team builders are for single-level teams: supervisors that delegate to leaf workers, swarms of peers, and so on. For recursive composition (Reflexion around a Supervisor, Supervisor of Supervisors) use the explicit Agent(architecture=...) form, so you can pass one architecture as a field of another.

# Single level: use Team team = Team.supervisor(workers={...}, model="claude-opus-4-7") # Nested: use the explicit form agent = Agent( "...", model="claude-opus-4-7", architecture=Reflexion( base=Supervisor(workers={...}), ), )

See Recursive composition.


Source

loomflow/team.py

Team and Agent(architecture=...) build the same thing. Team.supervisor(workers={...}) returns an Agent with a Supervisor(workers={...}) architecture, plus the persistent_subagents wiring described above. Use Team when you want the familiar one-call builder, and the explicit form for composition.

Last updated on