Fluent AgentBuilder -- a convenience facade over the agent surface.
v9.2.0 (issue #31). AgentBuilder composes the settled additive surface
(provider, model, domain, tools, memory, and declarative sub-agents) into a
readable chain, then hands off to the same SymfonicAgent /
FrameworkConfig / HMSFactory primitives you'd call directly -- it adds
NO behaviour of its own, so anything the builder does you can also do by
constructing SymfonicAgent(...) by hand.
Example::
from symfonic.agent import AgentBuilder, SubAgentSpec
from symfonic.core.providers import AnthropicProvider
agent = (
AgentBuilder()
.provider(AnthropicProvider())
.model("claude-sonnet-4-5", temperature=0.4)
.domain("support", "A customer-support assistant.")
.tools(lookup_order, issue_refund)
.enable_hms()
.memory(embeddings=embedder) # in-memory HMS
.sub_agent("researcher", "Deep web research.", tools=[web_search])
.build()
)
AgentBuilder
AgentBuilder(*, config: FrameworkConfig | None = None)
Chainable builder that assembles a :class:SymfonicAgent.
Every method returns self for chaining; :meth:build produces the
agent. A ModelProvider is the only hard requirement.
Start a builder, optionally extending an existing base config.
Parameters:
| Name |
Type |
Description |
Default |
config
|
FrameworkConfig | None
|
A base :class:FrameworkConfig to layer overrides onto.
Defaults to FrameworkConfig(). Anything the builder sets
(model, domain, flags) overrides this base; everything else is
inherited.
|
None
|
Source code in src/symfonic/agent/builder.py
| def __init__(self, *, config: FrameworkConfig | None = None) -> None:
"""Start a builder, optionally extending an existing base config.
Args:
config: A base :class:`FrameworkConfig` to layer overrides onto.
Defaults to ``FrameworkConfig()``. Anything the builder sets
(model, domain, flags) overrides this base; everything else is
inherited.
"""
self._base_config = config
self._provider: ModelProvider | None = None
self._tools: list[Any] = []
self._sub_specs: list[SubAgentSpec] = []
self._overrides: dict[str, Any] = {}
self._model_overrides: dict[str, Any] = {}
self._domain: DomainTemplate | None = None
self._domain_name: str | None = None
self._domain_description: str | None = None
self._orchestrator: MemoryOrchestrator | None = None
self._embeddings: EmbeddingProvider | None = None
self._in_memory: bool = False
|
build
Construct the SymfonicAgent from the accumulated configuration.
Raises:
| Type |
Description |
ValueError
|
|
Source code in src/symfonic/agent/builder.py
| def build(self) -> SymfonicAgent:
"""Construct the ``SymfonicAgent`` from the accumulated configuration.
Raises:
ValueError: If no provider was set.
"""
if self._provider is None:
raise ValueError(
"AgentBuilder requires a provider; call .provider(...) before "
".build()"
)
from symfonic.agent.engine import SymfonicAgent
orchestrator = self._orchestrator
if orchestrator is None and self._in_memory:
from symfonic.agent.factory import HMSFactory
orchestrator = HMSFactory.build_in_memory(
embedding_provider=self._embeddings
)
return SymfonicAgent(
model_provider=self._provider,
config=self._assemble_config(),
tools=self._tools or None,
sub_agents=self._sub_specs or None,
orchestrator=orchestrator,
)
|
domain
domain(
name: str | None = None,
description: str | None = None,
*,
template: DomainTemplate | None = None,
) -> AgentBuilder
Set the agent's domain -- either a full template or name/desc.
Source code in src/symfonic/agent/builder.py
| def domain(
self,
name: str | None = None,
description: str | None = None,
*,
template: DomainTemplate | None = None,
) -> AgentBuilder:
"""Set the agent's domain -- either a full ``template`` or name/desc."""
if template is not None:
self._domain = template
else:
self._domain_name = name
self._domain_description = description
return self
|
enable_hms
enable_hms(on: bool = True) -> AgentBuilder
Toggle the HMS system-prompt pipeline (enable_hms_prompt).
Source code in src/symfonic/agent/builder.py
| def enable_hms(self, on: bool = True) -> AgentBuilder:
"""Toggle the HMS system-prompt pipeline (``enable_hms_prompt``)."""
self._overrides["enable_hms_prompt"] = on
return self
|
lazy_tooling(on: bool = True) -> AgentBuilder
Toggle lazy tool routing (lazy_tooling).
Source code in src/symfonic/agent/builder.py
| def lazy_tooling(self, on: bool = True) -> AgentBuilder:
"""Toggle lazy tool routing (``lazy_tooling``)."""
self._overrides["lazy_tooling"] = on
return self
|
memory
memory(
orchestrator: MemoryOrchestrator | None = None,
*,
embeddings: EmbeddingProvider | None = None,
auto_hydrate: bool = True,
auto_consolidate: bool = True,
) -> AgentBuilder
Attach HMS memory.
Pass a pre-built orchestrator OR embeddings to build an
in-memory HMS at :meth:build time (delegates to
HMSFactory.build_in_memory). Enables auto_hydrate /
auto_consolidate by default; override per call.
Source code in src/symfonic/agent/builder.py
| def memory(
self,
orchestrator: MemoryOrchestrator | None = None,
*,
embeddings: EmbeddingProvider | None = None,
auto_hydrate: bool = True,
auto_consolidate: bool = True,
) -> AgentBuilder:
"""Attach HMS memory.
Pass a pre-built ``orchestrator`` OR ``embeddings`` to build an
in-memory HMS at :meth:`build` time (delegates to
``HMSFactory.build_in_memory``). Enables ``auto_hydrate`` /
``auto_consolidate`` by default; override per call.
"""
if orchestrator is not None:
self._orchestrator = orchestrator
elif embeddings is not None:
self._embeddings = embeddings
self._in_memory = True
self._overrides.setdefault("auto_hydrate", auto_hydrate)
self._overrides.setdefault("auto_consolidate", auto_consolidate)
return self
|
model
model(
model_name: str | None = None,
*,
temperature: float | None = None,
max_tokens: int | None = None,
top_p: float | None = None,
top_k: int | None = None,
) -> AgentBuilder
Override model knobs; unset ones inherit the base config's model.
Source code in src/symfonic/agent/builder.py
| def model(
self,
model_name: str | None = None,
*,
temperature: float | None = None,
max_tokens: int | None = None,
top_p: float | None = None,
top_k: int | None = None,
) -> AgentBuilder:
"""Override model knobs; unset ones inherit the base config's model."""
for key, val in (
("model_name", model_name),
("temperature", temperature),
("max_tokens", max_tokens),
("top_p", top_p),
("top_k", top_k),
):
if val is not None:
self._model_overrides[key] = val
return self
|
option
option(**overrides: Any) -> AgentBuilder
Set any other FrameworkConfig field(s) verbatim.
Source code in src/symfonic/agent/builder.py
| def option(self, **overrides: Any) -> AgentBuilder:
"""Set any other ``FrameworkConfig`` field(s) verbatim."""
self._overrides.update(overrides)
return self
|
provider
provider(provider: ModelProvider) -> AgentBuilder
Set the LLM provider (required).
Source code in src/symfonic/agent/builder.py
| def provider(self, provider: ModelProvider) -> AgentBuilder:
"""Set the LLM provider (required)."""
self._provider = provider
return self
|
sub_agent
sub_agent(
name: str,
description: str,
*,
when_to_use: str | None = None,
tools: Any = (),
domain_description: str | None = None,
model_name: str | None = None,
temperature: float | None = None,
max_tokens: int | None = None,
provider: ModelProvider | None = None,
) -> AgentBuilder
Declare a child agent as a :class:SubAgentSpec (repeatable).
Source code in src/symfonic/agent/builder.py
| def sub_agent(
self,
name: str,
description: str,
*,
when_to_use: str | None = None,
tools: Any = (),
domain_description: str | None = None,
model_name: str | None = None,
temperature: float | None = None,
max_tokens: int | None = None,
provider: ModelProvider | None = None,
) -> AgentBuilder:
"""Declare a child agent as a :class:`SubAgentSpec` (repeatable)."""
self._sub_specs.append(
SubAgentSpec(
name=name,
description=description,
when_to_use=when_to_use,
tools=tuple(tools),
domain_description=domain_description,
model_name=model_name,
temperature=temperature,
max_tokens=max_tokens,
provider=provider,
)
)
return self
|
sub_agent_spec
sub_agent_spec(spec: SubAgentSpec) -> AgentBuilder
Add a pre-constructed :class:SubAgentSpec.
Source code in src/symfonic/agent/builder.py
| def sub_agent_spec(self, spec: SubAgentSpec) -> AgentBuilder:
"""Add a pre-constructed :class:`SubAgentSpec`."""
self._sub_specs.append(spec)
return self
|
tools(*tools: Any) -> AgentBuilder
Add tools (repeatable; accepts multiple per call).
Source code in src/symfonic/agent/builder.py
| def tools(self, *tools: Any) -> AgentBuilder:
"""Add tools (repeatable; accepts multiple per call)."""
self._tools.extend(tools)
return self
|