liksi logo

L'agentic AI au-delà de Python : le réveil de l'écosystème JVM

Mathieu Durand - Publié le 10 octobre 2025
L'agentic AI au-delà de Python : le réveil de l'écosystème JVM

2025 marque un tournant décisif : l’écosystème Java/Kotlin pour l’IA est désormais mature, avec des frameworks de niveau production qui rivalisent - et dans certains cas surpassent - leurs équivalents Python. Des frameworks comme LangChain4j, Spring AI, Embabel et Koog transforment radicalement la manière dont nous construisons des applications intelligentes.

Cette évolution soulève des questions essentielles : pourquoi choisir Java/Kotlin plutôt que Python pour développer des agents IA ? Qu’est-ce qu’un système agentique exactement ? Et quel framework choisir selon son contexte ?

Plongeons dans l’univers des agents IA sur la JVM dans ce (gros) dossier et découvrons comment ces technologies redéfinissent le développement d’applications intelligentes.

Sommaire

  1. Pourquoi Java/Kotlin plutôt que Python pour les agents IA ?
  2. Des prompts aux agents : l’évolution du développement IA
  3. LangChain4j : la flexibilité pour workflows LLM complexes
  4. Spring AI : l’IA native dans l’écosystème Spring
  5. Embabel : la planification déterministe pour les agents enterprise
  6. Koog : le framework multiplateforme de JetBrains
  7. Quel framework choisir ?
  8. Conclusion : l’écosystème JVM est prêt pour les agents IA
  9. Ressources utiles

Pourquoi Java/Kotlin plutôt que Python pour les agents IA ?

Python dispose d’excellents frameworks pour les agents IA comme LangGraph (pour les workflows agentiques avec graphes d’états) et CrewAI (pour les systèmes multi-agents collaboratifs). Ces frameworks ont prouvé leur valeur et dominent actuellement l’écosystème agentique. Cependant, pour les applications enterprise en production, Java et Kotlin offrent des avantages décisifs.

La type safety : un atout majeur pour la production

L’un des arguments les plus convaincants en faveur de Java/Kotlin pour les agents IA est la type safety. Contrairement à Python et son typage dynamique, Java et Kotlin offrent une vérification stricte des types à la compilation. Les erreurs sont détectées avant l’exécution, l’IDE garantit la cohérence lors des refactorings, et l’autocomplétion intelligente accompagne le développeur à chaque étape. Cette type safety s’étend de bout en bout : des réponses LLM aux définitions de tools, tout est typé et validé.

Rod Johnson, créateur de Spring et d’Embabel, le dit clairement : “En construisant pour la JVM, nous avons créé des capacités qui surpassent Python, incluant la type safety à travers toute la stack : réponses LLM, définitions de tools, étapes de workflow IA — tout est typé, validé et supporté par l’IDE.”

Performance et scalabilité en production

Si Python excelle pour le prototypage rapide et la recherche, Java brille en production. La vitesse d’exécution et la consommation de ressources sont optimisées, la gestion de charges importantes est éprouvée depuis des années, et la JVM mature apporte un garbage collection avancé avec des optimisations JIT sophistiquées. Avec Java 21+, les virtual threads offrent une concurrence native performante qui simplifie considérablement le développement d’applications à forte concurrence.

Intégration avec la logique métier existante

L’argument peut-être le plus pragmatique : la plupart de la logique métier enterprise existe déjà en Java. Construire des agents IA dans le même écosystème que votre code métier permet de réutiliser directement vos services, repositories et utilitaires existants. Pas besoin d’API REST ou gRPC pour créer une frontière technologique entre l’agent et votre métier. Vous gardez une cohérence architecturale avec des patterns, conventions et outils communs, et votre équipe reste unifiée avec les mêmes développeur·se·s qui partagent la même expertise.

L’écosystème mature de la JVM

L’écosystème Java/Kotlin offre des avantages significatifs pour les applications IA en production. Spring Boot simplifie la configuration, la gestion des dépendances et l’observabilité. La sécurité enterprise est native avec Spring Security, OAuth2 et les systèmes d’authentification éprouvés. L’observabilité repose sur des standards comme Micrometer, OpenTelemetry et les outils APM reconnus. Le tooling est robuste avec Maven/Gradle, des pipelines CI/CD matures et des frameworks de testing avancés.

Alors, Python ou Java/Kotlin ? La meilleure approche peut être hybride : exploiter la flexibilité de Python pour le développement et l’expérimentation rapide de modèles, puis déployer ces modèles via ONNX ou TorchScript dans des systèmes basés sur Java pour un service stable, long-terme et scalable.

Mais pour les agents IA qui orchestrent de la logique métier, Java et Kotlin offrent aujourd’hui des avantages décisifs.

Des prompts aux agents : l’évolution du développement IA

Du prompt engineering au context engineering

Le développement d’applications IA a considérablement évolué ces dernières années. Ce qui a commencé avec du prompt engineering — l’art de rédiger des instructions pour les LLM — s’est transformé en quelque chose de plus sophistiqué.

Anthropic décrit cette évolution comme le passage au context engineering : plutôt que de simplement écrire de bonnes instructions, nous gérons maintenant l’ensemble optimal de tokens durant l’inférence du LLM. Le prompt engineering n’a pas disparu, il a évolué et s’est intégré dans des architectures plus larges.

Qu’est-ce qu’un système agentique ?

Un agent IA ne se limite pas à répondre à un prompt. C’est un système qui raisonne et planifie en décomposant les tâches complexes en étapes, agit de manière autonome en prenant des décisions et en exécutant des actions, utilise des tools pour appeler des fonctions, des APIs ou des bases de données, maintient une mémoire pour se souvenir du contexte conversationnel et des interactions passées, et peut collaborer avec d’autres agents spécialisés.

Point important : un agent n’a pas nécessairement besoin d’un LLM pour fonctionner. Le LLM est souvent utilisé pour le raisonnement et la compréhension du langage naturel, mais la planification et l’orchestration peuvent reposer sur d’autres algorithmes d’IA. Embabel, par exemple, utilise GOAP (Goal-Oriented Action Planning), un algorithme traditionnel d’IA, pour la planification déterministe, le LLM n’intervenant que pour l’interaction avec l’utilisateur.

Un système agentique va encore plus loin en permettant à plusieurs agents spécialisés de collaborer, en s’adaptant aux besoins en temps réel grâce à une décomposition dynamique des tâches, en distribuant l’intelligence entre plusieurs agents qui coordonnent leurs actions, et en réfléchissant de manière récursive sur la stratégie à adopter.

Quand utiliser des agents vs du prompt engineering simple ?

La question clé : avez-vous vraiment besoin d’un agent ?

Le prompt engineering simple suffit quand la tâche est unique et directe, ne nécessite ni mémoire ni contexte persistant, ne requiert aucun outil externe, et que la réponse peut être générée en un seul appel au LLM.

Un agent devient nécessaire quand la tâche nécessite plusieurs étapes et du raisonnement, que vous avez besoin d’accéder à des données externes ou des outils, que le contexte conversationnel est important, ou que les décisions doivent être prises dynamiquement en fonction des résultats intermédiaires.

Un système multi-agents s’impose quand vous avez des domaines d’expertise distincts qui doivent collaborer, que les tâches peuvent être traitées en parallèle pour gagner en efficacité, ou que la coordination entre spécialistes est nécessaire pour résoudre des problèmes complexes.

Les bénéfices dans le contexte actuel

Pourquoi les systèmes agentiques gagnent-ils en popularité en 2025 ? D’abord, les entreprises veulent automatiser des workflows sophistiqués qui impliquent des tâches complexes. Ensuite, les agents permettent de connecter les LLM aux sources de données internes de l’entreprise, donnant accès au contexte métier réel. L’explicabilité est également cruciale : les agents offrent une traçabilité complète des actions et décisions prises. La spécialisation joue aussi un rôle important, avec différents agents dédiés à différents domaines d’expertise. Enfin, les frameworks matures disponibles aujourd’hui sont véritablement production-ready, avec observabilité et gestion d’erreurs intégrées.

Passons maintenant en revue les quatre principaux frameworks de l’écosystème JVM pour construire ces agents.

LangChain4j : la flexibilité pour workflows LLM complexes

Principes généraux

LangChain4j est la version Java du populaire framework Python LangChain. Lancé en 2023, il s’est rapidement imposé comme une référence pour construire des agents IA sur la JVM. Sa maturité se reflète dans son partenariat stratégique avec Microsoft et les audits de sécurité dont il a bénéficié. Le framework offre une flexibilité maximale, ayant été conçu spécifiquement pour les workflows LLM complexes, et propose le support le plus étendu de l’écosystème avec le plus grand nombre de providers LLM et vector stores. L’approche déclarative avec des annotations comme @Tool, @UserMessage ou @MemoryId simplifie considérablement le code, et le concept d’AI Services permet de transformer des interfaces Java en agents.

Le framework repose sur plusieurs concepts fondamentaux. Le ChatModel fournit une abstraction pour interagir avec différents LLM, les Tools permettent au LLM d’appeler des fonctions Java (function calling), la Memory gère le contexte conversationnel, et les Chains orchestrent plusieurs appels LLM en séquence.

Exemple concret : système multi-agents avec routing

Construisons un système où un agent router dispatche les questions vers des experts spécialisés :

// Interface pour un expert médical
interface MedicalExpert {
    @UserMessage("""
        Tu es un expert médical.
        Analyse la requête suivante d'un point de vue médical
        et fournis la meilleure réponse possible.
        La requête est : {{it}}.
        """)
    @Tool("Expert médical")
    String handleMedicalRequest(String request);
}

// Interface pour un expert technique
interface TechnicalExpert {
    @UserMessage("""
        Tu es un expert technique.
        Analyse la requête suivante d'un point de vue technique
        et fournis la meilleure réponse possible.
        La requête est : {{it}}.
        """)
    @Tool("Expert technique")
    String handleTechnicalRequest(String request);
}

// Interface pour un expert juridique
interface LegalExpert {
    @UserMessage("""
        Tu es un expert juridique.
        Analyse la requête suivante d'un point de vue juridique
        et fournis la meilleure réponse possible.
        La requête est : {{it}}.
        """)
    @Tool("Expert juridique")
    String handleLegalRequest(String request);
}

// Router qui dispatche vers le bon expert
interface RouterAgent {
    @UserMessage("""
        Analyse la requête utilisateur et catégorise-la comme
        'juridique', 'médicale' ou 'technique'.
        Transmets ensuite la requête telle quelle à l'expert
        correspondant fourni comme outil.
        Retourne la réponse reçue de l'expert sans modification.

        La requête utilisateur est : '{{it}}'.
        """)
    String route(String request);
}

Instanciation et utilisation :

import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.service.AiServices;

ChatModel model = OpenAiChatModel.builder()
    .apiKey(System.getenv("OPENAI_API_KEY"))
    .modelName("gpt-4")
    .build();

// Construction des experts
MedicalExpert medicalExpert = AiServices.builder(MedicalExpert.class)
    .chatModel(model)
    .build();

TechnicalExpert technicalExpert = AiServices.builder(TechnicalExpert.class)
    .chatModel(model)
    .build();

LegalExpert legalExpert = AiServices.builder(LegalExpert.class)
    .chatModel(model)
    .build();

// Construction du router avec les experts comme tools
RouterAgent router = AiServices.builder(RouterAgent.class)
    .chatModel(model)
    .tools(medicalExpert, technicalExpert, legalExpert)
    .build();

// Utilisation
String response = router.route("Je me suis cassé la jambe, que dois-je faire ?");
System.out.println(response);
// Le router détectera que c'est médical et appellera medicalExpert

LangChain4j brille par sa flexibilité : si vous voulez expérimenter avec différentes stratégies de mémoire, chaîner plusieurs appels LLM, ou gérer des workflows complexes, c’est le framework le plus polyvalent.

Spring AI : l’IA native dans l’écosystème Spring

Principes généraux

Spring AI apporte l’intelligence artificielle dans l’écosystème Spring avec une approche cohérente et familière pour les développeur·se·s Spring Boot. Passé en version 1.0 GA en mai 2025, il représente l’approche officielle de Spring pour les applications IA. L’intégration Spring Boot est native avec auto-configuration, starters et properties, offrant une portabilité des modèles exceptionnelle grâce à une abstraction uniforme pour plus de 20 providers LLM. Le framework propose des patterns enterprise éprouvés comme Chain, Routing, Parallelization ou Orchestrator-Workers, et son ChatClient fluent API rend la construction de prompts complexes intuitive. Le support du Model Context Protocol (MCP) assure l’interopérabilité, tandis que la maturité opérationnelle héritée de Spring apporte observabilité, sécurité et testing intégrés.

Les concepts centraux s’articulent autour du ChatClient qui fournit une API fluide pour interagir avec les LLM, du ChatModel offrant une abstraction portable entre providers, des Prompts avec construction structurée via SystemMessage et UserMessage, des Workflows réutilisables pour orchestrer les agents, et des Structured outputs permettant la conversion automatique vers des objets Java.

Exemple concret : agent de routing avec experts spécialisés

Créons un agent qui peut analyser le sentiment d’un feedback client en accédant à des données externes et en prenant des décisions :

@Service
public class CustomerFeedbackAgent {

    private final ChatClient chatClient;
    private final CustomerRepository customerRepository;
    private final TicketService ticketService;

    public CustomerFeedbackAgent(
        ChatClient.Builder chatClientBuilder,
        CustomerRepository customerRepository,
        TicketService ticketService
    ) {
        this.chatClient = chatClientBuilder
            .defaultSystem("""
                Tu es un agent d'analyse de feedback client.
                Tu peux consulter l'historique client et créer des tickets automatiquement
                selon la gravité du feedback.
                """)
            .build();
        this.customerRepository = customerRepository;
        this.ticketService = ticketService;
    }

    public record FeedbackAnalysis(
        String sentiment,          // POSITIVE, NEGATIVE, NEUTRAL
        int severityScore,         // 0-10
        boolean requiresTicket,
        String suggestedAction,
        List<String> detectedIssues
    ) {}

    public String processFeedback(String customerId, String feedback) {
        // L'agent analyse d'abord le feedback
        FeedbackAnalysis analysis = chatClient.prompt()
            .user(u -> u.text("""
                Analyse ce feedback client : "{feedback}"

                Détermine :
                - Le sentiment général
                - La gravité (0-10)
                - Si un ticket doit être créé
                - L'action suggérée
                - Les problèmes détectés
                """)
                .param("feedback", feedback))
            .call()
            .entity(FeedbackAnalysis.class);

        // L'agent prend des décisions autonomes
        if (analysis.requiresTicket() && analysis.severityScore() >= 7) {
            // Consulte l'historique client
            Customer customer = customerRepository.findById(customerId).orElseThrow();

            // Crée automatiquement un ticket prioritaire
            String ticketId = ticketService.createPriorityTicket(
                customerId,
                analysis.detectedIssues(),
                analysis.suggestedAction()
            );

            return String.format(
                "Feedback négatif grave détecté (score: %d/10). " +
                "Ticket prioritaire #%s créé automatiquement. " +
                "Action suggérée : %s",
                analysis.severityScore(),
                ticketId,
                analysis.suggestedAction()
            );
        }

        return String.format(
            "Feedback analysé : %s (score: %d/10). %s",
            analysis.sentiment(),
            analysis.severityScore(),
            analysis.suggestedAction()
        );
    }
}

Cet agent autonome analyse le feedback, consulte des données externes (historique client), prend des décisions (créer ou non un ticket), et exécute des actions selon sa logique interne. C’est bien plus qu’un simple appel de LLM.

Spring AI excelle quand vous voulez ajouter l’IA à une application Spring Boot existante, bénéficier de la maturité opérationnelle de Spring, ou gérer les fonctionnalités IA aux côtés de microservices classiques. Son approche cohérente avec Spring Boot en fait un choix naturel pour les équipes Spring.

Embabel : la planification déterministe pour les agents enterprise

Principes généraux

Embabel est le nouveau framework d’agents créé par Rod Johnson, le fondateur de Spring Framework. Lancé en 2025, Embabel apporte une approche radicalement différente des autres frameworks : la planification déterministe via Goal-Oriented Action Planning (GOAP).

Rod Johnson affirme : “Depuis que j’ai fondé Spring Framework, je n’ai jamais été aussi convaincu qu’un nouveau projet est nécessaire.”

Ce qui distingue Embabel, c’est son utilisation du Goal-Oriented Action Planning (GOAP), un algorithme d’IA non-LLM pour la planification, combiné à une type safety maximale où tout est fortement typé de bout en bout. La planification déterministe rend les agents explicables et prévisibles, ce qui est crucial en production. Le framework se positionne à un plus haut niveau d’abstraction en se construisant sur Spring AI et LangChain4j, tout en restant enterprise-ready et conçu pour la production. Écrit en Kotlin avec une excellente interopérabilité Java, il reste accessible aux deux communautés.

L’architecture repose sur quatre concepts : les Goals qui définissent les objectifs que l’agent cherche à atteindre, les Actions qui sont les tâches atomiques que l’agent peut exécuter, le Planner qui utilise l’algorithme GOAP pour trouver le chemin optimal vers le goal, et le Strong typing qui garantit des vérifications compile-time partout.

Qu’est-ce que GOAP (Goal-Oriented Action Planning) ?

Contrairement aux autres frameworks qui laissent le LLM planifier, Embabel utilise GOAP, un algorithme traditionnel d’IA utilisé dans les jeux vidéo. Le processus suit quatre étapes : d’abord, l’agent connaît ses objectifs possibles grâce à la définition de goals. Ensuite, chaque action est définie avec ses préconditions et ses effets. Le planning automatique permet à GOAP de trouver le chemin optimal vers le goal. Enfin, les actions sont exécutées dans l’ordre planifié.

Les avantages de GOAP sont considérables. L’approche est déterministe : le même input produit toujours le même plan. Elle est explicable : vous voyez exactement pourquoi une action a été choisie et dans quel ordre. Elle est efficace : pas de tokens LLM gaspillés pour la planification elle-même. Et elle est fiable : pas d’hallucination possible dans le processus de décision puisque l’algorithme de planification n’utilise pas de LLM.

Type safety de bout en bout

Embabel élimine toutes les “clés magiques” des prompts :

// Autres frameworks : clés string magiques
@UserMessage("Analyse {{request}}") // ⚠️ Erreur typo non détectée

// Embabel : tout est typé
public record AnalysisRequest(String content) {}
public record AnalysisResult(String analysis, int confidence) {}

// Erreurs de type détectées à la compilation

Exemple concret : agent de support client avec Spring

Construisons un agent de support intégré à Spring Boot qui réutilise directement vos services métier pour consulter les commandes, vérifier le stock, et initier des remboursements :

@Agent(description = "Résout les problèmes de support client en analysant les commandes et en initiant des remboursements si nécessaire")
class CustomerSupportAgent(
    private val orderService: OrderService,
    private val stockService: StockService,
    private val refundService: RefundService
) {

    // Action 1 : Extraire les informations du message utilisateur
    @Action
    fun extractCustomerRequest(userInput: UserInput): CustomerRequest =
        PromptRunner().createObject(
            """
            Analyse ce message d'un client et extrait :
            - L'identifiant client (customerId)
            - Une description claire du problème

            Message : ${userInput.message}
            """.trimIndent()
        )

    // Action 2 : Récupérer la commande via le service métier
    @Action
    fun fetchOrder(request: CustomerRequest): Order? {
        return orderService.findByCustomerId(request.customerId)
    }

    // Action 3 : Vérifier le stock disponible
    @Action
    fun checkStock(order: Order): StockInfo {
        return stockService.checkAvailability(order.items)
    }

    // Action 4 : Initier un remboursement si nécessaire
    @Action
    fun initiateRefundIfNeeded(
        request: CustomerRequest,
        order: Order,
        stockInfo: StockInfo
    ): RefundConfirmation? {
        val shouldRefund = PromptRunner().createObject<Boolean>(
            """
            Analyse la situation suivante et détermine si un remboursement doit être initié :

            Problème client : ${request.issueDescription}
            Commande : ${order.id}, montant ${order.totalAmount}            Stock disponible : ${stockInfo.items}

            Retourne true si un remboursement est justifié, false sinon.
            """.trimIndent()
        )

        return if (shouldRefund) {
            refundService.initiateRefund(order.id)
        } else null
    }

    // Action finale : Générer un résumé pour le client
    @AchievesGoal(description = "Générer un résumé de résolution pour le client")
    @Action
    fun generateResolution(
        request: CustomerRequest,
        order: Order?,
        stockInfo: StockInfo?,
        refund: RefundConfirmation?
    ): ResolutionSummary =
        PromptRunner().withTemperature(0.7).createObject(
            """
            Génère un message de résolution professionnel et empathique pour le client.

            Problème : ${request.issueDescription}
            Commande trouvée : ${order != null}
            ${if (order != null) "Détails commande : ${order.id}, ${order.status}" else ""}
            Remboursement initié : ${refund != null}
            ${if (refund != null) "Remboursement : ${refund.refundId}, ${refund.amount}€" else ""}

            Le message doit être en français, courtois et clair.
            """.trimIndent()
        )
}

@RestController
@RequestMapping("/api/support")
class SupportController(
    private val agent: CustomerSupportAgent
) {

    @PostMapping("/resolve")
    fun resolveIssue(@RequestBody message: String): ResponseEntity<String> {
        val userInput = UserInput(message)
        val result = agent.run(userInput)
        return ResponseEntity.ok(result.text)
    }
}

Cet exemple montre l’intégration parfaite d’Embabel avec Spring Boot. L’agent @Agent est automatiquement découvert et enregistré comme bean Spring. Les services métier (OrderService, StockService, RefundService) sont injectés via le constructeur. Chaque méthode @Action représente une étape que l’agent peut exécuter, et l’annotation @AchievesGoal indique que generateResolution termine l’exécution de l’agent. GOAP planifie automatiquement l’ordre optimal d’exécution des actions pour atteindre le goal.

L’approche en trois phases

Embabel fonctionne en trois phases distinctes. La phase de Discovery permet à l’agent de découvrir les actions et goals depuis votre code. La phase de Planning utilise GOAP pour calculer le plan optimal sans solliciter le LLM. Enfin, la phase d’Execution exécute les actions dans l’ordre planifié, le LLM étant utilisé uniquement pour interagir avec l’utilisateur.

Cette séparation apporte une efficacité remarquable en évitant de gaspiller des tokens pour la planification, une traçabilité totale car vous voyez exactement ce qui a été planifié avant l’exécution, et une testabilité accrue puisque vous pouvez tester le planner indépendamment de l’exécution.

Utilisation depuis Java

Bien qu’écrit en Kotlin, Embabel s’utilise facilement depuis Java grâce à l’excellente interopérabilité :

public class CustomerSupportAgent {

    public Result handleCustomerIssue(String customerId) {
        CustomerContext context = new CustomerContext(customerId);

        EmbabelAgent<CustomerContext> agent =
            EmbabelAgent.<CustomerContext>builder()
                .addAction(new FetchOrderAction())
                .addAction(new CheckStockAction())
                .addAction(new InitiateRefundAction())
                .goal(CustomerGoal.ResolveIssue.INSTANCE)
                .llm(chatModel)
                .build();

        return agent.execute(context);
    }
}

Embabel est idéal quand vous avez besoin de planification explicable et déterministe, que vous construisez des agents enterprise critiques nécessitant une forte type safety, ou que vous voulez maximiser l’efficacité en évitant les tokens de planification.

Rod Johnson résume : “Il n’y a aucune raison d’écrire des agents en Python à moins que vous soyez déjà dans l’écosystème Python.”

Koog : le framework multiplateforme de JetBrains

Principes généraux

Koog est le framework officiel de JetBrains pour construire des agents IA en Kotlin. Annoncé à KotlinConf 2025 et open-sourcé sous licence Apache 2.0, Koog représente l’approche Kotlin-first pour les agents IA. Ce qui distingue Koog, c’est d’abord sa nature multiplateforme : le même code fonctionne sur JVM, Android, iOS, JS et WasmJS. Le DSL Kotlin idiomatique offre une syntaxe expressive et type-safe qui rend le code élégant. L’observabilité est native avec support d’OpenTelemetry, Langfuse et W&B Weave. La tolérance aux pannes est intégrée via des retries automatiques et la persistence d’agents. L’optimisation des tokens passe par une compression intelligente de l’historique. Le support Agent-to-Agent (A2A) standardise la communication inter-agents. Le framework est utilisable en production — JetBrains l’a conçu en s’appuyant sur l’expérience de leurs propres outils IA.

L’architecture s’articule autour de l’Agent DSL pour la construction déclarative d’agents, du Memory management qui gère automatiquement le contexte, de la Tool integration qui simplifie la connexion aux fonctions Kotlin, de l’Observability avec tracing et monitoring intégrés, et du support Multi-agent coordination via A2A natif.

Le DSL Koog : agents production-ready

Koog exploite pleinement les capacités de Kotlin pour offrir un DSL élégant et production-ready :

// Définir les tools métier
class SupportTools(
    private val orderService: OrderService,
    private val refundService: RefundService
) : ToolSet {

    @Tool
    @LLMDescription("Récupère le statut d'une commande")
    fun getOrderStatus(
        @LLMDescription("Identifiant de la commande") orderId: String
    ): String {
        return orderService.getStatus(orderId)
    }

    @Tool
    @LLMDescription("Initie un remboursement pour une commande")
    fun initiateRefund(
        @LLMDescription("Identifiant de la commande") orderId: String
    ): String {
        return refundService.initiate(orderId)
    }
}

// Créer l'agent avec observabilité native
val supportAgent = AIAgent(
    promptExecutor = simpleOpenAIExecutor(System.getenv("OPENAI_API_KEY")),
    llmModel = OpenAIModels.Chat.GPT4o,
    systemPrompt = "Tu es un agent de support client expert.",
    toolRegistry = ToolRegistry {
        tools(SupportTools(orderService, refundService))
    }
) {
    // Observabilité native avec Tracing
    install(Tracing) {
        addMessageProcessor(TraceFeatureMessageLogWriter(logger))
    }
}

Koog offre une observabilité native via le système Tracing qui capture automatiquement tous les événements : appels LLM, exécutions de tools, latence, événements de stratégie, etc.

Exemple concret : agent d’analyse avec tools et mémoire

Un agent qui interroge une base de données et génère des visualisations :

// Définir les tools d'analyse
class DataAnalysisTools(
    private val database: Database,
    private val chartService: ChartService
) : ToolSet {

    @Tool
    @LLMDescription("Exécute une requête SQL sur la base de données")
    fun executeQuery(
        @LLMDescription("Requête SQL à exécuter") sql: String
    ): Map<String, Any> {
        if (!isSafeQuery(sql)) error("Requête non sécurisée")

        return database.executeQuery(sql).let {
            mapOf("rows" to it.toList(), "count" to it.size)
        }
    }

    @Tool
    @LLMDescription("Génère un graphique à partir de données")
    fun generateChart(
        @LLMDescription("Type de graphique") type: String,
        @LLMDescription("Données à visualiser") data: List<*>
    ): String {
        return chartService.generate(type, data)
    }
}

// Créer l'agent avec mémoire
val memoryProvider = LocalFileMemoryProvider(
    config = LocalMemoryConfig("data-analyst-memory"),
    storage = SimpleStorage(JVMFileSystemProvider.ReadWrite),
    fs = JVMFileSystemProvider.ReadWrite,
    root = Path("./agent-memory")
)

val dataAnalysisAgent = AIAgent(
    promptExecutor = simpleOpenAIExecutor(System.getenv("OPENAI_API_KEY")),
    llmModel = OpenAIModels.Chat.GPT4oMini,
    systemPrompt = "Tu es un analyste de données expert en SQL.",
    toolRegistry = ToolRegistry {
        tools(DataAnalysisTools(database, chartService))
    }
) {
    install(AgentMemory) {
        this.memoryProvider = memoryProvider
        featureName = "data-analysis"
    }
}

// Utilisation
suspend fun analyzeData(userQuery: String): String {
    val result = dataAnalysisAgent.run(userQuery)
    return result.text
}

L’agent peut décider lui-même quels tools appeler, dans quel ordre, et combien de fois selon les besoins de l’analyse. La mémoire lui permet de se souvenir du contexte des analyses précédentes.

Koog excelle quand vous construisez en Kotlin et voulez une syntaxe idiomatique, que vous avez besoin d’observabilité production-grade, que vous visez le multiplateforme (backend + mobile), ou que vous voulez des agents communicants via A2A.

L’approche JetBrains, basée sur leur expérience avec leurs propres produits IA, fait de Koog un choix solide pour les agents en production.

Quel framework choisir ?

Nous avons exploré quatre frameworks puissants. Comment choisir ?

Tableau comparatif

Critère LangChain4j Spring AI Embabel Koog
Niveau d’abstraction Moyen Moyen Élevé Moyen
Type safety ⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐
Support LLM providers ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐
Intégration Spring ⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐
Observabilité ⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐⭐
Multiplateforme ❌ JVM only ❌ JVM only ❌ JVM only ✅ JVM, Android, iOS, JS
Planification LLM-based LLM-based GOAP (déterministe) LLM-based
Langage principal Java Java Kotlin Kotlin
Maturité ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐ (nouveau) ⭐⭐⭐
Courbe d’apprentissage Moyenne Facile (si Spring) Moyenne Moyenne (si Kotlin)

Recommandations par contexte

LangChain4j s’impose si vous recherchez la flexibilité maximale pour expérimenter, si vous avez besoin du plus large support de providers LLM et vector stores du marché, si vous construisez des workflows LLM complexes avec chaînes et orchestration, si vous n’êtes pas nécessairement ancré dans l’écosystème Spring, ou si vous préférez une approche Java-first avec annotations déclaratives.

Spring AI est le choix naturel si vous avez déjà une application Spring Boot existante, si vous voulez bénéficier de la maturité opérationnelle de Spring en termes de sécurité, observabilité et testing, si vous privilégiez la portabilité entre modèles LLM, si vous aimez les patterns enterprise éprouvés comme Chain, Routing ou Orchestrator-Workers, ou si vous gérez les fonctionnalités IA aux côtés de microservices classiques.

Embabel devient pertinent si vous avez besoin de planification déterministe et explicable, si vous construisez des agents enterprise critiques où la fiabilité est primordiale, si vous voulez la type safety maximale de bout en bout, si vous préférez éviter de gaspiller des tokens pour la planification, si vous êtes à l’aise avec Kotlin (ou Java avec interop), ou si vous cherchez un plus haut niveau d’abstraction que les frameworks classiques.

Koog s’impose si vous construisez en Kotlin et voulez une syntaxe idiomatique, si vous avez besoin d’observabilité production-grade native, si vous visez le multiplateforme avec un code partagé entre backend, Android et iOS, si vous voulez des agents communicants via le protocole A2A, si vous appréciez la tolérance aux pannes et la persistence automatiques, ou si vous faites confiance à l’expertise JetBrains forgée avec leurs propres produits IA.

Notre perspective chez Liksi

Chez Liksi, notre approche privilégierait Spring AI comme point d’entrée naturel pour nos projets Spring Boot existants, nous tournerions vers LangChain4j pour les cas nécessitant une flexibilité maximale et un support étendu de providers, nous évaluerions Embabel pour les agents critiques nécessitant explicabilité et planification déterministe, et nous considérerions Koog pour les projets Kotlin-first et les besoins multiplateforme.

L’important est de choisir en fonction de votre contexte, pas selon les tendances.

Conclusion : l’écosystème JVM est prêt pour les agents IA

Nous avons exploré quatre frameworks puissants qui démontrent une réalité indéniable : l’écosystème Java/Kotlin est désormais mature pour construire des agents IA en production.

Ce qu’il faut retenir

Java et Kotlin offrent des avantages décisifs pour les agents IA : la type safety avec validation compile-time, refactoring sûr et support IDE complet ; un caractère production-ready avec performance, scalabilité et observabilité éprouvées ; une intégration enterprise fluide permettant la réutilisation de la logique métier existante ; et un écosystème mature avec Spring, des solutions de sécurité robustes et un tooling avancé.

Nous avons exploré quatre approches complémentaires. LangChain4j apporte flexibilité et support étendu pour workflows complexes. Spring AI offre une intégration naturelle Spring Boot avec patterns enterprise éprouvés. Embabel se distingue par sa planification déterministe et sa type safety maximale. Koog combine Kotlin idiomatique, observabilité native et support multiplateforme.

Les agents IA deviennent pertinents pour les tâches multi-étapes nécessitant du raisonnement, l’accès à des données externes et tools, les situations où le contexte conversationnel est important, et les cas nécessitant une coordination entre différents domaines d’expertise.

L’avenir des agents sur la JVM

2025 marque un tournant : Python n’est plus le seul choix légitime pour l’IA. Bien que des frameworks Python comme LangGraph et CrewAI dominent aujourd’hui l’écosystème agentique, les frameworks JVM offrent désormais les mêmes capacités avec des avantages additionnels en type safety et production-readiness. Ils apportent même des innovations uniques comme le GOAP d’Embabel pour la planification déterministe. Ils bénéficient enfin de la maturité opérationnelle héritée de l’écosystème enterprise Java, forgée sur des décennies de déploiements critiques.

Les partenariats stratégiques entre Microsoft et LangChain4j, Spring et Kotlin, ou JetBrains avec Koog, montrent que les grands acteurs investissent massivement dans cet écosystème.

Ressources utiles

Documentation officielle

LangChain4j :

Spring AI :

Embabel :

Koog :

Articles et blogs techniques

  • “You Can Build Better AI Agents in Java Than Python” - Rod Johnson, août 2025
  • “Java’s AI Awakening: LangChain4j vs Spring AI” - Medium, août 2025
  • “2025 Is the Last Year of Python Dominance in AI” - The New Stack
  • “From Python to Kotlin: How JetBrains Revolutionized AI Agent Development” - Medium, septembre 2025
  • “Effective Context Engineering for AI Agents” - Anthropic Engineering

Comparaisons et guides

  • “Leading Java AI Frameworks: LangChain4j vs Spring AI” - LinkedIn Technical Analysis
  • “Enterprise-Ready AI Agents in Java & Spring Boot” - Bayram EKER, Medium
  • “Python vs. Java in AI Late 2024: Comprehensive Ecosystem Comparison” - Medium

Vidéos et conférences

  • Spring I/O 2025 - Sessions sur Spring AI et agents
  • KotlinConf 2025 - Présentation officielle de Koog
  • Devoxx 2025 - Talks sur LangChain4j et agents JVM
  • “Codepocalypse Now: LangChain4j vs. Spring AI” - Viktor Gamov

Communautés

Ces ressources vous permettront d’approfondir votre exploration des systèmes agentiques sur la JVM et de choisir l’approche la plus adaptée à vos besoins !

Derniers articles