Embabel Framework - Rest API Based AI Agent

Embabel Framework: Build a REST API Based AI Agent

Learn how to build REST API based AI agents using the Embabel framework. Step-by-step guide to create intelligent agents with Spring Boot and GOAP planning.

1. Introduction

Welcome back to our series on the Embabel framework!  In our first article, “Embabel Framework: Create Goal-Driven AI Agents for the JVM,” we explored the fundamentals of building goal-driven AI agents on the JVM. We covered core concepts like GOAP planning, actions, and goals, and built our first intelligent agent—a shell-based meeting summarizer.

While the shell interface is great for testing and debugging, real-world applications often need to expose AI agents through REST APIs for integration with web applications, mobile apps, and other services.

In this tutorial, we’ll take the next step in our Embabel journey by transforming our meeting summarizer agent into a production-ready REST API. You’ll learn how to expose Embabel agents as RESTful endpoints, handle HTTP requests, and integrate intelligent AI capabilities into your Spring Boot applications. By the end of this guide, you’ll have a fully functional REST API that accepts meeting transcripts and returns structured summaries with key points and action items.

2. Building REST API Based AI Agent with Embabel Framework

We’re building a REST API-based meeting summarizer agent that:

  • Accepts meeting transcripts via POST requests
  • Extracts key discussion points automatically
  • Identifies action items with responsible persons and deadlines
  • Returns structured JSON responses
  • Leverages GOAP planning for intelligent execution

Don’t worry if you missed our first post; this guide covers the complete code from scratch. This beautifully demonstrates a key advantage of the Embabel framework: the core AI logic is completely reusable. We’ll be creating the same intelligent agent, but this time, we will wrap it in a REST API, showcasing how easily you can take an Embabel agent from a development tool to a production-ready service.



⚙️ Project Structure & Setup

First, let’s get a bird’s-eye view of our project. A well-organized structure is key to a maintainable application.

embabel-meeting-summarizer-agent
├── src
│   └── main
│       ├── java
│       │   └── com
│       │       └── bootcamptoprod
│       │               ├── agent
│       │               │   └── MeetingSummarizerAgent.java
│       │               ├── config
│       │               │   └── ConfigureGoogleGeminiModels.java
│       │               ├── controller
│       │               │   └── SummarizerController.java
│       │               ├── dto
│       │               │   └── MeetingSummary.java
│       │               │   └── KeyPoints.java
│       │               │   └── ActionItems.java
│       │               │   └── SummaryRequest.java
│       │               └── EmbabelMeetingSummarizerApplication.java
│       └── resources
│           └──application.yml
└── pom.xml
Project Structure

Understanding the Project Structure

Here’s a quick breakdown of what each key file and package does:

  • SummarizerController.java: New REST controller that exposes our agent via HTTP endpoints
  • MeetingSummarizerAgent.java: This is the heart of our application. It’s the agent class where we define our goal and the individual Action methods (findKeyPoints, findActionItems, createSummary) that the agent can perform to achieve that goal.
  • dto package (ActionItems.java, KeyPoints.java, MeetingSummary.java, SummaryRequest.java): This directory holds our Data Transfer Objects (DTOs). These are simple Java record classes that define the structure of our data, including the incoming API request (SummaryRequest.java) and the final summary output (MeetingSummary.java), which are used by the agent to process information.
  • ConfigureGoogleGeminiModels.java: This is a Spring @Configuration class responsible for setting up and providing the LLM (in this case, Google Gemini) that our agent will use to process information. We will be using free model from Google Gemini due to which we have added this configuration. If you are using OpenAI or Anthrophic you can configure the OPENAI_API_KEY or ANTHROPIC_API_KEY environment variables.
  • EmbabelMeetingSummarizerApplication.java: The main class that boots up our Spring Boot application. It contains the crucial @EnableAgents annotation that tells Embabel to find and activate our MeetingSummarizerAgent.
  • application.properties: Our configuration file. This is where we set the default LLM for Embabel to use (gemini-2.0-flash-exp) and configure logging levels for easier debugging.
  • pom.xml: The Maven project file. It manages all our project’s dependencies, including the most important one for this project: embabel-agent-starter, which provides all the core Embabel agent functionalities.


Diving Into the Code

Let’s break down each component of our application.

Step 1: Configure Maven Dependencies

Every Spring Boot project starts with the pom.xml file. This is where we tell Maven which libraries our project needs to function. Our pom.xml now includes spring-boot-starter-web to build a web application and embabel-agent-starter for the core agent functionalities.

<properties>
	<java.version>21</java.version>
	<embabel-agent.version>0.2.0-SNAPSHOT</embabel-agent.version>
</properties>

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <dependency>
    <groupId>com.embabel.agent</groupId>
    <artifactId>embabel-agent-starter</artifactId>
    <version>${embabel-agent.version}</version>
  </dependency>
  <dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-actuator</artifactId>
	</dependency>
</dependencies>

<repositories>
	<repository>
		<id>embabel-releases</id>
		<url>https://repo.embabel.com/artifactory/libs-release</url>
		<releases>
			<enabled>true</enabled>
		</releases>
		<snapshots>
			<enabled>false</enabled>
		</snapshots>
	</repository>
	<repository>
		<id>embabel-snapshots</id>
		<url>https://repo.embabel.com/artifactory/libs-snapshot</url>
		<releases>
			<enabled>false</enabled>
		</releases>
		<snapshots>
			<enabled>true</enabled>
		</snapshots>
	</repository>
</repositories>
pom.xml

In this configuration:

  • This Maven configuration sets up our Spring Boot project with Java 21.
  • The key dependency here is embabel-agent-starter, which brings in all the necessary components to create Embabel application. This will also bring the spring-ai dependencies that are required for our application.
  • The dependency spring-boot-starter-web Provides REST API capabilities, embedded Tomcat server, and Spring MVC
  • We’ve also included custom repositories to fetch the latest Embabel artifacts.
  • The Actuator dependency adds health checks and metrics endpoints for production monitoring.

Step 2: Configure Application Properties

Next, let’s configure our application settings in application.yml:

spring:
  application:
    name: embabel-meeting-summarizer-agent

embabel:
  models:
    defaultLlm: gemini-2.0-flash-exp

logging:
  level:
    org.springframework.ai: DEBUG

management:
  endpoints:
    web:
      exposure:
        include: "*"
application.yaml

📄 Configuration Overview

  • defaultLlm: Sets Google Gemini Flash as our default language model
  • logging.level: Enables DEBUG logging for Spring AI to trace LLM interactions
  • management.endpoints: Exposes all actuator endpoints for monitoring (health, metrics, etc.)

This configuration ensures our REST API is observable and easy to debug during development.



Step 3: Application Entry Point

This is the main class that bootstraps our entire application.

package com.bootcamptoprod;

import com.embabel.agent.config.annotation.EnableAgents;
import com.embabel.agent.config.annotation.LoggingThemes;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableAgents(
    loggingTheme = LoggingThemes.STAR_WARS
)
public class EmbabelMeetingSummarizerApplication {

    public static void main(String[] args) {
        SpringApplication.run(EmbabelMeetingSummarizerApplication.class, args);
    }
}
EmbabelMeetingSummarizerApplication.java

Explanation:

  • This is our Spring Boot application entry point.
  • The @EnableAgents annotation activates Embabel’s agent framework capabilities. This annotation scans for agent definitions and registers them with the Spring context automatically.
  • The loggingTheme = LoggingThemes.STAR_WARS parameter adds fun, themed logging output to make debugging more engaging (you’ll see Star Wars-themed log messages!).
  • This class bootstraps both Spring Boot and Embabel frameworks simultaneously

Step 4: Create Data Transfer Object (DTOs)

Our DTOs define the structure of data flowing through the application. We have one new DTO for REST:

package com.bootcamptoprod.dto;

public record SummaryRequest(
    String transcript
) {}
SummaryRequest.java

Explanation:

This record receives the meeting transcript from HTTP POST requests. Unlike the shell version which used UserInput, here we are using the custom request object.


package com.bootcamptoprod.dto;

import java.util.List;

public record MeetingSummary(
    List<String> keyPoints,
    List<String> actionItems
) {}
MeetingSummary.java

Explanation:

This Java record represents the final output of our agent – a complete meeting summary containing both key discussion points and action items.


package com.bootcamptoprod.dto;

import java.util.List;

public record KeyPoints(
    List<String> points
) {}
KeyPoints.java

Explanation:

This record holds the key discussion points extracted from a meeting transcript. Each point represents an important topic or decision discussed during the meeting. The AI will populate this structure with human-readable bullet points.


package com.bootcamptoprod.dto;

import java.util.List;

public record ActionItems(
    List<String> actionItems
) {}
ActionItems.java

Explanation:

This record stores action items identified in the meeting. The AI extracts tasks that require follow-up and formats them as clear, actionable statements.



Step 5: Google Gemini Model Configuration

This configuration class is responsible for creating a bean for our Google Gemini model.

package com.bootcamptoprod.config;

import com.embabel.agent.api.models.OpenAiCompatibleModelFactory;
import com.embabel.common.ai.model.Llm;
import com.embabel.common.ai.model.PerTokenPricingModel;
import io.micrometer.observation.ObservationRegistry;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.time.LocalDate;

@Configuration
public class ConfigureGoogleGeminiModels extends OpenAiCompatibleModelFactory {

    public ConfigureGoogleGeminiModels(@NotNull ObservationRegistry observationRegistry,
                                       @Value("${GOOGLE_GEMINI_API_KEY}") String apiKey) {
        super(
            "https://generativelanguage.googleapis.com",  // Base URL
            apiKey,                                       // API key reference
            "/v1beta/openai/chat/completions",            // Chat Completion path
            null,                                         // Embeddings path
            observationRegistry                           // Metrics registry
        );
    }

    @Bean
    Llm gemini2lash() {
        return openAiCompatibleLlm(
            "gemini-2.0-flash-exp",               // Model identifier
            new PerTokenPricingModel(0, 0),       // Pricing (free tier)
            "Google Gemini",                      // Provider name
            LocalDate.of(2025, 1, 1)              // Knowledge cutoff date
        );
    }
}
ConfigureGoogleGeminiModels.java

Explanation:

  • This configuration class registers Google Gemini as an AI model provider.
  • By extending OpenAiCompatibleModelFactory, we leverage Gemini’s OpenAI-compatible API.
  • The constructor configures the base URL and endpoint for Gemini’s API.
  • The @Value("${GOOGLE_GEMINI_API_KEY}") annotation injects your API key, which you must provide as an environment variable when running the application.
  • The gemini2Flash() bean method creates a model instance with zero pricing (useful for free tier or internal tracking) and metadata about the model.
  • The ObservationRegistry integration enables automatic metrics collection for model usage.

NOTE: We will be using free model from Google Gemini due to which we have added this configuration class. If you are using OpenAI or Anthrophic you can directly configure the OPENAI_API_KEY or ANTHROPIC_API_KEY environment variables. In that case, this class will not be required.


Step 6: The Meeting Summarizer Agent

This is where we define our AI agent and its capabilities.

package com.bootcamptoprod.agent;

import com.bootcamptoprod.dto.ActionItems;
import com.bootcamptoprod.dto.KeyPoints;
import com.bootcamptoprod.dto.MeetingSummary;
import com.bootcamptoprod.dto.SummaryRequest;
import com.embabel.agent.api.annotation.AchievesGoal;
import com.embabel.agent.api.annotation.Action;
import com.embabel.agent.api.annotation.Agent;
import com.embabel.agent.api.common.OperationContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Agent(
    name = "meeting-summarizer-agent",
    description = "Summarizes a meeting transcript with actionable and key insights.",
    version = "1.0.0",
    beanName = "meetingSummarizerAgent"
)
public class MeetingSummarizerAgent {

    private static final Logger log = LoggerFactory.getLogger(MeetingSummarizerAgent.class);

    @Action
    public KeyPoints findKeyPoints(SummaryRequest summaryRequest, OperationContext context) {
        log.info("[MeetingSummarizerAgent] Starting extraction of key points from transcript.");

        KeyPoints result = context.ai()
            .withDefaultLlm()
            .createObjectIfPossible(
                """
                Read the following meeting transcript carefully and identify the main 
                discussion points. Summarize them into clear, concise bullet points, 
                highlighting key decisions and topics discussed. For each point, include 
                the name of the responsible person or team if mentioned in the transcript:
                %s
                """.formatted(summaryRequest.transcript()),
                KeyPoints.class
            );

        log.info("[MeetingSummarizerAgent] Extracted key points: {}", result.points());
        return result;
    }

    @Action
    public ActionItems findActionItems(SummaryRequest summaryRequest, OperationContext context) {
        log.info("[MeetingSummarizerAgent] Starting extraction of action items from transcript.");
        
        ActionItems result = context.ai()
            .withDefaultLlm()
            .createObjectIfPossible(
                """
                Read the following meeting transcript and extract all action items 
                assigned, mentioning responsible persons and deadlines if available:
                %s
                """.formatted(summaryRequest.transcript()),
                ActionItems.class
            );
            
        log.info("[MeetingSummarizerAgent] Extracted action items: {}", result.actionItems());
        return result;
    }

    @Action
    @AchievesGoal(description = "Summarize a meeting transcript into clear key points and assigned action items with responsible person and deadlines if available")
    public MeetingSummary createSummary(KeyPoints keyPoints, ActionItems actionItems, OperationContext context) {
        log.info("[MeetingSummarizerAgent] Composing final meeting summary.");
        
        MeetingSummary summary = new MeetingSummary(
            keyPoints.points(), 
            actionItems.actionItems()
        );
        
        log.info("[MeetingSummarizerAgent] Meeting summary created: {}", summary);
        return summary;
    }
}
MeetingSummarizerAgent.java

Explanation:

This is the heart of our application – the intelligent agent.

  1. @Agent: This annotation marks the class as an Embabel agent, providing metadata like its name and description.
  2. @Action: This annotation designates methods that the agent can perform.
  3. findKeyPoints and findActionItems: These actions take the SummaryRequest (which contains the meeting transcript) and use the OperationContext to interact with the LLM. Each action is responsible for a specific task: one extracts key discussion points, and the other extracts assigned action items.
  4. @AchievesGoal: This annotation on the createSummary method defines the agent’s ultimate objective. Embabel’s GOAP planner sees this goal and automatically works backward to determine which actions it needs to run (in this case, findKeyPoints and findActionItems) to gather the necessary inputs for this final step.
  5. createSummary: This final action takes the outputs from the previous two actions (KeyPoints and ActionItems) and combines them into the final MeetingSummary object, thus achieving the goal.
  6. OperationContext: It provides access to AI models through a fluent API (context.ai().withDefaultLlm().createObject()), which handles prompt execution and response parsing automatically. The createObject method is a powerful feature of Embabel that automatically maps the LLM’s response to our specified DTO.


Step 7: Create the REST Controller

This is the bridge between the web and our agent. It defines the API endpoint and uses Embabel’s AgentPlatform to invoke our agent programmatically.

package com.bootcamptoprod.controller;

import com.bootcamptoprod.dto.MeetingSummary;
import com.bootcamptoprod.dto.SummaryRequest;
import com.embabel.agent.api.common.autonomy.AgentInvocation;
import com.embabel.agent.core.AgentPlatform;
import com.embabel.agent.core.ProcessOptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/v1/meeting")
public class SummarizerController {

    private static final Logger log = LoggerFactory.getLogger(SummarizerController.class);

    private final AgentPlatform agentPlatform;

    public SummarizerController(AgentPlatform agentPlatform) {
        this.agentPlatform = agentPlatform;
    }

    @PostMapping("/summarize")
    public MeetingSummary summarizeMeeting(@RequestBody SummaryRequest request) {

        var meetingSummaryAgentInvocation = AgentInvocation
            .builder(agentPlatform)
            .options(ProcessOptions.builder().verbosity(v -> {
                v.showPrompts(true);
                v.showLlmResponses(true);
                v.showPlanning(true);
                v.debug(true);
            }).build())
            .build(MeetingSummary.class);

        MeetingSummary meetingSummary = meetingSummaryAgentInvocation.invoke(request);
        log.info("Result: {}", meetingSummary);
        return meetingSummary;
    }
}
SummarizerController.java

Explanation:

  1. @RestController & @RequestMapping: These standard Spring annotations designate this class as a web controller. It’s configured to handle all incoming HTTP requests to the /api/v1/meeting path.
  2. @PostMapping & @RequestBody: The @PostMapping("/summarize") annotation maps HTTP POST requests to the summarizeMeeting method. The @RequestBody annotation tells Spring to deserialize the incoming JSON payload into our SummaryRequest DTO.
  3. AgentPlatform: This is a core Service Provider Interface (SPI) in Embabel that represents the runtime environment for all agents. Think of the AgentPlatform as the central coordinator or “Mission Control” for all your AI agents. It’s the core Embabel component that knows about every agent you’ve created, manages their lifecycle, and provides the environment to run them. It is injected into our controller via dependency injection, providing the necessary entry point to interact with the Embabel framework from our web layer. This gives our controller access to the entire Embabel agent system.
  4. AgentInvocation: This provides a high-level, type-safe API for programmatically invoking agents, which is the standard approach for integrating Embabel into applications like web services. If AgentPlatform is “Mission Control,” then AgentInvocation is the smart and type-safe “Mission Request Form” you fill out to launch a specific task. Instead of manually telling Embabel which agent to run, you describe the outcome you want, and AgentInvocation figures out the rest. Let’s break down how we use its builder in our code:
    • AgentInvocation.builder(agentPlatform): Initializes the invocation process, linking it to the core agent runtime.
    • .options(…): This allows us to configure ProcessOptions for the agent’s run. This step is like filling out the optional details on our mission form. Here, we configure the verbosity to show prompts, LLM responses, and planning steps in the logs. This is incredibly useful for debugging, as it gives you a play-by-play of the agent’s thought process.
    • .build(MeetingSummary.class): This is the most powerful part. We don’t tell Embabel to use the meeting-summarizer-agent. Instead, we tell it what we want as our final result: an object of type MeetingSummary.class. Embabel intelligently scans all registered agents, finds the one whose @AchievesGoal annotation promises to produce a MeetingSummary, and selects it for the job. This makes your code goal-oriented and highly maintainable.
    • .invoke(request): This method triggers the synchronous execution of the selected agent. It places the request object (our SummaryRequest DTO) onto the agent’s internal state manager (the “blackboard”). The GOAP planner then formulates and executes the necessary sequence of @Action methods(running findKeyPoints, then findActionItems, then createSummary) to achieve the goal, ultimately returning the final MeetingSummary object as the HTTP response.


3. Testing the Application

With the application running, you can now test the endpoint using any API client like curl or Postman.

curl --location 'http://localhost:8080/api/v1/meeting/summarize' \
--header 'Content-Type: application/json' \
--data '{
    "transcript": "Hi everyone, thanks for joining today. Let’s start with the authentication module, Raj, how’s the backend going? Yeah, the login and registration endpoints are complete, the password reset flow is still pending but I should have it done by Wednesday. Okay, that’s good to hear. Meera, what about the frontend side? The login screen is ready and I’ll integrate Raj’s API tomorrow, but I still need the finalized error messages from QA for the registration part. Alright, I’ll share that document today so you can move forward. Great, thanks. Any blockers from QA? The only issue right now is we don’t have test data for multiple failed login attempts. I can generate a seed script for that before the end of the month. Perfect, that should help. Now for the sprint review next week, can we plan to demo the complete login and registration flow? Yes, that should be fine as long as the APIs are stable. I’ll run regression testing on Friday and update everyone if I find issues. Sounds good, let’s close here then, thanks everyone for the updates."
}'
Terminal

Expected JSON Response:

You will receive a clean JSON response containing the structured summary, ready to be used by any frontend or consuming service.

{
    "keyPoints": [
        "Backend login and registration endpoints are complete (Raj).",
        "Password reset flow pending, expected completion by Wednesday (Raj).",
        "Frontend login screen is ready, API integration tomorrow (Meera).",
        "Frontend registration needs finalized error messages from QA (Meera).",
        "QA needs test data for multiple failed login attempts.",
        "Seed script for failed login attempts will be created by the end of the month (QA).",
        "Plan to demo complete login and registration flow next week.",
        "Regression testing on Friday (QA)."
    ],
    "actionItems": [
        "Raj: Complete password reset flow by Wednesday",
        "Meera: Integrate Raj’s API tomorrow",
        "Meera: Finalize registration part when error messages are shared",
        "QA: Generate seed script for multiple failed login attempts before the end of the month",
        "QA: Run regression testing on Friday and update everyone if issues"
    ]
}
API Response

4. What Happened Behind the Scenes

  1. Request Received: Controller receives SummaryRequest with transcript.
  2. Agent Invocation: AgentPlatform identifies meeting-summarizer-agent.
  3. GOAP Planning: Planner determines execution path: findKeyPoints → findActionItems → createSummary.
  4. Action Execution: Each action calls the LLM with structured prompts.
  5. Response Mapping: LLM responses are automatically mapped to KeyPoints and ActionItems DTOs
  6. Goal Achievement: createSummary combines results into the final MeetingSummary.
  7. JSON Response: Spring Boot serializes MeetingSummary to JSON and returns it.

The entire process is logged with Star Wars-themed messages, making debugging both informative and entertaining!


Key Differences from Shell Version:

  • Entry Point: HTTP endpoint instead of a shell command
  • Input Format: JSON request body instead of command-line string
  • Invocation: Programmatic AgentInvocation instead of the shell’s automatic invocation
  • Output: JSON response instead of console output

The agent logic and GOAP planning remain identical—only the delivery mechanism changed.



5. Video Tutorial

To see these concepts in action, check out our step-by-step video tutorial.  It walks you through building the intelligent meeting summarizer as a REST API from scratch, showing you how to leverage the power of Embabel and Spring Boot to create a reliable, goal-driven AI Agents.

📺 Watch on YouTube:

6. Source Code

You can find the complete source code for this intelligent REST API based Agent on our GitHub. To get started, simply clone the repository, set your GOOGLE_GEMINI_API_KEY as an environment variable, and run the Spring Boot application. It’s the quickest way to experiment with and build upon the goal-driven AI Agent we created in this tutorial

🔗 Embabel Demo: https://github.com/BootcampToProd/embabel-meeting-summarizer-agent



7. Things to Consider

When creating agents using the Embabel framework, keep these important factors in mind:

  1. API Security: Always implement authentication and authorization for production APIs. Consider using Spring Security with JWT tokens or OAuth2 for secure access.
  2. Rate Limiting: LLM APIs have rate limits and costs. Implement rate limiting to prevent abuse and control costs.
  3. Error Handling: Add comprehensive exception handling with @ControllerAdvice to return meaningful error responses when agent execution fails or LLM calls time out.
  4. Asynchronous Processing: For long-running agent tasks, consider running the AgentInvocation asynchronously in a separate thread to avoid blocking the HTTP request thread.
  5. Monitoring: Use Spring Boot Actuator endpoints to monitor agent performance, LLM token usage, and response times. Set up alerts for failures or performance degradation.
  6. Input Validation: Add validation annotations to SummaryRequest to ensure transcripts meet minimum requirements (e.g., @NotBlank, @Size(min=10)).

8. FAQs

How is invoking an agent via the API different from the shell?

Can I still use multiple AI models in a REST-based agent?

How can I switch from Google Gemini to another LLM like OpenAI’s GPT-4

How does the agent get the SummaryRequest object when it’s only passed to the invoke method in the controller?

The API call in the example is synchronous. What if my agent’s task takes several minutes to complete?

Can I have multiple agents in one Spring Boot application? How does AgentInvocation know which one to pick?

Can I pass more than just one object to the invoke method?



9. Conclusion

Building REST API-based AI agents with Embabel demonstrates the framework’s versatility and production-readiness.. The power of Embabel lies in its separation of concerns—agent logic remains clean and focused while the framework handles planning, execution, and delivery. Whether you need shell interfaces for testing or REST APIs for web integration, Embabel’s architecture adapts seamlessly to your delivery requirements while maintaining the same reliable, goal-driven intelligence powered by GOAP planning.

10. Learn More

#

Interested in learning more?

Embabel Framework: Create Goal-Driven AI Agents for the JVM



Add a Comment

Your email address will not be published.