> ## Documentation Index
> Fetch the complete documentation index at: https://docs.leeroo.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Coding Agents

> Pluggable code generation backends

## Overview

Coding agents are responsible for generating and modifying code based on prompts. Kapso supports multiple agents, each with different strengths.

## Available Agents

| Agent         | Description                    | Best For                 |
| ------------- | ------------------------------ | ------------------------ |
| `aider`       | Git-centric diff-based editing | General purpose, default |
| `gemini`      | Google Gemini SDK              | Fast generation          |
| `claude_code` | Anthropic Claude Code CLI      | Complex refactoring      |
| `openhands`   | OpenHands with sandbox         | Isolated execution       |

## Agent Interface

All agents implement `CodingAgentInterface`:

```python theme={null}
class CodingAgentInterface(ABC):
    def initialize(self, workspace: str) -> None:
        """Initialize for a specific workspace."""

    def generate_code(self, prompt: str, debug_mode: bool = False) -> CodingResult:
        """Generate or modify code based on prompt."""

    def cleanup(self) -> None:
        """Clean up resources."""

    def get_cumulative_cost(self) -> float:
        """Return total cost accumulated."""

    def supports_native_git(self) -> bool:
        """Return True if agent handles its own commits."""
```

## Aider (Default)

Git-centric pair programming with diff-based editing.

### Features

* Automatic git commits
* Diff-based file editing
* Context-aware code understanding
* Cost tracking

### Configuration

```yaml theme={null}
coding_agent:
  type: "aider"
  model: "gpt-4o-mini"
  debug_model: "gpt-4o-mini"
```

### Usage

```python theme={null}
from kapso.execution.coding_agents.factory import CodingAgentFactory

config = CodingAgentFactory.build_config(
    agent_type="aider",
    model="gpt-4o-mini",
)

agent = CodingAgentFactory.create(config)
agent.initialize("/path/to/workspace")

result = agent.generate_code("Implement a sorting algorithm")
print(f"Files changed: {result.files_changed}")
print(f"Cost: ${result.cost:.4f}")
```

## Claude Code

Anthropic's Claude Code CLI for complex tasks.

### Features

* Advanced reasoning
* Complex refactoring
* MCP tool support
* Explicit OAuth, Anthropic API-key, and AWS Bedrock authentication

### Installation

```bash theme={null}
npm install -g @anthropic-ai/claude-code
```

### Configuration

```yaml theme={null}
coding_agent:
  type: "claude_code"
  model: "claude-sonnet-4-20250514"
  agent_specific:
    auth_mode: "auto"
    claude_md_path: "CLAUDE.md"
```

`auth_mode` accepts four values:

| Mode      | Credential source                                       | Behavior                                                     |
| --------- | ------------------------------------------------------- | ------------------------------------------------------------ |
| `auto`    | AWS, then `ANTHROPIC_API_KEY`, then Claude CLI OAuth    | Selects the first available source in that order             |
| `bedrock` | Bedrock bearer token, AWS access keys, or `AWS_PROFILE` | Validates AWS credentials and sets the Bedrock provider flag |
| `api_key` | `ANTHROPIC_API_KEY`                                     | Requires direct Anthropic API credentials                    |
| `oauth`   | `CLAUDE_CODE_OAUTH_TOKEN` or `claude auth login`        | Uses the current user's Claude CLI subscription login        |

The low-level Claude Code adapter defaults to `auto`. Kapso's generic search
presets continue to default to `bedrock`, so upgrading does not silently switch
an existing AWS experiment to a developer's local subscription.

Explicit modes remove conflicting provider flags and higher-precedence
credentials from the Claude subprocess environment. For example, `oauth`
ignores an inherited `ANTHROPIC_API_KEY`, while `api_key` ignores an inherited
Bedrock flag. The parent process environment is never modified.

### OAuth

Authenticate the local Claude CLI, then choose `oauth`:

```bash theme={null}
claude auth login
claude auth status
```

```yaml theme={null}
coding_agent:
  type: "claude_code"
  model: "claude-opus-4-6"
  agent_specific:
    auth_mode: "oauth"
```

For a non-interactive environment, `CLAUDE_CODE_OAUTH_TOKEN` is also accepted.
See Anthropic's [authentication documentation](https://code.claude.com/docs/en/authentication)
for token setup and the terms that apply to subscription credentials.

### Anthropic API key

```bash theme={null}
export ANTHROPIC_API_KEY=...
```

```yaml theme={null}
coding_agent:
  type: "claude_code"
  model: "claude-opus-4-6"
  agent_specific:
    auth_mode: "api_key"
```

### AWS Bedrock

For AWS Bedrock:

```yaml theme={null}
coding_agent:
  type: "claude_code"
  model: "us.anthropic.claude-opus-4-6-v1"
  agent_specific:
    auth_mode: "bedrock"
    aws_region: "us-east-1"
```

Set one supported AWS credential source and a region:

```bash theme={null}
AWS_ACCESS_KEY_ID=...
AWS_SECRET_ACCESS_KEY=...
AWS_REGION=us-east-1
```

`AWS_BEARER_TOKEN_BEDROCK` or `AWS_PROFILE` can be used instead of access keys.

### Compatibility migration

`use_bedrock` remains supported for one compatibility period and emits a
`DeprecationWarning`:

```yaml theme={null}
agent_specific:
  use_bedrock: true   # same as auth_mode: bedrock
  # use_bedrock: false  # same as auth_mode: api_key
```

When both keys are present, `auth_mode` wins. New configurations should only
use `auth_mode`.

## Gemini

Google Gemini SDK for fast generation.

### Features

* Fast response times
* Good for iterative refinement
* Cost-effective

### Configuration

```yaml theme={null}
coding_agent:
  type: "gemini"
  model: "gemini-2.0-flash"
  debug_model: "gemini-2.0-flash"
```

Set API key:

```bash theme={null}
GOOGLE_API_KEY=your-google-api-key
```

## OpenHands

OpenHands agent with sandboxed execution.

<Warning>
  OpenHands has conflicting dependencies with `aider-chat`. Use a **separate conda environment**.
</Warning>

### Installation

```bash theme={null}
# Create separate environment
conda create -n openhands_env python=3.12
conda activate openhands_env
pip install openhands-ai litellm
```

### Features

* Sandboxed execution
* Docker-based isolation
* Full system access in sandbox

### Configuration

```yaml theme={null}
coding_agent:
  type: "openhands"
  model: "gpt-4o"
  agent_specific:
    sandbox_type: "docker"
```

## CodingResult

All agents return a standardized result:

```python theme={null}
@dataclass
class CodingResult:
    success: bool           # Whether generation succeeded
    output: str             # Agent's response text
    files_changed: List[str]  # Modified files
    error: Optional[str]    # Error message if failed
    cost: float             # Cost in dollars
    commit_message: Optional[str]  # Agent-generated message
    metadata: Dict[str, Any]  # Agent-specific data
```

## Structured JSON Output

When used with `kapso.evolve()`, the developer agent must return a structured JSON at the end of its response:

```json theme={null}
{
    "code_changes_summary": "Brief description of changes made",
    "evaluation_script_path": "kapso_evaluation/evaluate.py",
    "evaluation_output": "Full output from running evaluation"
}
```

This JSON is extracted by the search strategy and used by the feedback generator to validate results and decide whether to continue.

### Example Agent Output

````
I've implemented the random forest classifier. Here's what I did:

1. Created main.py with the classifier implementation
2. Added data loading and preprocessing
3. Created kapso_evaluation/evaluate.py to test accuracy

Running evaluation...
Loading data...
Training model...
Accuracy: 0.92

```json
{
    "code_changes_summary": "Implemented random forest classifier with GridSearchCV for hyperparameter tuning. Added cross-validation and accuracy reporting.",
    "evaluation_script_path": "kapso_evaluation/evaluate.py",
    "evaluation_output": "Loading data...\nTraining model...\nAccuracy: 0.92"
}
````

````

## Feedback Generator Role

Coding agents also power the feedback generator. The default feedback generator uses `claude_code`, but any agent can be used:

```python
from kapso.execution.feedback_generator import FeedbackGenerator
from kapso.execution.coding_agents.factory import CodingAgentFactory

# Use gemini for feedback generation
config = CodingAgentFactory.build_config(
    agent_type="gemini",
    model="gemini-2.0-flash",
)

feedback_gen = FeedbackGenerator(coding_agent_config=config)
````

## CodingAgentConfig

Configuration passed to agents:

```python theme={null}
@dataclass
class CodingAgentConfig:
    agent_type: str         # "aider", "gemini", etc.
    model: str              # Primary model
    debug_model: str        # Model for debugging
    workspace: str = ""     # Working directory
    use_git: bool = True    # Git integration
    agent_specific: Dict[str, Any] = field(default_factory=dict)
```

## Creating Custom Agents

```python theme={null}
from kapso.execution.coding_agents.base import CodingAgentInterface, CodingResult
from kapso.execution.coding_agents.factory import register_agent

@register_agent("my_custom_agent")
class MyCustomAgent(CodingAgentInterface):
    def initialize(self, workspace: str) -> None:
        self.workspace = workspace
        # Setup agent

    def generate_code(self, prompt: str, debug_mode: bool = False) -> CodingResult:
        # Generate code
        model = self.config.debug_model if debug_mode else self.config.model

        # Call your API
        response = my_api.generate(prompt, model=model)

        # Track cost
        self._cumulative_cost += response.cost

        return CodingResult(
            success=True,
            output=response.text,
            files_changed=response.files,
            cost=response.cost,
        )

    def cleanup(self) -> None:
        # Clean up resources
        pass

    def supports_native_git(self) -> bool:
        return False  # Let ExperimentSession handle commits
```

## Git Integration

Agents can handle git in two ways:

### Native Git (Aider)

Agent commits changes automatically:

```python theme={null}
def supports_native_git(self) -> bool:
    return True  # Aider auto-commits
```

### Session-Managed Git (Others)

ExperimentSession commits after generation:

```python theme={null}
def supports_native_git(self) -> bool:
    return False  # Session will commit
```

## Agent Capabilities

```python theme={null}
def get_capabilities(self) -> Dict[str, bool]:
    return {
        "native_git": self.supports_native_git(),
        "sandbox": False,
        "planning_mode": False,
        "cost_tracking": True,
        "streaming": False,
    }
```

## Listing Agents

```bash theme={null}
PYTHONPATH=. python -m src.cli --list-agents
```

Output:

```
Available Coding Agents:
==================================================
  aider: Git-centric pair programming with diff-based editing
  gemini: Google Gemini SDK for code generation
  claude_code: Anthropic Claude Code CLI for complex refactoring
  openhands: OpenHands agent with sandboxed execution (separate env required)
```
