> ## 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.

# Search Strategies

> How solutions are explored and selected

## Overview

Search strategies control how Kapso explores the solution space. They generate solution candidates, run experiments, and track results.

## Available Strategies

| Strategy                | Description                                             | Best For                |
| ----------------------- | ------------------------------------------------------- | ----------------------- |
| `generic`               | Claude Code + MCP gates for ideation and implementation | General problem solving |
| `benchmark_tree_search` | Tree-based exploration with handler evaluation          | MLE-Bench, ALE-Bench    |

## Generic Search

The main strategy for general problem solving. Uses Claude Code with MCP gates for both ideation and implementation.

```mermaid theme={null}
flowchart LR
    A[Generate Solution via MCP] --> B[Implement Code]
    B --> C[Run & Evaluate]
    C --> D[Generate Feedback]
    D --> A
```

### Configuration

```yaml theme={null}
search_strategy:
  type: "generic"
  params:
    idea_generation_model: "us.anthropic.claude-opus-4-5-20251101-v1:0"
    implementation_model: "us.anthropic.claude-opus-4-5-20251101-v1:0"
    auth_mode: "bedrock"
    parent_policy: "best"
    aws_region: "us-east-1"
    gate_failure_policy: "warn"
    ideation_timeout: 300
    implementation_timeout: 600
    ideation_gates: ["research", "experiment_history", "repo_memory", "leeroopedia"]
    implementation_gates: ["research", "repo_memory", "leeroopedia"]
```

The generic strategy deliberately keeps `bedrock` as its default authentication
profile. Set `auth_mode` to `auto`, `api_key`, or `oauth` to opt into another
Claude Code credential source. The deprecated `use_bedrock` boolean is still
accepted for compatibility.

Gate requirements are checked before each agent is configured. `warn` (the
default) removes unavailable gates and logs a warning, `skip` removes them
silently, and `error` stops configuration. Unknown gate names always fail. See
[Capability-Aware MCP Gates](/docs/evolve/mcp-gates).

`parent_policy` controls experiment lineage. `best` (the default) refines the
best valid candidate; `baseline` starts every candidate from `main`. Ideation
reads from a detached worktree of that same selected ref, so its code and
RepoMemory context match the implementation base. See
[Parent Selection](/docs/evolve/parent-selection) for lineage and resume
semantics.

### Usage

```python theme={null}
from kapso.execution.search_strategies import SearchStrategyFactory

strategy = SearchStrategyFactory.create(
    strategy_type="generic",
    problem_handler=handler,
    llm=llm,
    coding_agent_config=config,
    params={"ideation_timeout": 300},
)

strategy.run(context, budget_progress=0.0)
best = strategy.get_best_experiment()
```

### MCP Gates

The generic strategy uses MCP gates for external knowledge access:

| Gate                 | Tools                                                                                                                                                    | Purpose                                                            |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| `research`           | `research_*`                                                                                                                                             | Deep research capabilities                                         |
| `experiment_history` | `get_top_experiments`, `get_recent_experiments`, `search_similar_experiments`                                                                            | Learn from past experiments                                        |
| `repo_memory`        | `get_repo_memory_section`, `list_repo_memory_sections`, `get_repo_memory_summary`                                                                        | Repository understanding                                           |
| `leeroopedia`        | `search_knowledge`, `build_plan`, `review_plan`, `verify_code_math`, `diagnose_failure`, `propose_hypothesis`, `query_hyperparameter_priors`, `get_page` | Curated ML/AI knowledge via [Leeroopedia](https://leeroopedia.com) |

## Benchmark Tree Search

Advanced strategy for benchmarks that explores solutions as a tree structure.

```mermaid theme={null}
flowchart TB
    ROOT["Root"]
    N1["Node 1: Approach A"]
    N2["Node 2: Approach B"]
    N3["Node 3: A + optimization"]
    N4["Node 4: A + different data"]

    ROOT --> N1
    ROOT --> N2
    N1 --> N3
    N1 --> N4

    N3 -.->|"best: 0.92"| BEST["Best Result"]
```

### Algorithm

Each iteration:

1. **Prune**: Remove unpromising solutions (after 20% budget)
2. **Expand**: Generate new child solutions from selected nodes
3. **Select**: Pick best nodes to experiment with
4. **Run**: Execute experiments in parallel

```python theme={null}
def run(self, context, budget_progress):
    # Prune after initial exploration
    if budget_progress >= 20:
        self.prune_bad_solutions(context)

    # Expand nodes with new solutions
    self.expand(context, budget_progress)

    # Select best nodes to experiment
    best_nodes = self.select(
        context,
        top_k=experiments_count,
        exclude_experimented_nodes=True
    )

    # Run experiments in parallel
    with ThreadPoolExecutor() as executor:
        for node in best_nodes:
            executor.submit(self._run_for_node, node, context, branch_name)
```

### Configuration

```yaml theme={null}
search_strategy:
  type: "benchmark_tree_search"
  params:
    reasoning_effort: "medium"
    code_debug_tries: 5
    node_expansion_limit: 2
    node_expansion_new_childs_count: 5
    idea_generation_steps: 1
    first_experiment_factor: 1
    experimentation_per_run: 1
    per_step_maximum_solution_count: 10
    exploration_budget_percent: 30
    idea_generation_model: "gpt-4o-mini"
```

### Parameters

| Parameter                         | Default        | Description                       |
| --------------------------------- | -------------- | --------------------------------- |
| `node_expansion_limit`            | 2              | Nodes to expand per iteration     |
| `node_expansion_new_childs_count` | 5              | Solutions generated per expansion |
| `code_debug_tries`                | 5              | Max debug attempts per solution   |
| `exploration_budget_percent`      | 30             | When to switch to exploitation    |
| `idea_generation_model`           | `gpt-4.1-mini` | Model for solution generation     |
| `experimentation_per_run`         | 1              | Experiments per iteration         |
| `first_experiment_factor`         | 1              | Multiplier for first iteration    |

### Exploration vs Exploitation

```mermaid theme={null}
flowchart LR
    subgraph Exploration["Exploration (0-30%)"]
        E1["Diverse solutions"]
        E2["LLM selects by potential"]
    end

    subgraph Exploitation["Exploitation (30-100%)"]
        X1["Focus on top scorers"]
        X2["Refine best solutions"]
    end

    Exploration -->|"budget > 30%"| Exploitation
```

## Node Structure (SearchNode)

```python theme={null}
@dataclass
class SearchNode:
    node_id: int
    parent_node_id: Optional[int] = None
    
    # Step 1: Solution generation
    solution: str = ""
    
    # Step 2: Implementation
    branch_name: str = ""
    code_changes_summary: str = ""
    
    # Step 3: Evaluation
    evaluation_script_path: str = ""
    evaluation_output: str = ""
    
    # Step 4: Feedback
    feedback: str = ""
    score: Optional[float] = None
    should_stop: bool = False
    evaluation_valid: bool = True
    
    # Metadata
    had_error: bool = False
    error_message: str = ""
    workspace_dir: str = ""
```

## Strategy Comparison

| Strategy                | Evaluation        | Stop Decision                | Use Case           |
| ----------------------- | ----------------- | ---------------------------- | ------------------ |
| `generic`               | Agent-built       | Feedback generator           | `kapso.evolve()`   |
| `benchmark_tree_search` | Handler's `run()` | Handler's `stop_condition()` | MLE/ALE benchmarks |

## Creating Custom Strategies

```python theme={null}
from kapso.execution.search_strategies.base import SearchStrategy
from kapso.execution.search_strategies.factory import register_strategy

@register_strategy("my_custom_search")
class MyCustomSearch(SearchStrategy):
    def __init__(self, config, workspace_dir=None):
        super().__init__(config, workspace_dir)
        # Custom initialization

    def run(self, context, budget_progress=0.0):
        # Generate and run experiments
        solution = self.generate_solution(context)
        result = self._implement(
            solution, context,
            branch_name="experiment_0",
        )
        self.node_history.append(result)

    def get_experiment_history(self, best_last=False):
        if best_last:
            return sorted(self.node_history, key=lambda x: x.score)
        return self.node_history

    def get_best_experiment(self):
        valid = [e for e in self.node_history if not e.had_error]
        return max(valid, key=lambda x: x.score) if valid else None

    def checkout_to_best_experiment_branch(self):
        best = self.get_best_experiment()
        if best:
            self.workspace.switch_branch(best.branch_name)
```
