<?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: srijithunni7182</title>
    <description>The latest articles on DEV Community by srijithunni7182 (@srijithunni7182).</description>
    <link>https://dev.to/srijithunni7182</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%2F3894712%2Fe640fd49-f998-4aa5-be79-97f01e45044e.jpeg</url>
      <title>DEV Community: srijithunni7182</title>
      <link>https://dev.to/srijithunni7182</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/srijithunni7182"/>
    <language>en</language>
    <item>
      <title>Building Production AI Agents in Java: Introducing llm4j and the Loom Orchestration DSL</title>
      <dc:creator>srijithunni7182</dc:creator>
      <pubDate>Thu, 23 Apr 2026 17:17:02 +0000</pubDate>
      <link>https://dev.to/srijithunni7182/building-production-ai-agents-in-java-introducing-llm4j-and-the-loom-orchestration-dsl-10bi</link>
      <guid>https://dev.to/srijithunni7182/building-production-ai-agents-in-java-introducing-llm4j-and-the-loom-orchestration-dsl-10bi</guid>
      <description>&lt;p&gt;The AI agent ecosystem has a Python problem.&lt;/p&gt;

&lt;p&gt;Not that Python is bad — it's a great language. But when you're building production systems that need type safety, JVM performance, Spring Boot integration, enterprise security controls, and the ability to onboard a team of Java engineers without retraining them on a new ecosystem — the Python-first assumption of most AI frameworks starts to feel like a tax.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;llm4j&lt;/strong&gt; is a Java-native AI agent framework that doesn't ask you to pay that tax. It's built from the ground up for the JVM, ships on Maven Central, and includes a purpose-built orchestration DSL called &lt;strong&gt;Loom&lt;/strong&gt; that solves a problem most frameworks don't even acknowledge: the coordination layer of a multi-agent system should be symbolic, not probabilistic.&lt;/p&gt;

&lt;p&gt;Let me show you what that means in practice.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Stack at a Glance
&lt;/h2&gt;

&lt;p&gt;llm4j is organized into three layers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;llm4j/
├── ai-agent4j          # Core library — LLM clients, ReAct agents, RAG, memory
├── ai-agent4j-addons   # Local embeddings (ONNX/DJL), pgvector, Pinecone
└── loom/
    ├── ai-agent4j-loom # Loom DSL runtime — Lexer, Parser, AST, HarnessExecutor
    ├── vscode-loom     # VS Code extension for .loom files
    └── ctk             # Conformance Test Kit — behavioral contracts for all runtimes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use &lt;code&gt;ai-agent4j&lt;/code&gt; standalone as a lightweight LLM client and ReAct agent framework. Or you can layer Loom on top for complex multi-agent orchestration. They're designed to work together but are independently useful.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 1: ai-agent4j — The Core Library
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;io.github.srijithunni7182&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;ai-agent4j&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;5.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  A Minimal LLM Client
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;LLMConfig&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LLMConfig&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;apiKey&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;getenv&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"GOOGLE_API_KEY"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;defaultModel&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"gemini-1.5-flash"&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="nc"&gt;LLMClient&lt;/span&gt; &lt;span class="n"&gt;client&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;DefaultLLMClient&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;GoogleProvider&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="nc"&gt;LLMResponse&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;chat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;LLMRequest&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;addUserMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Summarize the key risks in this contract: {text}"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. No decorators, no async event loops, no Python runtime embedded in your JVM process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Provider Support
&lt;/h3&gt;

&lt;p&gt;ai-agent4j ships with first-class support for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Google Gemini&lt;/strong&gt; (1.5 Flash, Pro, 2.x) — the primary target, deeply optimized&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sarvam AI&lt;/strong&gt; — Indian language voice agents with TTS, STT, and translation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ollama&lt;/strong&gt; — local models (Gemma, Llama, Mistral) with zero cost and zero internet dependency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And a routing layer that makes provider switching transparent:&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="nc"&gt;LLMConfig&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LLMConfig&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;primaryModel&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"gpt-4o"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fallbackModels&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;"claude-3-haiku"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"gemini-1.5-flash"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RoutingStrategy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;COST_AWARE&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When your primary provider rate-limits or fails, the router falls over to the next option automatically. No retry boilerplate in your application code.&lt;/p&gt;

&lt;h3&gt;
  
  
  ReAct Agents with Tool Use
&lt;/h3&gt;

&lt;p&gt;The ReAct (Reasoning + Acting) loop is a first-class primitive:&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="nc"&gt;ReActAgent&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;ReActAgent&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;client&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;systemPrompt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"You are a financial analyst."&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;tool&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;WebSearchTool&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;tool&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;CalculatorTool&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;maxIterations&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&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="nc"&gt;AgentResult&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;run&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"What is the current P/E ratio of NVDA?"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent reasons, decides which tool to call, observes the result, and iterates until it has a final answer — or hits the iteration limit. The Thought-Action-Observation loop is fully transparent and auditable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Memory: Short-Term and Long-Term
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Conversation history&lt;/strong&gt; (short-term) is managed automatically. &lt;strong&gt;Semantic memory&lt;/strong&gt; (long-term) uses vector embeddings to recall relevant facts across sessions:&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="nc"&gt;ReActAgent&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;ReActAgent&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;client&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SemanticMemory&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;embeddingProvider&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;OnnxEmbeddingProvider&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"models/onnx/model.onnx"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"models/onnx/tokenizer.json"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;vectorStore&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;PGVectorStore&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"jdbc:postgresql://localhost/mydb"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"user"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"pass"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"agent_memory"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;384&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;similarityThreshold&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.85&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;maxResults&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&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;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent will automatically retrieve relevant memories before each response. No manual retrieval logic in your application.&lt;/p&gt;

&lt;h3&gt;
  
  
  RAG Pipelines
&lt;/h3&gt;

&lt;p&gt;The addons module adds local embeddings and persistent vector stores:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;io.github.srijithunni7182&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;ai-agent4j-addons&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;5.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Local embeddings — no API calls, no cost&lt;/span&gt;
&lt;span class="nc"&gt;OnnxEmbeddingProvider&lt;/span&gt; &lt;span class="n"&gt;embedder&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;OnnxEmbeddingProvider&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"models/onnx/model.onnx"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"models/onnx/tokenizer.json"&lt;/span&gt;
&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// pgvector for production persistence&lt;/span&gt;
&lt;span class="nc"&gt;PGVectorStore&lt;/span&gt; &lt;span class="n"&gt;store&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;PGVectorStore&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"jdbc:postgresql://localhost:5432/postgres"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"postgres"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"secret"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"document_embeddings"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;384&lt;/span&gt;
&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;embedder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;embed&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Your document chunk here"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"doc_001"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vector&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;"source"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"contracts"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"year"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"2024"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// Semantic search&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;SearchResult&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;search&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queryVector&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or use Pinecone for managed cloud storage — same API, different backend.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 2: Loom — The Orchestration DSL
&lt;/h2&gt;

&lt;p&gt;Here's where llm4j diverges from every other Java AI framework.&lt;/p&gt;

&lt;p&gt;Most multi-agent frameworks — in any language — ask you to express coordination logic in the same language as your application. Python functions, YAML configs, JSON schemas. The routing rules, the retry logic, the branching conditions — all of it lives in your application code, tightly coupled to the framework's execution model.&lt;/p&gt;

&lt;p&gt;This creates a problem that gets worse as your system grows: &lt;strong&gt;you can't tell where the AI ends and the application begins.&lt;/strong&gt; The coordination logic bleeds into your business logic. The retry handling bleeds into your prompt engineering. The whole thing becomes a tangle that's hard to read, hard to audit, and hard to hand to a new engineer.&lt;/p&gt;

&lt;p&gt;Loom's answer is a hard architectural boundary: &lt;strong&gt;the coordination layer is a separate language with its own runtime.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Core Idea: Neuro-Symbolic AI
&lt;/h3&gt;

&lt;p&gt;The term "neuro-symbolic" describes a system that combines neural components (LLMs — probabilistic, reasoning about content) with symbolic components (deterministic rules — routing, branching, safety constraints).&lt;/p&gt;

&lt;p&gt;The key insight is that these two things should not be mixed. The model should reason about content. The harness should govern coordination. And the boundary between them should be explicit, auditable, and enforced by a runtime — not inferred from a prompt.&lt;/p&gt;

&lt;p&gt;Loom is that harness, expressed as a DSL.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Real Loom Script
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// agents.loom

routing CostAware {
    strategy: "COST_AWARE"
    primary: "gpt-4o"
    fallback: ["claude-3-haiku", "gemini-1.5-flash"]
}

agent Researcher {
    model: "gpt-4o"
    system: "You are a rigorous research analyst."
    routing: CostAware
    knowledge {
        type: "RAG"
        path: "data/research_kb/"
        embedding: "text-embedding-3-small"
    }
}

agent Writer {
    model: "claude-3-opus"
    system: "You write clear, compelling technical articles."
}

agent Auditor {
    model: "gemini-1.5-pro"
    system: "You audit content for accuracy and compliance."
    output_schema: {
        status: enum["APPROVED", "NEEDS_REVISION"],
        issues: list&amp;lt;string&amp;gt;
    }
}

workflow ResearchAndPublish(topic) {

    // Retry with structured failure handling
    delegate "Research: {topic}" to Researcher -&amp;gt; findings
        retry 3
        on_failure {
            note "Research failed: {_error}"
            handoff "Manual research needed for: {topic}" to Writer
        }

    // Typed symbolic branching — not a string match
    alt (findings.status == "SUFFICIENT") {

        // Parallel execution — both run concurrently
        parallel {
            delegate "Write article: {findings}" to Writer -&amp;gt; draft
            delegate "Audit findings: {findings}" to Auditor -&amp;gt; audit
        }

        alt (audit.status == "APPROVED") {
            handoff "Publish: {draft}" to Writer
        } else {
            loop until (approved == "true") {
                delegate "Revise based on: {audit.issues}" to Writer -&amp;gt; draft
                human_prompt "Approve revised draft? (true/false)" -&amp;gt; approved
            }
        }

    } else {
        handoff "Insufficient research for: {topic}" to Researcher
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let me walk through what's happening here, because every construct is doing something specific.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;routing CostAware&lt;/code&gt;&lt;/strong&gt; — a global policy. When the Researcher's primary model rate-limits, the runtime falls over to the fallback list automatically. This is declared once and applied by name.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;knowledge { type: "RAG" }&lt;/code&gt;&lt;/strong&gt; — the Researcher has RAG-backed context. Before each call, the runtime retrieves relevant documents from the knowledge base and injects them into the prompt. Configured in the DSL, not in Java code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;output_schema&lt;/code&gt;&lt;/strong&gt; — the Auditor is constrained to return structured JSON. The runtime coerces the model's response before any condition is evaluated. &lt;code&gt;audit.status == "APPROVED"&lt;/code&gt; is a typed enum check, not a string match against free text.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;delegate ... retry 3 on_failure { }&lt;/code&gt;&lt;/strong&gt; — resilience contracts in the DSL. If the Researcher fails three times, the runtime executes the &lt;code&gt;on_failure&lt;/code&gt; block. The model never sees this logic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;parallel { }&lt;/code&gt;&lt;/strong&gt; — concurrent execution. Both the Writer and Auditor run in separate threads. Execution waits at the closing brace for both to complete.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;loop until&lt;/code&gt;&lt;/strong&gt; — symbolic retry. The runtime evaluates the condition. The model doesn't decide when to stop.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;human_prompt&lt;/code&gt;&lt;/strong&gt; — first-class human-in-the-loop. Execution suspends until input arrives.&lt;/p&gt;

&lt;p&gt;The entire coordination graph — retries, parallelism, branching, human approval gates — is in the &lt;code&gt;.loom&lt;/code&gt; file. The models only see their individual task strings.&lt;/p&gt;

&lt;h3&gt;
  
  
  Running It
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Build and alias the CLI&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;loom/ai-agent4j-loom &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; mvn clean &lt;span class="nb"&gt;install
alias &lt;/span&gt;&lt;span class="nv"&gt;weave&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'java -cp "target/classes:target/lib/*" io.github.llm4j.loom.cli.WeaveCLI'&lt;/span&gt;

&lt;span class="c"&gt;# Run&lt;/span&gt;
weave run research.loom &lt;span class="nt"&gt;--loot&lt;/span&gt; tools.loot &lt;span class="nt"&gt;--input&lt;/span&gt; &lt;span class="nv"&gt;topic&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Neuro-Symbolic AI"&lt;/span&gt;

&lt;span class="c"&gt;# Package for deployment&lt;/span&gt;
weave package research.loom &lt;span class="nt"&gt;--loot&lt;/span&gt; tools.loot &lt;span class="nt"&gt;--fat&lt;/span&gt; &lt;span class="nt"&gt;--out&lt;/span&gt; research-app.jar
java &lt;span class="nt"&gt;-jar&lt;/span&gt; research-app.jar &lt;span class="nv"&gt;topic&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Quantum Computing"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Embedding in a Spring Boot Application
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&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;ResearchService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;HarnessExecutor&lt;/span&gt; &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;ResearchService&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;Exception&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;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Files&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;readString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Path&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;"workflows/research.loom"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="nc"&gt;LoomScript&lt;/span&gt; &lt;span class="n"&gt;script&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;LoomParser&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;Lexer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;tokenize&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;parseScript&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="nc"&gt;ToolRegistry&lt;/span&gt; &lt;span class="n"&gt;registry&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;ToolRegistry&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;LootLoader&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;loadIntoRegistry&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"tools.loot"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;executor&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;HarnessExecutor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;registry&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;DefaultLLMClientFactory&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;initialize&lt;/span&gt;&lt;span class="o"&gt;();&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;research&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;topic&lt;/span&gt;&lt;span class="o"&gt;)&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;executor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;executeWorkflow&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ResearchAndPublish"&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;"topic"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;topic&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;h3&gt;
  
  
  The Full Primitive Set
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Primitive&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;delegate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Call one agent, await result, bind to variable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;broadcast&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fan out to multiple agents in parallel, collect combined result&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;handoff&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Terminal node — pass control to an agent and end the current branch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;parallel { }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Concurrent execution block — every statement runs in its own thread&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;alt&lt;/code&gt; / &lt;code&gt;else&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Symbolic conditional branching on typed variable values&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;loop until&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Retry block — executes until a symbolic condition is met&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;human_prompt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Blocking suspension — parks execution until human input arrives&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;guardrail&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Wraps a block — intercepts output before it escapes (e.g. PII detection)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;call&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Invoke a sub-workflow with isolated variable scope&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;observe&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Emit a structured trace event without affecting control flow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;note&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Inline documentation — ignored by the runtime&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;import&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Split large workflows across files — merged into a flat namespace&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Part 3: The Tooling
&lt;/h2&gt;

&lt;h3&gt;
  
  
  VS Code Extension
&lt;/h3&gt;

&lt;p&gt;Writing &lt;code&gt;.loom&lt;/code&gt; files without tooling is painful. The VS Code extension provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Syntax highlighting for &lt;code&gt;.loom&lt;/code&gt; and &lt;code&gt;.loot&lt;/code&gt; files&lt;/li&gt;
&lt;li&gt;Real-time LSP diagnostics — errors as you type, with precise line/column&lt;/li&gt;
&lt;li&gt;Hover documentation and go-to-definition for agents and workflows&lt;/li&gt;
&lt;li&gt;Completion for all Loom keywords and identifiers&lt;/li&gt;
&lt;li&gt;Workflow Outline sidebar — see the full structure of a script at a glance&lt;/li&gt;
&lt;li&gt;Run Workflow command — execute the current file via &lt;code&gt;weave&lt;/code&gt; without leaving the editor&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conformance Test Kit (CTK)
&lt;/h3&gt;

&lt;p&gt;This is the part that makes Loom a language rather than a library.&lt;/p&gt;

&lt;p&gt;The CTK is a suite of 15 canonical &lt;code&gt;.loom&lt;/code&gt; scripts — one per primitive — paired with expected execution traces and mock agent fixtures. Any Loom runtime (Java, Python, or future implementations) must pass the CTK to be considered conformant.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;loom/ctk
mvn &lt;span class="nb"&gt;test
&lt;/span&gt;mvn &lt;span class="nb"&gt;exec&lt;/span&gt;:java &lt;span class="nt"&gt;-Dexec&lt;/span&gt;.mainClass&lt;span class="o"&gt;=&lt;/span&gt;io.github.loom.ctk.CtkMain
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The trace comparison algorithm checks structure, not values — it verifies that the right agents were called in the right order with the right statement types, without being brittle to changes in model output. This is what makes behavioral parity across runtimes verifiable rather than assumed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Java for AI Agents?
&lt;/h2&gt;

&lt;p&gt;This is the question I get most often, so let me answer it directly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Type safety at the boundary.&lt;/strong&gt; The hardest problem in multi-agent systems is the boundary between model output (free text) and application logic (typed values). Java's type system, combined with Loom's output schemas, makes this boundary explicit and enforced at compile time where possible and at runtime where not.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JVM performance.&lt;/strong&gt; The HarnessExecutor uses Java's &lt;code&gt;CompletableFuture&lt;/code&gt; and thread pools for parallel execution. For workflows with many concurrent branches, the JVM's threading model is a genuine advantage over Python's GIL.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enterprise integration.&lt;/strong&gt; Spring Boot, Quarkus, Jakarta EE, JDBC, JPA — the Java ecosystem for enterprise integration is unmatched. If your AI agents need to talk to Oracle databases, SAP systems, or internal REST APIs with complex auth flows, you want to be in Java.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Existing teams.&lt;/strong&gt; Most enterprise engineering teams are Java shops. Asking them to adopt Python for AI work means new tooling, new CI/CD pipelines, new security reviews, and a split codebase. llm4j lets them build AI agents in the language they already know.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Auditability.&lt;/strong&gt; The Loom DSL produces a complete execution trace for every workflow run. Every &lt;code&gt;delegate&lt;/code&gt;, &lt;code&gt;broadcast&lt;/code&gt;, &lt;code&gt;call&lt;/code&gt;, and &lt;code&gt;handoff&lt;/code&gt; is recorded with its agent, payload, and output variable. This is not optional — it's built into the runtime. For regulated industries, this matters.&lt;/p&gt;




&lt;h2&gt;
  
  
  Project Stats
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Lines of Code&lt;/td&gt;
&lt;td&gt;13,700+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Test Cases&lt;/td&gt;
&lt;td&gt;438+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maven Central&lt;/td&gt;
&lt;td&gt;v5.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;License&lt;/td&gt;
&lt;td&gt;MIT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Java Version&lt;/td&gt;
&lt;td&gt;17+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Library Size&lt;/td&gt;
&lt;td&gt;~308 KB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/srijithunni7182/llm4j.git
&lt;span class="nb"&gt;cd &lt;/span&gt;llm4j

&lt;span class="c"&gt;# Build the core library&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;ai-agent4j &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; mvn clean &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="c"&gt;# Build and run the Loom sample&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ../loom/ai-agent4j-loom &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; mvn clean &lt;span class="nb"&gt;install
alias &lt;/span&gt;&lt;span class="nv"&gt;weave&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'java -cp "target/classes:target/lib/*" io.github.llm4j.loom.cli.WeaveCLI'&lt;/span&gt;
weave run samples/boardroom/main.loom &lt;span class="nt"&gt;--input&lt;/span&gt; &lt;span class="nv"&gt;topic&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"The future of AI agents"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or add the Maven dependency and start with the &lt;a href="https://github.com/srijithunni7182/llm4j/wiki/Getting-Started" rel="noopener noreferrer"&gt;Quick Start Guide&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;loom4py&lt;/strong&gt; is in active development — a native Python implementation of the Loom runtime that will be validated against the CTK for full behavioral parity with the Java reference. The goal: write a &lt;code&gt;.loom&lt;/code&gt; script once, run it on any conformant runtime.&lt;/p&gt;




&lt;h2&gt;
  
  
  Contribute
&lt;/h2&gt;

&lt;p&gt;llm4j is MIT licensed and actively developed. The repo is at:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/srijithunni7182/llm4j" rel="noopener noreferrer"&gt;https://github.com/srijithunni7182/llm4j&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Good first contributions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;New Loom samples&lt;/strong&gt; — real-world workflows in &lt;code&gt;loom/ai-agent4j-loom/samples/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;New tool implementations&lt;/strong&gt; — anything that implements the &lt;code&gt;Tool&lt;/code&gt; interface&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;New provider integrations&lt;/strong&gt; — OpenAI, Anthropic, Cohere&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;loom4py&lt;/strong&gt; — the Python runtime is the most impactful open contribution right now&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CTK runtime ports&lt;/strong&gt; — build a conformant Loom runtime in Go, Rust, or TypeScript&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're building multi-agent systems in Java and you've been waiting for a framework that takes the JVM seriously — this is it.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Star the repo, open an issue, or just say hello. The model reasons. The harness governs.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>agents</category>
      <category>java</category>
    </item>
  </channel>
</rss>
