Claude Agent SDK

The Claude Code SDK provides Java integration with Anthropic’s Claude Code CLI, enabling autonomous coding capabilities in Spring applications.

1. Overview

Claude Code is Anthropic’s autonomous coding agent that can read, write, and execute code across entire codebases. The Spring AI Claude Code integration makes it easy to incorporate these capabilities into Java applications.

2. Installation

2.1. Prerequisites

  1. Install Claude Code CLI:

    npm install -g @anthropic-ai/claude-code
  2. Authentication (Choose one method):

    Option A: Session Authentication (Recommended):

    claude auth login

    Option B: API Key:

    export ANTHROPIC_API_KEY="your-api-key-here"

    Get your API key from the Anthropic Console.

    Session authentication is preferred to avoid conflicts between authentication methods.
  3. Verify Installation:

    claude --version

2.2. Maven Dependencies

Add the following dependencies to your pom.xml:

<dependencies>
    <!-- Core AgentClient API -->
    <dependency>
        <groupId>org.springaicommunity.agents</groupId>
        <artifactId>spring-ai-agent-client</artifactId>
        <version>0.1.0-SNAPSHOT</version>
    </dependency>

    <!-- Claude Code integration -->
    <dependency>
        <groupId>org.springaicommunity.agents</groupId>
        <artifactId>spring-ai-claude-agent</artifactId>
        <version>0.1.0-SNAPSHOT</version>
    </dependency>
</dependencies>

3. Basic Usage

3.1. Quick Start

import org.springaicommunity.agents.client.AgentClient;
import org.springaicommunity.agents.client.AgentClientResponse;
import org.springaicommunity.agents.claude.ClaudeAgentModel;
import org.springaicommunity.agents.claude.ClaudeAgentOptions;
import org.springaicommunity.agents.claude.sdk.ClaudeAgentClient;

import java.nio.file.Paths;

public class ClaudeCodeExample {
    public static void main(String[] args) {
        // 1. Create the Claude Code client
        ClaudeAgentClient claudeClient = ClaudeAgentClient.create(
            Paths.get(System.getProperty("user.dir"))
        );

        // 2. Configure agent options
        ClaudeAgentOptions options = ClaudeAgentOptions.builder()
            .model("claude-sonnet-4-20250514")
            .yolo(true)
            .build();

        // 3. Create the agent model
        ClaudeAgentModel agentModel = new ClaudeAgentModel(claudeClient, options);

        // 4. Create AgentClient
        AgentClient agentClient = AgentClient.create(agentModel);

        // 5. Execute a goal
        AgentClientResponse response = agentClient.run(
            "Create a simple Calculator class with add, subtract, multiply, and divide methods"
        );

        System.out.println("Result: " + response.getResult());
        System.out.println("Success: " + response.isSuccessful());
    }
}

4. Configuration

4.1. ClaudeAgentClient

The ClaudeAgentClient manages communication with the Claude CLI:

// Create with default working directory
ClaudeAgentClient client = ClaudeAgentClient.create();

// Create with specific working directory
Path projectPath = Paths.get("/path/to/project");
ClaudeAgentClient client = ClaudeAgentClient.create(projectPath);

// Create with custom Claude command path
ClaudeAgentClient client = ClaudeAgentClient.create(
    projectPath,
    "/custom/path/to/claude"
);

4.2. ClaudeAgentOptions

Configure Claude-specific behavior:

ClaudeAgentOptions options = ClaudeAgentOptions.builder()
    // Model selection
    .model("claude-sonnet-4-0")  // or "claude-haiku-4-0"

    // Execution settings
    .yolo(true)                           // Allow modifications
    .timeout(Duration.ofMinutes(10))      // Execution timeout
    .maxTokens(8192)                      // Response length limit

    // Output preferences
    .verbose(true)                        // Detailed logging
    .outputFormat("json")                 // Structured output

    .build();

4.3. Model Options

Available Claude models:

Model Description Best For

claude-sonnet-4-0

Latest Sonnet model with enhanced coding capabilities

Complex refactoring, large codebases, architectural changes

claude-haiku-4-0

Faster model optimized for speed

Quick fixes, simple tasks, rapid prototyping

claude-opus-4-0

Most capable model for complex reasoning

Complex algorithms, system design, challenging debugging

5. Advanced Features

5.1. Working Directory Management

Claude Code operates within a specific directory context:

// Configure working directory via client
ClaudeAgentClient client = ClaudeAgentClient.create(
    Paths.get("/path/to/microservice")
);

// Or via AgentClient fluent API
AgentClientResponse response = agentClient
    .goal("Add validation to the UserController")
    .workingDirectory("/path/to/microservice")
    .run();

5.2. YOLO Mode

Control whether Claude can make changes without confirmation:

// Development mode - allow changes
ClaudeAgentOptions devOptions = ClaudeAgentOptions.builder()
    .yolo(true)
    .build();

// Analysis mode - read-only
ClaudeAgentOptions analysisOptions = ClaudeAgentOptions.builder()
    .yolo(false)
    .build();

5.3. Timeout Configuration

Set appropriate timeouts for different goal complexities:

// Quick tasks
ClaudeAgentOptions quickOptions = ClaudeAgentOptions.builder()
    .timeout(Duration.ofMinutes(2))
    .build();

// Complex refactoring
ClaudeAgentOptions complexOptions = ClaudeAgentOptions.builder()
    .timeout(Duration.ofMinutes(30))
    .build();

6. Error Handling

6.1. Common Exceptions

try {
    AgentClientResponse response = agentClient.run("Complex refactoring goal");

    if (!response.isSuccessful()) {
        System.err.println("Goal failed: " + response.getResult());
    }

} catch (ClaudeCodeExecutionException e) {
    // Claude CLI process failed
    System.err.println("Claude execution error: " + e.getMessage());

} catch (ClaudeCodeNotFoundException e) {
    // Claude CLI not installed or not in PATH
    System.err.println("Claude CLI not found: " + e.getMessage());

} catch (AgentTimeoutException e) {
    // Goal exceeded configured timeout
    System.err.println("Goal timed out: " + e.getTimeout());

} catch (AgentAuthenticationException e) {
    // Invalid or missing API key
    System.err.println("Authentication failed: " + e.getMessage());
}

6.2. Validation and Recovery

@Service
public class ClaudeCodeService {

    private final AgentClient agentClient;

    public ClaudeCodeService(AgentClient agentClient) {
        this.agentClient = agentClient;
    }

    public String refactorCode(String className, String requirements) {
        // Validate inputs
        if (className == null || className.trim().isEmpty()) {
            throw new IllegalArgumentException("Class name is required");
        }

        try {
            // First, analyze the code
            AgentClientResponse analysis = agentClient
                .goal("Analyze " + className + " and suggest improvements")
                .yolo(false) // Read-only analysis
                .run();

            if (!analysis.isSuccessful()) {
                throw new ServiceException("Analysis failed: " + analysis.getResult());
            }

            // Then perform refactoring
            AgentClientResponse refactoring = agentClient
                .goal("Refactor " + className + " based on: " + requirements)
                .yolo(true) // Allow modifications
                .run();

            return refactoring.getResult();

        } catch (Exception e) {
            // Log error and return meaningful message
            log.error("Refactoring failed for class: {}", className, e);
            throw new ServiceException("Unable to refactor " + className + ": " + e.getMessage());
        }
    }
}

7. Spring Boot Integration

7.1. Auto-Configuration

Create a configuration class for Claude Code:

@Configuration
@ConditionalOnProperty(name = "spring.ai.agent.claude.enabled", havingValue = "true", matchIfMissing = true)
public class ClaudeCodeConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public ClaudeAgentClient claudeCodeClient(@Value("${spring.ai.agent.claude.working-directory:#{systemProperties['user.dir']}}") String workingDir) {
        return ClaudeAgentClient.create(Paths.get(workingDir));
    }

    @Bean
    @ConditionalOnMissingBean
    public ClaudeAgentModel claudeCodeAgentModel(
            ClaudeAgentClient client,
            ClaudeAgentOptions options) {
        return new ClaudeAgentModel(client, options);
    }

    @Bean
    @ConditionalOnMissingBean
    public ClaudeAgentOptions claudeCodeAgentOptions(ClaudeCodeProperties properties) {
        return ClaudeAgentOptions.builder()
            .model(properties.getModel())
            .yolo(properties.isYolo())
            .timeout(properties.getTimeout())
            .maxTokens(properties.getMaxTokens())
            .verbose(properties.isVerbose())
            .build();
    }

    @Bean
    public AgentClient agentClient(ClaudeAgentModel agentModel) {
        return AgentClient.create(agentModel);
    }
}

7.2. Application Properties

Configure Claude Code via application.yml:

spring:
  ai:
    agent:
      claude:
        enabled: true
        model: claude-sonnet-4-0
        working-directory: /path/to/project
        yolo: false
        timeout: PT10M
        max-tokens: 8192
        verbose: true

Or application.properties:

spring.ai.agent.claude.enabled=true
spring.ai.agent.claude.model=claude-sonnet-4-0
spring.ai.agent.claude.working-directory=/path/to/project
spring.ai.agent.claude.yolo=false
spring.ai.agent.claude.timeout=PT10M
spring.ai.agent.claude.max-tokens=8192
spring.ai.agent.claude.verbose=true

8. Best Practices

8.1. Goal Formulation

Write specific, actionable goals for Claude:

// Good: Specific and contextual
agentClient.run("Add input validation to UserController.createUser() method using Bean Validation annotations");

// Good: Clear scope and requirements
agentClient.run("Refactor PaymentService to use the Strategy pattern for different payment processors");

// Avoid: Vague requests
agentClient.run("Fix the code");

// Avoid: Overly broad scope
agentClient.run("Rewrite the entire application");

8.2. Security Considerations

Always be cautious with YOLO mode in production:

@Profile("development")
@Configuration
public class DevelopmentClaudeConfig {

    @Bean
    public ClaudeAgentOptions devClaudeOptions() {
        return ClaudeAgentOptions.builder()
            .yolo(true) // OK for development
            .build();
    }
}

@Profile("production")
@Configuration
public class ProductionClaudeConfig {

    @Bean
    public ClaudeAgentOptions prodClaudeOptions() {
        return ClaudeAgentOptions.builder()
            .yolo(false) // Safe for production
            .build();
    }
}

8.3. Resource Management

Monitor and limit resource usage:

@Component
public class ClaudeCodeMonitor {

    private final MeterRegistry meterRegistry;
    private final AgentClient agentClient;

    public ClaudeCodeMonitor(MeterRegistry meterRegistry, AgentClient agentClient) {
        this.meterRegistry = meterRegistry;
        this.agentClient = agentClient;
    }

    public String executeWithMetrics(String goal) {
        return Timer.Sample.start(meterRegistry)
            .stop(Timer.builder("claude.goal.duration")
                .tag("goal", goal.substring(0, Math.min(goal.length(), 50)))
                .register(meterRegistry))
            .recordCallable(() -> {
                Counter.builder("claude.goal.count").register(meterRegistry).increment();

                AgentClientResponse response = agentClient.run(goal);

                Counter.builder("claude.goal.result")
                    .tag("success", String.valueOf(response.isSuccessful()))
                    .register(meterRegistry)
                    .increment();

                return response.getResult();
            });
    }
}

9. Troubleshooting

9.1. Common Issues

Claude CLI Not Found

Ensure Claude is installed and in your PATH:

# Verify installation
claude --version

# Check PATH
which claude  # macOS/Linux
where claude  # Windows

# Reinstall if needed
npm install -g @anthropic-ai/claude-code

API Key Issues

Verify your API key configuration:

# Check environment variable
echo $ANTHROPIC_API_KEY

# Test with Claude CLI directly
claude --help

Permission Denied

Ensure proper file permissions in working directory:

# Check directory permissions
ls -la /path/to/project

# Fix if needed
chmod -R u+rw /path/to/project

Timeout Issues

Increase timeout for complex tasks:

ClaudeAgentOptions options = ClaudeAgentOptions.builder()
    .timeout(Duration.ofMinutes(30)) // Longer timeout
    .build();

9.2. Debugging

Enable verbose logging to troubleshoot issues:

ClaudeAgentOptions debugOptions = ClaudeAgentOptions.builder()
    .verbose(true)
    .build();

Add logging configuration:

logging:
  level:
    org.springaicommunity.agents.claude: DEBUG
    org.springaicommunity.agents.client: DEBUG

10. Next Steps