Skip to content

spring-ai-community/spring-ai-bedrock-agentcore

Repository files navigation

Spring AI Bedrock AgentCore

A Spring Boot starter that enables existing Spring Boot applications to conform to the AWS Bedrock AgentCore Runtime contract with minimal configuration.

Features

  • Auto-configuration: Automatically sets up AgentCore endpoints when added as dependency
  • Annotation-based: Simple @AgentCoreInvocation annotation to mark agent methods
  • SSE Streaming: Server-Sent Events support with Flux<String> return types
  • Smart health checks: Built-in /ping endpoint with Spring Boot Actuator integration
  • Async task tracking: Convenient methods for background task tracking
  • Rate limiting: Built-in Bucket4j throttling for invocations and ping endpoints

Quick Start

1. Add Dependency

<dependency>
    <groupId>org.springaicommunity</groupId>
    <artifactId>spring-ai-bedrock-agentcore-starter</artifactId>
    <version>1.0.0-RC1</version>
</dependency>

2. Create Agent Method

@Service
public class MyAgentService {
    
    @AgentCoreInvocation
    public String handleUserPrompt(MyRequest request) {
        return "You said: " + request.prompt;
    }
}

3. Run Application

The application will automatically expose:

  • POST /invocations - Agent processing endpoint
  • GET /ping - Health check endpoint

Supported Method Signatures

Basic POJO Method

@AgentCoreInvocation
public MyResponse processRequest(MyRequest request) {
    return new MyResponse("Processed: " + request.prompt());
}

record MyRequest(String prompt) {}
record MyResponse(String message) {}

With AgentCore Context

@AgentCoreInvocation
public MyResponse processWithContext(MyRequest request, AgentCoreContext context) {
    var sessionId = context.getHeader(AgentCoreHeaders.SESSION_ID);
    return new MyResponse("Session " + sessionId + ": " + request.prompt());
}

Map Method (Flexible)

@AgentCoreInvocation
public Map<String, Object> processData(Map<String, Object> data) {
    return Map.of(
        "input", data,
        "response", "Processed: " + data.get("message"),
        "timestamp", System.currentTimeMillis()
    );
}

String Method (text/plain support)

@AgentCoreInvocation
public String handlePrompt(String prompt) {
    return "Response: " + prompt;
}

SSE Streaming with Spring AI

@AgentCoreInvocation
public Flux<String> streamingAgent(String prompt) {
    return chatClient.prompt().user(prompt).stream().content();
}

Configuration

The starter uses fixed configuration per AgentCore contract:

  • Port: 8080 (required by AgentCore)
  • Endpoints: /invocations, /ping (fixed paths)
  • Health Integration: Automatically integrates with Spring Boot Actuator when available

Health Monitoring

The /ping endpoint provides intelligent health monitoring:

Without Spring Boot Actuator:

  • Returns static "Healthy" status
  • Always responds with HTTP 200

With Spring Boot Actuator:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
  • Integrates with Actuator health checks
  • Maps Actuator status to AgentCore format:
    • UP → "Healthy" (HTTP 200)
    • DOWN → "Unhealthy" (HTTP 503)
    • Other → "Unknown" (HTTP 503)
  • Tracks status change timestamps
  • Thread-safe concurrent access

Background Task Tracking

AWS Bedrock AgentCore Runtime monitors agent health and may shut down agents that appear idle. When your agent starts long-running background tasks (like file processing, data analysis, or calling other long-running agents), the runtime needs to know the agent is still actively working to avoid premature termination.

The starter includes AgentCoreTaskTracker to communicate this state to the runtime:

@AgentCoreInvocation
public String asyncTaskHandling(MyRequest request, AgentCoreContext context) {
    agentCoreTaskTracker.increment();  // Tell runtime: "I'm starting background work"
    
    CompletableFuture.runAsync(() -> {
        // Long-running background work
    }).thenRun(agentCoreTaskTracker::decrement);  // Tell runtime: "Background work completed"
    
    return "Task started";
}

The '/ping' endpoint will return HealthyBusy while the AgentCoreTaskTracker is greater than 0.

How the Runtime Uses This Information:

  • "Healthy": Agent is ready, no background tasks → Runtime may scale down if idle
  • "HealthyBusy": Agent is healthy but actively processing → Runtime keeps agent alive
  • "Unhealthy": Agent has issues → Runtime may restart or replace agent

This prevents the runtime from shutting down your agent while it's processing important background work.

No additional configuration is required.

Rate Limiting

The starter includes built-in rate limiting using Bucket4j to protect against excessive requests. Rate limiting is deactivated by default and will be active only if limits are defined in properties.

Configuration:

# Customize rate limits in requests per minute (optional)
agentcore.throttle.invocations-limit=50
agentcore.throttle.ping-limit=200

Rate Limit Response (429):

{"error":"Rate limit exceeded"}

Rate limits are applied per client IP address and reset every minute.

API Reference

POST /invocations

Request (defined by user):

{
  "prompt": "Your prompt here"
}

Success Response (200) (defined by user):

{
  "response": "Agent response",
  "status": "success"
}

GET /ping

Response (200):

{
  "status": "Healthy",
  "time_of_last_update": 1697123456
}

Response (503) - When Actuator detects issues:

{
  "status": "Unhealthy", 
  "time_of_last_update": 1697123456
}

Custom Controller Override

The starter provides marker interfaces to override the default auto-configured controllers with custom implementations:

Override Invocations Controller

Implement AgentCoreInvocationsHandler to provide custom /invocations endpoint handling:

@RestController
public class CustomInvocationsController implements AgentCoreInvocationsHandler {
    
    @PostMapping("/invocations")
    public ResponseEntity<?> handleInvocations(@RequestBody String request) {
        // Custom invocation logic
        return ResponseEntity.ok("Custom response");
    }
}

Override Ping Controller

Implement AgentCorePingHandler to provide custom /ping endpoint handling:

@RestController
public class CustomPingController implements AgentCorePingHandler {
    
    @GetMapping("/ping")
    public ResponseEntity<?> ping() {
        // Custom health check logic
        return ResponseEntity.ok(Map.of("status", "Custom Healthy"));
    }
}

When these marker interfaces are implemented, the corresponding auto-configured controllers are automatically disabled.

See examples/spring-ai-override-invocations/ for a complete working example.

Examples

See the examples/ directory for complete working examples:

  • simple-spring-boot-app/ - Minimal AgentCore agent with async task tracking
  • spring-ai-sse-chat-client/ - SSE streaming with Spring AI and Amazon Bedrock
  • spring-ai-simple-chat-client/ - Traditional Spring AI integration (without AgentCore starter)
  • spring-ai-override-invocations/ - Custom controller override using marker interfaces

Requirements

  • Java 17+
  • Spring Boot 3.x
  • Maven or Gradle

License

This project is licensed under the Apache License 2.0.

About

Spring Boot integrations for Amazon Bedrock AgentCore

Topics

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published

Contributors 5

Languages