← All articles
Giona Granchelli

Why I Built TramAI: Governed AI for JVM Applications

The engineering decisions behind TramAI and why production AI systems need explicit boundaries, permissions, portability, and auditability.

TramAI logo, representing a governed AI runtime for JVM applications

Every side project starts with an idea. This one also started with a name I could not keep.

My first choice was Aurora. It captured the feeling of building something new, but the useful domains were already taken or priced beyond reason. I went back to Italian words connected to weaving because the system I was designing was meant to weave AI capabilities into existing software without tangling them into the rest of the application.

That search led to trama. In weaving, the trama is the weft: the horizontal thread drawn through the warp to create fabric. In everyday Italian, it also means the plot of a story or plan, the structure connecting separate events. Adding the final “I” produced TramAI: a reference to AI and, in Italian, a form that can mean “I wove.”

The name worked because it described the technical problem. Adding an AI model to an application is easy. Building an AI capability that remains understandable, controllable, and replaceable in production is not.

A simple AI call rarely stays simple

Most AI integrations begin with a short experiment: send a prompt to a model and display the response. That is useful for proving an idea, but production requirements arrive quickly.

The system needs conversation context. It needs access to company data without exposing everything. Different users and agents require different permissions. The team needs to understand which model handled a request and what information left the system. Some actions require approval. Providers change their prices, models, limits, and terms, so depending permanently on one API creates operational risk.

Without a deliberate architecture, these concerns spread across controllers, services, prompts, database code, and provider-specific clients. The AI behavior becomes difficult to test and even harder to explain. A new engineer cannot point to one boundary and say, “This is where the AI system starts, these are the capabilities it has, and these are the rules it follows.”

TramAI began as an attempt to create that boundary for Java and Kotlin applications.

AI needs an explicit place in the architecture

Business applications are usually described through familiar layers: data storage, backend logic, and a frontend or API. AI is often inserted directly into the backend as another integration. That works until the AI needs memory, tools, routing, policies, structured output, and audit records.

My working model is that AI deserves a distinct application layer. It still participates in normal business workflows, but its responsibilities are explicit:

  • model and provider selection;
  • prompt and context assembly;
  • memory boundaries;
  • tool and data permissions;
  • approval requirements;
  • structured outputs and validation;
  • audit and observability events.

This is not separation for its own sake. It makes AI behavior easier to test independently, gives security rules a clear home, and reduces the cost of changing providers or models. Most importantly, it gives teams a vocabulary for reviewing the system before it reaches production.

Governance is an engineering capability

The word “governance” often suggests policy documents and review meetings. Those matter, but an AI system cannot become governable through documentation alone. The runtime must enforce the decisions recorded in those documents.

If an agent should not read sensitive customer data, that restriction needs to exist in code. If sending information to an external provider requires approval, the workflow must stop until that approval exists. If a team promises that a particular category of data remains inside its infrastructure, model routing must respect that classification.

This leads to a deny-by-default approach. An agent receives only the tools and information explicitly granted to it. Capabilities are visible rather than inferred. Sensitive actions can require a human decision, and the execution history should show which decision allowed the workflow to continue.

That model is familiar in secure application design. AI makes it more important because a model can choose among tools and generate new requests at runtime. The system surrounding the model has to remain deterministic about what is permitted, even when the model output is probabilistic.

Sovereignty means retaining practical choices

European discussions about AI sovereignty can become abstract. For an engineering team, sovereignty has concrete questions:

  • Where is company and customer data processed?
  • Can a workload use a self-hosted model when required?
  • Can the organization change providers without rewriting the application?
  • Can it inspect and export the records needed to explain an AI-assisted decision?
  • Who controls deployment, credentials, retention, and network boundaries?

Sovereignty does not mean every company must operate every model itself. It means the architecture preserves meaningful control. A low-risk workload might use a hosted provider, while sensitive processing stays inside a controlled environment. The important part is that this is an intentional routing decision rather than an accidental consequence of whichever API was integrated first.

TramAI is designed around this portability. Application code should depend on stable AI concepts instead of leaking one provider’s request format throughout the codebase. Providers can then be selected according to the workload, data classification, cost, or operational requirements.

Why the JVM is a useful home for this work

Many organizations already run their critical systems on Java and Kotlin. Their teams understand dependency injection, typed interfaces, structured configuration, observability, testing, and long-lived service operation. Requiring those organizations to move the entire AI layer into an unfamiliar language or isolated prototype stack creates another boundary to maintain.

The JVM is not the only place to build AI software, but it is a practical place to integrate AI into established business systems. Strong types help make contracts visible. Mature application frameworks provide reliable configuration and lifecycle management. Existing security and monitoring practices can be extended instead of replaced.

The aim is not to hide the uncertainty of model output behind a type system. It is to make everything around that uncertainty more explicit: inputs, outputs, capabilities, routing decisions, failures, retries, and approvals.

For a code-level comparison of these concerns in TramAI, Spring AI, and LangChain4j, read Java for Production AI Agents. It includes typed output, tool calling, approval, routing, observability, and runnable companion code.

The honest status

TramAI is still evolving. It is built from real architectural concerns, but it should be evaluated like any developing technical product: against a specific workload, with tests and operational requirements made explicit.

I am not trying to replace careful system design with a framework. A framework can provide useful primitives and consistent boundaries, but teams still need to decide what data an agent may see, which actions require approval, what happens when a provider fails, and how human operators recover a workflow.

That is also why I am building TramAI in public-facing increments rather than presenting AI governance as a finished checkbox. The difficult parts deserve to be visible. Feedback from engineers working with actual JVM applications is more valuable than a long list of features without production context.

What this means for companies adopting AI

The first useful AI project does not need to be large. It needs a clear operational problem, bounded data access, an observable outcome, and a path to human review.

A lead-intake agent, document classification workflow, internal knowledge assistant, or support triage tool can all be sensible starting points. The architecture becomes important when the prototype is expected to touch real customer data or make consequential choices.

Before implementation, I ask teams to answer four questions:

  1. What specific workflow should improve?
  2. Which data is required, and which data must remain unavailable?
  3. What may the system do autonomously, and what requires approval?
  4. How will the team measure whether the workflow became better?

Those questions keep the project grounded in business value while creating the boundaries a governed system needs.

Building with intention

The weaving metaphor still fits. Useful AI systems connect models, data, tools, people, and existing software. The result is only strong when those threads follow a deliberate structure.

TramAI is my attempt to give JVM teams that structure: a clear place for AI behavior, explicit permissions, portable providers, and evidence of how a workflow ran. It is also a practical expression of how I believe production AI should be built: with the model treated as one component inside a controlled system, not as the system itself.

You can explore the project at tramai.dev. If your company is deciding where AI fits into an existing workflow, book a consultation or review the AI Readiness Audit. We can start with the operational problem and define the smallest useful, governable implementation.