Skip to content

Expose Camel routes as quarkus-langchain4j tools #8768

Description

@zbendhiba

Describe the feature here

TLDR

Add a new camel-quarkus extension that lets Camel routes participate as tools in aquarkus-langchain4j AI service.

Problem

Quarkus langchain4j tools are Java methods with @tool. That works for simple logic. But if your tool needs to do some integration, you end up rewriting integration code by hand inside the method. You lose Camel's 300+ connectors, and EIP patterns.

Apache Camel already has camel-langchain4j-tools, but it runs its own agent loop. If you use both Camel Quarkus and Quarkus LangChain4j in the same app today, there is no bridge.

Solution

A @CamelTool annotation on a RouteBuilder class. It marks which routes are tools and declares their parameters. The RouteBuilder class is then used in @toolbox or @RegisterAiService(tools=...) like any other tool class.

No changes needed in quarkus-langchain4j.

Example

 @CamelTool(
      routeId = "send-email",
      name = "send-email",
      description = "Sends a transactional email to a user",
      parameters = {
          @ToolParam(name = "to",      type = "string", description = "Recipient email address", required = true),
          @ToolParam(name = "subject", type = "string", description = "Email subject line",       required = true),
          @ToolParam(name = "body",    type = "string", description = "Plain text body",          required = false)
      }
  )
  @CamelTool(
      routeId = "get-order-status",
      name = "get-order-status",
      description = "Returns the current status of a customer order",
      parameters = {
          @ToolParam(name = "orderId", type = "string", description = "The order ID", required = true)
      }
  )
  @ApplicationScoped
  public class AgentRoutes extends RouteBuilder {
      @Override
      public void configure() {
          from("direct:send-email").routeId("send-email")
              .to("smtp://{{mail.host}}");

          from("direct:get-order-status").routeId("get-order-status")
              .to("sql:SELECT status FROM orders WHERE id = :#${header.orderId}");
      }
  }

Use the same classe in the AI service:

@RegisterAiService(tools = AgentRoutes.class)
  public interface SupportAiService {
      String chat(String userMessage);
  }

Parameters and result

When the LLM calls a tool, arguments are set as Exchange headers. The route reads them with ${header.orderId}, ${header.to}, etc. The Exchange body after the route runs is the result returned to the LLM.
No Java records. Standard Camel headers.

Implementation

  • Build-time: scan @CamelTool on RouteBuilder classes, generate ToolSpecification
  • Build fails if a routeId in @CamelTool has no matching .routeId() in the app

Out of scope

  • YAML DSL routes, because we focuse here on Quarkus DX experience only
  • Camel routes in a separate app

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions