symfonic.agent.triage¶
triage ¶
Intent triage — pre-hydration routing primitives.
Provides the IntentClassifier (v7.0 T06) used by the hydration path
to route turns into action / knowledge / ambiguous lanes.
The default deterministic heuristic runs without any LLM call; an LLM
fallback is tracked for v7.1.
IntentClassifier ¶
Deterministic verb+keyword intent classifier.
Thread-safe and stateless. Safe to reuse across turns. Callers wire
this into the hydration path via FrameworkConfig.intent_filter_mode
(see engine.py). Scoring lives in
:mod:symfonic._intent_scoring, shared with the
capabilities.triage port; this module owns the lexicon and the
DomainTemplate input.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ambiguity_confidence_floor
|
float
|
Verdicts below this confidence value
are labelled |
0.55
|
min_action_signals
|
int
|
Minimum number of distinct signals required
before |
2
|
Source code in src/symfonic/agent/triage/intent.py
classify ¶
Classify query into action / knowledge / ambiguous.
Never raises. On empty input returns an ambiguous verdict
with confidence 0.0.
Source code in src/symfonic/agent/triage/intent.py
IntentVerdict
dataclass
¶
IntentVerdict(label: IntentLabel, confidence: float, matched_tool_keywords: list[str] = list(), reasoning: str = '', action_score: float = 0.0, knowledge_score: float = 0.0)
Classifier verdict for a single turn.
Attributes:
| Name | Type | Description |
|---|---|---|
label |
IntentLabel
|
One of |
confidence |
float
|
0.0–1.0 heuristic confidence. Values below 0.55
are coerced to |
matched_tool_keywords |
list[str]
|
Tool names whose trigger keywords overlap
with the current query (per |
reasoning |
str
|
Short human-readable note — which signals fired. |
action_score |
float
|
Raw action-lane score prior to normalisation. |
knowledge_score |
float
|
Raw knowledge-lane score prior to normalisation. |
to_event_payload ¶
Return a minimal payload suitable for an ExtensionEvent.
Source code in src/symfonic/agent/triage/intent.py
estimate_dropped_tokens ¶
Rough token estimate for the tools we chose not to bind.
Used for the tool_routing_decision telemetry event so
operators can correlate classifier behaviour with token savings
without instrumenting the provider payload themselves. Uses the
standard chars // 4 rule of thumb against description +
name. Schemas are ignored: the estimate is a floor, not a
ceiling.
Source code in src/symfonic/agent/triage/tool_routing.py
narrow_tools_for_intent ¶
narrow_tools_for_intent(verdict: IntentVerdict | None, all_tools: Sequence[Any], domain: DomainTemplate | None, *, always_include: Sequence[str] = DEFAULT_ALWAYS_INCLUDE) -> list[Any]
Return the subset of all_tools to bind for the current turn.
Decision matrix:
verdictisNoneor the verdict isambiguous— returnall_toolsunchanged. Conservative fallback preserves recall whenever the signal is noisy.verdict.label == "knowledge"— return only thealways_includetools that exist inall_tools. The classifier is confident the turn is a lookup; the LLM should not need action tools.verdict.label == "action"— keep any tool whose name appears inverdict.matched_tool_keywords(per the domain'stool_trigger_keywordsmap). Tools with no keyword list declared in the domain are always kept for back-compat (v6.1.8 semantics: absent entry means "always include"). Always add thealways_includetools.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
verdict
|
IntentVerdict | None
|
Output of |
required |
all_tools
|
Sequence[Any]
|
The full tool manifest registered on the agent.
Each element must expose a |
required |
domain
|
DomainTemplate | None
|
The active |
required |
always_include
|
Sequence[str]
|
Tool names that must appear in every
narrowed set regardless of verdict. Defaults to
|
DEFAULT_ALWAYS_INCLUDE
|
Returns:
| Type | Description |
|---|---|
list[Any]
|
A list of tools preserving the input order. Never raises; |
list[Any]
|
unknown tool names, missing |
list[Any]
|
|
T3.1.2: the decision matrix itself now lives in
:class:~symfonic.capabilities.tools.IntentRoutingStage. This
function is the synchronous v7.0.1 entry point and keeps its exact
contract — including returning [] for an empty input and the
input list (not a stage abstention) for the fallback paths.