{"slug": "we-built-a-bidirectional-context-loop-between-web-apps-and-ai-agents", "title": "We built a bidirectional context loop between web apps and AI agents", "summary": "The Tabforge AI team developed a bidirectional context loop between web applications and AI agents, enabling continuous state streaming rather than stateless prompt-response interactions. The system uses structured semantic events from the app to the AI and an event stream from the AI back to the app, creating a closed loop that eliminates fragile glue code. This framework-agnostic approach allows AI to participate in application execution without coupling to the UI.", "body_md": "Source code: [Tabforge AI](https://github.com/tabforgeai/tabforge-ai)\n\nMost AI integrations in business apps feel the same:\n\nYou send a prompt → the model returns an answer → you try to glue it into your app.\n\nIt works, but it always feels slightly disconnected from what’s actually happening in the UI.\n\nThe AI doesn’t really know what the user is doing.\n\nAnd the app doesn’t really know what the AI just did.\n\nWe ran into that problem while building EasyAI / TabForge, and ended up with something we didn’t originally set out to build:\n\na bidirectional context loop between the application and the AI runtime.\n\n**The problem:** AI in apps is stateless\n\nEven when you pass “context”, it’s usually:\n\nBut the real state lives elsewhere:\n\nSo you end up doing things like:\n\nIt works, but it’s fragile.\n\n**\n\nAmbient Activity Memory (App → AI)**\n\nThe first thing we added was a way for the application to continuously describe what is happening inside it.\n\nNot as logs.Not as analytics.\n\nBut as structured semantic events tied to actual UI actions.\n\nSo instead of:\n\n*“here is an order id”*\n\nthe system already knows:\n\nNow when the user says:\n\n*“cancel this order”*\n\nthere is no ambiguity about what “this” refers to. The AI doesn’t guess context.It already has it.\n\n**EasyAIEvent (AI → App)**\n\nOnce the AI started understanding the app state, the next obvious question was:\n\n*what does the AI give back to the application?*\n\nNot just a final answer, but the execution itself.\n\nSo every agent run can optionally emit a structured event stream:\n\n`.withEventListener(event -> {`\n\nlog.info(\"[{}] {} — {}\", event.source(), event.phase(), event.title());\n\n})\n\nNo framework coupling.No HTTP assumptions.No UI dependencies.\n\nJust a pure event stream that your app can consume however it wants.\n\n*What this enables (more interesting part)*\n\nOnce you have both directions:\n\nApp → AI\n\nThe system knows what the user is doing.\n\nAI → App\n\nThe system exposes what the agent is doing. You end up with something simple but powerful:\n\n*a closed loop between UI state and AI execution state*\n\n**\n\nWhy this matters in practice**\n\nThis removes a bunch of glue code that usually creeps into AI integrations:\n\nInstead:\n\n**Important design choice**\n\nThe event model is intentionally framework-agnostic:\n\n(source, phase, status, title, detail, toolName, sequence, timestamp)\n\nIt does not know anything about:\n\nHTTP, WebSockets, SSE, UI frameworks\n\nThat part is left to the application.\n\nWe ship a minimal example that maps the event stream to a real-time UI panel using SSE, but it stays outside the core library.\n\n**Where this is going**\n\nThe interesting part is not the event system itself. It’s what becomes possible when:\n\nYou start to move from *“AI calls inside an app”* toward something closer to:\n\n*AI as a participant in application execution, not just a function you call*\n\n**If you strip everything away**\n\nAt its core, this is all we tried to solve:\n\n*How do we make AI systems aware of application state without coupling them to the UI?*\n\nAnd the answer turned out to be:\n\n**Don’t pass state. Stream it in both directions.**\n\nIf you want to explore it:\n\nGitHub: [https://github.com/tabforgeai/tabforge-ai](https://github.com/tabforgeai/tabforge-ai)\n\nFull example: [https://github.com/tabforgeai/tabforge-ai-demo](https://github.com/tabforgeai/tabforge-ai-demo)", "url": "https://wpnews.pro/news/we-built-a-bidirectional-context-loop-between-web-apps-and-ai-agents", "canonical_source": "https://dev.to/java_freepascal_dev/we-built-a-bidirectional-context-loop-between-web-apps-and-ai-agents-2mfg", "published_at": "2026-06-25 13:39:49+00:00", "updated_at": "2026-06-25 13:43:14.972516+00:00", "lang": "en", "topics": ["ai-agents", "developer-tools", "ai-infrastructure"], "entities": ["Tabforge AI", "EasyAI", "TabForge"], "alternates": {"html": "https://wpnews.pro/news/we-built-a-bidirectional-context-loop-between-web-apps-and-ai-agents", "markdown": "https://wpnews.pro/news/we-built-a-bidirectional-context-loop-between-web-apps-and-ai-agents.md", "text": "https://wpnews.pro/news/we-built-a-bidirectional-context-loop-between-web-apps-and-ai-agents.txt", "jsonld": "https://wpnews.pro/news/we-built-a-bidirectional-context-loop-between-web-apps-and-ai-agents.jsonld"}}