Get Started
What Is TramAI
TramAI is a structured-first AI library for the JVM. You define typed interfaces with @AiService, TramAI handles the LLM calls, JSON extraction, parsing, validation, and retries. The result is a typed object -- not a raw string you need to parse yourself.
In Spring Boot you add dev.tramai:tramai-spring-boot-starter and your @AiService interfaces become injectable beans -- the same pattern as @Service or @Repository. No enabling annotation is required, and the runtime is selected with tramai.profile (standard or sovereign), not with a different dependency. Your AI contract is a first-class citizen of your architecture, not a utility you call manually.
No prompt templates, no chains, no agent frameworks. One annotation on a Kotlin interface or Java interface, one data class for the return type, and you are calling an LLM like a local function. TramAI works standalone or inside Spring Boot, and every module is opt-in.
Add Dependencies
Always import the BOM first so all TramAI modules stay on the same version (0.6.0). Module artifacts are then unpinned.
Standalone (any JVM app)
dependencies {
implementation(platform("dev.tramai:tramai-bom:0.6.0"))
implementation("dev.tramai:tramai-standalone")
implementation("dev.tramai:tramai-openai")
}
<dependencyManagement>
<dependencies>
<dependency>
<groupId>dev.tramai</groupId>
<artifactId>tramai-bom</artifactId>
<version>0.6.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>dev.tramai</groupId>
<artifactId>tramai-standalone</artifactId>
</dependency>
<dependency>
<groupId>dev.tramai</groupId>
<artifactId>tramai-openai</artifactId>
</dependency>
</dependencies>
Spring Boot
dependencies {
implementation(platform("dev.tramai:tramai-bom:0.6.0"))
implementation("dev.tramai:tramai-spring-boot-starter")
implementation("dev.tramai:tramai-spring-provider-openai")
}
Replace tramai-openai with tramai-anthropic, tramai-ollama, or tramai-deepseek for standalone apps. In Spring Boot, use the matching adapter instead: tramai-spring-provider-openai, tramai-spring-provider-anthropic, or tramai-spring-provider-ollama. The unified starter covers both the standard and sovereign runtimes -- the profile is a property, not an extra artifact. Add tramai-observability for OpenTelemetry, tramai-testing for test helpers, or tramai-orchestration for workflows -- each is additive and optional.
Define Your First Service
Write a typed contract. TramAI generates a JSON schema from the return type and wires the prompt to the model.
Kotlin
import dev.tramai.core.annotations.AiService
import dev.tramai.core.annotations.Operation
data class Analysis(
val sentiment: String,
val confidence: Double,
val keyPoints: List<String>,
)
@AiService
interface ReviewAnalyzer {
@Operation(
prompt = "Analyze this product review. Return sentiment (positive/negative/neutral), confidence 0-1, and 1-3 key points.",
model = "gpt-4o",
)
suspend fun analyze(review: String): Analysis
}
Java
import dev.tramai.core.annotations.AiService;
import dev.tramai.core.annotations.Operation;
public record Analysis(
String sentiment,
double confidence,
List<String> keyPoints
) {}
@AiService
public interface ReviewAnalyzer {
@Operation(
prompt = "Analyze this product review. Return sentiment (positive/negative/neutral), confidence 0-1, and 1-3 key points.",
model = "gpt-4o"
)
Analysis analyze(String review);
}
Key points:
- The return type (data class or record) determines the JSON schema -- TramAI generates it automatically.
- The
@Operationprompt describes the task; TramAI handles schema injection and parsing. model = "gpt-4o"is required -- you must specify which registered model to use.- Kotlin methods use
suspend(AI calls are I/O-bound); Java methods are blocking by default.
Configure and Run
import dev.tramai.standalone.Tramai
import dev.tramai.openai.OpenAiProvider
suspend fun main() {
val tramai = Tramai {
provider(
OpenAiProvider(apiKey = System.getenv("OPENAI_API_KEY")),
name = "openai",
)
model("gpt-4o", "openai")
}
val analyzer = tramai.create<ReviewAnalyzer>()
val result = analyzer.analyze(
"Great product, fast shipping."
)
println(result)
}
Set OPENAI_API_KEY in your environment and run normally:
OPENAI_API_KEY=sk-... ./gradlew run
What happens under the hood: TramAI builds the full prompt from your @Operation text and generates a JSON schema from Analysis, sends the prompt + schema to the configured model, parses the JSON response into Analysis -- if parsing or validation fails it retries automatically (default: 2 retries) -- and returns a typed Analysis object. No manual JSON parsing, no regex, no error handling in your code.
What Is New in 0.6.0
- Spring Boot onboarding is the unified
tramai-spring-boot-starter; the runtime is selected withtramai.profile: standard | sovereign, and@EnableTramaiis not required under Boot. - Provider configuration in Spring comes from explicit adapter artifacts (
tramai-spring-provider-openai,-anthropic,-ollama). - Tool calls are governed at three enforcement points, with policy decisions and tool permission decisions exported as evidence.
- JDBC stores sanitize driver failures; cancellation is preserved everywhere instead of being wrapped.
Full detail: 0.6.0 changelog and migration guide from 0.5.0.
What's Next
- Spring Boot -- auto-configure TramAI in your existing app with YAML config and dependency injection: Spring Boot Guide
- Providers -- switch to Anthropic, Ollama, Bedrock, or any OpenAI-compatible provider: Providers Guide
- Tutorial -- build a complete Invoice Analyzer with tests: Tutorial
