TramAI - governed AI workflows for Java and Kotlin

Architecture Overview

TramAI is a structured-first, observability-native AI workflow library for the JVM. The core product goal is to let application code interact with AI through typed interface methods instead of framework-specific chains, agents, or prompt orchestration objects.

This page describes the runtime shape. For the module-level picture — layers, ownership, and the machine-readable catalog — see Module Architecture.


Core Flow

  1. Application code defines an @AiService interface.
  2. TramAI generates a proxy for that interface at startup.
  3. A method call is translated into an AI operation.
  4. Inputs are rendered into model messages.
  5. If the return type is structured, TramAI generates or loads a cached schema and validates the response.
  6. Provider resolution selects the primary route and any configured fallbacks.
  7. The provider call is wrapped in observability instrumentation when OpenTelemetry is available.
  8. The provider returns raw model output plus metadata.
  9. TramAI either returns raw text, streams chunks, or parses and validates structured output.
  10. Parse failures enter a retry loop with validation feedback.

Ownership of each stage is stable and documented: the engine owns invocation, provider admission, tool lifecycle, and retry; tramai-structured owns schema generation, extraction, and structured failure analysis; provider adapters own transport and vendor translation only.


Layer Stack

In a Spring Boot application, TramAI adds AI as a 4th architectural layer:

Presentation Layer   @Controller / @RestController  — HTTP endpoints
Business Logic       @Service                        — Application logic
AI Layer             @AiService                      — Typed AI contracts  ← NEW
Persistence          @Repository / @Entity           — Data access

The @AiService annotation marks an interface as an AI service contract.

With the unified tramai-spring-boot-starter (tramai-spring-core + tramai-spring-sovereign), annotated interfaces become Spring beans through auto-configuration; @EnableTramai is not required for that. It remains a way to select a Spring model, not a runtime profile — the runtime profile is chosen with tramai.profile.

In standalone mode (no Spring), the same typed contract pattern applies via Tramai { ... } and Tramai.create<Service>() — the engine-owned infrastructure still exists, just without the DI container. TramaiEngine is AutoCloseable; close it so engine-owned coroutine scopes and resources are released.


Major Layers

Application Layer
    @AiService interfaces — any framework or plain JVM

Proxy Layer
    JDK dynamic proxy generated at startup
    TramaiInvocationHandler intercepts method calls, routes to the engine

Operation Engine
    Operation planning | Prompt rendering | Provider execution | Structured output | Retry

Governance Layer
    Policy enforcement points, DLP, approval suspension, audit, evidence

Observability Layer
    OTel span wraps every provider attempt
    GenAI semantic conventions, auto-detected

Provider Layer
    OpenAI | Anthropic | Ollama | Gemini | Bedrock | Azure OpenAI | DeepSeek

Application Layer

Consumer-defined @AiService interfaces. This is the only API surface most developers interact with.

Proxy Layer

Runtime-generated implementations that intercept method calls and transform them into AI operations. Uses JDK dynamic proxies through java.lang.reflect.Proxy.

Operation Engine

Operation planning, prompt rendering, provider dispatch, streaming, tool calling, parsing, retry, circuit breaking, caching, and token budgets all live in tramai-engine. Schema generation and structured response handling live in tramai-structured, whose contracts the engine consumes.

Governance Layer

Policy checks, DLP and redaction, approval gates, replay safety, audit, and evidence. Approval suspension stores a durable continuation and raises ApprovalSuspendedException; resume goes through the stored approval record rather than trusting a raw replay payload.

Observability Layer

OpenTelemetry spans, metrics, and semantic attributes, auto-detected when OTel is on the classpath. tramai-observability is optional and stays off the core happy path.

Provider Layer

Implementations for OpenAI (and OpenAI-compatible endpoints), Anthropic, Ollama, Azure OpenAI, Bedrock, Gemini, and DeepSeek. Each is a separate opt-in module. Providers are transport adapters: they must not implement retries, fallbacks, or circuit-breaker logic.

Orchestration Layer (Optional)

Typed workflow coordination above the engine, in tramai-orchestration: aiStep, localStep, gateStep, branchStep, parallelStep, external-step shapes, and checkpoint/resume. It composes the core runtime — it does not replace the engine as the owner of provider execution, retries, or tool loops.


Architectural Priorities

  1. Typed contracts over prompt engineering — Application code never manipulates raw prompt strings
  2. Framework-agnostic core with optional adapters
  3. Automatic observability with OpenTelemetry semantic conventions
  4. Kotlin-first APIs with Java-compatible entry points
  5. Explicit module boundaries so higher-level runtime features do not leak into the core library contract

Design Philosophy

  1. Typed contracts over prompt engineering — Inputs and outputs are typed data classes, not raw strings
  2. Observable by default — Every AI call emits an OpenTelemetry span automatically
  3. Fail loudly, recover gracefully — Structured output failures are retried with validation feedback; unsafe governance paths fail closed
  4. Boring to use, interesting to build — Minimal consumer API surface
  5. Kotlin-native, Java-friendly — Idiomatic Kotlin APIs with Java-callable entry points everywhere

Core Library Boundaries

The core @AiService runtime deliberately does not turn application code into an autonomous agent framework. In particular, the core does not handle:

  • autonomous agent loops
  • hidden cross-step orchestration
  • peer-to-peer agent chat
  • fine-tuning workflows

Where those concerns exist in this repository, they live in optional modules above the core library surface. The design goal is composability: application teams can use typed AI services alone, or add memory, RAG, orchestration, scheduling, server, MCP, or platform layers without changing the core execution model.


Module Structure

TramAI 0.6.0 ships 60 Gradle projects across 10 layers. The authoritative inventory is config/quality/module-catalog.yml, verified against settings.gradle.kts on every build — this page deliberately does not keep a second copy of it.

The 10 layers, in conceptual dependency order:

LayerWhat lives there
core-contractstramai-core (annotations, request models, provider registry, exceptions), tramai-bom
runtime-executiontramai-engine, tramai-structured, tramai-orchestration, tramai-standalone
governance-securitytramai-security, tramai-sovereign
persistencetramai-persistence-file, tramai-persistence-jdbc
provider-adaptersthe seven provider modules, behind the provider SPI
framework-integrationstramai-spring-core, the starters, provider starters, secrets
operations-observabilitytramai-observability, tramai-platform, and the server/MCP/dashboard surfaces
higher-capabilitiesmemory, RAG, embeddings, scheduler, vector stores
applications-examplesexecutable examples, excluded from the release
testing-supportTCKs, fakes, and consumer boundary tests

See Module Architecture for layer responsibilities, the exact boundary rules, and how ./gradlew verify060Architecture enforces them, or Module Design for the consumer-facing "which modules do I add" view.