Wednesday, 14 October 2026

Building a Document Summary AI Agent: Understanding the Perception Module in Action

  

In the previous post, we explored the Perception Module, the component that allows an AI agent to observe, interpret, and normalize information from the outside world before sending it to the Foundation Model for reasoning.

 

While the concepts are important, the best way to understand perception is to see it in action.

 

In this post, we'll build a Document Summary AI Agent that continuously monitors a folder for new documents. Whenever a file is added, the agent automatically detects its format, extracts its content using the appropriate processor, normalizes the extracted information, and sends a clean prompt to the Foundation Model to generate a concise summary.

 

Unlike traditional document processing applications that require users to manually upload files, this agent is event-driven. The arrival of a new document becomes the perception event that triggers the entire agentic loop.

 

Along the way, we'll learn how a File Watcher acts as the agent's sense, how different document types are processed through specialized processors, and how the Perception Module transforms heterogeneous inputs into a unified representation that the LLM can understand.

 

By the end of this post, you'll have built a practical AI agent that demonstrates one of the most fundamental principles of Agentic AI: before an AI agent can reason, it must first perceive its environment.

Proposed Project Structure

document-summary-agent
│
├── agent
│   ├── FileSummaryAgent.java
│   └── AgentConfiguration.java
│
├── perception
│   ├── PerceptionUtil.java
│   ├── PerceptionResult.java
│   └── SupportedFileType.java
│
├── watcher
│   └── FileWatcher.java
│
├── model
│   └── DocumentSummary.java
│
└── Application.java

   

Project Overview

This sample application demonstrates how an AI Agent processes incoming documents using the Perception Module before passing the normalized information to the Foundation Model (LLM) for reasoning.

 

The project is organized into logical packages that closely map to the architecture of an AI agent.

 

a. agent

The agent package represents the Foundation Model of the AI agent. It is responsible for reasoning over the normalized information produced by the Perception Module and generating a structured document summary.

 

FileSummaryAgent.java

This is the AI Agent interface built using LangChain4j AI Services.

 

Instead of working with files directly, it receives a normalized prompt generated by the Perception Module and returns a structured DocumentSummary object.

 

Its responsibility is purely reasoning. It has no knowledge of PDFs, Word documents, Apache Tika, or file systems.

 

AgentConfiguration.java

This class creates and configures the AI agent.

 

It initializes the underlying Ollama Llama 3.2 model, configures the language model settings, and wires the model with the FileSummaryAgent interface.

 

Think of this class as the factory responsible for creating the Foundation Model.

 

b. perception

The perception package represents the Perception Module, which acts as the senses of the AI agent.

 

Its responsibility is to translate messy real-world documents into clean, structured text that the Foundation Model can understand.

 

PerceptionUtil.java

This is the heart of the Perception Module. It performs several perception-related tasks:

 

·      Detects the document type

·      Extracts metadata

·      Extracts textual content using Apache Tika

·      Normalizes the extracted information

·      Builds a unified prompt for the Foundation Model

 

This class acts as the translator between the external world and the LLM.

 

PerceptionResult.java

This class represents everything perceived from an incoming document. It stores information such as:

 

·      File name

·      File type

·      MIME type

·      Metadata

·      Extracted content

·      Normalized prompt

 

Instead of returning raw text, the Perception Module returns a rich object describing everything it discovered about the document.

 

SupportedFileType.java

This enumeration defines the document formats supported by the Perception Module, such as PDF, Word, Text, JSON, and Markdown.

 

It enables the perception layer to identify and route different document types appropriately.

 

c. watcher

The watcher package represents the Perception Trigger. Rather than continuously polling for work, the agent remains idle until an event occurs.

 

FileWatcher.java

This class continuously monitors a folder using Java's WatchService. Whenever a new document arrives, it triggers the AI agent workflow by:

 

·      Detecting the new file

·      Invoking the Perception Module

·      Passing the normalized prompt to the Foundation Model

·      Displaying the generated summary

 

The File Watcher is not responsible for understanding documents. Its sole purpose is to detect events and initiate the perception process.

 

d. model

The model package contains the business objects exchanged between the AI agent and the application.

 

DocumentSummary.java

This class represents the structured output generated by the Foundation Model.

 

Instead of returning free-form text, the AI agent produces a strongly typed Java object containing:

 

·      Executive Summary

·      Key Topics

·      Important Points

·      Action Items

·      Conclusion

 

This demonstrates how Large Language Models can generate structured business objects rather than plain text responses.

 

e. Application.java

This is the application's entry point. Its responsibility is simply to wire together all the components:

 

·      Creates the Foundation Model

·      Creates the Perception Module

·      Starts the File Watcher

·      Launches the continuous perception loop

 

The application itself contains almost no business logic. Instead, it coordinates the collaboration between the individual components.

 

Follow below step-by-step procedure to build the working application

 

Step 1: Create new maven project 'document-summary-agent'

 

Step 2: Update pom.xml with dependencies.

 

pom.xml

 

<project xmlns="http://maven.apache.org/POM/4.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.sample.app</groupId>
   <artifactId>document-summary-agent</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <properties>

      <!-- Java -->
      <maven.compiler.release>23</maven.compiler.release>
      <jline.version>3.30.6</jline.version>
      <jansi.version>2.4.2</jansi.version>
      <jackson.version>2.20.0</jackson.version>
      <slf4j.version>2.0.17</slf4j.version>
      <logback.version>1.5.20</logback.version>
      <langchain4j.version>1.17.2</langchain4j.version>

   </properties>

   <dependencies>

      <!-- ========================= -->
      <!-- LangChain4j               -->
      <!-- ========================= -->

      <dependency>
         <groupId>dev.langchain4j</groupId>
         <artifactId>langchain4j</artifactId>
         <version>${langchain4j.version}</version>
      </dependency>

      <!-- Source:
      https://mvnrepository.com/artifact/dev.langchain4j/langchain4j-ollama -->
      <dependency>
         <groupId>dev.langchain4j</groupId>
         <artifactId>langchain4j-ollama</artifactId>
         <version>${langchain4j.version}</version>
      </dependency>


      <!-- ========================= -->
      <!-- Console UI                -->
      <!-- ========================= -->

      <!-- Interactive Terminal -->

      <dependency>
         <groupId>org.jline</groupId>
         <artifactId>jline</artifactId>
         <version>${jline.version}</version>
      </dependency>

      <!-- ASCII Banner -->

      <dependency>
         <groupId>com.github.lalyos</groupId>
         <artifactId>jfiglet</artifactId>
         <version>0.0.9</version>
      </dependency>

      <!-- ========================= -->
      <!-- JSON                      -->
      <!-- ========================= -->

      <dependency>
         <groupId>com.fasterxml.jackson.core</groupId>
         <artifactId>jackson-databind</artifactId>
         <version>${jackson.version}</version>
      </dependency>

      <!-- ========================= -->
      <!-- Logging                   -->
      <!-- ========================= -->

      <dependency>
         <groupId>org.slf4j</groupId>
         <artifactId>slf4j-api</artifactId>
         <version>${slf4j.version}</version>
      </dependency>

      <dependency>
         <groupId>ch.qos.logback</groupId>
         <artifactId>logback-classic</artifactId>
         <version>${logback.version}</version>
      </dependency>

      <!-- Source:
      https://mvnrepository.com/artifact/org.apache.tika/tika-core -->
      <dependency>
         <groupId>org.apache.tika</groupId>
         <artifactId>tika-core</artifactId>
         <version>3.3.1</version>
      </dependency>

      <!-- Source:
      https://mvnrepository.com/artifact/org.apache.tika/tika-langdetect -->
      <dependency>
         <groupId>org.apache.tika</groupId>
         <artifactId>tika-langdetect</artifactId>
         <version>3.3.1</version>
         <type>pom</type>
      </dependency>

      <dependency>
         <groupId>org.apache.tika</groupId>
         <artifactId>tika-langdetect-optimaize</artifactId>
         <version>3.3.1</version>
      </dependency>

      <dependency>
         <groupId>org.apache.tika</groupId>
         <artifactId>tika-parser-pdf-module</artifactId>
         <version>3.3.1</version>
      </dependency>

      <dependency>
         <groupId>org.apache.tika</groupId>
         <artifactId>tika-parser-microsoft-module</artifactId>
         <version>3.3.1</version>
      </dependency>

   </dependencies>

   <build>

      <plugins>

         <!-- Java Compiler -->

         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.14.1</version>
            <configuration>
               <release>23</release>
            </configuration>
         </plugin>

         <!-- Unit Tests -->

         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>3.5.4</version>
         </plugin>

         <!-- Build Executable JAR -->

         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.6.0</version>

            <executions>
               <execution>
                  <phase>package</phase>
                  <goals>
                     <goal>shade</goal>
                  </goals>

                  <configuration>

                     <filters>
                        <filter>
                           <artifact>*:*</artifact>

                           <excludes>
                              <exclude>META-INF/*.SF</exclude>
                              <exclude>META-INF/*.DSA</exclude>
                              <exclude>META-INF/*.RSA</exclude>
                           </excludes>

                        </filter>
                     </filters>

                     <transformers>

                        <transformer
                           implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />

                        <transformer
                           implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                           <mainClass>com.sample.documents.Application</mainClass>
                        </transformer>

                     </transformers>

                  </configuration>
               </execution>
            </executions>
         </plugin>

         <plugin>
            <groupId>com.diffplug.spotless</groupId>
            <artifactId>spotless-maven-plugin</artifactId>
            <version>2.46.1</version> <!-- Use the latest version -->
            <configuration>
               <!-- Target only relevant files -->
               <java>
                  <includes>
                     <include>src/main/java/**/*.java</include>
                     <include>src/test/java/**/*.java</include>
                  </includes>

                  <!-- Apply Google Java Format -->
                  <googleJavaFormat>
                     <version>1.24.0</version>
                     <style>GOOGLE</style> <!-- Or AOSP for 4-space
                     indents -->
                  </googleJavaFormat>

                  <!-- Extra clean-up steps -->
                  <removeUnusedImports />
                  <trimTrailingWhitespace />
                  <endWithNewline />
               </java>
            </configuration>
            <executions>
               <execution>
                  <!-- Automatically check style during the compile phase -->
                  <goals>
                     <goal>check</goal>
                  </goals>
                  <phase>compile</phase>
               </execution>
            </executions>
         </plugin>

      </plugins>

   </build>
</project>

Step 3: Create package com.sample.documents.model and define DocumentSummary class.

 

DocumentSummary.java

package com.sample.documents.model;

import dev.langchain4j.model.output.structured.Description;
import java.util.List;

/**
 * Represents the structured summary generated by the AI Agent.
 *
 * <p>This model encapsulates the key sections extracted from a document, making it suitable for
 * displaying in a UI, exporting to JSON, or persisting to a database.
 */
@Description("Summary generated from a document")
public class DocumentSummary {

  @Description("Detailed summary of the document")
  private String summary;

  @Description("The major topics discussed in the document")
  private List<String> keyTopics;

  @Description("Important observations, facts, or highlights")
  private List<String> importantPoints;

  @Description("Tasks, follow-ups, or action items identified in the document")
  private List<String> actionItems;

  @Description("Overall conclusion of the document")
  private String conclusion;

  public String getSummary() {
    return summary;
  }

  public void setSummary(String summary) {
    this.summary = summary;
  }

  public List<String> getKeyTopics() {
    return keyTopics;
  }

  public void setKeyTopics(List<String> keyTopics) {
    this.keyTopics = keyTopics;
  }

  public List<String> getImportantPoints() {
    return importantPoints;
  }

  public void setImportantPoints(List<String> importantPoints) {
    this.importantPoints = importantPoints;
  }

  public List<String> getActionItems() {
    return actionItems;
  }

  public void setActionItems(List<String> actionItems) {
    this.actionItems = actionItems;
  }

  public String getConclusion() {
    return conclusion;
  }

  public void setConclusion(String conclusion) {
    this.conclusion = conclusion;
  }

  @Override
  public String toString() {

    return """
            ==================================================
            Executive Summary
            ==================================================
            %s

            ==================================================
            Key Topics
            ==================================================
            %s

            ==================================================
            Important Points
            ==================================================
            %s

            ==================================================
            Action Items
            ==================================================
            %s

            ==================================================
            Conclusion
            ==================================================
            %s
            """
        .formatted(
            nullSafe(summary),
            formatList(keyTopics),
            formatList(importantPoints),
            formatList(actionItems),
            nullSafe(conclusion));
  }

  private String formatList(List<String> items) {

    if (items == null || items.isEmpty()) {
      return "N/A";
    }

    StringBuilder builder = new StringBuilder();

    for (String item : items) {
      builder.append("• ").append(item).append(System.lineSeparator());
    }

    return builder.toString().trim();
  }

  private String nullSafe(String value) {
    return value == null || value.isBlank() ? "N/A" : value;
  }
}

   

Step 4: Create package com.sample.documents.watcher and define FileWatcher class.

 

FileWatcher.java

package com.sample.documents.watcher;

import com.sample.documents.agent.FileSummaryAgent;
import com.sample.documents.model.DocumentSummary;
import com.sample.documents.perception.PerceptionResult;
import com.sample.documents.perception.PerceptionUtil;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;

/**
 * Watches a directory for newly added documents.
 *
 * <p>The FileWatcher acts as the perception trigger of the AI Agent. Whenever a new file is
 * detected, it invokes the Perception Module, which extracts and normalizes the document before
 * passing it to the Foundation Model for summarization.
 */
public class FileWatcher {

  private final Path watchDirectory;
  private final PerceptionUtil perceptionUtil;
  private final FileSummaryAgent summaryAgent;

  public FileWatcher(
      Path watchDirectory, PerceptionUtil perceptionUtil, FileSummaryAgent summaryAgent) {

    this.watchDirectory = watchDirectory;
    this.perceptionUtil = perceptionUtil;
    this.summaryAgent = summaryAgent;
  }

  /** Starts monitoring the directory. */
  public void start() throws IOException, InterruptedException {

    if (!Files.exists(watchDirectory)) {
      Files.createDirectories(watchDirectory);
    }

    try (WatchService watchService = FileSystems.getDefault().newWatchService()) {

      watchDirectory.register(watchService, StandardWatchEventKinds.ENTRY_CREATE);

      System.out.println("=================================================");
      System.out.println("📂 Watching folder : " + watchDirectory.toAbsolutePath());
      System.out.println("Waiting for new documents...");
      System.out.println("=================================================");

      while (true) {

        WatchKey key = watchService.take();

        for (WatchEvent<?> event : key.pollEvents()) {

          if (event.kind() == StandardWatchEventKinds.OVERFLOW) {
            continue;
          }

          @SuppressWarnings("unchecked")
          WatchEvent<Path> pathEvent = (WatchEvent<Path>) event;

          Path file = watchDirectory.resolve(pathEvent.context());

          process(file);
        }

        if (!key.reset()) {
          break;
        }
      }
    }
  }

  /** Executes the perception pipeline and invokes the AI agent. */
  private void process(Path file) {

    try {

      // Wait briefly so the file copy operation completes.
      Thread.sleep(500);

      if (!Files.isRegularFile(file)) {
        return;
      }

      System.out.println();
      System.out.println("=================================================");
      System.out.println("📄 New File Detected");
      System.out.println("=================================================");
      System.out.println(file.getFileName());

      // -------------------------------
      // Perception Module
      // -------------------------------
      System.out.println();
      System.out.println("🧠 Perception Module");

      PerceptionResult result = perceptionUtil.perceive(file);

      System.out.println("✔ File Type : " + result.getFileType());
      System.out.println("✔ MIME Type : " + result.getMimeType());
      System.out.println("✔ Size      : " + result.getFileSize() + " bytes");
      System.out.println("✔ Content Extracted");
      System.out.println("✔ Prompt Constructed");

      // -------------------------------
      // Foundation Model
      // -------------------------------
      System.out.println();
      System.out.println("🤖 Foundation Model");
      System.out.println("Generating summary...");

      DocumentSummary summary = summaryAgent.chat(result.getNormalizedPrompt());

      // -------------------------------
      // Output
      // -------------------------------
      System.out.println();
      System.out.println("=================================================");
      System.out.println("📋 DOCUMENT SUMMARY");
      System.out.println("=================================================");
      System.out.println(summary);
      System.out.println("=================================================");

    } catch (Exception ex) {

      System.err.println("Failed to process file: " + file.getFileName());
      ex.printStackTrace();
    }
  }
}

   

Step 5: Create package ‘com.sample.documents.agent’ and define FileSummaryAgent class.

 

FileSummaryAgent.java

package com.sample.documents.agent;

import com.sample.documents.model.DocumentSummary;

import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;

/**
 * AI Agent responsible for summarizing documents.
 *
 * <p>This agent represents the <b>Foundation Model</b> in our architecture. It does not understand
 * files, PDFs, Word documents, or metadata. Instead, it receives a clean, normalized prompt
 * produced by the Perception Module and generates an intelligent summary.
 */
public interface FileSummaryAgent {

  @SystemMessage(
      """
        You are an expert document analysis assistant.

        Populate the DocumentSummary object using only the supplied document.

        Do not invent information.
        """)
  DocumentSummary chat(@UserMessage String normalizedPrompt);
}

   

Define AgentConfiguration class.

 

AgentConfiguration.java

package com.sample.documents.agent;

import static dev.langchain4j.model.chat.Capability.RESPONSE_FORMAT_JSON_SCHEMA;

import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.ollama.OllamaChatModel;
import dev.langchain4j.service.AiServices;

/**
 * Creates and configures the AI Agent.
 *
 * <p>This configuration wires the FileSummaryAgent interface with the Ollama Llama 3.2 chat model.
 */
public final class AgentConfiguration {

  private static final String BASE_URL = "http://localhost:11434";
  private static final String MODEL_NAME = "llama3.2";

  private AgentConfiguration() {}

  /**
   * Creates the File Summary AI Agent.
   *
   * @return configured FileSummaryAgent
   */
  public static FileSummaryAgent createFileSummaryAgent() {

    ChatModel chatModel =
        OllamaChatModel.builder()
            .baseUrl(BASE_URL)
            .modelName(MODEL_NAME)
            .supportedCapabilities(RESPONSE_FORMAT_JSON_SCHEMA)
            .temperature(0.2)
            .build();

    return AiServices.create(FileSummaryAgent.class, chatModel);
  }
}

   

Step 6: Define classes related to Perception.

 

SupportedFileType.java

package com.sample.documents.perception;

/** Supported document types that can be processed by the Perception Module. */
public enum SupportedFileType {
  PDF,
  WORD,
  TEXT,
  JSON,
  MARKDOWN,
  HTML,
  XML,
  UNKNOWN
}

   

PerceptionResult.java

package com.sample.documents.perception;

/**
 * Represents the output of the Perception Module.
 *
 * <p>This object contains everything extracted from the incoming document, including metadata, raw
 * content, and the final normalized prompt that will be sent to the Foundation Model.
 */
public class PerceptionResult {

  private String fileName;

  private SupportedFileType fileType;

  private String mimeType;

  private long fileSize;

  private String title;

  private String author;

  private String language;

  private String content;

  private String normalizedPrompt;

  public String getFileName() {
    return fileName;
  }

  public void setFileName(String fileName) {
    this.fileName = fileName;
  }

  public SupportedFileType getFileType() {
    return fileType;
  }

  public void setFileType(SupportedFileType fileType) {
    this.fileType = fileType;
  }

  public String getMimeType() {
    return mimeType;
  }

  public void setMimeType(String mimeType) {
    this.mimeType = mimeType;
  }

  public long getFileSize() {
    return fileSize;
  }

  public void setFileSize(long fileSize) {
    this.fileSize = fileSize;
  }

  public String getTitle() {
    return title;
  }

  public void setTitle(String title) {
    this.title = title;
  }

  public String getAuthor() {
    return author;
  }

  public void setAuthor(String author) {
    this.author = author;
  }

  public String getLanguage() {
    return language;
  }

  public void setLanguage(String language) {
    this.language = language;
  }

  public String getContent() {
    return content;
  }

  public void setContent(String content) {
    this.content = content;
  }

  public String getNormalizedPrompt() {
    return normalizedPrompt;
  }

  public void setNormalizedPrompt(String normalizedPrompt) {
    this.normalizedPrompt = normalizedPrompt;
  }
}

   

PerceptionUtil.java

 

package com.sample.documents.perception;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import org.apache.tika.Tika;
import org.apache.tika.langdetect.optimaize.OptimaizeLangDetector;
import org.apache.tika.language.detect.LanguageDetector;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.parser.AutoDetectParser;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.sax.BodyContentHandler;
import org.xml.sax.ContentHandler;

/**
 * Perception Module.
 *
 * <p>Responsible for:
 *
 * <ul>
 *   <li>Detecting document type
 *   <li>Extracting metadata
 *   <li>Extracting textual content
 *   <li>Normalizing the extracted content
 *   <li>Building a prompt for the Foundation Model
 * </ul>
 */
public class PerceptionUtil {

  private final Tika tika = new Tika();

  /**
   * Perceives a document and produces a normalized prompt.
   *
   * @param file document path
   * @return perception result
   */
  public PerceptionResult perceive(Path file) {

    try {

      Metadata metadata = new Metadata();
      ContentHandler handler = new BodyContentHandler(-1);
      AutoDetectParser parser = new AutoDetectParser();

      ParseContext context = new ParseContext();

      try (InputStream inputStream = Files.newInputStream(file)) {
        parser.parse(inputStream, handler, metadata, context);
      }

      String content = handler.toString();

      System.out.println("Content length = " + content.length());
      System.out.println(content);

      PerceptionResult result = new PerceptionResult();

      result.setFileName(file.getFileName().toString());
      result.setFileSize(Files.size(file));
      result.setMimeType(tika.detect(file));
      result.setFileType(detectFileType(file));
      result.setTitle(metadata.get("title"));
      result.setAuthor(metadata.get("Author"));
      result.setLanguage(detectLanguage(content));
      result.setContent(content);

      result.setNormalizedPrompt(buildPrompt(result));

      return result;

    } catch (Exception ex) {
      throw new RuntimeException("Failed to perceive document: " + file, ex);
    }
  }

  /** Detects the supported file type. */
  private SupportedFileType detectFileType(Path file) {

    String name = file.getFileName().toString().toLowerCase();

    if (name.endsWith(".pdf")) {
      return SupportedFileType.PDF;
    }

    if (name.endsWith(".doc") || name.endsWith(".docx")) {
      return SupportedFileType.WORD;
    }

    if (name.endsWith(".txt")) {
      return SupportedFileType.TEXT;
    }

    if (name.endsWith(".json")) {
      return SupportedFileType.JSON;
    }

    if (name.endsWith(".md")) {
      return SupportedFileType.MARKDOWN;
    }

    if (name.endsWith(".html") || name.endsWith(".htm")) {
      return SupportedFileType.HTML;
    }

    if (name.endsWith(".xml")) {
      return SupportedFileType.XML;
    }

    return SupportedFileType.UNKNOWN;
  }

  /** Detects the language of the extracted content. */
  private String detectLanguage(String text) throws IOException {

    if (text == null || text.isBlank()) {
      return "Unknown";
    }

    LanguageDetector detector = new OptimaizeLangDetector().loadModels();

    return detector.detect(text).getLanguage();
  }

  /** Builds the normalized prompt that will be sent to the LLM. */
  private String buildPrompt(PerceptionResult result) {

    StringBuilder builder = new StringBuilder();

    builder.append("Document Information\n");
    builder.append("--------------------\n");
    builder.append("File Name : ").append(result.getFileName()).append('\n');
    builder.append("Document Type : ").append(result.getFileType()).append('\n');
    builder.append("MIME Type : ").append(result.getMimeType()).append('\n');
    builder.append("Language : ").append(result.getLanguage()).append('\n');

    if (result.getTitle() != null) {
      builder.append("Title : ").append(result.getTitle()).append('\n');
    }

    if (result.getAuthor() != null) {
      builder.append("Author : ").append(result.getAuthor()).append('\n');
    }

    builder.append("\n");
    builder.append("Document Content\n");
    builder.append("----------------\n");
    builder.append(result.getContent());

    return builder.toString();
  }
}

   

Step 7: Define main Application class.

 

Application.java

 

package com.sample.documents;

import com.sample.documents.agent.AgentConfiguration;
import com.sample.documents.agent.FileSummaryAgent;
import com.sample.documents.perception.PerceptionUtil;
import com.sample.documents.watcher.FileWatcher;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * Entry point for the Document Summary AI Agent.
 *
 * <p>This application demonstrates the Perception Module in an AI Agent. It continuously monitors a
 * folder for newly added documents. When a document arrives, the following pipeline is executed:
 *
 * <pre>
 * New Document
 *       │
 *       ▼
 * File Watcher
 *       │
 *       ▼
 * Perception Module
 *       │
 *       ▼
 * Foundation Model (LLM)
 *       │
 *       ▼
 * Structured Document Summary
 * </pre>
 */
public class Application {

  /** Folder monitored for incoming documents. */
  private static Path WATCH_DIRECTORY = null;

  public static void main(String[] args) throws Exception {

    System.out.println("===============================================");
    System.out.println("      Document Summary AI Agent");
    System.out.println("===============================================");
    System.out.println();

    if (args[0] == null) {
      System.out.println("Watch Directory Path is not Set");
      System.exit(1);
    }

    WATCH_DIRECTORY = Paths.get(args[0]);
    // WATCH_DIRECTORY = Paths.get("/Users/Shared/files");

    // Create the Foundation Model (AI Agent)
    FileSummaryAgent summaryAgent = AgentConfiguration.createFileSummaryAgent();

    // Create the Perception Module
    PerceptionUtil perceptionUtil = new PerceptionUtil();

    // Create the File Watcher
    FileWatcher watcher = new FileWatcher(WATCH_DIRECTORY, perceptionUtil, summaryAgent);

    System.out.println("AI Agent Initialized");
    System.out.println("Perception Module Ready");
    System.out.println("Watching folder: " + WATCH_DIRECTORY.toAbsolutePath());
    System.out.println();
    System.out.println("Drop a PDF, DOCX, TXT, JSON or Markdown file into the folder...");
    System.out.println();

    // Start monitoring the folder
    watcher.start();
  }
}

   

Build the Project

Open a terminal and navigate to the directory containing the `pom.xml` file. Then run the following command to build the project:

 

mvn clean package

   

Run the Application

After the build completes successfully, the ` document-summary-agent-0.0.1-SNAPSHOT.jar` file will be available in the `target` directory. Start the application by running:

 

java -jar ./target/document-summary-agent-0.0.1-SNAPSHOT.jar {FOLDER_TO_WATCH}

 

Once the application starts, copy or move any file into the `{FOLDER_TO_WATCH}` directory that was specified when launching the application.

 

For example, I copied following file.

 

demo.txt

 

Artificial Intelligence Agent Architecture

Introduction

Artificial Intelligence (AI) agents are software systems capable of perceiving their environment, reasoning over information, making decisions, and performing actions to achieve specific goals. Unlike traditional applications that execute predefined logic, AI agents dynamically adapt their behavior based on incoming information.

Modern AI agents are typically composed of multiple architectural components that work together in a continuous loop.

Core Components

1. Perception Module

The Perception Module acts as the senses of the AI agent. It receives information from various sources such as user messages, PDF documents, images, audio recordings, REST APIs, databases, or scheduled events.

The primary responsibility of the perception layer is normalization. Since Large Language Models understand textual information, the perception module converts every incoming input into clean, structured text.

For example:

• PDF documents are converted into plain text.
• Images are analyzed using vision models to generate textual descriptions.
• Audio files are converted into transcripts using speech-to-text models.
• JSON responses are summarized into natural language.

This normalization process ensures that the reasoning engine receives consistent input regardless of the original source.

2. Foundation Model

The Foundation Model represents the reasoning engine of the AI agent. It analyzes the normalized information, understands the user's intent, performs logical reasoning, and determines the next action.

Popular foundation models include GPT, Llama, Gemma, Claude, and Mistral.

3. Planning Module

Planning determines how the agent should accomplish a goal.

Simple requests may require only a single action, while complex requests can involve multiple reasoning steps, task decomposition, prioritization, and dependency management.

4. Memory Module

Memory enables an AI agent to retain knowledge across interactions.

Short-term memory stores recent conversations, while long-term memory stores historical knowledge, user preferences, and previously learned information.

Memory helps the agent generate contextually relevant responses.

5. Action Module

After reasoning, the agent performs one or more actions.

Examples include:

• Calling REST APIs
• Querying databases
• Sending emails
• Executing shell commands
• Generating reports
• Updating enterprise applications

The Action Module is responsible for interacting with external systems.

Benefits

An agent-based architecture provides several advantages:

• Better adaptability
• Modular design
• Easier maintenance
• Multi-modal input support
• Improved reasoning capabilities
• Better user experience

Challenges

Despite their advantages, AI agents introduce several engineering challenges.

Large Language Models may hallucinate facts when provided with incomplete information. Processing large documents increases token consumption and response latency. Security, prompt injection, and data privacy must also be carefully considered when building production-grade systems.

Future Direction

The next generation of AI agents will become increasingly autonomous. They will continuously observe events, collaborate with other agents, invoke enterprise tools, and learn from previous interactions.

Organizations are expected to build specialized agents for software development, customer support, finance, healthcare, legal analysis, and scientific research.

Conclusion

A well-designed AI agent consists of multiple independent modules working together in a continuous cycle of Perceive, Reason, Plan, and Act. Among these components, the Perception Module plays a foundational role because it bridges the gap between messy real-world information and the clean textual representation required by the Foundation Model. Without effective perception, even the most powerful language model cannot reason accurately.

   

Find the sample response below.

 

=================================================
📋 DOCUMENT SUMMARY
=================================================
==================================================
Executive Summary
==================================================
The document discusses the architecture of Artificial Intelligence (AI) agents, which are software systems capable of perceiving their environment, reasoning over information, making decisions, and performing actions to achieve specific goals.

==================================================
Key Topics
==================================================
• Artificial Intelligence Agent Architecture
• Perception Module
• Foundation Model
• Planning Module
• Memory Module
• Action Module

==================================================
Important Points
==================================================
• AI agents are composed of multiple architectural components that work together in a continuous loop.
• The Perception Module acts as the senses of the AI agent, converting incoming input into clean, structured text.
• The Foundation Model represents the reasoning engine of the AI agent, analyzing normalized information and determining the next action.
• Memory enables an AI agent to retain knowledge across interactions, generating contextually relevant responses.
• An agent-based architecture provides several advantages, including better adaptability, modular design, and improved reasoning capabilities.

==================================================
Action Items
==================================================
N/A

==================================================
Conclusion
==================================================
A well-designed AI agent consists of multiple independent modules working together in a continuous cycle of Perceive, Reason, Plan, and Act. The Perception Module plays a foundational role in bridging the gap between messy real-world information and clean textual representation required by the Foundation Model.

=================================================

   

You can download this application from this link.


 

 

Previous                                                    Next                                                    Home

No comments:

Post a Comment