Actions and tools
Choose between an action, a tool object, a built-in toolkit and an MCP server for something the model can call.
All four reach the model the same way: each turns into a function in the tool list sent with a chat turn. They differ in where the code lives and what the framework wraps around it.
Which one to use
| You have | Use | Register it with |
|---|---|---|
| Work that belongs to a role, and needs contracts, resilience, approvals or typed routing | An @ActionSpec method on a Role | AgentBuilder.role(...) |
| A helper function on a plain object | An @Tool method | AgentBuilder.toolPojos(...) |
A toolkit that already ships in tnsai-tools | A BuiltInTool constant | AgentBuilder.builtInTools(...) |
| Tools served by an MCP server | An MCP_TOOL action that names the server | AgentBuilder.role(...) |
Actions are tools
An @ActionSpec action is sent to the model as a function by default. Its name, description and parameters become the function schema, and the model can call it during a chat turn. Two cases are left out:
excludeFromLLM = true. The action stays callable from code, for example withagent.executeAction(...), but the model never sees it.MCP_TOOLactions. The action itself is configuration: it names the server. The tools that server lists are sent instead.
An action or MCP tool that the access gate would refuse is also left out of the list. See Principal and authority.
An LLM action runs a model call. It does not add tools of its own.
All four on one agent
package com.example.tnsai.docs;
import com.tnsai.accountability.AuthorityScope;
import com.tnsai.agents.Agent;
import com.tnsai.agents.AgentBuilder;
import com.tnsai.annotations.ActionSpec;
import com.tnsai.annotations.Tool;
import com.tnsai.annotations.ToolParam;
import com.tnsai.enums.ActionType;
import com.tnsai.enums.BuiltInTool;
import com.tnsai.identity.AgentPrincipal;
import com.tnsai.llm.LLMClient;
import com.tnsai.models.role.RoleIdentity;
import com.tnsai.roles.Role;
import java.util.Map;
public final class ActionsAndToolsExample {
private ActionsAndToolsExample() {}
public static final class OrdersRole extends Role {
@Override
public RoleIdentity getIdentity() {
return new RoleIdentity("orders", "Answer questions about orders", "support");
}
@ActionSpec(type = ActionType.LOCAL, description = "Look up an order by id")
public String findOrder(String orderId) {
return "Order " + orderId + ": shipped";
}
@ActionSpec(type = ActionType.LOCAL, description = "Rebuild the order index",
excludeFromLLM = true)
public String reindex() {
return "reindexed";
}
}
public static final class CurrencyTools {
@Tool(name = "convert_currency", description = "Convert an amount between currencies")
public double convert(
@ToolParam(description = "Amount to convert") double amount,
@ToolParam(description = "ISO code to convert from, e.g. EUR") String from,
@ToolParam(description = "ISO code to convert to, e.g. USD") String to) {
return amount;
}
}
public static Agent build(LLMClient llm, AgentPrincipal principal, AuthorityScope scope) {
return AgentBuilder.create()
.llm(llm)
.role(Role.create(OrdersRole.class))
.toolPojos(new CurrencyTools())
.builtInTools(BuiltInTool.WEB_SEARCH_TOOLS)
.principal(principal)
.authorityScope(scope)
.build();
}
public static Object reindexFromCode(Agent agent) {
return agent.executeAction("reindex", Map.of());
}
}- The model sees
findOrder,convert_currencyand the web search tools. - It does not see
reindex, which your code runs throughexecuteAction. WEB_SEARCH_TOOLScreatescom.tnsai.tools.search.WebSearchToolsfromtnsai-tools. Without that module on the classpath,BuiltInToolInstantiationExceptionis thrown.
Keep secrets out of schemas
Names, descriptions and parameter descriptions of actions and tools are sent to the model. Keep API keys and other credentials in the environment, not in any of them. To approve or reject a call at run time, use a tool call filter rather than wording in the schema. See Tool approval.
Related
- Actions: action types and the action pipeline.
- Custom tools: write an
@Toolobject. - Tool catalog: every
BuiltInToolconstant. - MCP client: connect to an MCP server.
- Tools: registering and running tools.