Annotation Interface Tool


@Documented @Retention(RUNTIME) @Target(METHOD) public @interface Tool
Marks a method as a tool that an LLM agent can call.

Methods annotated with @Tool on any POJO are discovered by the framework via reflection when the containing object instance is registered with a Role through Role.tools(). Each @Tool method becomes a separate logical tool exposed to the LLM with its own JSON Schema derived from the method signature plus ToolParam annotations on its parameters.

Usage


 public class CsvTools {

     @Tool(description = "Extract specific columns from a CSV file at the given path")
     public List<Map<String, String>> csvColumns(
         @ToolParam(description = "Absolute file path") String path,
         @ToolParam(description = "Column names to extract") List<String> columns
     ) throws IOException {
         // real implementation — body actually runs
     }
 }
 

Then in a Role:


 @Override
 public List<Object> tools() {
     return List.of(new CsvTools(), new JsonTools(), new MyCustomTool());
 }
 

Convention

  • name() defaults to the method name when left empty.
  • description() is required — the LLM uses this to decide when to invoke the tool. Missing or thin descriptions degrade tool-call quality measurably.
  • The method body executes when the LLM emits a tool call; the return value is JSON-serialised and fed back into the model.
  • timeoutMs() can bound an individual call. The default (0) adds no dispatcher deadline and preserves the enclosing agent's timeout policy.
  • Cross-cutting annotations (Traced, Metered, Fallback, InputGuardrail, OutputGuardrail) can be applied to the same method and are honoured by the tool dispatcher.
Since:
0.5.7 (LangChain-style tool refactor — see issue #188)
See Also:
  • Required Element Summary

    Required Elements
    Modifier and Type
    Required Element
    Description
    Human-readable description that appears in the LLM tool catalog.
  • Optional Element Summary

    Optional Elements
    Modifier and Type
    Optional Element
    Description
    Same runtime access policy as ActionSpec; not a side-effect hint.
    Declares whether runtime dispatch requires an active, stable Idempotent policy for this tool (TNS-299).
    boolean
    Whether this tool's effect is idempotent (calling twice with the same arguments has the same observable effect as calling once).
    Optional keywords for fuzzy lookup inside the framework registry.
    Tool name surfaced to the LLM.
    boolean
    Whether this tool's invocation should be gated through the agent's configured ToolCallFilter for explicit per-call approval.
    Classification of this tool's observable effect (TNS-299).
    int
    Maximum wall-clock time for one invocation of this tool, in milliseconds.
  • Element Details

    • execution

      ExecutionPolicy[] execution
      Same runtime access policy as ActionSpec; not a side-effect hint.
      Default:
      {}
    • name

      String name
      Tool name surfaced to the LLM. Defaults to the method name if left empty — typical case is to leave it empty and let reflection use the Java method name.
      Returns:
      the tool name (empty means "use method name")
      Default:
      ""
    • description

      String description
      Human-readable description that appears in the LLM tool catalog. Required — the LLM relies on this to decide when to call the tool. Be specific about inputs, outputs, side effects, and when NOT to use the tool.
      Returns:
      the tool description (must be non-empty)
    • keywords

      String[] keywords
      Optional keywords for fuzzy lookup inside the framework registry. Not surfaced to the LLM — purely a discovery aid for tools and tests.
      Returns:
      keyword array (empty by default)
      Default:
      {}
    • timeoutMs

      int timeoutMs
      Maximum wall-clock time for one invocation of this tool, in milliseconds. A positive value is enforced by the POJO tool dispatcher; expiry raises a retryable ToolTimeoutException. The timed-out invocation is interrupted on a best-effort basis and may continue if its code ignores interruption.

      The default 0 adds no per-tool deadline, preserving existing behavior and any timeout policy applied by the enclosing agent.

      Returns:
      the per-invocation deadline in milliseconds, or 0 to use no additional dispatcher deadline
      Since:
      0.14.0 (TAN-2958)
      Default:
      0
    • idempotent

      boolean idempotent
      Whether this tool's effect is idempotent (calling twice with the same arguments has the same observable effect as calling once). Hint for the framework's retry / fallback layer; idempotent tools are eligible for automatic retry on transient failures.
      Returns:
      true if idempotent
      Default:
      false
    • requiresConfirmation

      boolean requiresConfirmation
      Whether this tool's invocation should be gated through the agent's configured ToolCallFilter for explicit per-call approval. Mark true for irreversible or financially material operations (payment execution, deleting a remote resource, posting to a public channel, anything classifiable as HIGH or CRITICAL blast radius).

      Orthogonal to idempotent(): idempotency is a retry-layer hint, confirmation is a runtime safety gate. Issue AGENT-V006 (the ToolApprovalValidator) warns at build time when a tool declares requiresConfirmation = true but the agent has no ToolCallFilter wired through AgentBuilder.toolCallFilter(...) — without one, the runtime will execute the call unattended.

      Returns:
      true if the call should require explicit approval via the configured tool-call filter
      Since:
      0.8.5 (issue #234 — AGENT-V006 prerequisite)
      Default:
      false
    • sideEffect

      SideEffect sideEffect
      Classification of this tool's observable effect (TNS-299). ToolMethodRegistry retains this metadata for the runtime dispatcher and logs a registration-time warning when SideEffect.EXTERNAL tools omit an idempotencyHint().

      Orthogonal to idempotent(): idempotent is a retry-layer hint about call safety; this enum classifies where the effect lives (in-process / disk / external API).

      Returns:
      the effect classification — defaults to SideEffect.NONE so existing tools retain their current behaviour
      Since:
      0.10.0 (TNS-299)
      Default:
      NONE
    • idempotencyHint

      IdempotencyHint idempotencyHint
      Declares whether runtime dispatch requires an active, stable Idempotent policy for this tool (TNS-299).
      • IdempotencyHint.NONE — no tracking; default for pure / read-only tools.
      • IdempotencyHint.OPTIONAL — dispatch unguarded unless an independent @Idempotent policy is present.
      • IdempotencyHint.REQUIRED — refuse to dispatch unless @Idempotent supplies a stable HASH_INPUT or EXPLICIT key strategy and a positive cache TTL. Reserve for tools where a duplicate would cause real damage (payments, public posts, deletes). Durability of the record is the caller's responsibility: the default store is in-memory and per-process — wire a durable store through AgentBuilder.idempotencyStore(...) for restart-safe protection (TAN-5933).
      Returns:
      the hint — defaults to IdempotencyHint.NONE so existing tools retain their current behaviour
      Since:
      0.10.0 (TNS-299)
      Default:
      NONE