<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: bsorrentino</title>
    <description>The latest articles on DEV Community by bsorrentino (@bsorrentino).</description>
    <link>https://dev.to/bsorrentino</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F53518%2Ff0ff1ba7-a659-49a7-92e4-4fac9e829916.png</url>
      <title>DEV Community: bsorrentino</title>
      <link>https://dev.to/bsorrentino</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bsorrentino"/>
    <language>en</language>
    <item>
      <title>Interesting reading for who are approaching use AI for developing at scale</title>
      <dc:creator>bsorrentino</dc:creator>
      <pubDate>Mon, 30 Mar 2026 07:48:38 +0000</pubDate>
      <link>https://dev.to/bsorrentino/interesting-reading-for-who-are-approaching-use-ai-for-developing-at-scale-2okf</link>
      <guid>https://dev.to/bsorrentino/interesting-reading-for-who-are-approaching-use-ai-for-developing-at-scale-2okf</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/incomplete_developer/spec-driven-development-return-of-best-practices-44b0" class="crayons-story__hidden-navigation-link"&gt;Spec-Driven Development: Return of Best Practices&lt;/a&gt;
    &lt;div class="crayons-article__cover crayons-article__cover__image__feed"&gt;
      &lt;iframe src="https://www.youtube.com/embed/SYNSj-nwZyo" title="Spec-Driven Development: Return of Best Practices"&gt;&lt;/iframe&gt;
    &lt;/div&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/incomplete_developer" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1237870%2Fd4f4f10a-3000-409a-8c61-f712e1bb5b87.png" alt="incomplete_developer profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/incomplete_developer" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Incomplete Developer
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Incomplete Developer
                
              
              &lt;div id="story-author-preview-content-3409072" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/incomplete_developer" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1237870%2Fd4f4f10a-3000-409a-8c61-f712e1bb5b87.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Incomplete Developer&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/incomplete_developer/spec-driven-development-return-of-best-practices-44b0" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Mar 26&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/incomplete_developer/spec-driven-development-return-of-best-practices-44b0" id="article-link-3409072"&gt;
          Spec-Driven Development: Return of Best Practices
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/specdrivendevelopment"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;specdrivendevelopment&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/vibecoding"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;vibecoding&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/incomplete_developer/spec-driven-development-return-of-best-practices-44b0" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;4&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/incomplete_developer/spec-driven-development-return-of-best-practices-44b0#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>specdrivendevelopment</category>
      <category>vibecoding</category>
      <category>ai</category>
    </item>
    <item>
      <title>Agent Definition Language (ADL): The Open Source Standard for Defining AI Agents 👀. Looks promising

https://www.nextmoca.com/blogs/agent-definition-language-adl-the-open-source-standard-for-defining-ai-agents</title>
      <dc:creator>bsorrentino</dc:creator>
      <pubDate>Tue, 10 Feb 2026 09:28:44 +0000</pubDate>
      <link>https://dev.to/bsorrentino/agent-definition-language-adl-the-open-source-standard-for-defining-ai-agents-looks-ibd</link>
      <guid>https://dev.to/bsorrentino/agent-definition-language-adl-the-open-source-standard-for-defining-ai-agents-looks-ibd</guid>
      <description>&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://www.nextmoca.com/blogs/agent-definition-language-adl-the-open-source-standard-for-defining-ai-agents" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fstatic1.squarespace.com%2Fstatic%2F68793d703bfc192900e52897%2Ft%2F69367d5c303f115f30ef293d%2F1765178760762%2FChatGPT%2BImage%2BDec%2B7%252C%2B2025%2Bat%2B10_59_56%2BPM.png%3Fformat%3D1500w" height="506" class="m-0" width="760"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://www.nextmoca.com/blogs/agent-definition-language-adl-the-open-source-standard-for-defining-ai-agents" rel="noopener noreferrer" class="c-link"&gt;
            Agent Definition Language (ADL): The Open Source Standard for Defining AI Agents — Next Moca 
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            GitHub Repository:     https://github.com/nextmoca/adl
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.squarespace-cdn.com%2Fcontent%2Fv1%2F68793d703bfc192900e52897%2F3868b990-79f4-4dc0-b01c-f46e74d833a2%2Ffavicon.ico%3Fformat%3D100w" width="100" height="100"&gt;
          nextmoca.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


</description>
    </item>
    <item>
      <title>Observability matter</title>
      <dc:creator>bsorrentino</dc:creator>
      <pubDate>Fri, 06 Feb 2026 17:47:43 +0000</pubDate>
      <link>https://dev.to/bsorrentino/observability-matter-24m3</link>
      <guid>https://dev.to/bsorrentino/observability-matter-24m3</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/bsorrentino/langgraph4j-hooks-and-opentelemetry-1egk" class="crayons-story__hidden-navigation-link"&gt;LangGraph4j Hooks and OpenTelemetry&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/bsorrentino" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F53518%2Ff0ff1ba7-a659-49a7-92e4-4fac9e829916.png" alt="bsorrentino profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/bsorrentino" class="crayons-story__secondary fw-medium m:hidden"&gt;
              bsorrentino
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                bsorrentino
                
              
              &lt;div id="story-author-preview-content-3237947" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/bsorrentino" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F53518%2Ff0ff1ba7-a659-49a7-92e4-4fac9e829916.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;bsorrentino&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/bsorrentino/langgraph4j-hooks-and-opentelemetry-1egk" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Feb 6&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/bsorrentino/langgraph4j-hooks-and-opentelemetry-1egk" id="article-link-3237947"&gt;
          LangGraph4j Hooks and OpenTelemetry
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/langgraph4j"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;langgraph4j&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/agents"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;agents&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/observability"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;observability&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/opentelemetry"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;opentelemetry&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/bsorrentino/langgraph4j-hooks-and-opentelemetry-1egk" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;3&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/bsorrentino/langgraph4j-hooks-and-opentelemetry-1egk#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              2&lt;span class="hidden s:inline"&gt; comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            3 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




</description>
      <category>langgraph4j</category>
      <category>agents</category>
      <category>observability</category>
      <category>opentelemetry</category>
    </item>
    <item>
      <title>LangGraph4j Hooks and OpenTelemetry</title>
      <dc:creator>bsorrentino</dc:creator>
      <pubDate>Fri, 06 Feb 2026 17:44:50 +0000</pubDate>
      <link>https://dev.to/bsorrentino/langgraph4j-hooks-and-opentelemetry-1egk</link>
      <guid>https://dev.to/bsorrentino/langgraph4j-hooks-and-opentelemetry-1egk</guid>
      <description>&lt;h2&gt;
  
  
  Why Observability Matters
&lt;/h2&gt;

&lt;p&gt;Agentic workflows are dynamic: nodes may run conditionally, in parallel, or be skipped entirely. When something fails, a simple stack trace is rarely enough. &lt;strong&gt;Observability&lt;/strong&gt; gives you a unified view of &lt;strong&gt;what&lt;/strong&gt; happened, &lt;strong&gt;where&lt;/strong&gt; it happened, and &lt;strong&gt;why&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In practice, observability helps you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understand end-to-end execution flow.&lt;/li&gt;
&lt;li&gt;Detect performance bottlenecks early.&lt;/li&gt;
&lt;li&gt;Correlate errors with specific nodes, edges, and state transitions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Telemetry Matters
&lt;/h2&gt;

&lt;p&gt;Observability is only possible if you collect high‑quality telemetry. Telemetry is the raw signal: &lt;strong&gt;traces&lt;/strong&gt;, &lt;strong&gt;logs&lt;/strong&gt;, and &lt;strong&gt;metrics&lt;/strong&gt;. Without it, probably,  you are debugging your system partially.&lt;/p&gt;

&lt;p&gt;In agent graphs, telemetry becomes even more important because state and control flow are distributed across steps. The same workflow can behave differently depending on state, configuration, or external tool results.&lt;/p&gt;

&lt;h2&gt;
  
  
  The LangGraph4j hooks
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://langgraph4j.github.io/langgraph4j/core/hooks/" rel="noopener noreferrer"&gt;LangGraph4j hooks&lt;/a&gt; are small, composable interceptors that sit around &lt;strong&gt;nodes&lt;/strong&gt; and &lt;strong&gt;conditional edges&lt;/strong&gt;. They let you run custom logic &lt;strong&gt;before&lt;/strong&gt;, &lt;strong&gt;after&lt;/strong&gt;, or &lt;strong&gt;wrapping&lt;/strong&gt; the core action, without modifying the node itself. &lt;br&gt;
Hooks can be registered globally (applies to all nodes/edges) or by ID (targeted to a specific node/edge), and their execution order is &lt;strong&gt;LIFO&lt;/strong&gt;(Last In First Out) for &lt;code&gt;BeforeCall&lt;/code&gt;/&lt;code&gt;AfterCall&lt;/code&gt;, &lt;strong&gt;FIFO&lt;/strong&gt;(First In First Out) for &lt;code&gt;WrapCall&lt;/code&gt;. &lt;br&gt;
This makes them a precise, low‑friction mechanism for cross‑cutting concerns like tracing, metrics, logging, or state inspection.&lt;/p&gt;
&lt;h2&gt;
  
  
  How Hooks Enable Observability
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://langgraph4j.github.io/langgraph4j/core/hooks/" rel="noopener noreferrer"&gt;Hooks&lt;/a&gt; provide lifecycle interception points around node and edge execution. This is the ideal place to add logging, metrics, or traces without contaminating business logic.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://github.com/langgraph4j/langgraph4j" rel="noopener noreferrer"&gt;LangGraph4j&lt;/a&gt; you can intercept execution &lt;strong&gt;before&lt;/strong&gt;, &lt;strong&gt;after&lt;/strong&gt;, or &lt;strong&gt;around&lt;/strong&gt; node/edge calls. Here is a minimal example that measures node execution time and logs it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;graph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StateGraph&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="nc"&gt;MyState&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SCHEMA&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;serializer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addWrapCallNodeHook&lt;/span&gt;&lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="n"&gt;nodeId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// add Wrap call node hook&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentTimeMillis&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;call&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;whenComplete&lt;/span&gt;&lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;ms&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentTimeMillis&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
                &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"node '{}' took {}ms"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nodeId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ms&lt;/span&gt; &lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="o"&gt;});&lt;/span&gt;
    &lt;span class="o"&gt;})&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addNode&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="s"&gt;"node1"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;action1&lt;/span&gt; &lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addNode&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="s"&gt;"node2"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;action2&lt;/span&gt; &lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;....&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;compile&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This pattern scales: you can plug in structured logs, metrics counters, or spans with the same hook mechanism.&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenTelemetry in the Java Ecosystem
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://opentelemetry.io/docs/what-is-opentelemetry/" rel="noopener noreferrer"&gt;OpenTelemetry&lt;/a&gt; is the standard for observability across modern platforms. In Java it provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tracing&lt;/strong&gt; via spans&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Metrics&lt;/strong&gt; via meters&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logs&lt;/strong&gt; via instrumentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You configure it once and export telemetry to a backend like &lt;strong&gt;&lt;a href="https://www.jaegertracing.io" rel="noopener noreferrer"&gt;Jaeger&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;Grafana&lt;/strong&gt;, or the &lt;strong&gt;OpenTelemetry Collector&lt;/strong&gt;. The key benefit here is &lt;strong&gt;portability&lt;/strong&gt;: you are not locked to a single vendor.&lt;/p&gt;

&lt;h2&gt;
  
  
  How LangGraph4j Hooks Enable OpenTelemetry
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/langgraph4j/langgraph4j" rel="noopener noreferrer"&gt;LangGraph4j&lt;/a&gt; includes a dedicated module, &lt;code&gt;langgraph4j-opentelemetry&lt;/code&gt;, that provides hook implementations ready for tracing node and edge execution. Consider it as a reference implementation about &lt;strong&gt;how to integrate OpenTelemetry in LangGraph4j&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The module includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;OTELWrapCallTraceHook&lt;/code&gt;: creates spans for each node and edge call, adding config/state attributes and start/end events.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;OTELWrapCallTraceSetParentHook&lt;/code&gt;: creates a parent span so node/edge spans are grouped inside a workflow scope.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A minimal integration looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;otelHook&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OTELWrapCallTraceHook&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MyState&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;serializer&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;parentHook&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OTELWrapCallTraceSetParentHook&lt;/span&gt;&lt;span class="o"&gt;.&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MyState&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;scope&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MyWorkflow"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;groupName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"stream"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;workflow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StateGraph&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="nc"&gt;MyState&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SCHEMA&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;serializer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addWrapCallNodeHook&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;otelHook&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addWrapCallEdgeHook&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;otelHook&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addWrapCallNodeHook&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parentHook&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addWrapCallEdgeHook&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parentHook&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addNode&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="s"&gt;"node1"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;action1&lt;/span&gt; &lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addNode&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="s"&gt;"node2"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;action2&lt;/span&gt; &lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addContitionalEdges&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="s"&gt;"node2"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;edgeAction&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; 
            &lt;span class="nc"&gt;EdgeMappings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"node1"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toEnd&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;        
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;compile&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps node logic clean while producing rich, correlated traces for the entire workflow.&lt;/p&gt;

&lt;p&gt;Below an example of output in &lt;a href="https://www.jaegertracing.io" rel="noopener noreferrer"&gt;Jaeger&lt;/a&gt; tracing platform&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwi3989g7rpnk6794wb5d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwi3989g7rpnk6794wb5d.png" alt="jaeger" width="800" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Hooks are the foundation for observability in &lt;a href="https://github.com/langgraph4j/langgraph4j" rel="noopener noreferrer"&gt;LangGraph4j&lt;/a&gt;: they give you structured interception points without affect your main workflow code. OpenTelemetry builds on top of this by standardizing how telemetry is collected and exported in the Java ecosystem.&lt;br&gt;
Combined, they deliver production-grade visibility for complex agent workflows.&lt;br&gt;
Checkout project, try it and let me know your feedback and ... happy AI coding! 👋&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://opentelemetry.io/docs/what-is-opentelemetry/" rel="noopener noreferrer"&gt;OpenTelemetry&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://bsorrentino.github.io/bsorrentino/ai/2026/02/04/LangGraph4j-Hooks-and-OpenTelemertry.html" rel="noopener noreferrer"&gt;https://bsorrentino.github.io&lt;/a&gt; on February 4, 2026&lt;/em&gt;.&lt;/p&gt;

</description>
      <category>langgraph4j</category>
      <category>agents</category>
      <category>observability</category>
      <category>opentelemetry</category>
    </item>
    <item>
      <title>I read this in a post: "AI agents are 5% models and 95% engineering glue." I completely agree, but I feel like it's not so clear among software engineers.
This helps us to understand that we need to focus on adding value around models.</title>
      <dc:creator>bsorrentino</dc:creator>
      <pubDate>Sat, 31 Jan 2026 08:55:24 +0000</pubDate>
      <link>https://dev.to/bsorrentino/i-read-this-in-a-post-ai-agents-are-5-models-and-95-engineering-glue-i-completely-agree-but-23nl</link>
      <guid>https://dev.to/bsorrentino/i-read-this-in-a-post-ai-agents-are-5-models-and-95-engineering-glue-i-completely-agree-but-23nl</guid>
      <description></description>
      <category>ai</category>
      <category>architecture</category>
      <category>programming</category>
    </item>
    <item>
      <title>Top GitHub Users By Public Contributions in Italy 

https://github.com/gayanvoice/top-github-users/blob/main/markdown/public_contributions/italy.md 

I'm at 26th place 👨‍💻 🚀😉</title>
      <dc:creator>bsorrentino</dc:creator>
      <pubDate>Fri, 23 Jan 2026 15:04:34 +0000</pubDate>
      <link>https://dev.to/bsorrentino/top-github-users-by-public-contributions-in-italy-1o1i</link>
      <guid>https://dev.to/bsorrentino/top-github-users-by-public-contributions-in-italy-1o1i</guid>
      <description>&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://github.com/gayanvoice/top-github-users/blob/main/markdown/public_contributions/italy.md" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frepository-images.githubusercontent.com%2F373383893%2F3812a400-d11b-11eb-8238-bd579de69457" height="640" class="m-0" width="1280"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://github.com/gayanvoice/top-github-users/blob/main/markdown/public_contributions/italy.md" rel="noopener noreferrer" class="c-link"&gt;
            top-github-users/markdown/public_contributions/italy.md at main · gayanvoice/top-github-users · GitHub
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Check your ranking in GitHub! Don't forget to star ⭐ this repository. - gayanvoice/top-github-users
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.githubassets.com%2Ffavicons%2Ffavicon.svg" width="32" height="32"&gt;
          github.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


</description>
    </item>
    <item>
      <title>[Top GitHub Users By Public Contributions in Italy]
(https://github.com/gayanvoice/top-github-users/blob/main/markdown/public_contributions/italy.md)

I'm at 26th place 👨‍💻 🚀😉</title>
      <dc:creator>bsorrentino</dc:creator>
      <pubDate>Fri, 23 Jan 2026 14:58:26 +0000</pubDate>
      <link>https://dev.to/bsorrentino/top-github-users-by-public-contributions-in-italy-1jp</link>
      <guid>https://dev.to/bsorrentino/top-github-users-by-public-contributions-in-italy-1jp</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://github.com/gayanvoice/top-github-users/blob/main/markdown/public_contributions/italy.md" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frepository-images.githubusercontent.com%2F373383893%2F3812a400-d11b-11eb-8238-bd579de69457" height="auto" class="m-0"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://github.com/gayanvoice/top-github-users/blob/main/markdown/public_contributions/italy.md" rel="noopener noreferrer" class="c-link"&gt;
            top-github-users/markdown/public_contributions/italy.md at main · gayanvoice/top-github-users · GitHub
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Check your ranking in GitHub! Don't forget to star ⭐ this repository. - gayanvoice/top-github-users
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.githubassets.com%2Ffavicons%2Ffavicon.svg"&gt;
          github.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;




</description>
      <category>community</category>
      <category>github</category>
      <category>opensource</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Exploring Javelit, the Java counterpart to Streamlit, for rapid prototyping and AI agents using LangGraph4j.</title>
      <dc:creator>bsorrentino</dc:creator>
      <pubDate>Sat, 20 Dec 2025 20:42:38 +0000</pubDate>
      <link>https://dev.to/bsorrentino/exploring-javelit-the-java-counterpart-to-streamlit-for-rapid-prototyping-and-ai-agents-using-5gmi</link>
      <guid>https://dev.to/bsorrentino/exploring-javelit-the-java-counterpart-to-streamlit-for-rapid-prototyping-and-ai-agents-using-5gmi</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/bsorrentino/experimenting-with-javelit-the-streamlit-for-java-bll" class="crayons-story__hidden-navigation-link"&gt;Experimenting with Javelit - The Streamlit for Java&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/bsorrentino" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F53518%2Ff0ff1ba7-a659-49a7-92e4-4fac9e829916.png" alt="bsorrentino profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/bsorrentino" class="crayons-story__secondary fw-medium m:hidden"&gt;
              bsorrentino
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                bsorrentino
                
              
              &lt;div id="story-author-preview-content-3117821" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/bsorrentino" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F53518%2Ff0ff1ba7-a659-49a7-92e4-4fac9e829916.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;bsorrentino&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/bsorrentino/experimenting-with-javelit-the-streamlit-for-java-bll" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Dec 20 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/bsorrentino/experimenting-with-javelit-the-streamlit-for-java-bll" id="article-link-3117821"&gt;
          Experimenting with Javelit - The Streamlit for Java
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/java"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;java&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ui"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ui&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ux"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ux&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/javelit"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;javelit&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/bsorrentino/experimenting-with-javelit-the-streamlit-for-java-bll#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




</description>
      <category>java</category>
      <category>ui</category>
      <category>ux</category>
      <category>javelit</category>
    </item>
    <item>
      <title>Experimenting with Javelit - The Streamlit for Java</title>
      <dc:creator>bsorrentino</dc:creator>
      <pubDate>Sat, 20 Dec 2025 20:41:56 +0000</pubDate>
      <link>https://dev.to/bsorrentino/experimenting-with-javelit-the-streamlit-for-java-bll</link>
      <guid>https://dev.to/bsorrentino/experimenting-with-javelit-the-streamlit-for-java-bll</guid>
      <description>&lt;h2&gt;
  
  
  Starting from Python development ecosystem
&lt;/h2&gt;

&lt;p&gt;At the beginning of my journey with agentic applications, I started with the Python programming language, leveraging &lt;a href="https://docs.langchain.com/oss/python/langchain/overview" rel="noopener noreferrer"&gt;LangChain&lt;/a&gt;/&lt;a href="https://docs.langchain.com/oss/python/langgraph/overview" rel="noopener noreferrer"&gt;LangGraph&lt;/a&gt;. For testing and documentation, I relied on the simple yet powerful &lt;a href="https://jupyter.org" rel="noopener noreferrer"&gt;Jupyter Notebooks&lt;/a&gt;. Simultaneously, for rapid prototyping, I adopted the amazing &lt;a href="https://streamlit.io" rel="noopener noreferrer"&gt;Streamlit&lt;/a&gt; framework, which empowered me to quickly develop functional applications with an effective UI and excellent UX. &lt;/p&gt;

&lt;h2&gt;
  
  
  Moving from Python ecosystem to the Java one
&lt;/h2&gt;

&lt;p&gt;When I started developing &lt;a href="https://github.com/langgraph4j/langgraph4j" rel="noopener noreferrer"&gt;LangGraph4j&lt;/a&gt;, I tried to replicate my Python development ecosystem in Java. So I've experimented with the Java Notebooks through the &lt;a href="https://github.com/padreati/rapaio-jupyter-kernel" rel="noopener noreferrer"&gt;rapaio-jupyter-kernel&lt;/a&gt; project, which allowed me to replicate the development experience I had with &lt;a href="https://jupyter.org" rel="noopener noreferrer"&gt;Jupyter Notebooks&lt;/a&gt; in Python quite well. For rapid prototyping, I relied almost entirely on &lt;a href="https://spring.io/projects/spring-boot" rel="noopener noreferrer"&gt;Spring Boot&lt;/a&gt; framework, which is a fairly fast and enjoyable programming experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Javelit come to play 🚀
&lt;/h2&gt;

&lt;p&gt;Going on my efforts on &lt;a href="https://github.com/langgraph4j/langgraph4j" rel="noopener noreferrer"&gt;LangGraph4j&lt;/a&gt; and continuously monitoring the most interesting and promising Java projects on GitHub, I discovered &lt;a href="https://javelit.io" rel="noopener noreferrer"&gt;Javelit&lt;/a&gt;. This project intrigued me because of its reference to &lt;a href="https://streamlit.io" rel="noopener noreferrer"&gt;Streamlit&lt;/a&gt;, and after a review, I was amazed to realize that the dynamic programming model popularized by &lt;a href="https://streamlit.io" rel="noopener noreferrer"&gt;Streamlit&lt;/a&gt; had been adapted for Java by this initiative, which is cool.😎&lt;br&gt;
So I started to evaluate it as part of may java development ecosystem and below i'll share with you my experience about it.&lt;/p&gt;
&lt;h2&gt;
  
  
  What is Javelit 👀
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://javelit.io" rel="noopener noreferrer"&gt;Javelit&lt;/a&gt; is a tool to quickly build interactive app frontends in Java, particularly for data apps, but it’s not limited to them. It helps you quickly develop rapid prototypes, with a live-reload loop, so that you can quickly experiment and update the app instantly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Javelit’s architecture allows you to write apps the same way you write plain Java methods. Any time something must be updated on the screen, Javelit reruns your entire Java main method from top to bottom.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So you have to think about it &lt;strong&gt;as if your entire UI code runs inside a continuous loop&lt;/strong&gt; that refreshes whenever something needs updating on the screen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://javelit.io" rel="noopener noreferrer"&gt;Javelit&lt;/a&gt; provides developers with a rich set of prebuilt &lt;a href="https://docs.javelit.io/develop/api-reference" rel="noopener noreferrer"&gt;components&lt;/a&gt; that make it easy to get started. &lt;/p&gt;

&lt;p&gt;Just to provide you an idea of the &lt;a href="https://javelit.io" rel="noopener noreferrer"&gt;Javelit&lt;/a&gt; approach below the inevitable "&lt;em&gt;Hello World&lt;/em&gt;" code snippet&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;/// usr/bin/env jbang "$0" "$@" ; exit $?&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.javelit.core.Jt&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Jt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello World!"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;Jt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;markdown&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"""
            ## My first official message
            Hello World!
            """&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, once &lt;a href="https://javelit.io" rel="noopener noreferrer"&gt;Javelit&lt;/a&gt; is &lt;a href="https://docs.javelit.io/get-started/installation/standalone#install-javelit" rel="noopener noreferrer"&gt;installed&lt;/a&gt;, you’d run it with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;javelit run App.java
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Use Javelit with LangGraph4j
&lt;/h2&gt;

&lt;p&gt;I've decided to use &lt;a href="https://javelit.io" rel="noopener noreferrer"&gt;Javelit&lt;/a&gt; to develop some examples of &lt;a href="https://github.com/langgraph4j/langgraph4j" rel="noopener noreferrer"&gt;LangGraph4j&lt;/a&gt; usage and below, I show you how have used &lt;a href="https://javelit.io" rel="noopener noreferrer"&gt;Javelit&lt;/a&gt; to implement a demo app to run the &lt;strong&gt;LangGraph4j powered React Agent&lt;/strong&gt;. &lt;br&gt;
For simplicity I've reported only the meaningful code snippets, but for a complete code take a look to &lt;a href="https://github.com/langgraph4j/langgraph4j/blob/main/spring-ai/spring-ai-agent/src/test/java/JtAgentExecutorApp.java" rel="noopener noreferrer"&gt;&lt;code&gt;JtAgentExecutorApp.java&lt;/code&gt;&lt;/a&gt; for &lt;a href="https://spring.io/projects/spring-ai#overview" rel="noopener noreferrer"&gt;spring AI&lt;/a&gt; based implementation. &lt;/p&gt;

&lt;p&gt;As &lt;a href="https://streamlit.io" rel="noopener noreferrer"&gt;Streamlit&lt;/a&gt; in &lt;a href="https://javelit.io" rel="noopener noreferrer"&gt;Javelit&lt;/a&gt; entire application consist in just one &lt;code&gt;main()&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JtAgentExecutorApp&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nc"&gt;Jt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"LangGraph4J React Agent"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// create a LangGraph4j Agent&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AgentExecutor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;chatModel&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/* instantiate the preferred ChatModel */&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toolsFromObject&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MyTools&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="cm"&gt;/* Custom Tools */&lt;/span&gt;  &lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;compile&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; 

            &lt;span class="c1"&gt;// input: the user message&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;userMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Jt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;textArea&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"user message:"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"user message"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;labelVisibility&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JtComponent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;LabelVisibility&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;HIDDEN&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

            &lt;span class="c1"&gt;// button: start agent processing &lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Jt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;button&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"start agent"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isBlank&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// if button pressed&lt;/span&gt;

                &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;outputComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Jt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;expander&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Workflow Steps"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

                &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GraphInput&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"messages"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UserMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userMessage&lt;/span&gt;&lt;span class="o"&gt;)));&lt;/span&gt;

                &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;generator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

                &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;startTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Instant&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

                &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;generator&lt;/span&gt; &lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

                    &lt;span class="nc"&gt;Jt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sessionState&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;remove&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"streaming"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                    &lt;span class="nc"&gt;Jt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"""
                            #### %s
                            %s
                            """&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;formatted&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;node&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;
                            &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;Object:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;collect&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Collectors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;joining&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\n\n"&lt;/span&gt;&lt;span class="o"&gt;)))&lt;/span&gt;
                    &lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outputComponent&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;

                &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;elapsedTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;between&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;startTime&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Instant&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

                &lt;span class="nc"&gt;Jt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"finished in %ds%n"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;formatted&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elapsedTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toSeconds&lt;/span&gt;&lt;span class="o"&gt;())).&lt;/span&gt;&lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;Jt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getMessage&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output of the &lt;a href="https://javelit.io" rel="noopener noreferrer"&gt;Javelit&lt;/a&gt; app looks like: &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Chat model selection view&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0eje5auie6ujogfw56t7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0eje5auie6ujogfw56t7.png" alt="Chat model selection view" width="800" height="726"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Start agent view&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm9bbp83jkrwr35vjqh9a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm9bbp83jkrwr35vjqh9a.png" alt="Start agent view" width="800" height="308"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Results view&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6vz18hyzxbhxbdw74irx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6vz18hyzxbhxbdw74irx.png" alt="Results view" width="800" height="799"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  👉 try yourself 👀 🚀 🤯
&lt;/h3&gt;

&lt;p&gt;If you want try yourself (after installed &lt;a href="https://javelit.io" rel="noopener noreferrer"&gt;javelit&lt;/a&gt;) run the command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;javelit run https://github.com/langgraph4j/langgraph4j/tree/main/spring-ai/spring-ai-agent/src/test/java
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://javelit.io" rel="noopener noreferrer"&gt;Javelit&lt;/a&gt; brings the power of rapid prototyping and interactive web app development to the Java ecosystem, much like &lt;a href="https://streamlit.io" rel="noopener noreferrer"&gt;Streamlit&lt;/a&gt; does for Python. With its simple, loop-based programming model, developers can quickly build data-driven applications without needing extensive frontend knowledge, leveraging familiar Java syntax and the rich JVM ecosystem. The live-reload feature enables instant experimentation and iteration, making it ideal for prototyping AI agents, data visualizations, and interactive tools. By integrating seamlessly with libraries like &lt;a href="https://github.com/langgraph4j/langgraph4j" rel="noopener noreferrer"&gt;LangGraph4j&lt;/a&gt; combined with both &lt;a href="https://spring.io/projects/spring-ai#overview" rel="noopener noreferrer"&gt;Spring AI&lt;/a&gt; and &lt;a href="https://docs.langchain4j.dev" rel="noopener noreferrer"&gt;LangChain4j&lt;/a&gt;, &lt;a href="https://javelit.io" rel="noopener noreferrer"&gt;Javelit&lt;/a&gt; empowers Java developers to create engaging user interfaces effortlessly, bridging the gap between backend logic and user-facing applications.&lt;br&gt;&lt;br&gt;
Checkout project, try it and let me know your feedback and ... happy coding! 👋&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://glaforge.dev/posts/2025/10/24/javelit-to-create-quick-interactive-app-frontends-in-java/" rel="noopener noreferrer"&gt;Javelit to create quick interactive app frontends in Java&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://bsorrentino.github.io/bsorrentino/ai/2025/12/20/Experiment-Javelit-Streamlit-for-Java.html" rel="noopener noreferrer"&gt;https://bsorrentino.github.io&lt;/a&gt; on December 20, 2025.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>ui</category>
      <category>ux</category>
      <category>javelit</category>
    </item>
    <item>
      <title>Very interesting. I agree with sentence "prompts are becoming as important as code dependencies" so it will be important apply the dependencies management approach also for prompt management</title>
      <dc:creator>bsorrentino</dc:creator>
      <pubDate>Fri, 12 Dec 2025 10:22:25 +0000</pubDate>
      <link>https://dev.to/bsorrentino/very-interesting-i-agree-with-sentence-prompts-are-becoming-as-important-as-code-dependencies-so-e30</link>
      <guid>https://dev.to/bsorrentino/very-interesting-i-agree-with-sentence-prompts-are-becoming-as-important-as-code-dependencies-so-e30</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/devdiaries" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F161574%2F66c19c0b-5ffa-4d1a-b555-e417464d81a0.jpg" alt="devdiaries"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/devdiaries/prpm-the-universal-package-manager-for-ai-prompts-36cf" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;PRPM - The Universal Package Manager for AI Prompts&lt;/h2&gt;
      &lt;h3&gt;Dev Diaries ・ Dec 9 '25&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#devchallenge&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#muxchallenge&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#showandtell&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#video&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>devchallenge</category>
      <category>muxchallenge</category>
      <category>showandtell</category>
      <category>video</category>
    </item>
    <item>
      <title>🧠🤖 LangGraph4j Deep Agents (Agent 2.0)</title>
      <dc:creator>bsorrentino</dc:creator>
      <pubDate>Fri, 17 Oct 2025 15:07:17 +0000</pubDate>
      <link>https://dev.to/bsorrentino/langgraph4j-deep-agents-agent-20-1d74</link>
      <guid>https://dev.to/bsorrentino/langgraph4j-deep-agents-agent-20-1d74</guid>
      <description>&lt;h2&gt;
  
  
  Why Deep Agents (Agent 2.0)?
&lt;/h2&gt;

&lt;p&gt;Classic agents often run a simple loop: &lt;strong&gt;think → call a tool → observe → repeat&lt;/strong&gt;. That’s great for quick, transactional queries, but it breaks down on multi-hour or multi-day tasks (hallucinations, loss of goal, looping, no recovery).&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Deep Agents&lt;/strong&gt; try fix this by &lt;strong&gt;changing the architecture&lt;/strong&gt; (not just the prompt) based on the four pillars below:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Explicit Planning&lt;/strong&gt; – The agent continuously maintains a plan (e.g., a TODO in Markdown) with clear statuses instead of hiding intent in a just chain-of-thought.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hierarchical Delegation (Sub-Agents)&lt;/strong&gt; – An &lt;strong&gt;Orchestrator&lt;/strong&gt; delegates to specialized agents (Researcher, Coder, Writer, …), each working in a clean context and returning synthesized results.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persistent Memory&lt;/strong&gt; – Intermediate artifacts (notes, code, data) are written to external storage (filesystem, vector store, …) and referenced by path/query rather than stuffing everything into the context window.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extreme Context Engineering&lt;/strong&gt; – Long, specific instructions define: when to plan vs. act, when to spawn sub-agents and the human-in-the-loop(HITL) rules.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Reference Architecture
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2dvh90fvinygxjcee78f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2dvh90fvinygxjcee78f.png" alt="Deep Agents Architecture" width="800" height="575"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Reference Implementation in Java using LangGraph4j
&lt;/h2&gt;

&lt;p&gt;Since the &lt;a href="https://github.com/langgraph4j/langgraph4j" rel="noopener noreferrer"&gt;LangGraph4j&lt;/a&gt; is inpired by (more popular) &lt;a href="https://github.com/langchain-ai/langgraph" rel="noopener noreferrer"&gt;LangGraph&lt;/a&gt; python version, I've decided to adapt its python based &lt;a href="https://github.com/langchain-ai/deepagents" rel="noopener noreferrer"&gt;Deep Agents reference implementation&lt;/a&gt; to Java using &lt;a href="https://github.com/langgraph4j/langgraph4j" rel="noopener noreferrer"&gt;LangGraph4j&lt;/a&gt; and &lt;a href="https://spring.io/projects/spring-ai" rel="noopener noreferrer"&gt;Spring AI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The project is on &lt;a href="https://github.com/langgraph4j/langgraph4j-deepagents.git" rel="noopener noreferrer"&gt;Github&lt;/a&gt;. This repository demonstrates the four pillars of Deep Agents, it includes sample code that create a &lt;strong&gt;Deep Researcher Agent&lt;/strong&gt; that use &lt;a href="https://www.tavily.com" rel="noopener noreferrer"&gt;Tavily&lt;/a&gt; as web search engine and &lt;strong&gt;OpenAI gpt-4o-mini model&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let's look at a sequence diagram for a Deep Agent handling a complex request: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc2oevotyyr15qno70auf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc2oevotyyr15qno70auf.png" alt="sequence" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Below a representative code snippet that implements the Deep Agents in the diagram&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Create a Research Sub Agent&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;researchSubagent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DeepAgent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SubAgent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"research-agent"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"""
        Used to research more in depth questions. Only give this researcher one topic at a time.
        Do not pass multiple sub questions to this researcher.
        Instead, you should break down a large topic into the necessary components, and then call multiple research agents in parallel, one for each sub question.
        """&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"""
        You are a dedicated researcher. Your job is to conduct research based on the users questions.
        Conduct thorough research and then reply to the user with a detailed answer to their question

        ........(to be continued).............. 
        """&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="s"&gt;"internet_search"&lt;/span&gt; &lt;span class="o"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Create a Critique Sub Agent&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;critiqueSubAgent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="nc"&gt;DeepAgent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SubAgent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"critique-agent"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Used to critique the final report. Give this agent some information about how you want it to critique the report."&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"""
            You are a dedicated editor. You are being tasked to critique a report.

            You can find the report at `final_report.md`.

            You can find the question/topic for this report at `question.txt`.

            ........(to be continued).............. 
            """&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Create a Main Agent&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;deepAgent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DeepAgent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;instructions&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"""
        You are an expert researcher. Your job is to conduct thorough research, and then write a polished report.

        The first thing you should do is to write the original user question to `question.txt` so you have a record of it.

        Use the research-agent to conduct deep research. It will respond to your questions/topics with a detailed answer.

        When you think you enough information to write a final report, write it to `final_report.md`

        You can call the critique-agent to get a critique of the final report. After that (if needed) you can do more research and edit the `final_report.md`

        ........(to be continued).............. 

        """&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;subAgents&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;researchSubagent&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;critiqueSubAgent&lt;/span&gt; &lt;span class="o"&gt;))&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;chatModel&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chatModel&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;internetSearch&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;compile&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="nc"&gt;CompileConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;recursionLimit&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;userMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""
                        What is langgraph4j project?
                        """&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;runnableConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RunnableConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                        &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"messages"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UserMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userMessage&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; 
                        &lt;span class="n"&gt;runnableConfig&lt;/span&gt; &lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;peek&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;node&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;reduce&lt;/span&gt;&lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;orElseThrow&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="sh"&gt;"""
        ================================
        TODO
        ================================
        """&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;todos&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;forEach&lt;/span&gt;&lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;printf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"""
                -----------
                %s
                -----------
                """&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="sh"&gt;"""
        ================================
        FILES
        ================================
        """&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;files&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;forEach&lt;/span&gt;&lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;printf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"""
                file: '%s'
                -----------
                %s
                -----------
                """&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="sh"&gt;"""
        ================================
        FINAL RESULT
        ================================
        """&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;printf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="s"&gt;"result: %s\n"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;lastMessage&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AssistantMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cast&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;AssistantMessage:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;getText&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;orElseThrow&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;Deep Agents architecture is a try &lt;strong&gt;to move beyond one-loop “shallow” agents&lt;/strong&gt; to explicit planning hierarchical delegation, persistent memory, and rigorous context engineering. &lt;a href="https://github.com/langgraph4j/langgraph4j" rel="noopener noreferrer"&gt;LangGraph4j&lt;/a&gt; can help to experiment in Labs and deliver in production complex Agentic Workflow on top of JVM. &lt;br&gt;
Checkout project, try it and let me know your feedback and ... happy AI coding! 👋&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.langchain.com/deep-agents/" rel="noopener noreferrer"&gt;Deep Agents (LangChain Blog)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/hwchase17/deepagents" rel="noopener noreferrer"&gt;Langchain Deepagents (Github)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.philschmid.de/agents-2.0-deep-agents" rel="noopener noreferrer"&gt;Agents 2.0: From Shallow to Deep Agents (Phil Schmid Blog)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Originally published at &lt;a href="https://bsorrentino.github.io/bsorrentino/ai/2025/10/17/langgraph4j-deepagents.html" rel="noopener noreferrer"&gt;https://bsorrentino.github.io&lt;/a&gt; on October 17, 2025.&lt;/p&gt;

</description>
      <category>langgraph4j</category>
      <category>ai</category>
      <category>agents</category>
      <category>springai</category>
    </item>
    <item>
      <title>LangGraph4j Meets AG-UI - Building UI/UX in AI Agents era</title>
      <dc:creator>bsorrentino</dc:creator>
      <pubDate>Mon, 25 Aug 2025 09:36:42 +0000</pubDate>
      <link>https://dev.to/bsorrentino/langgraph4j-meets-ag-ui-building-uiux-in-ai-agents-era-2pp7</link>
      <guid>https://dev.to/bsorrentino/langgraph4j-meets-ag-ui-building-uiux-in-ai-agents-era-2pp7</guid>
      <description>&lt;h2&gt;
  
  
  AI Agents ecosystem evolution
&lt;/h2&gt;

&lt;p&gt;The rapid evolution of artificial intelligence has brought a new wave of innovation: the rise of AI agents. These agents—autonomous, intelligent, and capable of interacting with users and services—are changing how we build applications, automate workflows, and even communicate online. However, as this ecosystem expands, a new challenge has emerged: interoperability. How can these agents reliably talk to each other, work with external tools, and offer seamless experiences to human users?&lt;/p&gt;

&lt;p&gt;This challenge has led to the development of new standards—protocols that define how AI agents communicate with the world and each other. Among the most notable are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://dev.to**Agent-to-Tools**"&gt;MCP&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Standardizing Agent to Tools/Services Communication&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://dev.to**Agent-to-Agent%20Protocol**"&gt;A2A&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Standardizing Agent to Agent Communication &lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://dev.to**Agent-to-User**"&gt;AG-UI&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Standardizing Agent to User Communication  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;In this article we will focus on &lt;a href="https://ag-ui.com" rel="noopener noreferrer"&gt;AG-UI&lt;/a&gt; protocol an how it helps us to develop an effective User eXperience in using AI Agents&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What is AG-UI protocol ?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://ag-ui.com" rel="noopener noreferrer"&gt;AG-UI&lt;/a&gt;&lt;/strong&gt; bridges the gap between AI agents and their human users, ensuring that interactions are intuitive, consistent, and user-friendly. It defines the structure for how agents present information, take user input, and handle conversations—regardless of the underlying platform or application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why AG-UI Compliance Matters
&lt;/h3&gt;

&lt;p&gt;By aligning with &lt;a href="https://ag-ui.com" rel="noopener noreferrer"&gt;AG-UI&lt;/a&gt;, LangGraph4j agents can present rich, interactive interfaces to user, whether embedded in web apps, desktop tools, or chatbots. This standardization means that developers can focus on building great agent logic, while relying on &lt;a href="https://ag-ui.com" rel="noopener noreferrer"&gt;AG-UI&lt;/a&gt; to handle the complexities of user interaction.&lt;/p&gt;

&lt;h2&gt;
  
  
  LangGraph4j and AG-UI
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/langgraph4j/langgraph4j" rel="noopener noreferrer"&gt;LangGraph4j&lt;/a&gt;&lt;/strong&gt; is a Java-based framework designed for building and orchestrating AI agent workflows. It is already capable to use &lt;strong&gt;&lt;a href="https://modelcontextprotocol.io" rel="noopener noreferrer"&gt;MCP&lt;/a&gt;&lt;/strong&gt; servers inside workflow steps and has also experimented integration with &lt;strong&gt;&lt;a href="https://a2aprotocol.ai" rel="noopener noreferrer"&gt;A2A&lt;/a&gt;&lt;/strong&gt; (see &lt;a href="https://github.com/langgraph4j/langgraph4j-examples/blob/main/spring-ai/a2a-server-implby-a2a4j" rel="noopener noreferrer"&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Copilotkit integration
&lt;/h3&gt;

&lt;p&gt;With its latest project, &lt;a href="https://github.com/langgraph4j/langgraph4j-copilotkit" rel="noopener noreferrer"&gt;langgraph4j-copilotkit&lt;/a&gt;, we have evaluated how to make &lt;a href="https://github.com/langgraph4j/langgraph4j" rel="noopener noreferrer"&gt;LangGraph4j&lt;/a&gt; compliant with the &lt;a href="https://ag-ui.com" rel="noopener noreferrer"&gt;AG-UI&lt;/a&gt; protocol,  integrating &lt;a href="https://www.copilotkit.ai/" rel="noopener noreferrer"&gt;CopilotKit&lt;/a&gt; that is its reference implementation for help and enhance developer experience in building better either User Interfaces (UI) and User eXperience (UX).&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;The architecture of the &lt;a href="https://github.com/langgraph4j/langgraph4j-copilotkit" rel="noopener noreferrer"&gt;langgraph4j-copilotkit&lt;/a&gt; integration is designed to enable seamless communication between a user-facing frontend and the &lt;a href="https://github.com/langgraph4j/langgraph4j" rel="noopener noreferrer"&gt;LangGraph4j&lt;/a&gt; backend. Here’s a breakdown of the key components and their interactions:&lt;/p&gt;

&lt;p&gt;The following diagram illustrates a diagram that shows the sequence of messages exchanged between main actors of the architecture:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuvl8ngptsljyd5u8bvzk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuvl8ngptsljyd5u8bvzk.png" alt="diagram" width="800" height="223"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Explanation of the diagram:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;User &amp;amp; Frontend (CopilotKit):&lt;/strong&gt; The user interacts with a web application that has the &lt;a href="https://www.copilotkit.ai/" rel="noopener noreferrer"&gt;CopilotKit&lt;/a&gt; SDK integrated. CopilotKit handles the UI rendering and state management, translating user actions into requests compliant with the &lt;a href="https://ag-ui.com" rel="noopener noreferrer"&gt;AG-UI&lt;/a&gt; protocol.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Backend (langgraph4j-copilotkit):&lt;/strong&gt; A backend server, built with a framework like Spring Boot, includes the &lt;a href="https://github.com/langgraph4j/langgraph4j-copilotkit" rel="noopener noreferrer"&gt;langgraph4j-copilotkit&lt;/a&gt; library. This library exposes an endpoint that listens for &lt;a href="https://ag-ui.com" rel="noopener noreferrer"&gt;AG-UI&lt;/a&gt; requests from the frontend. It acts as a bridge, translating incoming requests into executable commands for the &lt;a href="https://github.com/langgraph4j/langgraph4j" rel="noopener noreferrer"&gt;LangGraph4j&lt;/a&gt; agent, and in turn translates the agent's responses into compatible &lt;a href="https://ag-ui.com" rel="noopener noreferrer"&gt;AG-UI&lt;/a&gt; events.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The communication is typically asynchronous and streaming. As the &lt;a href="https://github.com/langgraph4j/langgraph4j" rel="noopener noreferrer"&gt;LangGraph4j&lt;/a&gt; agent produces results or requires further input, &lt;a href="https://github.com/langgraph4j/langgraph4j-copilotkit" rel="noopener noreferrer"&gt;langgraph4j-copilotkit&lt;/a&gt; streams these events back to the frontend in the &lt;a href="https://ag-ui.com" rel="noopener noreferrer"&gt;AG-UI&lt;/a&gt; format. CopilotKit then dynamically updates the UI, creating a responsive and interactive user experience.&lt;/p&gt;

&lt;p&gt;This architecture decouples the frontend presentation layer from the backend agentic logic, allowing developers to build sophisticated AI agents with &lt;a href="https://github.com/langgraph4j/langgraph4j" rel="noopener noreferrer"&gt;LangGraph4j&lt;/a&gt; while providing a rich, standardized user interface with &lt;code&gt;CopilotKit&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example - Approval action (Human-in-the-Loop)
&lt;/h2&gt;

&lt;p&gt;This example demonstrates how to implement a "Human-in-the-Loop" (HITL) approval action using &lt;a href="https://github.com/langgraph4j/langgraph4j-copilotkit" rel="noopener noreferrer"&gt;langgraph4j-copilotkit&lt;/a&gt;. The user will be asked to approve an action (&lt;code&gt;sendEmail&lt;/code&gt;) before it is executed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Frontend
&lt;/h3&gt;

&lt;p&gt;The frontend uses &lt;code&gt;@copilotkit/react-core&lt;/code&gt; and &lt;code&gt;@copilotkit/react-ui&lt;/code&gt; to create the chat interface and handle the approval action. The &lt;code&gt;useCopilotAction&lt;/code&gt; hook is used to define the &lt;code&gt;sendEmail&lt;/code&gt; action. When the action is triggered, it renders a confirmation dialog asking the user for approval.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;chatApproval.tsx&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useCopilotAction&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@copilotkit/react-core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;CopilotChat&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@copilotkit/react-ui&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;SimpleChatWithApproval&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nf"&gt;useCopilotAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sendEmail&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sends an email after user approval.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;address&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;subject&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;body&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;renderAndWaitForResponse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;respond&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;renderAndWaitForResponse&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;respond&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;inProgress&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Sending&lt;/span&gt; &lt;span class="nx"&gt;Email&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h2&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Preparing&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;send&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;executing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Confirm&lt;/span&gt; &lt;span class="nx"&gt;Email&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h2&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Send&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/b&amp;gt; with subject "&amp;lt;b&amp;gt;{args.subject}&amp;lt;/&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;?&amp;lt;/p&amp;gt;
              &amp;lt;p&amp;gt;&amp;lt;i&amp;gt;{args.body}&amp;lt;/i&amp;gt;&amp;lt;/p&amp;gt;
              &amp;lt;div&amp;gt;
                &amp;lt;button onClick={() =&amp;gt; respond?.('APPROVED')}&amp;gt;
                  Approve
                &amp;lt;/button&amp;gt;
                &amp;lt;button onClick={() =&amp;gt; respond?.('REJECTED')}&amp;gt;
                  Cancel
                 &amp;lt;/button&amp;gt;
              &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
          );
      }
     return &amp;lt;&amp;gt;&amp;lt;/&amp;gt;
  }});

  return (
    &amp;lt;CopilotChat
      instructions={&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="nx"&gt;You&lt;/span&gt; &lt;span class="nx"&gt;are&lt;/span&gt; &lt;span class="nx"&gt;assisting&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;best&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;you&lt;/span&gt; &lt;span class="nx"&gt;can&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;Answer&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;best&lt;/span&gt; &lt;span class="nx"&gt;way&lt;/span&gt; &lt;span class="nx"&gt;possible&lt;/span&gt; &lt;span class="nx"&gt;given&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="nx"&gt;you&lt;/span&gt; &lt;span class="nx"&gt;have&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;}
      labels={{
        title: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="nx"&gt;Your&lt;/span&gt; &lt;span class="nx"&gt;Assistant&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;,
        initial: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="nx"&gt;Hi&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="err"&gt;👋&lt;/span&gt; &lt;span class="nx"&gt;How&lt;/span&gt; &lt;span class="nx"&gt;can&lt;/span&gt; &lt;span class="nx"&gt;I&lt;/span&gt; &lt;span class="nx"&gt;assist&lt;/span&gt; &lt;span class="nx"&gt;you&lt;/span&gt; &lt;span class="nx"&gt;today&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;,
      }}
      className=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;full&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;
    /&amp;gt;
  );

}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  LangGraph4j Agent
&lt;/h3&gt;

&lt;p&gt;The backend is a &lt;a href="https://github.com/langgraph4j/langgraph4j" rel="noopener noreferrer"&gt;LangGraph4j&lt;/a&gt; agent that defines the &lt;code&gt;sendEmail&lt;/code&gt; tool. The &lt;code&gt;AgentExecutorEx&lt;/code&gt; is configured to require approval for the &lt;code&gt;sendEmail&lt;/code&gt; tool. When the tool is about to be executed, the agent will be interrupted, and an approval request will be sent to the frontend.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;AGUIAgentExecutor.java&lt;/code&gt;&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AGUIAgentExecutor&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;AGUILangGraphAgent&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// define tools&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Tools&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nd"&gt;@Tool&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Send an email to someone"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;sendEmail&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="nd"&gt;@ToolParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"destination address"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="nd"&gt;@ToolParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"subject of the email"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="nd"&gt;@ToolParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"body of the email"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;
        &lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// This is a placeholder for the actual implementation&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"mail sent to %s with subject %s"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="nc"&gt;GraphData&lt;/span&gt; &lt;span class="nf"&gt;buildStateGraph&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;GraphStateException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="c1"&gt;// Create agent&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="nc"&gt;AgentExecutorEx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;chatModel&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;LLM&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toolsFromObject&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Tools&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;approvalOn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="s"&gt;"sendEmail"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                         &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nodeId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                                        &lt;span class="nc"&gt;InterruptionMetadata&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;nodeId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;)&lt;/span&gt;
                                        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;GraphData&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// invoked on interruption to provide approval information back to the client&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;State&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;AgentState&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Approval&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;onInterruption&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AGUIType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;RunAgentInput&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;InterruptionMetadata&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;State&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"messages"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;orElseThrow&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IllegalStateException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"messages not found into given state"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;lastOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;flatMap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;MessageUtil:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;asAssistantMessage&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;AssistantMessage:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;hasToolCalls&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;AssistantMessage:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;getToolCalls&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;toolCalls&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                    &lt;span class="n"&gt;toolCalls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;toolCall&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;toolCall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;isBlank&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt;
                                &lt;span class="no"&gt;UUID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;randomUUID&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt;
                                &lt;span class="n"&gt;toolCall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
                        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Approval&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;toolCall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;toolCall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;arguments&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;);&lt;/span&gt;
                    &lt;span class="o"&gt;}).&lt;/span&gt;&lt;span class="na"&gt;toList&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;orElseGet&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;List:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This setup allows for a seamless HITL workflow where the user has the final say on critical actions, all orchestrated through the AG-UI protocol and the &lt;a href="https://github.com/langgraph4j/langgraph4j-copilotkit" rel="noopener noreferrer"&gt;langgraph4j-copilotkit&lt;/a&gt; integration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Demo
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fad86vlo315suofmz4f07.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fad86vlo315suofmz4f07.gif" alt="demo" width="1024" height="576"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We can state that the future of AI development will be to have a &lt;strong&gt;Unified AI Agent Ecosystem&lt;/strong&gt;.&lt;br&gt;
The convergence of these standards like &lt;a href="https://modelcontextprotocol.io" rel="noopener noreferrer"&gt;MCP&lt;/a&gt;, &lt;a href="https://a2aprotocol.ai" rel="noopener noreferrer"&gt;A2A&lt;/a&gt;, and &lt;a href="https://ag-ui.com" rel="noopener noreferrer"&gt;AG-UI&lt;/a&gt; is a step toward this vision. &lt;/p&gt;

&lt;p&gt;We consider crucial keep working to improve support of them in &lt;a href="https://github.com/langgraph4j/langgraph4j" rel="noopener noreferrer"&gt;LangGraph4j&lt;/a&gt; to provide a complete infrastructure for AI Agents to communicate with tools, collaborate with each other, and engage users in a standardized and interoperable manner.&lt;/p&gt;

&lt;p&gt;As more frameworks and tools adopt these protocols, we can expect to see a new generation of AI-powered applications that are more flexible, extensible and, with &lt;a href="https://ag-ui.com" rel="noopener noreferrer"&gt;AG-UI&lt;/a&gt;, more user-centric than ever before.&lt;/p&gt;

&lt;p&gt;Hope this could help your AI Java developing journey, in the meanwhile happy AI coding! 👋&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://bsorrentino.github.io/bsorrentino/ai/2025/08/21/LangGraph4j-meets-AG-UI.html" rel="noopener noreferrer"&gt;https://bsorrentino.github.io&lt;/a&gt; on August 21, 2025&lt;/em&gt;.&lt;/p&gt;

</description>
      <category>langgraph4j</category>
      <category>copilotkit</category>
      <category>langchain4j</category>
      <category>springai</category>
    </item>
  </channel>
</rss>
