Class LLMCapabilityValidator
- All Implemented Interfaces:
Validator
- AGENT-V003 (function calling) — fires when the agent
will pass tools to the LLM (external tools registered, OR a
role declares an
ActionType.LLMaction) butLLMCapabilities.supportsFunctionCalling()reports false. - AGENT-V004 (declarative capability requirements,
issue #238) — for each role that declares
@RoleSpec(requires = {LLMCapability.X, ...}), fires once per requested capability the LLM reports as unsupported. Lets consumers express "this role needs streaming / structured output / vision" at design time and catch the mismatch before first chat instead of at firststreamChatWithTools/chatWithFormat/multimodal call.
The two checks share an LLM-introspection prologue (one
llm.getCapabilities() call) but emit independent issues; a
single agent can surface both at once if both signals fire.
AGENT-V003 — function calling
The agent passes tools to the LLM when one of two signals is true:
- External tools are registered on the builder
(
toolPojos/dynamicTools/builtInTools) — surfaced viaValidationContext.hasExternalTools() - Any role has at least one action with type
ActionType.LLM— LLM-as-dispatcher picks among the role's own actions
If neither signal fires, the LLM is used purely for chat / text
generation and function-calling support is irrelevant. If at least one
signal fires AND the LLM reports it does not support function calling,
the agent will throw LLMCapabilityException on the first chat
that wants to call a tool — typically minutes or hours into production.
Severity
Emitted as Severity.WARNING, not
ERROR. The issue table in #85 specifies ERROR but the codebase
convention (see LlmPresenceValidator for AGENT-V002) is to
soft-launch new validators as warnings: a model whose
getCapabilities() reports no function-calling may still work
(model registry incomplete, custom provider with conservative defaults,
etc.), and warning-level keeps existing builds compiling. Switch to
ERROR in a follow-up PR once consumers have had time to either fix the
underlying mismatch or suppress with
.relaxValidation("AGENT-V003").
Conservative skip rules
- No LLM configured → AGENT-V002 owns that case; this validator silent
LLMClient.getCapabilities()returnsnull(some mocks / test doubles don't implement it) → silent. Cannot distinguish "doesn't support FC" from "doesn't know yet"- Capabilities reports FC supported → silent regardless of model registry coverage
AGENT-V004 — declarative capability requirements
Roles annotate their LLM needs via
@RoleSpec(requires = {LLMCapability.STREAMING, ...}).
The validator iterates ValidationContext.roles(), reads each
role's RoleSpec.requires(), and emits a separate
AGENT-V004 WARNING per capability the LLM does not support.
Roles without @RoleSpec or with an empty requires
array contribute no signal — keeps the check opt-in by declaration.
Conservative skip rules (shared)
- No LLM configured → AGENT-V002 owns that case; this validator silent
LLMClient.getCapabilities()returnsnullor throws → silent. Cannot distinguish "doesn't support FC" from "doesn't know yet"- Role's
@RoleSpec.requires()array empty → V004 silent for that role regardless of LLM
- Since:
- 0.8.4 (issue #85 phase 1); V004 added 0.8.5 (issue #238)
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionid()Short, stable id for logging and test assertions (e.g.Inspect the agent configuration and return any issues detected.
-
Constructor Details
-
LLMCapabilityValidator
public LLMCapabilityValidator()
-
-
Method Details
-
id
Description copied from interface:ValidatorShort, stable id for logging and test assertions (e.g."llm-presence"). -
validate
Description copied from interface:ValidatorInspect the agent configuration and return any issues detected. Returning an empty list means "no problems found by this validator".
-