Class ToolMethodDispatcher
ToolMethod.
Slim resolver: looks the name up in the ToolMethodRegistry, then delegates
to ToolMethod.invoke(Map, ObjectMapper). Each variant of ToolMethod
owns its own dispatch semantics:
StaticToolMethod— Jackson-coerces each LLM argument to the parameter's static Java type, then callsMethod.invoke(java.lang.Object, java.lang.Object...).DynamicToolMethod— passes the argument map verbatim to the registered handler (typically a remote-proxy callback).
Input guardrails
For a guarded StaticToolMethod, dispatch validates the raw argument map,
materializes defaults and Jackson coercions exactly once, then validates those effective
values before idempotency resolution or body invocation. An immutable, null-tolerant snapshot
of the exact effective values accepted by the guardrail is used for both the idempotency key
and the reflected method call.
DynamicToolMethod has no annotation target, so this annotation-driven guardrail path
does not apply to dynamic tools.
Idempotency protection (issue #91)
Tools whose underlying method (or declaring class) carries
Idempotent are routed through IdempotencyResolver before
the body runs: the resolver consults an IdempotencyStore keyed by
the call's derived key, returns the cached outcome on a hit, or executes
the body and caches the new outcome on a miss. Tools without
@Idempotent bypass the resolver entirely (zero overhead). Only
StaticToolMethod variants are subject to this discovery —
DynamicToolMethods have no annotation source and always run
unprotected; idempotency for dynamic tools needs a richer construction
API tracked as a follow-up.
Error semantics
- Unknown tool name →
IllegalArgumentExceptionwith the name and the registry's known names. - A static tool input guardrail rejection propagates directly as
GuardrailViolationException. - Coercion / invocation errors are surfaced from the variant's
invoke— seeStaticToolMethod.invoke(Map, ObjectMapper)for the full taxonomy.
- Since:
- 0.5.7 (LangChain-style tool refactor — see issue #188; slimmed in 0.7.0
when
ToolMethodbecame a sealed interface; idempotency wiring added in 0.8.6 — issue #91)
-
Constructor Summary
ConstructorsConstructorDescriptionToolMethodDispatcher(ToolMethodRegistry registry) ToolMethodDispatcher(ToolMethodRegistry registry, com.fasterxml.jackson.databind.ObjectMapper mapper) ToolMethodDispatcher(ToolMethodRegistry registry, com.fasterxml.jackson.databind.ObjectMapper mapper, IdempotencyStore idempotencyStore) Full constructor with an explicitIdempotencyStore. -
Method Summary
Modifier and TypeMethodDescriptionvoidauthorizeTool(String name, Map<String, Object> arguments) Preflight shares exactly the dispatch gate and does not invoke a tool or cache.voidconfigureExecution(AgentPrincipal principal, AuthorityScope authority, AccessSubject agent) Resolve, dispatch.Look up a tool by name without dispatching.registry()Shared provider and gate used by an owning ActionExecutor.voidsetAccessAuthority(AuthorityScope authority) voidsetAccessPrincipal(AgentPrincipal principal) Host startup wiring; never set from request data.
-
Constructor Details
-
ToolMethodDispatcher
-
ToolMethodDispatcher
public ToolMethodDispatcher(ToolMethodRegistry registry, com.fasterxml.jackson.databind.ObjectMapper mapper) -
ToolMethodDispatcher
public ToolMethodDispatcher(ToolMethodRegistry registry, com.fasterxml.jackson.databind.ObjectMapper mapper, IdempotencyStore idempotencyStore) Full constructor with an explicitIdempotencyStore. Use to wire a Redis / Postgres adapter (when those land) or to share one store instance across multiple agents in the same process.- Parameters:
registry- tool name → method registry (required)mapper- Jackson mapper forStaticToolMethodtype coercionidempotencyStore- store consulted forIdempotenttools (required; passInMemoryIdempotencyStorefor the default per-process behaviour)- Since:
- 0.8.6 (issue #91)
-
-
Method Details
-
securityEnforcer
Shared provider and gate used by an owning ActionExecutor. -
accessGate
-
setAccessPrincipal
Host startup wiring; never set from request data. -
setAccessAuthority
-
configureExecution
public void configureExecution(AgentPrincipal principal, AuthorityScope authority, AccessSubject agent) -
authorizeTool
Preflight shares exactly the dispatch gate and does not invoke a tool or cache. -
idempotencyStore
- Returns:
- the
IdempotencyStoreconsulted forIdempotenttools. Useful for tests that need to inspect or pre-populate the cache. - Since:
- 0.8.6 (issue #91)
-
lookup
Look up a tool by name without dispatching. Returnsnullwhen no such tool is registered.- Since:
- 0.7.0 (delegate so callers don't have to hold the registry separately)
-
registry
- Returns:
- the underlying
ToolMethodRegistry. Use for catalog enumeration (e.g. building the LLM tool catalog fromToolMethod.parametersSchema()).
-
dispatch
Resolve, dispatch.Checked exceptions thrown by the tool body are wrapped in
RuntimeExceptionso the dispatch signature staysthrows-free. The original checked exception is thecause.- Parameters:
toolName- the tool name as emitted by the LLMarguments- the LLM's argument map (Jackson-friendly)- Returns:
- the tool's return value (caller serialises back to the LLM)
- Throws:
IllegalArgumentException- for unknown tool nameGuardrailViolationException- when a static tool's input guardrail rejects the callRuntimeException- wrapping any checked exception thrown by the tool body. Unchecked exceptions propagate as-is.
-