TnsAI
Core

Tool Integration

A `Tool` is an external capability that an agent can invoke during a conversation. Tools are registered via `AgentBuilder.tool()` and exposed to the LLM as function definitions. The LLM decides when and how to call them.

Registering Tools

Before an agent can use a tool, you need to register it during agent construction. You can add tools one at a time with .tool() or pass a list with .tools(). Once registered, the agent automatically exposes them to the LLM so it can decide when to call each one.

Agent agent = AgentBuilder.create()
    .llm(llm)
    .role(role)
    .tool(new BraveSearchTool())        // Single tool
    .tools(List.of(                      // Multiple tools
        new CalculatorTool(),
        new WikipediaTool()
    ))
    .build();

Registered tools are automatically included in getToolsForLLM() and presented to the LLM as callable functions.

Tool Interface

To create a tool, you implement the Tool interface. At minimum, a tool needs a name, a description (which the LLM reads to understand what the tool does), and an execute method that performs the actual work. The optional metadata methods let you declare behavior hints like whether the tool needs user confirmation before running.

Every tool implements the Tool interface:

public interface Tool {
    String execute(String query) throws Exception;
    String getName();
    String getDescription();

    // Optional metadata
    default boolean requiresConfirmation() { return false; }
    default boolean isIdempotent() { return true; }
    default boolean isParallelizable() { return true; }
    default ToolCategory getCategory() { return ToolCategory.GENERAL; }
    default int getPriority() { return 50; }
}

See the Tools Reference for the full tool catalog and the Custom Tools guide for creating your own.

Tool Call Filters

Sometimes you want to restrict what an agent can do at runtime. Tool call filters let you intercept every tool call before it executes and decide whether to allow, block, or redirect it. This is useful for enforcing safety policies, preventing destructive operations, or guiding the LLM toward better tool usage.

Control which tools the agent is allowed to call:

agent.setToolCallFilter((toolName, arguments) -> {
    // Block dangerous tools
    if (toolName.equals("file_write")) return false;

    // Allow everything else
    return true;
});

For more nuanced control, use ToolCallAction:

agent.setToolCallFilter((toolName, arguments) -> {
    if (toolName.equals("sql_query")) {
        String query = (String) arguments.get("query");
        if (query.toUpperCase(Locale.ROOT).contains("DROP")) {
            return ToolCallAction.block();
        }
        if (query.toUpperCase(Locale.ROOT).contains("DELETE")) {
            return ToolCallAction.guide("Use soft deletes instead of DELETE statements");
        }
    }
    return ToolCallAction.allow();
});
ActionBehavior
ToolCallAction.allow()Proceed as-is
ToolCallAction.block()Reject the call
ToolCallAction.guide(message)Provide corrective feedback to the LLM
ToolCallAction.fallback(suggestion)Suggest an alternative tool or approach

Tool Call Listeners

Tool call listeners let you observe tool execution without affecting it. They fire callbacks when a tool call starts and when it completes, giving you the tool name, arguments, result, and how long it took. This is the right place to add logging, track latency metrics, or build debugging dashboards.

Monitor tool execution for logging, metrics, or debugging:

agent.setToolCallListener(new ToolCallListener() {
    @Override
    public void onToolCallStart(String toolName, Map<String, Object> arguments) {
        log.info("Calling tool: {} with args: {}", toolName, arguments);
    }

    @Override
    public void onToolCallComplete(String toolName, Object result, boolean success, long latencyMs) {
        log.info("Tool {} completed in {}ms (success={})", toolName, latencyMs, success);
    }
});

On this page