Routing Workflow
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>routing-workflow</artifactId>
<version>${agentic-patterns.version}</version>
</dependency>
RoutingWorkflow
RoutingWorkflow
routes the request to a selected route for handling.
RoutingChoice
RoutingWorkflow
has a list of RoutingChoice
s. A RoutingChoice
has a name
, a description
, and an agent
to handle the request.
package com.javaaidev.agenticpatterns.routingworkflow;
import com.javaaidev.agenticpatterns.taskexecution.TaskExecutionAgent;
/**
* A routing choice
*
* @param name Name of the route
* @param description Description of the route
* @param agent Task of the route
* @param <Request> Task input type
* @param <Response> Task output type
*/
public record RoutingChoice<Request, Response>(
String name,
String description,
TaskExecutionAgent<Request, Response> agent) {
}
RoutingSelector
RoutingSelector
selects the target route for an input.
DefaultRoutingSelector
uses a default prompt template to instruct an LLM to select the routing target. This default prompt template has two variables:
choices
, routing choices formatted from the list ofRoutingChoice
s.input
, the task input formatted using theroutingInputFormatter
function.
You can provide your own routing prompt template by overriding the getPromptTemplate
method. In this case, you also need to override getPromptContext
method to provide values of variables used in your prompt template.
Builder
The builder of RoutingWorkflow
provides the addRoutingChoice
to add a RoutingChoice
.
Example
The example is an agent for customer support. This agent has three routes, payment
, shipping
and general
. The agent for each route is a TaskExecutionAgent
using system text to simulate as a customer support agent. These routes are added using addRoutingChoices
of the builder.
package com.javaaidev.agenticpatterns.examples.routingworkflow;
import com.javaaidev.agenticpatterns.routingworkflow.DefaultRoutingSelector;
import com.javaaidev.agenticpatterns.routingworkflow.RoutingChoice;
import com.javaaidev.agenticpatterns.routingworkflow.RoutingWorkflow;
import com.javaaidev.agenticpatterns.taskexecution.TaskExecutionAgent;
import io.micrometer.observation.ObservationRegistry;
import java.util.List;
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;
@Configuration
public class CustomerSupportConfiguration {
@Bean
@Qualifier("customerSupportWorkflow")
public RoutingWorkflow<CustomerSupportRequest, CustomerSupportResponse> customerSupportWorkflow(
ChatClient.Builder chatClientBuilder,
SimpleLoggerAdvisor simpleLoggerAdvisor,
ObservationRegistry observationRegistry
) {
var chatClient = chatClientBuilder.defaultAdvisors(simpleLoggerAdvisor).build();
var routes = List.of(
new CustomerSupportRoute("payment", "Handle queries about payment and refund",
"You are a customer support agent for payment, be polite and helpful"),
new CustomerSupportRoute("shipping", "Handle queries about shipping",
"You are a customer support agent for shipping, be polite and helpful"),
new CustomerSupportRoute("general", "Handle general queries",
"You are a customer support agent for general questions, be polite and helpful")
);
var routingChoices = routes.stream().map(route -> new RoutingChoice<>(
route.name(),
route.description(),
TaskExecutionAgent.<CustomerSupportRequest, CustomerSupportResponse>defaultBuilder()
.chatClient(chatClient)
.promptTemplate("{question}")
.responseType(CustomerSupportResponse.class)
.chatClientRequestSpecUpdater(spec -> spec.system(route.agentSystemText()))
.name("CustomerSupport_" + route.name)
.observationRegistry(observationRegistry)
.build()
)).toList();
return RoutingWorkflow.<CustomerSupportRequest, CustomerSupportResponse>builder()
.addRoutingChoices(routingChoices)
.routingSelector(
DefaultRoutingSelector.<CustomerSupportRequest, CustomerSupportResponse>builder()
.chatClient(chatClient)
.name("RoutingSelector")
.observationRegistry(observationRegistry)
.build())
.name("CustomerSupportWorkflow")
.observationRegistry(observationRegistry)
.build();
}
record CustomerSupportRoute(String name, String description, String agentSystemText) {
}
}
Given a task input, the input will be sent to an LLM first to select the routing target, then the agent for selected route is called to handle the input.