Build and demo Java AI agent systems with langchain4j-agentic: workflow patterns, supervisor, custom Planner strategies (incl. the flagship typed-verdict / CriticResult-style critic pattern), plus MCP tools, A2A remote agents, build setup, and conference-demo storylines. Pinned to 1.15.0 / 1.15.0-beta25.
84
89%
Does it follow best practices?
Impact
100%
4.76xAverage score across 2 eval scenarios
Passed
No known issues
Wiring langchain4j-mcp (Model Context Protocol — external tools) and langchain4j-agentic-a2a (Agent-to-Agent protocol — remote agents). Both pinned at 1.15.0-beta25.
MCP is about tools; A2A is about agents. Complementary, not competing. An agent can use MCP tools and call a remote A2A agent in the same workflow.
| Goal | Use |
|---|---|
| Agent needs filesystem / GitHub / Confluent MCP tools | langchain4j-mcp |
| Two of your agents talk over HTTP | langchain4j-agentic-a2a (client) |
| Call an agent hosted elsewhere | langchain4j-agentic-a2a (client) |
| Host an agent others can call | A2A server (Quarkus quarkus-langchain4j-a2a, or io.github.a2asdk directly) — out of scope here |
Adapts MCP tools into a LangChain4j ToolProvider. Two transports: stdio (spawn a subprocess) and HTTP/SSE (hosted server). MCP tools are dynamic, so they go through .toolProviders(...), not .tools(...).
npx)import dev.langchain4j.mcp.McpToolProvider;
import dev.langchain4j.mcp.client.DefaultMcpClient;
import dev.langchain4j.mcp.client.transport.stdio.StdioMcpTransport;
var fsTransport = new StdioMcpTransport.Builder()
.command(List.of("npx", "-y", "@modelcontextprotocol/server-filesystem",
System.getProperty("user.home") + "/workspace"))
.logEvents(true)
.build();
var fsClient = new DefaultMcpClient.Builder()
.transport(fsTransport)
.build();
ToolProvider mcpTools = McpToolProvider.builder()
.mcpClients(fsClient)
.build();
var agent = AgenticServices.agentBuilder(MyAgent.class)
.chatModel(claude)
.toolProviders(mcpTools) // NOT .tools(...)
.maxSequentialToolsInvocations(10)
.build();
// MANDATORY: close cleanly or you orphan the npx subprocess
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
try { fsClient.close(); } catch (Exception ignored) {}
}));Two footguns:
.toolProviders(...) — MCP tools are discovered at runtime.node subprocesses running. On macOS, pkill -f "modelcontextprotocol/server" cleans up between rehearsals.import dev.langchain4j.mcp.client.transport.http.HttpMcpTransport;
var transport = new HttpMcpTransport.Builder()
.sseUrl("https://mcp-confluent.ai-assisted.engineering/sse")
.timeout(Duration.ofSeconds(60))
.logRequests(true)
.logResponses(true)
.build();
var client = new DefaultMcpClient.Builder().transport(transport).build();
ToolProvider confluentTools = McpToolProvider.builder().mcpClients(client).build();The Confluent MCP server (https://mcp-confluent.ai-assisted.engineering/sse) is a natural demo target: list topics, describe schemas, query Flink — all from a Java agent.
McpToolProvider.builder().mcpClients(client1, client2, client3) merges tool sets (filesystem + git + a domain server simultaneously). stdio and HTTP clients can be mixed.
langchain4j-agentic-a2a is a client-only library for the A2A protocol (a Linux Foundation project). It transitively pulls io.github.a2asdk:a2a-java-sdk-client — don't declare those yourself.
public interface SummarizationAgent {
@Agent
String summarize(@V("text") String text);
}
var remoteSummarizer = AgenticServices
.a2aBuilder("http://localhost:8081", SummarizationAgent.class)
.inputNames("text")
.outputName("summary")
.build();The returned object implements the interface and is interchangeable with a local agent — drop it into any builder:
var pipeline = AgenticServices.sequenceBuilder()
.subAgents(localResearcher, remoteSummarizer, localWriter)
.build();Under the hood: JSON-RPC over HTTP; the Agent Card is discovered at {baseUrl}/.well-known/agent.json. Untyped variant: a2aBuilder(url).inputNames(...).outputName(...).build() → an UntypedAgent.
Client-only here. To host, use quarkus-langchain4j-a2a (wraps an AiService as an A2A server — cleanest for a Quarkus demo) or the io.github.a2asdk server SDK directly. For a talk, two Quarkus apps on localhost (one hosts, one calls via a2aBuilder) is the most conference-Wi-Fi-proof setup.
var agent = AgenticServices.agentBuilder(MyAgent.class)
.chatModel(claude)
.toolProviders(mcpFilesystem, mcpGithub) // MCP for tools
.build();
var remotePeer = AgenticServices.a2aBuilder("http://peer:8081", PeerAgent.class).build();
var system = AgenticServices.sequenceBuilder()
.subAgents(agent, remotePeer) // A2A for the remote agent
.build();Local agent with MCP tools calling a remote agent over A2A — the "modern agent system" shape worth showing to architects.
npx -y @modelcontextprotocol/server-… can take 5–10s the first time. Pre-warm before the demo.1.0.0 but the Java SDK is still Beta1 — stable in practice, expect cosmetic API drift.{baseUrl}/.well-known/agent.json is reachable before the talk; the client fails fast if it isn't.