# TabForge AI: a complete platform for building Java Web + AI apps

> Source: <https://dev.to/java_freepascal_dev/tabforge-ai-a-complete-platform-for-building-java-web-ai-apps-4ian>
> Published: 2026-08-11 12:18:56+00:00

Modern AI UX — chat panels, tool-calling agents, assistants that remember context and even suggest your next step — has lived in JavaScript SaaS for years. The Java enterprise stack has been left doing it the hard way.

**TabForge AI closes that gap**. It's a complete platform for building AI-powered web apps on Jakarta EE + PrimeFaces — from the multi-tab UI shell down to a clean, provider-agnostic AI layer. Library, live demo, starter project, and a drop-in UI template — all shipped.

Here's the whole thing, top to bottom.

## 1. Tabs as annotated beans — DynTabs

You describe a tab; the framework handles opening, closing, lifecycle, and state. Each open tab gets its own isolated CDI bean via a custom `@TabScoped`

scope.

```
  @Named
  @TabScoped
  @DynTab(name = "OrdersDynTab", uniqueIdentifier = "Orders",
          title = "Orders", includePage = "/WEB-INF/orders.xhtml",
          trackActivity = true)
  public class OrdersBean extends BaseDyntabCdiBean {
      // open the same tab twice → two independent instances
  }
```

java

No manual navigation, no page-state juggling. Open a tab, get a bean; close it, it's gone.

One fluent entry point over LangChain4j. Chat, tools, agents, and structured extraction — provider-agnostic, so the model behind it is a config detail.

```
  // A typed assistant with a business service exposed as tools
  OrdersAssistant ai = EasyAI.assistant(OrdersAssistant.class)
          .withTools(orderService)
          .build();

  String reply = ai.ask("cancel order ORD-002");
```

You opt methods in as tools explicitly — no accidental exposure:

```
  @EasyTool("Cancels an active order")
  public String cancelOrder(String orderId) { ... }
```

Agents are powerful but unpredictable. When you want a repeatable, testable process, flow() lets you own the steps and call the model only at the edges that actually need language:

``` php
 EasyAI.flow()
      .step("understand", ctx -> EasyAI.extract(OrderRequest.class).from(ctx.inputText()))
      .step("checkStock", ctx -> inventory.check(ctx.get("understand", OrderRequest.class)))
      .step("place",      ctx -> orders.place(ctx.get("understand", OrderRequest.class)))
      .build()
      .run(userText);
```

Your logic stays in plain Java. The LLM does one job: turn language into structure.

The framework quietly records what the user does in the app — opening a record, running a search — and makes that timeline available to the assistant. So deixis just works:

```
  @ActivityTracked(type = BUSINESS_ACTION, verb = "view",
                   entityType = "order", entityIdParams = "orderId")
  public String viewOrder(String orderId) { ... }
```

Now the user can open an order and type "cancel this" — no id — and the assistant resolves "this" from what it just

saw them do.

This is the piece you normally only see in Copilot, Gmail's Smart Compose, or Notion AI — and almost never as a first-class pattern in a Java web framework.

Built on Ambient Memory, the app can offer the next useful step before you ask. Open two orders for the same customer, and a dismissible chip appears: "*Looking at several Acme orders — want a quick account summary?*"

The important part: it's not a black-box agent watching you. A small, deterministic rule — plain Java you write and unit-test — decides if and what to suggest. The model only phrases the sentence.

```
  public interface SuggestionRule {
      Optional<Suggestion> evaluate(List<UserActivityEvent> recent);
  }
```

Detect synchronously (cheap, predictable), phrase-and-push asynchronously, with a per-user cooldown so it's helpful and never naggy. Deterministic code decides; the model is reserved for the one thing it's good at.

A self-contained PrimeFaces template: responsive layout, light/dark/dim themes, a transport-agnostic AI panel (chat + live activity over SSE), a command palette, and now proactive suggestion chips. Drop-in — no build dependency.

Getting started

The fastest path is the starter — a pre-wired WAR you clone and deploy. Or add the library to an existing Jakarta EE 11+ project:

```
  <dependency>
      <groupId>io.github.tabforgeai</groupId>
      <artifactId>tabforge-ai</artifactId>
      <version>3.1.0</version>
  </dependency>
```

Chat- and tools-only apps stay lean; RAG and vector-store integrations are optional add-ons you pull in only if you use them.

The philosophy

One idea runs through all of it: let deterministic code decide, and reserve the model for the irreducible — language. That's what makes AI in a serious enterprise app predictable, testable, and safe.

Proactive UX just arrived, first-class, in the Java stack.

The library

[demo app](https://github.com/tabforgeai/tabforge-ai-demo)

[ready to use starter](https://github.com/tabforgeai/tabforge-ai-starter-)

[See it in action](https://youtu.be/qNDD9mfFEJk)

All OpenSource
