# Profiles

Profiles define the agent's identity, tools, and behaviour for a specific domain.

## Profile definition (`navi/profiles/base.py`)

```python
@dataclass
class AgentProfile:
    id: str                          # unique identifier (used in API, sessions, switch_profile)
    name: str                        # human-readable name
    description: str                 # shown in profile selector
    system_prompt: str               # domain-specific instructions
    enabled_tools: list[str]         # tool names available to this profile
    model: str = "..."               # Ollama model to use
    temperature: float = 0.7
    max_iterations: int = 50
    planning_enabled: bool = False   # whether to run the planning phase before the loop
    llm_backend: str = "ollama"      # backend key in BackendRegistry
```

## Built-in profiles

| Profile ID | Name | Model | Temperature | Planning |
|---|---|---|---|---|
| `secretary` | Personal Secretary | gemma4:26b-a4b-it-q4_K_M | 0.7 | Yes |
| `server_admin` | Server Administrator | gemma4:26b-a4b-it-q4_K_M | 0.2 | Yes |
| `smart_home` | Smart Home Assistant | gemma4:26b-a4b-it-q4_K_M | 0.3 | Yes |

All profiles have the same base tool set:
```
todo, scratchpad, switch_profile,
web_search, web_view, http_request,
filesystem, code_exec, terminal, ssh_exec, image_view,
memory_search, memory_forget,
reload_tools, write_tool, list_tools, tool_manual,
spawn_agent
```

User tools from `tools/enabled.json` are merged in on top of the profile's `enabled_tools` list.

## System prompt construction

The final system prompt the LLM sees is:

```
{NAVI_PERSONA}

---

{profile.system_prompt}
```

`NAVI_PERSONA` is the global personality layer — loaded from `settings.navi_persona` or `settings.navi_persona_file`. It contains: personality, self-extension rules, planning/scratchpad instructions, delegation guidance, memory rules.

`profile.system_prompt` is the domain-specific layer: tool priorities, workflow rules, scratchpad section names, safety rules for that domain.

The system message is **never stored** in `session.context`. It is injected fresh on every LLM call. Profile switches take effect immediately.

## Adding a new profile

1. Create `navi/profiles/my_profile.py`:
```python
from .base import AgentProfile

my_profile = AgentProfile(
    id="my_profile",
    name="My Profile",
    description="What this profile is for.",
    system_prompt="""Mode: ...

## Tool priorities
1. web_search — ...
2. filesystem — ...

## Scratchpad sections
- findings, errors, plan

## Safety rules
...""",
    enabled_tools=[
        "todo", "scratchpad", "switch_profile",
        "web_search", "filesystem", "code_exec",
        "memory_search", "memory_forget",
        "reload_tools", "write_tool", "list_tools", "tool_manual",
        "spawn_agent",
    ],
    model="gemma4:26b-a4b-it-q4_K_M",
    temperature=0.5,
    planning_enabled=True,
)
```

2. Register it in `navi/profiles/__init__.py`:
```python
from .my_profile import my_profile
ALL_PROFILES = [..., my_profile]
```

## Profile switching

`switch_profile` tool updates `session.profile_id` in the DB. In `run_stream()`, after each tool execution batch, the agent checks if `session.profile_id` changed and reloads profile + tools. The switch takes full effect on the next LLM call within the same run.

Rules from the persona:
- Don't switch for a single off-topic question.
- Switch when the session domain clearly changes (e.g. coding → server admin).
- Never switch back and forth repeatedly in one conversation.

## Per-profile scratchpad sections

Each profile defines named sections appropriate for its domain:

| Profile | Scratchpad sections |
|---|---|
| secretary | `findings`, `sources`, `drafts` |
| server_admin | `status`, `logs`, `errors`, `plan` |
| smart_home | `state`, `config`, `errors` |
