Skip to main content

Task Execution Agent

To use this agent, add the Maven dependency to your project, replacing ${agentic-patterns.version} with the latest version.

Latest version: Maven Central Version

<dependency>
<groupId>com.javaaidev.agenticpatterns</groupId>
<artifactId>task-execution</artifactId>
<version>${agentic-patterns.version}</version>
</dependency>

See Javadoc here: javadoc

Usage

TaskExecutionAgent

To create a Task Execution agent, you can create a subclass of TaskExecutionAgent. When constructing a TaskExecutionAgent, parameters in the table below can be provided.

ParameterRequired?TypeDescription
chatClientyesChatClientSpring AI ChatClient
promptTemplateyesStringPrompt template
responseTypenoTypeType of response, only required when auto-detection fails
promptTemplateContextProvidernoFunction<Request, Map<String, Object>>Function to provide context for the prompt template
chatClientRequestSpecUpdaternoConsumer<ChatClientRequestSpec>Customize the request sent to an LLM
namenoStringName of this agent
observationRegistrynoObservationRegistryMicrometer ObservationRegistry for tracing

TaskExecutionAgent is a parameterized type with request type and response type.

If the prompt template contains variables, then the promptTemplateContextProvider function can be used to provide values for these variables. The request object is provided to build the Map<String, Object> context. The default implementation uses Jackson ObjectMapper to convert the input object to JSON string first, then convert the JSON string to a Map<String, Object>.

If you want to customize the request sent to an LLM, you can provide a chatClientRequestSpecUpdater to modify the ChatClientRequestSpec object. For example, you can add a system text.

Use chatClientRequestSpecUpdater to customize request
spec -> {
spec.system(
"You are a customer support agent for general questions, be polite and helper");
}

The call method is used to send a request to an LLM and receive the response.

Builder

TaskExecutionAgent provides a Builder to build TaskExecutionAgent. Use the TaskExecutionAgent.defaultBuilder method to create a builder.

The code below shows how to use a builder to create a TaskExecutionAgent.

Example of using builder
var agent = TaskExecutionAgent.<JokeInput, JokeOutput>defaultBuilder()
.name("test")
.responseType(JokeOutput.class)
.chatClient(chatClient)
.promptTemplate("""
tell me {count} jokes
""")
.build();
var output = agent.call(new JokeInput(2));

Example

Let's see an sample agent to generate test users. This agent is create by using TaskExecutionAgent.defaultBuilder.

Build agent
package com.javaaidev.agenticpatterns.examples.taskexecution;

import com.javaaidev.agenticpatterns.core.AgentUtils;
import com.javaaidev.agenticpatterns.taskexecution.TaskExecutionAgent;
import io.micrometer.observation.ObservationRegistry;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Description;

@Configuration
public class UserGenerationConfiguration {

@Bean
@Description("Generate test users")
@Qualifier("userGenerationAgent")
public TaskExecutionAgent<UserGenerationRequest, UserGenerationResponse> userGenerationAgent(
ChatClient.Builder chatClientBuilder,
SimpleLoggerAdvisor simpleLoggerAdvisor,
ObservationRegistry observationRegistry
) {
var chatClient = chatClientBuilder.defaultAdvisors(simpleLoggerAdvisor).build();
return TaskExecutionAgent.<UserGenerationRequest, UserGenerationResponse>defaultBuilder()
.chatClient(chatClient)
.responseType(UserGenerationResponse.class)
.promptTemplate(
AgentUtils.loadPromptTemplateFromClasspath("prompt_template/generate-user.st"))
.name("UserGeneration")
.observationRegistry(observationRegistry)
.build();
}
}

The request type is UserGenerationRequest, which contains the number of users to generate. The response type is UserGenerationResponse, which contains a list of Users.

The prompt template is loaded from a classpath resource. Below is the content of this prompt template.

Prompt template
Goal: Generate {count} users

Requirements:
- Id should be a version 4 random UUID.
- Name should be using the format "$firstName $lastName".
- Email address should be using the format "$firstName.$lastName@$domain".
- For an address,
- Country or region must use ISO 3166 alpha-2 code.
- For province/state/city, they should be generated based on the country or region.
- Address line can be fake.
- Zip code should use the format based on the country or region.
- When generating multiple users, choose different countries or regions for those users.
- For a user, generate 1 to 3 addresses. At least one address has the type HOME.

Now we can expose a REST API to call this agent.

REST controller for agent
package com.javaaidev.agenticpatterns.examples.taskexecution;

import com.javaaidev.agenticpatterns.taskexecution.TaskExecutionAgent;
import org.springframework.beans.factory.annotation.Qualifier;
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("/users_generation")
public class UserGenerationAgentController {

private final TaskExecutionAgent<UserGenerationRequest, UserGenerationResponse> userGenerationAgent;

public UserGenerationAgentController(
@Qualifier("userGenerationAgent") TaskExecutionAgent<UserGenerationRequest, UserGenerationResponse> userGenerationAgent) {
this.userGenerationAgent = userGenerationAgent;
}

@PostMapping
public UserGenerationResponse generateUsers(@RequestBody UserGenerationRequest request) {
return userGenerationAgent.call(request);
}
}

When calling the REST API, we can get the test users in JSON. Below is the returned JSON when count is set to 1.

Generated users
{
"users": [
{
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"name": "John Doe",
"email": "john.doe@example.com",
"mobilePhone": "+1234567890",
"addresses": [
{
"id": "c9bf9e57-1685-4c89-bafb-ff5af830be8a",
"addressType": "HOME",
"countryOrRegion": "US",
"provinceOrState": "NY",
"city": "New York",
"addressLine": "123 Fake Street",
"zipCode": "10001"
},
{
"id": "d3b07384-d9a1-4f3b-8f3d-2c7e0e3f5b2f",
"addressType": "OFFICE",
"countryOrRegion": "US",
"provinceOrState": "NY",
"city": "New York",
"addressLine": "456 Another Ave",
"zipCode": "10002"
}
]
}
]
}