Repository: harbor-framework/harbor
Issue: `--agent-import-path` is ignored when no `-a` agent is specified
Root cause: Configuration Error


## Summary

When using `--agent-import-path` to specify a custom agent without also passing `-a`, the custom agent is ignored and the default `oracle` agent is used instead.

## Steps to Reproduce

1. Create a custom agent in `agents/my_agent.py`:

```python
from harbor.agents.installed.claude_code import ClaudeCode

class MyCustomAgent(ClaudeCode):
    @staticmethod
    def name() -> str:
        return "my-custom-agent"
```

2. Run a trial with only `--agent-import-path`:

```bash
uv run harbor trials start \
    -p datasets/hello-world \
    --agent-import-path agents.my_agent:MyCustomAgent \
    -m anthropic/claude-sonnet-4-20250514
```

3. Observe the output shows `Agent: oracle` instead of the custom agent

## Expected Behavior

The custom agent specified via `--agent-import-path` should be used.

## Actual Behavior

The `oracle` agent is used, completely ignoring the `--agent-import-path` flag.

## Root Cause

The issue is in the interaction between the `AgentConfig` model validator and how the CLI updates the config.

### 1. Model Validator in `AgentConfig`

In `src/harbor/models/trial/config.py`:

```python
class AgentConfig(BaseModel):
    name: str | None = None
    import_path: str | None = None
    # ...

    @model_validator(mode="after")
    def set_default_name(self):
        if self.name is None and self.import_path is None:
            self.name = AgentName.ORACLE.value
        return self
```

When `TrialConfig` is first created (before CLI arguments are applied), both `name` and `import_path` are `None`, so the validator sets `name = "oracle"`.

### 2. CLI Updates Config After Creation

In `src/harbor/cli/trials.py`:

```python
if agent_name is not None:
    config.agent.name = agent_name
if agent_import_path is not None:
    config.agent.import_path = agent_import_path
```

When `--agent-import-path` is passed (but not `-a`), `agent_name` is `None` so it doesn't update `config.agent.name`. But `name` is already `"oracle"` from the validator.

### 3. Factory Prioritizes Name Over Import Path

In `src/harbor/agents/factory.py`:

```python
def create_agent_from_config(cls, config: AgentConfig, ...):
    if config.name is not None and config.name in AgentName.__members__.values():
        return cls.create_agent_from_name(...)  # Uses "oracle"
    elif config.import_path is not None:
        return cls.create_agent_from_import_path(...)  # Never reached!
```

Since `config.name` is `"oracle"` (a valid `AgentName`), the first branch executes and `import_path` is never used.

## Proposed Fix

In `src/harbor/cli/trials.py`, clear the `name` when `import_path` is set so that `import_path` takes precedence:

```python
if agent_import_path is not None:
    config.agent.import_path = agent_import_path
    config.agent.name = None  # Clear name so import_path takes precedence
```

The same fix should be verified for `src/harbor/cli/jobs.py`, though jobs.py creates new `AgentConfig` objects with both values in the constructor, so it may not have this issue.

## Workaround

Until fixed, users must pass an invalid agent name to skip the first branch in the factory, though this is not a practical workaround.

## Environment

- Harbor version: latest (as of 2024-12-21)
- Python: 3.11+