symfonic.capabilities.tools.stages.intent¶
intent ¶
Intent-routing stage — per-turn narrowing from an intent verdict.
Extracted from symfonic.agent.triage.tool_routing.narrow_tools_for_intent
(v7.0.1), which remains the public entry point and now delegates here so
there is one implementation of the decision matrix rather than two.
IntentRoutingStage ¶
IntentRoutingStage(*, verdict: Any = None, trigger_keywords: Mapping[str, Sequence[str]] | None = None, always_include: Sequence[str] = DEFAULT_ALWAYS_INCLUDE)
Narrow the turn's tools from an IntentVerdict-shaped object.
Decision matrix (unchanged from v7.0.1):
- no verdict, or
ambiguous— abstain. A noisy signal must not cost recall. knowledge— keep only the always-include names.action— keep the verdict's matched tools, plus every tool the domain declares no trigger keywords for (pre-v6.1.8 semantics: an absent entry means "always include"), plus always-include.
Source code in src/symfonic/capabilities/tools/stages/intent.py
decide ¶
The decision matrix, synchronously.
Split out because the v7.0.1 entry point
(narrow_tools_for_intent) is synchronous and is called from
inside a running event loop. One implementation, two callers —
the alternative was asyncio.run from a coroutine, which
raises, or a second copy of the matrix, which drifts.