symfonic.agent.warnings¶
warnings ¶
Custom warning types for the symfonic agent framework.
Import and use warnings.filterwarnings to silence any of these
selectively without silencing the entire Python warning system.
LazySkillResolutionWarning ¶
Bases: UserWarning
Emitted when a procedural skill does not resolve to a registered tool.
v9.3.0 (issue #36). With lazy_tooling=True the engine resolves the
per-turn tool subset from the procedural memory layer. Each active skill
must name a registered tool: the canonical identifier is the skill's
action_tool metadata (the same field the L1 PRE-FLIGHT synthesiser
reads) when present, otherwise MemoryEntry.content.
Descriptive/instructional skill text belongs in the steps /
context metadata, NOT in content when content is being used as
the tool identifier.
When a resolved name does not match any registered/bound tool it is dropped (it cannot select a real tool anyway) and this warning fires once per agent instance. Left unresolved, such a name would be rendered into the HMS system prompt as a phantom "active tool" the model is told it can call — degrading routing and inviting hallucinated tool calls.
Fix: store the exact registered tool name in the skill's
metadata["action_tool"] (or content); keep prose in the steps /
context fields.
To silence this warning once you understand the trade-off::
import warnings
from symfonic.agent.warnings import LazySkillResolutionWarning
warnings.filterwarnings("ignore", category=LazySkillResolutionWarning)
See docs/guides/06-lazy-tooling.md for the storage contract.
LazyToolingWarning ¶
Bases: UserWarning
Emitted when lazy_tooling is enabled but prerequisites are missing.
lazy_tooling=True silently does nothing unless ALL three of the
following conditions are met at construction time:
enable_hms_prompt=True— the HMS system-prompt pipeline is the only codepath that calls_lazy_resolve_tools(). Without it, tool filtering is never triggered.- A populated procedural memory layer — the
CapabilityRouterqueriesMemoryLayer.PROCEDURALto score skills against the query. If the layer is absent (or has no entries), the router has nothing to filter from. DomainTemplate.tool_manifestis non-empty — the router filters tools by matching procedural skills against the manifest. An empty manifest means every request sends all tool schemas to the LLM.
Consequence of missing prerequisites: all registered tool schemas are sent to the LLM on every request, which can easily consume 3–5 k extra tokens per turn and trigger rate-limit (TPM) errors on smaller tiers.
To silence this warning once you understand the trade-off::
import warnings
from symfonic.agent.warnings import LazyToolingWarning
warnings.filterwarnings("ignore", category=LazyToolingWarning)
See docs/guides/06-lazy-tooling.md for the full activation recipe.
TranscriptPersistenceEphemeralWarning ¶
Bases: UserWarning
Emitted when transcript persistence is on but only MemorySaver is wired.
transcript_persistence_enabled=True requests a durable verbatim
transcript (state['messages'] per thread_id) so that
SymfonicAgent.get_transcript(...) and working-deque
rehydrate-on-resume survive a process restart. Durability requires a
durable LangGraph saver:
- A Postgres graph backend →
PostgresCheckpointerFactory(durable), or dev_sqlite_checkpoint_pathset →SqliteCheckpointerFactory(durable).
When NEITHER is configured the engine falls back to an in-process
MemorySaver. That saver IS wired (so get_transcript works
WITHIN the process lifetime), but every checkpoint is lost on restart:
the transcript will NOT survive a container eviction and working-deque
resume will rehydrate nothing. This is almost never what an adopter
who flipped transcript_persistence_enabled intended, so the engine
refuses to fail silently and emits this warning exactly ONCE per agent
instance (mirrors the emit-once shape of
:class:~symfonic.memory.warnings.MultiScopeIgnoredWarning).
To get a durable transcript, configure a Postgres graph backend OR set
FrameworkConfig.dev_sqlite_checkpoint_path.
To silence this warning once you understand the trade-off (e.g. an intentionally ephemeral dev session)::
import warnings
from symfonic.agent.warnings import TranscriptPersistenceEphemeralWarning
warnings.filterwarnings("ignore", category=TranscriptPersistenceEphemeralWarning)
See docs/concepts/conversation-persistence.md for the durable-saver recipe.