# 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:

```java
@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.

```java
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:

```java
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`.

```java
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

```java
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](catalog.md) — the 63 shipped POJO toolkits and their methods
- [Custom Tools](custom-tools.md) — write your own `@Tool` methods
- [Tool Integration](registration.md) — `setToolCallFilter` / `setToolCallListener` hooks
- [MCP Client](../../mcp/client.md) — bridge MCP tools into TnsAI as `DynamicToolMethod` instances
