How Embabel‑Agent Integrates with External Tools and Platforms: A Complete Integration Guide

Embabel-agent integrates with external tools and platforms through three core layers: LLM provider abstractions via Spring‑AI, MCP (Model Context Protocol) clients and servers for tool interoperability, and A2A protocol support for agent federation, all wired together with Spring Boot auto‑configuration.

The Embabel Agent Platform is a Spring‑aware, JVM‑native framework designed to connect language models, external tools, and observability systems through a unified architecture. This article examines how embabel-agent achieves deep integration with LLM providers, MCP‑based tools, and monitoring platforms using concrete source code references and working configuration examples.


LLM Provider Integration via Spring‑AI

Embabel-agent does not implement LLM clients directly. Instead, it relies on Spring‑AI's ChatModel abstraction, auto‑configuring provider‑specific beans through dedicated starter modules.

Supported Provider Starters

Provider Starter Artifact Configuration Class
OpenAI embabel-agent-starter-openai [OpenAiAutoConfiguration.java](https://github.com/embabel/embabel-agent/blob/main/embabel-agent-autoconfigure/models/embabel-agent-openai-autoconfigure/src/main/java/com/embabel/agent/autoconfigure/models/openai/OpenAiAutoConfiguration.java)
Anthropic embabel-agent-starter-anthropic LLMAnthropicStreamingBuilderIT (test reference)
Ollama emabel-agent-starter-ollama Production auto‑configuration shipped with starter
OCI Generative AI embabel-agent-starter-oci Oracle Cloud Infrastructure integration
Gemini embabel-agent-starter-gemini Google AI integration
MiniMax, Mistral‑AI Dedicated starters Provider‑specific model enums

Each starter creates a ChatModel bean that the AgentPlatform injects into action execution contexts. Runtime model selection occurs through the Ai fluent API:

import com.embabel.agent.core.model.models.OpenAiModels;
import static com.embabel.agent.core.model.models.OpenAiModels.GPT_4;

// OpenAI provider
return ai.withLlm(GPT_4)
         .createObject(prompt, Result.class);

// Anthropic provider  
return ai.withLlm(LlmAnthropicModels.CLAUDE)
         .createObject(prompt, Result.class);

The provider layer is completely interchangeable—no code changes are required beyond the withLlm() call.


MCP (Model Context Protocol) Tool Integration

MCP is the standardized protocol for exposing external capabilities to LLMs. Embabel-agent implements both client (consuming tools) and server (exposing tools) roles.

MCP Client: Consuming External Tools

The QuiteMcpClientAutoConfiguration creates resilient MCP clients that survive individual server failures. Unlike Spring‑AI's default implementation, this configuration tolerates startup errors and logs them without crashing the application.

Configure MCP clients in application.yml:

spring:
  ai:
    mcp:
      client:
        enabled: true
        name: embabel
        version: 1.0.0
        type: SYNC  # or ASYNC for non‑blocking operations

        stdio:
          connections:
            brave-search:
              command: docker
              args: [run, -i, --rm, brave/search:latest]
            wikipedia:
              command: docker
              args: [run, -i, --rm, wikipedia/mcp:latest]
            postgres:
              command: docker
              args: [run, -i, --rm, postgres/mcp:latest]

The resilience design is critical: if the brave-search container fails to start, the platform continues with wikipedia and postgres available. This behavior is implemented through custom exception handling in QuiteMcpClientAutoConfiguration that wraps standard Spring‑AI MCP client creation with fallback logic.

Enabling MCP Servers via @EnableAgents

The @EnableAgents annotation declares which MCP servers activate for a given agent configuration:

import com.embabel.agent.config.annotation.EnableAgents;

@Configuration
@EnableAgents(mcpServers = { "brave-search", "wikipedia", "postgres" })
public class TravelAgentConfiguration {
    // Additional beans...
}

During context initialization, the platform:

  1. Scans for @EnableAgents annotations
  2. Creates McpServer beans for each named server
  3. Registers them with the planning engine for goal‑selection

MCP Server: Exposing Tools to Other Agents

The AgentMcpServerAutoConfiguration module publishes an SSE endpoint at /sse that Claude Desktop, Copilot, or other MCP‑aware clients can consume.

Configuration properties control server behavior:

embabel:
  agent:
    mcp:
      server:
        enabled: true
        execution-mode: SYNC  # or ASYNC

        transport: sse        # Server‑Sent Events transport

When enabled, any @Action method with explicit tool descriptions becomes available through the MCP protocol to external consumers.


A2A Protocol: Agent‑to‑Agent Federation

Embabel-agent supports the A2A protocol for cross‑platform agent communication. Activating the a2a Spring profile starts an HTTP endpoint that accepts and responds to A2A messages:


# Start with A2A profile enabled

java -jar my-agent.jar --spring.profiles.active=a2a

The server binds to /a2a by default (e.g., http://localhost:8080/a2a), enabling:

  • Remote task discovery: Other A2A agents query capability advertisements
  • Secure delegation: Tasks execute with authenticated context propagation
  • Status streaming: Long‑running operations report progress via SSE

This integration allows embabel-agent instances to participate in heterogeneous agent ecosystems without protocol translation.


Observability Integration: Micrometer and OpenTelemetry

The embabel-agent-observability module auto‑configures tracing and metrics through EmbabelSpanEventListener and EmbabelMetricsEventListener.

Automatic Span Generation

Every action execution, LLM call, and tool invocation becomes a child span:


Agent: TravelPlannerAgent
├─ Action: FindHotels
│  ├─ @Tracked: enrichCustomer (PROCESSING)
│  │  └─ Tool: brave-search (300ms)
│  ├─ ChatModel: gpt-4 (Spring AI) (1.2s)
│  └─ Tool: postgres/query-hotels (45ms)
└─ status: completed (traceId: abc123...)

Custom Tracking with @Tracked

The @Tracked annotation adds business‑context spans:

import com.embabel.agent.observability.annotation.Tracked;
import com.embabel.agent.observability.annotation.TrackType;

@Service
public class CustomerEnrichmentService {

    @Tracked(
        value = "enrichCustomer",
        type = TrackType.PROCESSING,
        description = "Enriches a Customer record with external data sources"
    )
    public Customer enrich(Customer input, Map<String, Object> externalData) {
        // Implementation...
        return enrichedCustomer;
    }
}

Supported TrackType values include PROCESSING, VALIDATION, EXTERNAL_CALL, and AGGREGATION.

Exporter configuration follows standard Spring Boot properties:

management:
  tracing:
    sampling:
      probability: 1.0
  zipkin:
    tracing:
      endpoint: http://localhost:9411/api/v2/spans
  metrics:
    export:
      otlp:
        endpoint: http://localhost:4318/v1/metrics

Langfuse, Datadog, and custom OTel collectors are supported through Micrometer registries.


Platform Resilience: Auto‑Configuration Filtering

The AgentPlatformAutoConfigurationFilter prevents Spring‑AI's default MCP client auto‑configuration from activating when embabel-agent's resilient client is present. This avoids double‑bean registration and ensures the platform uses failure‑tolerant client implementations.

The filter implements AutoConfigurationImportFilter and excludes:

  • McpClientAutoConfiguration (Spring‑AI default)
  • ToolCallbackAutoConfiguration where conflicting

Complete Integration Example

The following configuration demonstrates a production‑ready embabel-agent setup with multiple LLM providers, MCP tools, A2A federation, and observability:

package com.example.travel;

import com.embabel.agent.config.annotation.EnableAgents;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableAgents(
    mcpServers = { "brave-search", "postgres", "wikipedia" },
    profiles = { "a2a" }
)
public class TravelAgentPlatformConfiguration {
}

# application.yml

spring:
  ai:
    mcp:
      client:
        enabled: true
        name: travel-platform
        version: 2.1.0
        type: ASYNC
        request-timeout: 30s
        stdio:
          connections:
            brave-search:
              command: docker
              args: [run, -i, --rm, -e, BRAVE_API_KEY=${BRAVE_KEY}, brave/search:latest]
            postgres:
              command: docker
              args: [run, -i, --rm, -e, DATABASE_URL=${DB_URL}, postgres/mcp:latest]

embabel:
  agent:
    mcp:
      server:
        enabled: true
        execution-mode: ASYNC

management:
  tracing:
    enabled: true
    sampling:
      probability: 0.1
  endpoints:
    web:
      exposure:
        include: health, metrics, prometheus
// Action using tool groups
@Agent(description = "Intelligent travel planning assistant")
public class TravelPlanner {

    @Action(
        description = "Find and rank hotels based on user preferences",
        toolGroups = { CoreToolGroups.WEB, CoreToolGroups.DATABASE }
    )
    public HotelRecommendations findHotels(
            UserPreferences preferences,
            TravelDates dates,
            Ai ai) {
        
        String prompt = buildHotelPrompt(preferences, dates);
        
        return ai.withLlm(selectModelForComplexity(preferences))
                 .toolGroup(CoreToolGroups.WEB)      // Requires brave-search
                 .toolGroup(CoreToolGroups.DATABASE) // Requires postgres
                 .createObject(prompt, HotelRecommendations.class);
    }
    
    private LlmModel selectModelForComplexity(UserPreferences prefs) {
        return prefs.requiresReasoning() 
            ? OpenAiModels.GPT_4 
            : OpenAiModels.GPT_4_MINI;
    }
}

Key Source Files Reference

Integration Layer Source File Purpose
Platform bootstrap [EnableAgents.java](https://github.com/embabel/embabel-agent/blob/main/embabel-agent-autoconfigure/embabel-agent-platform-autoconfigure/src/main/java/com/embabel/agent/config/annotation/EnableAgents.java) Declares MCP servers and activation profiles
MCP client resilience [QuiteMcpClientAutoConfiguration.java](https://github.com/embabel/embabel-agent/blob/main/embabel-agent-autoconfigure/embabel-agent-platform-autoconfigure/src/main/java/com/embabel/agent/autoconfigure/platform/QuiteMcpClientAutoConfiguration.java) Fault‑tolerant client creation
MCP server exposure [AgentMcpServerAutoConfiguration.java](https://github.com/embabel/embabel-agent/blob/main/embabel-agent-autoconfigure/embabel-agent-mcpserver-autoconfigure/src/main/java/com/embabel/agent/autoconfigure/mcpserver/AgentMcpServerAutoConfiguration.java) SSE endpoint for external tool consumers
Auto‑config filtering [AgentPlatformAutoConfigurationFilter.java](https://github.com/embabel/embabel-agent/blob/main/embabel-agent-autoconfigure/embabel-agent-platform-autoconfigure/src/main/java/com/embabel/agent/autoconfigure/platform/AgentPlatformAutoConfigurationFilter.java) Prevents Spring‑AI default bean conflicts
OpenAI provider [OpenAiAutoConfiguration.java](https://github.com/embabel/embabel-agent/blob/main/embabel-agent-autoconfigure/models/embabel-agent-openai-autoconfigure/src/main/java/com/embabel/agent/autoconfigure/models/openai/OpenAiAutoConfiguration.java) Example LLM provider wiring
Distributed tracing [EmbabelSpanEventListener.java](https://github.com/embabel/embabel-agent/blob/main/embabel-agent-observability/src/main/java/com/embabel/agent/observability/tracing/EmbabelSpanEventListener.java) Span creation and context propagation
Custom metrics [EmbabelMetricsEventListener.java](https://github.com/embabel/embabel-agent/blob/main/embabel-agent-observability/src/main/java/com/embabel/agent/observability/metrics/EmbabelMetricsEventListener.java) Micrometer metric registration
Business context tracking [Tracked.java](https://github.com/embabel/embabel-agent/blob/main/embabel-agent-observability/src/main/java/com/embabel/agent/observability/annotation/Tracked.java) Annotation for method‑level spans

Summary

  • LLM integration occurs through Spring‑AI ChatModel beans with provider‑specific starters for OpenAI, Anthropic, Ollama, and others
  • MCP client integration uses QuiteMcpClientAutoConfiguration for resilient, failure‑tolerant tool consumption
  • MCP server integration exposes agent capabilities via SSE endpoints configured in AgentMcpServerAutoConfiguration
  • Tool activation is declarative through @EnableAgents and runtime toolGroups in action definitions
  • A2A federation enables cross‑platform agent communication with profile‑based activation
  • Observability integrates Micrometer and OpenTelemetry through automatic span generation and @Tracked annotations
  • Platform stability is guaranteed by AgentPlatformAutoConfigurationFilter preventing conflicting auto‑configurations

Frequently Asked Questions

How do I add a custom MCP server to embabel-agent?

Create a Docker container or native binary that implements the MCP JSON‑RPC protocol over stdio, then register it in application.yml under spring.ai.mcp.client.stdio.connections. The QuiteMcpClientAutoConfiguration will automatically create a client and inject it into the AgentPlatform. No Java code changes are required—only YAML configuration and container availability.

What happens if an MCP server fails to start?

The platform continues operating with reduced functionality. Unlike Spring‑AI's default implementation, embabel-agent's resilient client catches startup exceptions, logs them at WARN level, and excludes the failed server from the tool registry. Other configured MCP servers remain available. This behavior is implemented in QuiteMcpClientAutoConfiguration.

Can I use multiple LLM providers in the same application?

Yes. Add multiple provider starters to your classpath, then select the provider at call time using ai.withLlm(ModelEnum.SPECIFIC_MODEL). The Ai interface maintains separate client instances per provider, allowing mixed usage within the same agent or even the same action sequence when combined with conditional logic.

How do I integrate with Langfuse or a custom tracing backend?

Configure standard Spring Boot management properties for OTLP or Zipkin export. The EmbabelSpanEventListener emits all agent, action, and tool spans with consistent trace IDs. For Langfuse specifically, use the OpenTelemetry intake endpoint: https://cloud.langfuse.com/api/public/otel as your management.otlp.tracing.endpoint.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →