Amp Agent SDK

The Amp CLI SDK provides Java integration with Sourcegraph’s Amp CLI, enabling autonomous coding capabilities in Spring applications.

1. Overview

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

2. Installation

2.1. Prerequisites

  1. Install Amp CLI:

    Follow the installation instructions at ampcode.com.

  2. Authentication (Choose one method):

    Option A: Session Authentication (Recommended):

    amp login

    Option B: API Key:

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

    Get your API key from the Amp Settings.

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

    amp --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>

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

Or use the Spring Boot starter:

<dependency>
    <groupId>org.springaicommunity.agents</groupId>
    <artifactId>spring-ai-starter-agent-amp</artifactId>
    <version>0.1.0-SNAPSHOT</version>
</dependency>

3. Basic Usage

3.1. Quick Start

import org.springaicommunity.agents.client.AgentClient;
import org.springaicommunity.agents.client.AgentClientResponse;
import org.springaicommunity.agents.amp.AmpAgentModel;
import org.springaicommunity.agents.amp.AmpAgentOptions;
import org.springaicommunity.agents.ampsdk.AmpClient;

import java.nio.file.Paths;

public class AmpExample {
    public static void main(String[] args) {
        // 1. Create the Amp client
        AmpClient ampClient = AmpClient.create(
            Paths.get(System.getProperty("user.dir"))
        );

        // 2. Configure agent options
        AmpAgentOptions options = AmpAgentOptions.builder()
            .model("amp-default")
            .dangerouslyAllowAll(true)
            .build();

        // 3. Create the agent model
        AmpAgentModel agentModel = new AmpAgentModel(ampClient, 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. AmpClient

The AmpClient manages communication with the Amp CLI:

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

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

// Create with custom Amp CLI path
AmpClient client = AmpClient.create(
    projectPath,
    "/custom/path/to/amp"
);

4.2. AmpAgentOptions

Configure Amp-specific behavior:

AmpAgentOptions options = AmpAgentOptions.builder()
    // Model selection (currently only amp-default available)
    .model("amp-default")

    // Execution settings
    .dangerouslyAllowAll(true)            // Allow modifications
    .timeout(Duration.ofMinutes(10))      // Execution timeout

    // CLI path (for non-standard installations)
    .executablePath("/custom/path/to/amp")

    .build();

4.3. Model Options

Currently available models:

Model Description Best For

amp-default

Default Amp model with full coding capabilities

General-purpose coding tasks, refactoring, debugging

Amp uses Sourcegraph’s models optimized for code understanding and generation.

5. Advanced Features

5.1. Working Directory Management

Amp operates within a specific directory context:

// Configure working directory via client
AmpClient client = AmpClient.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. Autonomous Mode

Control whether Amp can make changes without confirmation:

// Development mode - allow changes
AmpAgentOptions devOptions = AmpAgentOptions.builder()
    .dangerouslyAllowAll(true)
    .build();

// Analysis mode - read-only
AmpAgentOptions analysisOptions = AmpAgentOptions.builder()
    .dangerouslyAllowAll(false)
    .build();
The dangerouslyAllowAll option allows Amp to execute commands and make file changes without prompting. Use with caution in production environments.

5.3. Timeout Configuration

Set appropriate timeouts for different goal complexities:

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

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

6. Error Handling

6.1. Common Exceptions

import org.springaicommunity.agents.ampsdk.exceptions.AmpSDKException;

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

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

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

} catch (RuntimeException e) {
    // Other runtime errors (timeout, etc.)
    System.err.println("Unexpected error: " + e.getMessage());
}

6.2. Validation and Recovery

@Service
public class AmpService {

    private final AgentClient agentClient;

    public AmpService(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")
                .options(AmpAgentOptions.builder()
                    .dangerouslyAllowAll(false) // Read-only
                    .build())
                .run();

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

            // Then perform refactoring
            AgentClientResponse refactoring = agentClient
                .goal("Refactor " + className + " based on: " + requirements)
                .options(AmpAgentOptions.builder()
                    .dangerouslyAllowAll(true) // Allow modifications
                    .build())
                .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

The Spring Boot starter provides automatic configuration:

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    // AmpClient, AmpAgentModel, and AgentClient are auto-configured

    @Bean
    public CommandLineRunner demo(AgentClient agentClient) {
        return args -> {
            AgentClientResponse response = agentClient.run(
                "Create a REST controller for managing users"
            );
            System.out.println(response.getResult());
        };
    }
}

7.2. Application Properties

Configure Amp via application.yml:

spring:
  ai:
    agents:
      amp:
        model: amp-default
        timeout: PT10M
        dangerously-allow-all: false
        executable-path: /custom/path/to/amp  # Optional

Or application.properties:

spring.ai.agents.amp.model=amp-default
spring.ai.agents.amp.timeout=PT10M
spring.ai.agents.amp.dangerously-allow-all=false
spring.ai.agents.amp.executable-path=/custom/path/to/amp

7.3. Custom Configuration

Override auto-configuration with custom beans:

@Configuration
public class AmpConfiguration {

    @Bean
    public AmpAgentOptions customAmpOptions() {
        return AmpAgentOptions.builder()
            .model("amp-default")
            .dangerouslyAllowAll(true)
            .timeout(Duration.ofMinutes(15))
            .build();
    }

    @Bean
    public AmpClient customAmpClient() {
        return AmpClient.create(
            Paths.get("/path/to/project"),
            "/custom/path/to/amp"
        );
    }
}

8. Best Practices

8.1. Goal Formulation

Write specific, actionable goals for Amp:

// 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 autonomous mode in production:

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

    @Bean
    public AmpAgentOptions devAmpOptions() {
        return AmpAgentOptions.builder()
            .dangerouslyAllowAll(true) // OK for development
            .build();
    }
}

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

    @Bean
    public AmpAgentOptions prodAmpOptions() {
        return AmpAgentOptions.builder()
            .dangerouslyAllowAll(false) // Safe for production
            .build();
    }
}

8.3. Resource Management

Monitor and limit resource usage:

@Component
public class AmpMonitor {

    private final MeterRegistry meterRegistry;
    private final AgentClient agentClient;

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

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

                AgentClientResponse response = agentClient.run(goal);

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

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

9. Troubleshooting

9.1. Common Issues

Amp CLI Not Found

Ensure Amp is installed and in your PATH:

# Verify installation
amp --version

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

# Set AMP_CLI_PATH for custom installation
export AMP_CLI_PATH=/path/to/amp

API Key Issues

Verify your API key configuration:

# Check environment variable
echo $AMP_API_KEY

# Test with Amp CLI directly
amp --help

# Or use session authentication
amp login

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:

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

Stdin Prompt Issues

Amp requires prompts to be passed via stdin (not command-line arguments). The SDK handles this automatically, but if you encounter issues:

# Test manually
echo "Create a file test.txt" | amp --dangerously-allow-all -x

9.2. Debugging

Enable debug logging to troubleshoot issues:

logging:
  level:
    org.springaicommunity.agents.amp: DEBUG
    org.springaicommunity.agents.ampsdk: DEBUG
    org.springaicommunity.agents.client: DEBUG

9.3. Environment Variables

Key environment variables for testing and configuration:

Variable Purpose

AMP_API_KEY

Amp API key for authentication (alternative to amp login)

AMP_CLI_PATH

Custom path to Amp CLI executable (for non-standard installations)

10. Differences from Claude Agent

If you’re familiar with the Claude Agent integration, note these differences:

Feature Claude Amp

Authentication

claude auth login or ANTHROPIC_API_KEY

amp login or AMP_API_KEY

Autonomous mode flag

yolo(true)

dangerouslyAllowAll(true)

Prompt passing

Command-line argument

Stdin (handled automatically by SDK)

Model selection

Multiple models (Sonnet, Haiku, Opus)

Currently amp-default only

Default timeout

5 minutes

3 minutes

11. Next Steps