cd /news/ai-tools/tabforge-ai-a-complete-platform-for-… · home topics ai-tools article
[ARTICLE · art-91958] src=dev.to ↗ pub= topic=ai-tools verified=true sentiment=↑ positive

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

TabForge AI, a new platform for building AI-powered Java web applications on Jakarta EE and PrimeFaces, was released. It provides a multi-tab UI shell, a provider-agnostic AI layer built on LangChain4j, and features such as tool-calling agents, structured extraction, and proactive suggestions. The platform includes a library, live demo, starter project, and a drop-in UI template.

read3 min views1 publishedAug 11, 2026

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:

 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

ready to use starter

See it in action

All OpenSource

── more in #ai-tools 4 stories · sorted by recency
── more on @tabforge ai 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/tabforge-ai-a-comple…] indexed:0 read:3min 2026-08-11 ·