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, add @EnableTramai to your configuration class and AI services become injectable beans -- same pattern as @Service or @Repository. 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.4.0).
Standalone (any JVM app)
dependencies {
implementation(platform("dev.tramai:tramai-bom:0.4.0"))
implementation("dev.tramai:tramai-standalone")
implementation("dev.tramai:tramai-openai")
}
<dependencyManagement>
<dependencies>
<dependency>
<groupId>dev.tramai</groupId>
<artifactId>tramai-bom</artifactId>
<version>0.4.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
implementation(platform("dev.tramai:tramai-bom:0.4.0"))
implementation("dev.tramai:tramai-spring")
implementation("dev.tramai:tramai-openai")
Replace tramai-openai with tramai-anthropic, tramai-ollama, or tramai-deepseek. All providers follow the same pattern. 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'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
