Domain Objects
Domain objects in Embabel are not just strongly-typed data structures - they are real objects with behavior that can be selectively exposed to LLMs and used in agent actions.
Objects with Behavior
Section titled “Objects with Behavior”Unlike simple structs or DTOs, Embabel domain objects can encapsulate business logic and expose it to LLMs through the @Tool annotation.
For example:
@Entitypublic class Customer { private String name; private LoyaltyLevel loyaltyLevel; private List<Order> orders;
@Tool(description = "Calculate the customer's loyalty discount percentage") (1) public BigDecimal getLoyaltyDiscount() { return loyaltyLevel.calculateDiscount(orders.size()); }
@Tool(description = "Check if customer is eligible for premium service") public boolean isPremiumEligible() { return orders.stream() .mapToDouble(Order::getTotal) .sum() > 1000.0; }
public void updateLoyaltyLevel() { (2) // Internal business logic }}@Entityclass Customer( private val name: String, private val loyaltyLevel: LoyaltyLevel, private val orders: List<Order>) { @Tool(description = "Calculate the customer's loyalty discount percentage") (1) fun getLoyaltyDiscount(): BigDecimal { return loyaltyLevel.calculateDiscount(orders.size) }
@Tool(description = "Check if customer is eligible for premium service") fun isPremiumEligible(): Boolean { return orders.sumOf { it.total } > 1000.0 }
fun updateLoyaltyLevel() { (2) // Internal business logic }}- The
@Toolannotation exposes this method to LLMs when the object is added viaPrompRunner.withToolObject(). - Unannotated methods such as
updateLoyaltyLevelare never exposed to LLMs, regardless of their visibility level. This ensures that tool exposure is safe, explicit and controlled.
Selective Tool Exposure
Section titled “Selective Tool Exposure”The @Tool annotation allows you to selectively expose domain object methods to LLMs.
For example:
- Business Logic: Expose methods that provide safely invocable business value to the LLM
- Calculated Properties: Methods that compute derived values. This can help LLMs with calculations they might otherwise get wrong.
- Business Rules: Methods that implement domain-specific rules
Use of Domain Objects in Actions
Section titled “Use of Domain Objects in Actions”Domain objects can be used naturally in action methods, combining LLM interactions with traditional object-oriented programming. The availability of the domain object instances also drives Embabel planning.
@Actionpublic Recommendation generateRecommendation(Customer customer, OperationContext context) { var prompt = String.format( "Generate a personalized recommendation for %s based on their profile", customer.getName() );
return context.ai() .withToolObject(customer) (1) .withDefaultLlm() .createObject(prompt, Recommendation.class);}@Actionfun generateRecommendation(customer: Customer, context: OperationContext): Recommendation { val prompt = "Generate a personalized recommendation for ${customer.name} based on their profile"
return context.ai() .withToolObject(customer) (1) .withDefaultLlm() .createObject(prompt, Recommendation::class.java)}- The
Customerdomain object is provided as a tool object, allowing the LLM to call its@Toolmethods. The LLM has access tocustomer.getLoyaltyDiscount()andcustomer.isPremiumEligible().
Domain Understanding is Critical
Section titled “Domain Understanding is Critical”As outlined in Context Engineering Needs Domain Understanding, Rod Johnson’s blog introducing DICE (Domain-Integrated Context Engineering), domain understanding is fundamental to effective context engineering. Domain objects serve as the bridge between:
- Business Domain: Real-world entities and their relationships
- Agent Behavior: How LLMs understand and interact with the domain
- Code Actions: Traditional programming logic that operates on domain objects
Benefits
Section titled “Benefits”- Rich Context: LLMs receive both data structure and behavioral context
- Encapsulation: Business logic stays within domain objects where it belongs
- Reusability: Domain objects can be used across multiple agents
- Testability: Domain logic can be unit tested independently
- Evolution: Adding new tools to domain objects extends agent capabilities
This approach ensures that agents work with meaningful business entities rather than generic data structures, leading to more natural and effective AI interactions.