Newer
Older
navi-1 / docs / profiles.md

Profiles

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

Profile definition (navi/profiles/base.py)

Each profile is loaded from a directory under navi/profiles/<id>/:

  • config.json — all fields below
  • system_prompt.txt — domain-specific instructions
  • subagent_system_prompt.txt — injected into subagents spawned from this profile (optional)

All config.json fields

Identity

Key Type Default Description
id str required Unique profile identifier (matches directory name)
name str required Human-readable name shown in UI
description str required Longer description shown in profile picker
short_description str "" One-line summary injected into every profile's system prompt (cross-profile awareness)
full_description dict {} Structured dict: specialization, when_to_use, key_tools keys

LLM

Key Type Default Description
llm_backend str "ollama" Backend key: "ollama", "openai"
model str or list[str] ["gemma4:31b-cloud"] Model priority list — first available wins. String is accepted and auto-wrapped.
temperature float 0.7 Sampling temperature for main loop calls
max_iterations int 10 Hard cap on tool-calling iterations per turn
top_k int \ None None Ollama sampling top_k
top_p float \ None None Ollama sampling top_p
num_thread int \ None None CPU threads for local inference. None = Ollama default

Tools

Key Type Default Description
tools ToolConfig {} Required. Explicit tool configuration with two scopes: agent and subagent. Each scope has native: list[str] (built-in and user tool names) and mcp: dict[str, list[str]] (MCP server groups).

tools.agent controls what the main loop sees. tools.subagent controls what sub-agents spawned from this profile see. If tools.subagent is empty, it falls back to tools.agent.

spawn_agent may receive an optional profile_id. If omitted, the subagent uses the parent session's current profile. If provided, the subagent uses the selected profile's model, prompt, planning flags, and tools.subagent fallback.

MCP tool groups

Inside tools.{agent,subagent}.mcp, each key is an MCP server name and each value is a list of group names (or "*" for all groups). Named groups resolve to concrete tools via the server's config in mcp_servers.d/. Example:

{
  "mcp": {
    "navi-web": ["search", "browse", "request"]
  }
}

This exposes the tools mcp__navi-web__web_search, mcp__navi-web__web_view, and mcp__navi-web__http_request. * expands to every tool advertised by that server.

Deprecated tool fields

Older configs used enabled_tools, subagent_tools, and mcp_servers as flat top-level fields. The loader still auto-migrates them into tools.agent / tools.subagent for backward compatibility, but new profiles should use the explicit tools structure.

When tools.subagent is non-empty, only MCP groups listed there are exposed to the sub-agent. This prevents a profile's main MCP servers from leaking into restricted sub-agent contexts.

Thinking mechanics

Key Type Default Description
think_enabled bool true Pass think=True to LLM on every call (extended reasoning). Disable for latency-sensitive profiles.
iteration_budget_enabled bool true Inject remaining iteration count into context so the model knows when to wrap up.
goal_anchoring_enabled bool true Inject a goal-reminder system message every N iterations to prevent drift.
goal_anchoring_interval int 5 N for goal anchoring.
anti_stall_enabled bool true Detect looping without todo progress and inject a hard warning.
anti_stall_threshold int 8 Consecutive iterations without progress before stall warning fires.
step_validation_enabled bool false Reserved flag — todo validation is unconditional in the current implementation.

Bounded autonomy

One flag keeps an autonomous agent inside the user's literally requested scope. Defaults false (legacy "free flight" behavior — explore broadly, finish discovered work). Enabled on navi_code.

Key Type Default Description
scope_boundary_enabled bool false Inject a standing [Scope boundary] system message telling the agent to act strictly within the requested scope — do not expand to sibling/parent directories or projects, and do not execute discovered TODO/roadmap/milestone/backlog docs unless explicitly asked. Also gates the memory-facts scope filter (see below).

The memory-facts scope filter: when scope_boundary_enabled is on, _memory_facts_msg drops memory facts whose value is an absolute path outside the session cwd (e.g. a stale project_root pointing at another project). Facts inside the session cwd and non-path facts are kept. No facts are deleted — only injection is filtered. See docs/mechanics.md.

Planning

Top-level planning is agent-invoked: the agent calls the plan tool when a task warrants it (add it to tools.agent.native). There is no pre-turn gate — free conversation and trivial tasks execute immediately. The pipeline has two phases:

  • Phase 1 — Analysis: reformulates the task, identifies subtasks and unknowns, classifies COMPLEXITY: simple | medium | complex. Sub-agents can output DIRECT to skip planning for trivial subtasks (the shortcut is never offered at top level).
  • Phase 3 — Execution plan: assigns each subtask to TOOL / AGENT / SELF and uses adaptive plan depth.

When the plan is ready, the tool result tells the agent what to do next based on COMPLEXITY: complex — present the plan to the user and wait for confirmation; otherwise — proceed with execution. A re-plan is the same tool called with a reason (and optional updated_goal); it packs the current todo and scratchpad findings into the planning context and replaces the todo.

Key Type Default Description
planning_phase1_enabled bool true Enable Phase 1 (task analysis). When disabled, Phase 3 runs without analysis context.
planning_phase3_enabled bool true Enable Phase 3 (structured execution plan). When disabled, only Phase 1 (analysis) runs.

Sub-agent planning

Key Type Default Description
subagent_think_enabled bool \ None None Extended reasoning for sub-agents. None = inherit think_enabled from parent profile.
subagent_planning_enabled bool false Sub-agents spawned from this profile also run the planning pipeline before their tool loop.
context_providers list[str] [] Extra context providers to inject for this profile (by name). Global providers are always injected.
is_admin_only bool false If true, profile is hidden from non-admin users in the profile list.
is_subagent_only bool false If true, profile can only be used via spawn_agent; switch_profile is blocked. Useful for narrow specialist agents that should never become the main session profile.

Compression

Per-profile overrides for context compression. When set, they take precedence over the global settings (CONTEXT_KEEP_RECENT, CONTEXT_SUMMARY_MAX_TOKENS) inside compress_context / compress_session and the summary system prompt. The active profile is propagated to the compressor via Agent.set_profile() and to the post-turn CompressionWorker via WorkerContext.profile.

Key Type Default Description
compression_keep_recent int \ None None Override CONTEXT_KEEP_RECENT — number of recent turns kept verbatim. navi_code uses 12.
compression_max_tokens int \ None None Override CONTEXT_SUMMARY_MAX_TOKENS — max output tokens for the summary LLM call.
compression_prompt_file str \ None None Extra instructions appended to the summary system prompt (loaded from the profile dir).

See sessions.md for the full compression algorithm and mechanics.md for the catalog.

Sub-agent system prompt

Key Type Default Description
subagent_system_prompt str "" Inline sub-agent system prompt. If empty, the loader reads subagent_system_prompt.txt from the profile directory. Prepended on top of the parent's system_prompt when inherit_system_prompt=True.

Unknown keys

AgentProfile uses model_config = {"extra": "allow"}, so unknown keys in config.json are accepted and preserved (round-tripped through the admin panel's GET/PUT) rather than rejected. This lets profiles carry custom metadata without code changes. |


Active profiles

ID Name Models (priority order) Temp Planning
secretary Personal Secretary gemma4:31b-cloud, qwen3.5:397b-cloud, kimi-k2.6:cloud, gemma4:26b-a4b-it-q4_K_M, qwen3.6:27b 0.45 Yes
server_admin Server Administrator gemma4:31b-cloud → gemma4:26b-a4b-it-q4_K_M 0.3 Yes
developer Developer gemma4:31b-cloud, qwen3.5:397b-cloud, kimi-k2.6:cloud, gemma4:26b-a4b-it-q4_K_M, qwen3.6:27b 0.35 Yes
tool_developer Tool Developer gemma4:31b-cloud → gemma4:26b-a4b-it-q4_K_M 0.35 Yes
discuss Discussion gemma4:31b-cloud → gemma4:26b-a4b-it-q4_K_M 0.85 No
modeler_3d 3D Modeler gemma4:26b-a4b-it-q4_K_M → gemma4:31b-cloud 0.35 Yes
navi_code Navi Code gemma4:26b-a4b-it-q4_K_M → gemma4:31b-cloud 0.35 Yes

All profiles share a base tool set. User tools from tools/enabled.json are merged in at runtime.

navi_code

Terminal-first local coding assistant. Designed for the Navi Code CLI and single-user local deployments:

  • Native tools: todo, scratchpad, reflect, plan, switch_profile, list_profiles, filesystem, code_exec, terminal, image_view, ssh_exec, memory, list_tools, tool_manual, spawn_agent, schedule_recall, manage_recall.
  • MCP tools: navi-web (search, browse, request) — web lookup and page browsing.
  • Excluded: share_file, content_publish, gmail.
  • Planning: Phase 1 and Phase 3 enabled; the plan tool is in the native tool set, so the agent plans deliberately when a task warrants it. Phase 1 classifies COMPLEXITY: simple | medium | complex — complex tasks get "present the plan and wait for confirmation".
  • Bounded autonomy: scope_boundary_enabled is true — the agent stays within the requested scope (does not climb to sibling projects or execute discovered milestone/TODO docs). Flip it off to reproduce the legacy "free flight" behavior.
  • Safety: an authoritative backend permission gate for destructive tool calls is specified in permissions.md (designed, not yet implemented). The old prompt-level "confirm before destructive ops" nudge and the client-side permission dialog were removed.

Use it with NAVI_DEFAULT_PROFILE_ID=navi_code so POST /sessions without a profile_id creates a navi_code session automatically. See docs/navi_code.md for the full local-terminal setup.


System prompt construction

The LLM sees (injected fresh on every call, never stored in session):

{persona.txt content}

---

{profile system_prompt.txt content}

persona.txt — global layer: personality, CONTEXT FIRST principle, self-extension rules, scratchpad/todo/memory instructions, delegation rules.

system_prompt.txt — domain layer: tool priorities, workflow, safety rules for this profile.


Adding a profile

  1. Create directory navi/profiles/my_profile/
  2. Add config.json (minimal example):
    {
    "id": "my_profile",
    "name": "My Profile",
    "description": "...",
    "short_description": "...",
    "model": ["gemma4:31b-cloud", "gemma4:26b-a4b-it-q4_K_M"],
    "temperature": 0.5,
    "max_iterations": 20,
    "tools": {
     "agent": {
       "native": ["todo", "scratchpad", "plan", "filesystem", "terminal"],
       "mcp": {
         "navi-web": ["search"]
       }
     },
     "subagent": {
       "native": ["todo", "filesystem", "terminal"],
       "mcp": {}
     }
    },
    "planning_phase1_enabled": true,
    "planning_phase3_enabled": true,
    "think_enabled": true,
    "iteration_budget_enabled": true,
    "goal_anchoring_enabled": true,
    "goal_anchoring_interval": 5,
    "anti_stall_enabled": true,
    "anti_stall_threshold": 8,
    "step_validation_enabled": false,
    "scope_boundary_enabled": false,
    "subagent_planning_enabled": false
    }
  3. Add system_prompt.txt with domain-specific instructions.
  4. Optionally add subagent_system_prompt.txt.
  5. The profile is auto-discovered at startup — no registration needed.

Profile switching

switch_profile tool updates session.profile_id in the DB. After each tool execution batch, run_stream() checks for a profile change and reloads profile + tools. Takes effect on the next LLM call.

Rules (in persona): don't switch for a single off-topic question; switch when the domain clearly changes; never switch back and forth repeatedly.