Skip to main content

Routing Workflow

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>routing-workflow</artifactId>
<version>${agentic-patterns.version}</version>
</dependency>

See Javadoc here: javadoc

RoutingWorkflow

RoutingWorkflow routes the request to a selected route for handling.

RoutingChoice

RoutingWorkflow has a list of RoutingChoices. A RoutingChoice has a name, a description, and an agent to handle the request.

RoutingChoice
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 of RoutingChoices.
  • input, the task input formatted using the routingInputFormatter 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.

Agent for customer support
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.