Your assistant now knows what the user is doing — without being told.
Open an order on screen and type "cancel this", and it cancels the right order.
Switch tabs and ask "what am I looking at?", and it answers. No ids, no copy-paste,
no re-explaining context in the prompt.
To our knowledge, no other web app framework ships this out of the box.
It's possible because TabForge lives inside your Jakarta EE app: with TabScoped
it already knows which tab, which entity, and which action the user touched — so it
feeds the AI semantic, typed, in-app activity, never OCR or screen-scraping.
This is the mirror image of the 2.1 live event stream: where 2.1 streamed AI → UI,
2.2 streams UI → AI.
What's new: Ambient Activity Memory
A short, in-memory timeline of the user's recent actions is rendered into the assistant's
system message on every call — so the model resolves "this"/"that" on its own.
1. Capture (opt-in):
// navigation — records tab open/select automatically:
@DynTab(name = "OrdersDynTab", uniqueIdentifier = "Orders", trackActivity = true)
public class OrdersBean extends BaseDyntabCdiBean { ... }
// business actions — records "viewed order ORD-002":
@ActivityTracked(type = Type.BUSINESS_ACTION, verb = "view",
entityType = "order", entityIdParams = "orderId")
public String viewOrder(String orderId) { ... }
2. Inject (one builder call):
ActivityContext ctx = ActivityContext.of(activityStore)
.forSession(sessionId).forTab(tabId).build(); // omit forTab() for app-wide scope
OrdersAssistant bot = EasyAI.assistant(OrdersAssistant.class)
.withTools(orderService) // so it can ACT on "this"
.withActivityContext(ctx) // so it KNOWS what "this" is
.build();
bot.ask("cancel this"); // resolves to the order just viewedTwo ways to scope it:
- Per-tab deixis (forSession + forTab) → "cancel this order"
- Session-wide orientation (forSession only) → "what tab am I on?"
In-memory, per-session, and ephemeral by default (ActivityStore SPI,
InMemoryActivityStore default). Privacy-first: only labels and ids are stored, and the
timeline evaporates with the session. Nothing is captured unless you opt in.
Also in this release
- LangChain4J 1.15.1 → 1.16.3
- PrimeFaces 13.0.10 → 15.0.16 (jakarta classifier)
- Docs: new USE CASE 11 in the EasyAI Developer Guide + fully refreshed llms.txt
- Fix: menu-opened tabs now correctly record navigation activity
(DynTabManager.addTab carries over the trackActivity flag)
Compatibility
Additive minor release — no breaking changes. Everything new is opt-in
(@ActivityTracked, @DynTab(trackActivity=true), .withActivityContext(...),
package dyntabs.ai.activity).
<dependency>
<groupId>io.github.tabforgeai</groupId>
<artifactId>tabforge-ai</artifactId>
<version>2.2.0</version>
</dependency>
See it live
Demo app (Orders deixis tab + global "where am I" panel):
https://github.com/tabforgeai/tabforge-ai-demo