Skip to main content

Overview

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

Available Agents

AgentDescriptionBest For
aiderGit-centric diff-based editingGeneral purpose, default
geminiGoogle Gemini SDKFast generation
claude_codeAnthropic Claude Code CLIComplex refactoring
openhandsOpenHands with sandboxIsolated execution

Agent Interface

All agents implement CodingAgentInterface:
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

coding_agent:
  type: "aider"
  model: "gpt-4o-mini"
  debug_model: "gpt-4o-mini"

Usage

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
  • Bedrock integration option

Installation

npm install -g @anthropic-ai/claude-code

Configuration

coding_agent:
  type: "claude_code"
  model: "claude-sonnet-4-20250514"
  agent_specific:
    use_bedrock: false
    claude_md_path: "CLAUDE.md"

Bedrock Support

For AWS Bedrock:
coding_agent:
  type: "claude_code"
  agent_specific:
    use_bedrock: true
Set environment variables:
AWS_ACCESS_KEY_ID=...
AWS_SECRET_ACCESS_KEY=...
AWS_REGION=us-east-1

Gemini

Google Gemini SDK for fast generation.

Features

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

Configuration

coding_agent:
  type: "gemini"
  model: "gemini-2.0-flash"
  debug_model: "gemini-2.0-flash"
Set API key:
GOOGLE_API_KEY=your-google-api-key

OpenHands

OpenHands agent with sandboxed execution.
OpenHands has conflicting dependencies with aider-chat. Use a separate conda environment.

Installation

# 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

coding_agent:
  type: "openhands"
  model: "gpt-4o"
  agent_specific:
    sandbox_type: "docker"

CodingResult

All agents return a standardized result:
@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:
{
    "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:
@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

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:
def supports_native_git(self) -> bool:
    return True  # Aider auto-commits

Session-Managed Git (Others)

ExperimentSession commits after generation:
def supports_native_git(self) -> bool:
    return False  # Session will commit

Agent Capabilities

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

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)