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
-
Install Claude Code CLI:
npm install -g @anthropic-ai/claude-code
-
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. -
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 |
---|---|---|
|
Latest Sonnet model with enhanced coding capabilities |
Complex refactoring, large codebases, architectural changes |
|
Faster model optimized for speed |
Quick fixes, simple tasks, rapid prototyping |
|
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();
10. Next Steps
-
Learn about other agent integrations in Gemini CLI SDK
-
See practical examples in Sample Agents
-
Compare with the standard API in AgentClient vs ChatClient