Tools — Advanced
The function-shape POJO model deliberately keeps the tool surface small: a method, an annotation, a registry. Most "advanced" features that older docs covered (manifest generators, contract validators, security enforcers, parameter validators, retry/cache wrappers) were retired together with the legacy Tool interface in v0.6.0 / v0.7.0. Cross-cutting concerns now live one layer up — on the @ActionSpec annotation, on the agent's setToolCallFilter / setToolCallListener hooks, or on the dispatcher itself.
This page covers what's left in the advanced surface today.
Per-action LLM overrides
When an @ActionSpec(type = LLM) action needs its own system prompt or temperature without changing the agent's global LLM config, set them on the annotation:
@ActionSpec(
type = ActionType.LLM,
description = "Extract entities from text — must be deterministic",
llmSystemPrompt = "You are a precise NER extractor. Output JSON only.",
llmTemperature = 0.0f
)
public String extractEntities(String text) {
return "Extract entities from: " + text;
}llmSystemPrompt overrides the LLM client's default for the duration of this action; llmTemperature >= 0 overrides the chat temperature. A negative llmTemperature (the -1.0f default) means "fall back to the LLM client's default". Tool exposure stays at the agent level — every LLM action sees the agent's complete tool registry.
Inspecting the tool registry at runtime
Every agent built with AgentBuilder has a ToolMethodDispatcher whose registry() exposes the full set of registered tools. Use this when you need to introspect the catalog from inside a setToolCallListener, write tooling around tool discovery, or assert on registration in tests.
import com.tnsai.tools.method.ToolMethodDispatcher;
import com.tnsai.tools.method.ToolMethodRegistry;
ToolMethodDispatcher dispatcher = agent.getToolMethodDispatcher();
ToolMethodRegistry registry = dispatcher.registry();
for (var tool : registry.allMethods()) {
System.out.println(tool.name() + " — " + tool.description());
}Direct dispatch
ToolMethodDispatcher.dispatch(name, args) is the same entry point the LLM tool-call loop uses. Call it directly when you want to invoke a tool from non-LLM code (tests, batch jobs, smoke scripts) without spinning up the full chat path:
Object result = dispatcher.dispatch(
"csv_summary",
Map.of("path", "/data/sales.csv")
);Argument types are coerced via Jackson — pass a Map<String, Object> whose entries match the @ToolParam parameter names.
Composio integration
ComposioClient (com.tnsai.mcp.composio) provides direct access to the
Composio REST API for discovering and executing managed integrations. It lives
in tnsai-mcp; it is not one of the POJO toolkits in tnsai-tools.
import com.tnsai.mcp.composio.ComposioClient;
ComposioClient composio = new ComposioClient(System.getenv("COMPOSIO_API_KEY"));Operations
| Operation | Description |
|---|---|
listApps() | List available apps/integrations |
listTools(appName) | List actions for one app |
executeTool(toolName, params) | Execute an action |
getConnectionStatus(appName) | Inspect an app's connection status |
Direct usage
List<ComposioClient.ComposioApp> apps = composio.listApps();
List<ComposioClient.ComposioTool> tools = composio.listTools("github");
JsonNode issue = composio.executeTool(
"github_create_issue",
Map.of("repo", "owner/repo", "title", "Bug report", "body", "...")
);Cross-References
- Tool Catalog — the 63 shipped POJO toolkits and their methods
- Custom Tools — write your own
@Toolmethods - Tool Integration —
setToolCallFilter/setToolCallListenerhooks - MCP Client — bridge MCP tools into TnsAI as
DynamicToolMethodinstances
Advanced Tool Features
Beyond the basic registration paths covered in Tool Integration, the dispatcher layer exposes a small number of advanced surfaces: filter / listener composition, tool introspection, and direct invocation of tools outside the LLM loop.
Actions vs Tools
Three names sit next to each other in TnsAI. They are not interchangeable.