# Core Concepts Understanding Embabel's fundamental concepts is key to building sophisticated agents. This guide uses analogies and practical examples to explain how the framework thinks about intelligent automation. ## The Restaurant Analogy ๐Ÿฝ๏ธ Think of Embabel like a master chef's kitchen where different cooks (agents) can accomplish complex meals (goals) by combining their skills (actions) based on available ingredients (domain model). ### Traditional Programming = Fast Food Chain - **Fixed menu** (predetermined workflows) - **Rigid recipes** (hardcoded sequences) - **Limited flexibility** (can't adapt to new requests) ### Embabel = Master Chef Kitchen - **Dynamic planning** (chef creates custom recipes) - **Skill combination** (combines techniques creatively) - **Adaptive execution** (adjusts based on available ingredients) ## Core Framework Components ### 1. Agents ๐Ÿค– **What they are:** The orchestrating components that coordinate actions to achieve goals. **Restaurant analogy:** The head chef who oversees the entire cooking process. ```java @Agent(description = "Travel planning specialist") public class TravelPlannerAgent { // Actions and goals defined here } ``` **Key characteristics:** - **Spring-managed beans** - Full dependency injection support - **Stateless by design** - Safe for concurrent execution - **Domain-focused** - Each agent handles a specific business area ### 2. Goals ๐ŸŽฏ **What they are:** Desired outcomes that agents work toward achieving. **Restaurant analogy:** The specific dish you want to prepare (e.g., "prepare a romantic dinner for two vegetarians"). ```java @AchievesGoal( description = "Create comprehensive travel itinerary with activities and accommodations", export = @Export(remote = true, name = "travelPlanning") ) @Action public TravelItinerary createItinerary( Destination destination, TravelPreferences preferences, OperationContext context ) { // Implementation that satisfies the goal return context.ai().withDefaultLlm() .createObject("Create itinerary for " + destination.getName(), TravelItinerary.class); } ``` **Goal characteristics:** - **Declarative** - What you want, not how to get it - **Measurable** - Clear success criteria - **Composable** - Can be broken into sub-goals ### 3. Actions โšก **What they are:** Individual steps that agents can take to progress toward goals. **Restaurant analogy:** Specific cooking techniques like "chop vegetables," "heat pan," or "season to taste." ```java @Action public DestinationInfo searchDestinationInfo( String destination, OperationContext context ) { return context.ai().withDefaultLlm() .createObject(String.format(""" Research comprehensive information about %s including: - Best time to visit - Top attractions - Local customs and tips """, destination), DestinationInfo.class); } @Action(toolGroups = {ToolGroup.WEB}) public AccommodationOptions findAccommodations( Destination destination, AccommodationPreferences preferences, OperationContext context ) { // Uses web tools to search for hotels/accommodations return context.ai().withDefaultLlm() .createObject("Find accommodations in " + destination.getName(), AccommodationOptions.class); } ``` **Action types:** - **LLM-powered** - Leverage language models for reasoning - **Code-based** - Pure business logic without AI - **Tool-enabled** - Use external tools (web search, APIs, etc.) - **Hybrid** - Combine multiple approaches ### 4. Conditions โœ… **What they are:** Prerequisites and post-conditions that govern action execution. **Restaurant analogy:** Requirements like "vegetables must be fresh," "pan must be heated," or "sauce should be thick enough." ```java @Condition public boolean hasValidApiKey() { String apiKey = System.getenv("BOOKING_API_KEY"); return apiKey != null && !apiKey.isEmpty(); } @Condition public boolean destinationIsAccessible(Destination destination) { // Check travel advisories, visa requirements, etc. return destination.getTravelAdvisoryLevel().ordinal() <= TravelAdvisoryLevel.EXERCISE_CAUTION.ordinal(); } ``` **Most conditions are inferred** from data flow: ```java // The framework automatically infers that findAccommodations // requires a Destination object to be available @Action public AccommodationOptions findAccommodations(Destination destination) { // Implementation return new AccommodationOptions(); } ``` ### 5. Domain Model ๐Ÿ—๏ธ **What it is:** Rich business objects that represent your problem space and can have behavior. **Restaurant analogy:** Your ingredients, cooking tools, and recipe knowledge - everything the chef works with. ```java @JsonClassDescription("Travel destination with comprehensive details") public record Destination( String name, String country, Coordinates coordinates, ClimateInfo climate, AccessibilityInfo accessibility ) { // Domain behavior - exposed to LLMs via @Tool @Tool("Calculate travel distance between destinations") public Distance distanceTo(Destination other) { return calculateDistance(this.coordinates, other.coordinates); } } public record TravelPreferences( Budget budget, Duration duration, List interests, AccommodationType accommodationType, TravelStyle travelStyle ) {} ``` **Domain model benefits:** - **Type safety** - Compile-time checking and refactoring support - **Rich behavior** - Objects can have methods exposed to LLMs - **Clear contracts** - Well-defined interfaces between actions - **Jackson annotations** - Help LLMs understand object structure ### 6. GOAP Planning ๐Ÿง  **What it is:** Goal Oriented Action Planning - the AI algorithm that figures out how to achieve goals. **Restaurant analogy:** The master chef's ability to look at available ingredients and techniques, then create a novel recipe to achieve the desired dish. ```mermaid graph TD A[Current State] --> B[GOAP Planner] B --> C[Evaluate Available Actions] B --> D[Check Conditions] B --> E[Calculate Action Costs] B --> F[Generate Plan] F --> G[Execute Next Action] G --> H[Reassess State] H --> B H --> I[Goal Achieved!] ``` **GOAP characteristics:** - **Non-deterministic** - Can find multiple paths to the same goal - **Dynamic** - Replans after each action based on new state - **Cost-aware** - Considers efficiency and resource usage - **Composable** - Can combine actions from different agents ## Agent Execution Modes ### Focused Mode ๐ŸŽฏ **What:** User code requests specific functionality from a known agent. **When to use:** Code-driven flows, specific business processes, API endpoints. **Restaurant analogy:** Ordering a specific dish from a known chef. ```java @Service public class TravelService { private final TravelPlannerAgent travelAgent; public TravelService(TravelPlannerAgent travelAgent) { this.travelAgent = travelAgent; } public TravelItinerary planTrip(TripRequest request) { return agentPlatform.run(travelAgent.getClass(), request); } } ``` ### Closed Mode ๐Ÿ”’ **What:** Platform dynamically selects the best agent for the user's intent. **When to use:** User-driven requests where the appropriate agent should be chosen automatically. **Restaurant analogy:** Telling the maรฎtre d' what kind of cuisine you want, and they choose the right chef. ```java // Platform analyzes intent and selects appropriate agent Object result = agentPlatform.execute("I need help planning a business trip to Tokyo"); ``` ### Open Mode ๐ŸŒ **What:** Platform uses ALL available goals and actions to achieve user intent, potentially combining multiple agents. **When to use:** Complex, multi-faceted requests that might require combining capabilities. **Restaurant analogy:** Describing your perfect meal and having the entire kitchen staff collaborate to create something novel. ```java // Platform combines travel planning + research + booking + documentation Object result = agentPlatform.executeOpen(""" Research sustainable tourism options in Costa Rica, plan a 10-day eco-friendly itinerary, book accommodations, and create a detailed travel guide """); ``` ## The Power of GOAP Planning ### Traditional Approach (Finite State Machine) ```java // Rigid, predetermined sequence public TravelItinerary planTrip(TripRequest request) { Destination destination = validateDestination(request.getDestination()); List flights = searchFlights(destination, request.getDates()); List hotels = searchHotels(destination, request.getPreferences()); List activities = findActivities(destination, request.getInterests()); return combineIntoItinerary(flights, hotels, activities); } ``` ### Embabel Approach (GOAP Planning) ```java // Dynamic planning based on available actions and current state @Agent public class TravelPlannerAgent { @Action public Destination validateDestination(String destination) { return null; } @Action public FlightOptions searchFlights(Destination dest, DateRange dates) { return null; } @Action public HotelOptions searchHotels(Destination dest, Preferences prefs) { return null; } @Action public ActivityOptions findActivities(Destination dest, List interests) { return null; } @Action public VisaInfo checkVisaRequirements(Destination dest) { return null; } @Action public TransportOptions findLocalTransportation(Destination dest) { return null; } @Action public BudgetSummary createBudgetBreakdown(TripRequest request) { return null; } @AchievesGoal("Create comprehensive travel itinerary") @Action public TravelItinerary finalizeItinerary(/* various inputs */) { return null; } } ``` **The GOAP planner might discover novel sequences like:** 1. Validate destination โ†’ Check visa requirements โ†’ Search flights 2. Or: Search flights โ†’ Validate destination (if flights aren't available, reconsider) 3. Or: Check budget โ†’ Search accommodation โ†’ Find flights within remaining budget ## Data Flow and Conditions ### Automatic Condition Inference The framework automatically infers most conditions from your method signatures: ```java @Action public HotelReservation bookHotel( Destination destination, // Requires: destination must be available HotelPreferences preferences, // Requires: preferences must be defined PaymentMethod paymentMethod // Requires: valid payment method ) { // Implementation return new HotelReservation(); } ``` ### Explicit Conditions For complex business rules: ```java @Condition("User has sufficient budget for luxury accommodation") public boolean hasLuxuryBudget(Budget budget, Destination destination) { return budget.getAmount() >= destination.getAverageLuxuryHotelCost() * 1.2; } @Action @ConditionalOnCondition("hasLuxuryBudget") public LuxuryHotelReservation bookLuxuryHotel(Destination dest, Budget budget) { return new LuxuryHotelReservation(); } ``` ## Integration with Spring Framework ### Dependency Injection ```java @Agent public class TravelPlannerAgent { private final FlightService flightService; private final AccommodationService accommodationService; private final String defaultCurrency; public TravelPlannerAgent( FlightService flightService, // Injected AccommodationService accommodationService, // Injected @Value("${travel.default-currency}") String defaultCurrency // Configuration ) { this.flightService = flightService; this.accommodationService = accommodationService; this.defaultCurrency = defaultCurrency; } // Actions can use injected services } ``` ### Configuration and Profiles ```java @Configuration @Profile("production") public class ProductionTravelConfig { @Bean public FlightService realFlightService() { return new AmadeusFlightService(); } @Bean public PaymentProcessor realPaymentProcessor() { return new StripePaymentProcessor(); } } @Configuration @Profile("test") public class TestTravelConfig { @Bean public FlightService mockFlightService() { return new MockFlightService(); } } ``` ## Testing Strategy ### Unit Testing Actions ```kotlin @Test fun `should find appropriate accommodations for budget travelers`() { val context = FakeOperationContext() context.expectResponse(AccommodationOptions( hotels = listOf(BudgetHotel("Hostel Tokyo", 50.dollars)) )) val destination = Destination("Tokyo", "Japan") val preferences = AccommodationPreferences( budget = Budget(100.dollars), type = AccommodationType.BUDGET ) val result = agent.findAccommodations(destination, preferences, context) assertThat(result.hotels).hasSize(1) assertThat(result.hotels.first().pricePerNight).isLessThan(75.dollars) } ``` ### Integration Testing Flows ```kotlin @SpringBootTest class TravelPlannerAgentIntegrationTest { @Autowired private lateinit var agentPlatform: AgentPlatform @Test fun `should create complete travel itinerary`() { val request = TripRequest( destination = "Kyoto", dates = DateRange(LocalDate.now(), LocalDate.now().plusDays(3)), preferences = TravelPreferences(/* ... */) ) val result = agentPlatform.run(TravelPlannerAgent::class, request) assertThat(result).isInstanceOf() assertThat(result.accommodations).isNotEmpty() assertThat(result.activities).hasSize(3) // One per day } } ``` ## Next Steps Now that you understand the core concepts, explore: 1. **[Development Guide](Development-Guide.md)** - Writing your first agent 2. **[Advanced Agent Patterns](Advanced-Agent-Patterns.md)** - Complex workflows and error handling 3. **[Testing Guide](Testing.md)** - Comprehensive testing strategies 4. **[Spring Integration](Spring-Integration.md)** - Deep dive into Spring Framework integration The power of Embabel lies in its ability to **combine simple actions into complex behaviors** through intelligent planning, while maintaining the **type safety and testability** you expect from enterprise Java/Kotlin applications.