Task Execution Agent
To use this agent, add the Maven dependency to your project, replacing ${agentic-patterns.version}
with the latest version.
Latest version:
<dependency>
<groupId>com.javaaidev.agenticpatterns</groupId>
<artifactId>task-execution</artifactId>
<version>${agentic-patterns.version}</version>
</dependency>
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.
Parameter | Required? | Type | Description |
---|---|---|---|
chatClient | yes | ChatClient | Spring AI ChatClient |
promptTemplate | yes | String | Prompt template |
responseType | no | Type | Type of response, only required when auto-detection fails |
promptTemplateContextProvider | no | Function<Request, Map<String, Object>> | Function to provide context for the prompt template |
chatClientRequestSpecUpdater | no | Consumer<ChatClientRequestSpec> | Customize the request sent to an LLM |
name | no | String | Name of this agent |
observationRegistry | no | ObservationRegistry | Micrometer 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.
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
.
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
.
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 User
s.
The prompt template is loaded from a classpath resource. Below is the content of this 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.
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
.
{
"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"
}
]
}
]
}