Quickstart
Build your first TnsAI agent in 5 minutes. Prerequisites: Installation.
Your First Agent
Option 1: AgentBuilder (no subclassing)
import com.tnsai.agents.AgentBuilder;
import com.tnsai.roles.Role;
import com.tnsai.annotations.ActionSpec;
import com.tnsai.enums.ActionType;
import com.tnsai.llm.providers.AnthropicClient;
import com.tnsai.models.role.RoleIdentity;
import com.tnsai.models.role.Responsibility;
import com.tnsai.models.role.CoreDuty;
import com.tnsai.identity.LocalIdentityProvider;
import com.tnsai.identity.AgentDescriptor; // identity RECORD — not annotations.AgentSpec
import com.tnsai.accountability.RecordingLiabilitySink;
import com.tnsai.accountability.AuthorityScope;
import java.time.Duration;
import java.util.List;
// 1. Define a role with actions
public class AssistantRole extends Role {
@Override public RoleIdentity getIdentity() {
return new RoleIdentity("assistant",
"Friendly conversational agent", "support");
}
@Override public List<Responsibility> getResponsibilities() {
return List.of(new CoreDuty("greet",
"Greet users by name"));
}
@ActionSpec(type = ActionType.LOCAL,
description = "Greet the user by name")
public String greet(String name) {
return "Hello, " + name + "!";
}
}
// 2. Mint identity + accountability wiring (REQUIRED by AgentBuilder.build())
var principal = new LocalIdentityProvider().issue(
AgentDescriptor.builder()
.agentClass("com.example.AssistantAgent")
.systemPrompt("You are a friendly assistant.")
.toolNames(List.of())
.model("claude-sonnet-4-20250514")
.build());
var sink = new RecordingLiabilitySink(); // in-memory; FilesystemLiabilitySink in prod
var scope = AuthorityScope.unrestricted(Duration.ofHours(1));
// 3. Build and use the agent
var agent = AgentBuilder.create()
.llm(new AnthropicClient("claude-sonnet-4-20250514"))
.role(new AssistantRole())
.principal(principal)
.liabilitySink(sink)
.authorityScope(scope)
.build();
agent.start();
String response = agent.chat("Hi, my name is Alice");
System.out.println(response);Required. The
AgentBuilderpath needs the accountability trio —principal,liabilitySink, andauthorityScope. Without all three,build()throwsIllegalStateException(TNS-298); the framework ships no silent no-op default.RecordingLiabilitySinkis in-memory — useFilesystemLiabilitySinkfor production audit trails. See Accountability for the full identity / liability / scope model.
Option 2: Annotated Agent (subclass)
import com.tnsai.agents.Agent;
import com.tnsai.annotations.AgentSpec;
import com.tnsai.llm.LLMClient;
import com.tnsai.llm.providers.AnthropicClient;
import com.tnsai.roles.Role;
import java.util.List;
@AgentSpec(description = "A helpful research assistant")
public class ResearchAgent extends Agent {
@Override
protected LLMClient getLLM() {
return new AnthropicClient("claude-sonnet-4-20250514");
}
@Override
protected List<Role> getRoles() {
return List.of(new AssistantRole());
}
}
// Use it
var agent = new ResearchAgent();
agent.start();
String answer = agent.chat("What is quantum computing?");Adding Tools
For brevity the examples below omit the
.principal(...),.liabilitySink(...), and.authorityScope(...)calls — assume theprincipal,sink, andscopefrom Option 1. EveryAgentBuilder.build()still requires them.
Register shipped POJO toolkits by enum constant — compile-safe:
import com.tnsai.enums.BuiltInTool;
var agent = AgentBuilder.create()
.llm(new AnthropicClient("claude-sonnet-4-20250514"))
.role(new AssistantRole())
.builtInTools(
BuiltInTool.WEB_SEARCH_TOOLS, // brave_search, duckduckgo, wikipedia, …
BuiltInTool.PDF_TOOLS, // pdf_extract_text, pdf_metadata, …
BuiltInTool.MARKDOWN_TOOLS // markitdown
)
.build();Each enum entry registers every @Tool-annotated method on the backing POJO. The LLM sees them all (e.g. brave_search, pdf_extract_text, markitdown) and picks one per call.
For your own toolkits, register the POJO instances directly:
var agent = AgentBuilder.create()
.llm(llm)
.role(role)
.toolPojos(new MyDomainTools(), new MyAnalyticsTools())
.build();See Tools / Catalog for the full shipped catalog and Custom Tools for the @Tool annotation pattern.
Streaming
agent.streamChatWithTools("Summarize this paper", chunk -> {
if (chunk.isContent()) {
System.out.print(chunk.getContent());
}
});Structured Output
record WeatherInfo(String city, double temperature, String condition) {}
WeatherInfo weather = agent.chatWithFormat(
"What's the weather in Istanbul?",
WeatherInfo.class,
3 // max retries
);Next Steps
- Architecture Overview — How the modules fit together.
- Module Overview — What each module provides.
- Agents — Deep dive into a single agent's lifecycle and behavior.
- Capabilities: Tools — Using and creating tools.
- Production: Evaluation — Testing agent quality.