Skip to Content

Architecture helpers

Helpers for working with architectures directly. run_architecture runs an architecture once without you building an Agent (handy in tests), resolve_architecture turns a string like "react" into an architecture instance, and parse_score reads a 0–1 score out of an evaluator’s reply.

from loomflow.architecture import resolve_architecture from loomflow.architecture.helpers import parse_score from loomflow.team import run_architecture

run_architecture

async def run_architecture( architecture: Architecture, prompt: str, *, instructions: str = "", model: Model | str | None = None, memory: Memory | None = None, runtime: Runtime | None = None, budget: Budget | None = None, permissions: Permissions | None = None, hooks: HookRegistry | None = None, tools: list[Tool | Callable[..., object]] | ToolHost | Tool | Callable[..., object] | None = None, telemetry: Telemetry | None = None, audit_log: AuditLog | None = None, max_turns: int = 50, auto_consolidate: bool = False, ) -> RunResult: ...

Build a minimal Agent around any Architecture instance and run it once. Useful for testing orchestrators in isolation without wiring a full Agent yourself.

ParameterTypeDefaultDescription
architectureArchitecturerequiredThe orchestrator to run.
promptstrrequiredThe user message.
instructionsstr""System prompt for the shell Agent.
modelModel | str | NoneNoneThe model the architecture’s Dependencies will see. There is no default model, so pass one.
memory / runtime / budget / permissions / hooks / tools / telemetry / audit_log / max_turns / auto_consolidateAgent defaultsForwarded to the shell Agent.

It doesn’t take per-run options such as user_id or output_schema; for those, build an Agent(architecture=...) and call run().

Returns a RunResult, the same shape as agent.run().

Example: testing a Supervisor in isolation

import pytest from loomflow import Agent, ScriptedModel, ScriptedTurn, ToolCall from loomflow.architecture import Supervisor from loomflow.team import run_architecture @pytest.mark.anyio async def test_supervisor_delegates_to_writer(): writer = Agent( "Write the answer.", model=ScriptedModel(turns=[ScriptedTurn(text="Hello world.")]), ) supervisor_model = ScriptedModel(turns=[ ScriptedTurn(tool_calls=[ ToolCall(id="c1", tool="delegate", args={"worker": "writer", "instructions": "Say hello."}), ]), ScriptedTurn(text="Here you go: Hello world."), ]) sup = Supervisor(workers={"writer": writer}) result = await run_architecture(sup, "say hello", model=supervisor_model) assert "Hello world" in result.output

resolve_architecture

def resolve_architecture(spec: Architecture | str | None) -> Architecture: ...

Coerce an architecture spec to a concrete Architecture instance. Used internally by Agent.__init__; exposed for callers that want the same coercion semantics.

specResolves to
NoneReAct() (the default)
strLooked up in the KNOWN map (see below), then in installed entry points
Architecture instanceReturned as-is

Unknown strings raise ConfigError with the list of known names.

Known string specs

StringResolves to
"react"ReAct()
"plan-and-execute"PlanAndExecute()
"rewoo"ReWOO()
"reflexion"Reflexion()
"self-refine"SelfRefine()
"tree-of-thoughts"TreeOfThoughts()

Multi-agent architectures (Supervisor / Router / Swarm / Debate / ActorCritic / Blackboard) require an instance. The string resolver only knows single-agent loops, since multi-agent shapes need worker Agents as constructor arguments.

Example

from loomflow.architecture import resolve_architecture resolve_architecture(None) # ReAct() resolve_architecture("react") # ReAct() resolve_architecture("plan-and-execute") # PlanAndExecute() resolve_architecture("bogus") # raises ConfigError from loomflow.architecture import Supervisor arch = Supervisor(workers={"a": agent_a}) resolve_architecture(arch) is arch # True (returned as-is)

Entry-point discovery

Third-party packages can register custom architectures under [project.entry-points."loomflow.architecture"], so users can refer to them by string without an explicit import. Built-in names win over entry-point names with the same key. Discovery is cached on first lookup.


parse_score

def parse_score(text: str) -> float: ...

Read a score in [0.0, 1.0] out of a model’s free-form reply. The Reflexion and Tree of Thoughts evaluators and the ActorCritic critic are scored with it, so it is what your custom evaluator_prompt or critique_template has to satisfy. Use it in a custom architecture with an evaluator step. It lives in loomflow.architecture.helpers and is not re-exported from loomflow.architecture.

It looks for, in order: a "score" field in a JSON object (found inside prose or a code fence too), a score: / score= / rating: label, an unlabelled fraction, a line holding only a 0–1 number, and a decimal in prose. Scales are read as scales:

ReplyScore
score: 0.3, **Score:** 0.3, Score (0-1): 0.30.3
score: 7/10, 2 out of 100.7, 0.2
score: 40%, {"score": "40%"}0.4
score: 7, {"score": 7} (2 or more with no scale is out of 10; above 10, out of 100)0.7
0.7 alone on a line, scored 0.6 overall0.7, 0.6
score: -30.0
1 issue remains (a bare integer in prose is not a score)0.0

Results are clamped to [0.0, 1.0], and a reply with no score returns 0.0, which the built-in architectures treat as a failed evaluation. (Before 0.17, score: 3/10 and score: 40% read as 1.0, a false success, and so did score: 7.)

from loomflow.architecture.helpers import parse_score parse_score("Score: 7/10. Mostly right.") # 0.7 parse_score('Review: {"score": "40%"}') # 0.4 parse_score("No score here.") # 0.0

Source

loomflow/architecture/resolver.py · loomflow/team.py (the run_architecture definition) · loomflow/architecture/helpers.py (parse_score)

run_architecture vs Team.*. Team.* builders return an Agent you keep around for many runs. run_architecture builds a single-use shell, runs once and returns the result. Use Team for production wiring; use run_architecture for tests and one-off explorations.

Last updated on