| 2026-04-17 |
Fix subagent instruction conflicts across persona and profiles
...
Persona:
- Fix [STATUS: completed|limit_reached] reference (format was removed)
- Clarify three fields: task / briefing / system_prompt with distinct roles
- Clarify context_transfer vs briefing: transfer = working state, briefing = credentials
Secretary system_prompt:
- Replace vague "write all context to context_transfer" with explicit field breakdown
- task / briefing / system_prompt each described with their purpose
- context_transfer correctly limited to intermediate findings, not credentials
Server admin system_prompt:
- Same fix: explicit field breakdown for spawn_agent
- Remove dangling "see persona" reference for briefing ending
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 17 Apr
|
Subagent system prompt rework: separate from parent, briefing as system context
...
run_ephemeral:
- Add briefing param (passed from spawn_agent, injected into system prompt)
- Subagent system prompt is now completely separate from parent's system_prompt:
1. profile.subagent_system_prompt (executor persona)
2. custom_system_prompt (role specialisation for this task)
3. briefing (task context as system-level instruction)
Fallback to profile.system_prompt only if subagent_system_prompt is not defined
spawn_agent:
- task → user message only (the goal)
- briefing → system prompt (credentials, context, instructions)
- system_prompt → role specialisation injected alongside briefing
- Removed old user-message composition (## Context / ## Task split)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 17 Apr
|
Fix spawn_agent: restore briefing, fix status leakage, enable subagent planning
...
spawn_agent:
- Restore briefing param (task = goal, briefing = context — good separation)
- Add system_prompt as third param for role specialisation per task
- Remove [STATUS: ...] prefix that was leaking into Navi's responses and
causing hallucination — replaced with natural-language headers that are
less likely to be regurgitated verbatim
- completed → neutral header; limit_reached → explicit warning about incompleteness
Profiles:
- subagent_planning_enabled: false → true in all three profiles
(planning is on by default, disable per-profile if needed)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 17 Apr
|
Strengthen orchestration mandate: spawn first, inline last
...
secretary/server_admin system prompts:
- Explicit spawning rule: MUST spawn for any sub-task requiring 3+ tool calls
- Additional mandatory triggers listed (research, file processing, remote ops, large output)
- "If in doubt — spawn" as explicit fallback
- AGENT steps: "MANDATORY, never execute inline — defeats the orchestrator model"
- context_transfer pattern: write to scratchpad before spawning, injected automatically
persona.txt:
- Updated SUB-AGENT BRIEFING section: renamed to SUB-AGENTS
- Reflects new context_transfer automatic injection (no longer needs to be in task)
- Added: check [STATUS: ...] in result before deciding next action
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 17 Apr
|
Fix NameError in _run_planning: session.context → context after refactor
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 17 Apr
|

Improve subagent system: isolated tools, custom prompts, context transfer, timeout
...
AgentProfile:
- New fields: subagent_tools, subagent_planning_enabled, subagent_system_prompt
- loader.py: loads subagent_tools/subagent_planning_enabled from config.json,
reads optional subagent_system_prompt.txt per profile
Profiles:
- Each profile now has a dedicated subagent_tools list (focused subset, no admin tools)
- subagent_planning_enabled: false (configurable per profile)
- New subagent_system_prompt.txt per profile with executor-focused instructions
run_ephemeral:
- Uses profile.subagent_tools instead of enabled_tools
- Builds subagent context without persona or profiles block (focused executor)
- Injects subagent_system_prompt after profile.system_prompt
- Accepts context_transfer: priming exchange injected before task message
- Wall-clock timeout (default 5 min) checked per iteration
- Returns (result_text, completed: bool) instead of bare string
- Optionally runs planning phase if profile.subagent_planning_enabled
spawn_agent:
- Removed briefing param; task is now fully self-contained
- Added system_prompt param: custom injected prompt for this specific task
- Auto-reads parent scratchpad context_transfer section via get_section()
- Result prefixed with [STATUS: completed|limit_reached]
- Timeout 300s
scratchpad:
- Added get_section(session_id, section) helper for cross-session reads
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 17 Apr
|

Planning phases, context compression, and tool improvements
...
Agent:
- Planning now a 3-phase async generator: Analysis → Execution plan → AIHelper critic
- Yield PlanningStatus events before each phase (UI progress labels)
- Phase 1 runs with think=True for deeper analysis
- Phase 2 includes available tool list so executor assignments are accurate
- Phase 3: independent critic pass validates and corrects TOOL: names against real tool list
- Planning converted from list return to async generator (fixes token accounting)
Backend:
- Context compression threshold: 80% → 70% to trigger earlier
- Compressor summary prompt: structured sections (goal, work state, key facts, outputs, errors)
- Terminal output capped at 5000 chars to prevent context flooding
- Web search: region=wt-wt for DDG, country=ALL for Brave, language=all for SearxNG
- Scratchpad: mandate writing a 'goal' section at start of multi-step tasks
- secretary max_iterations: 40→25, temperature: 0.7→0.5
- server_admin max_iterations: 40→20
Webclient:
- ThinkingCard strips <thought> XML tags leaked by Ollama
- planning_status WS event wired to chat.onPlanningStatus()
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 17 Apr
|
Webclient UI improvements + backend fixes
...
Webclient:
- Draft persistence across page refreshes (localStorage, reactive watch)
- Image lightbox modal using UI kit classes on thumbnail click
- Copy button on user and assistant messages
- Selection reply toolbar: select assistant text → quote inserted into input
- User message rendering: proper HTML escaping, styled blockquote for > replies
- Markdown table fix: preprocessor to inject missing separator rows
- Planning status labels (rebuild dist)
Backend:
- Developer profile: enable subagent delegation, increase max_iterations to 35
- share_file: updated description + manual with absolute path requirement and URL sharing
- persona.txt: instructions for quote replies and GFM table format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 17 Apr
|
Audit and trim system prompts (~470 tokens saved)
...
persona.txt:
- Shortened personality paragraph (~30% cuts, no content loss)
- Removed duplicate list_tools instruction
- Removed hardcoded 'developer' profile rule (handled by dynamic profiles block)
- Condensed EXECUTION MODES fundamental blockers to one sentence
- Moved sub-agent briefing boilerplate here (single source of truth)
- Trimmed REFLECTION section (tool description handles the how)
- Removed redundant RESPONSE HYGIENE explanation sentence
- Moved 'never assume file exists' into EXECUTION DISCIPLINE
- Removed DOCUMENTATION section
profiles (all three):
- Replaced ~100-token sub-agent briefing boilerplate with pointer to persona
- developer: removed data persistence code block (covered by _template.py)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 17 Apr
|
reflect: force clarification when Detailer finds strategic ambiguity
...
Closing instruction now explicitly requires stopping to ask the user
if the Detailer identified ambiguities about core direction (what to
build, which approach, what the user actually wants). Prevents Navi
from using the Pragmatist's simplifications as an escape hatch when
the real problem is underspecified requirements.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 17 Apr
|
Add reflect tool: three parallel expert perspectives
...
ReflectTool runs Critic / Pragmatist / Detailer advisors concurrently
via asyncio.gather() + AIHelper.ask(). Each role has a distinct system
prompt designed to produce genuinely different analysis:
- Critic: challenges assumptions, surfaces risks and logical gaps
- Pragmatist: finds the simplest path, cuts unnecessary complexity
- Detailer: spots missing requirements, edge cases, ambiguities
Parameters: situation (required), assumptions (required list — the key
input that forces Navi to surface implicit beliefs), tried (optional).
Registered as a builtin with AIHelper injection. Added to all three
profiles. Persona updated with guidance on when to use it (complex or
ambiguous tasks before planning, or when stuck mid-execution).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 17 Apr
|
Add Prompts and Tools tabs to debug page
...
Backend:
- GET /agents/prompts — returns full built system prompt for every
profile, broken into sections (persona / profile / profiles block)
with char/token counts; mirrors Agent._build_system_prompt() exactly
- GET /agents/tools — now includes parameters schema alongside name
and description
Debug page:
- Tab bar: Context / Prompts / Tools
- Prompts tab: profile sidebar + collapsible sections per prompt part
(persona, profile prompt, profiles block), togglable tools list
- Tools tab: searchable list of all tools with description and
parameter table (name, type, description, required marker)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 17 Apr
|
Add standalone debug page at /debug
...
Replaces the old_webclient/debug.html with a proper self-contained
tool at debug/index.html. New features over the old page:
- Sidebar session list with profile, message count, pin indicator
- Auto-refresh toggle (3s interval)
- Refresh button
- Renders thinking blocks, is_plan and is_summary tags
- Shows tool call name on tool result messages
- Clickable image thumbnails (open full-size)
- All new fields from the current LLM context API
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 17 Apr
|
| 2026-04-16 |
Fix WS disconnect and missed stream on reconnect
...
Two related problems:
- During long AIHelper calls (non-streaming LLM), no data flows to the
WebSocket and browsers drop the connection after ~30-60s of inactivity.
Fixed with a 20s heartbeat: _stream_to_client now uses asyncio.wait_for
and sends {"type":"heartbeat"} on timeout to keep the connection alive.
- After reconnect, if the agent finished while the client was offline,
_runs no longer holds the session and no stream_start is sent. Client
would reconnect silently with no response shown. Fixed by sending
{"type":"session_sync"} on every new WS connection (after reattach
completes or immediately when no run is active) so the client knows
to reload session history.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 16 Apr
|
Count AIHelper tokens in session metrics
...
Adds prompt/completion token fields to LLMResponse, populated by
OllamaBackend.complete(). AIHelper emits AIHelperTokensUsed into the
current event sink after each LLM call; run_stream drains it into
_subagent_tokens so AIHelper usage is reflected in the turn token delta.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 16 Apr
|
Improve filesystem tool description: prioritize AI actions with examples
...
- Description now opens with explicit ALWAYS PREFER rule for query/smart_edit
- Each AI action has concrete examples (function lookup, renaming, config search)
- Standard actions demoted to 'use only when AI not applicable'
- question/instruction parameters include examples so the model understands
the full range of applicable cases
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 16 Apr
|

Add AIHelper + filesystem query/smart_edit AI actions
...
AIHelper (navi/core/ai_helper.py):
- Reusable LLM utility for AI-enhanced tools: ask() and ask_json()
- Reads current_model ContextVar (set per-turn) so tools always use
the session's active model without extra wiring
- Robust JSON extraction: strips markdown fences, bracket-matching fallback
current_model ContextVar (navi/tools/base.py):
- New ContextVar set by run_stream() and run_ephemeral() after profile
is resolved; AIHelper reads it to pick the right model automatically
filesystem query action:
- Natural language question about any file, chunked at ~20k tokens of
content (~80k chars) with 30-line overlap between chunks
- Single-chunk: one LLM call; multi-chunk: partial answers accumulated
then synthesized in a final call
filesystem smart_edit action:
- Natural language edit instruction on files up to ~200k chars
- LLM outputs JSON patch ops: replace / delete / insert (1-based lines)
- Ops validated then applied bottom-up to preserve line numbers
- Returns unified diff of changes; preserves trailing newline
registry: AIHelper created once, OllamaBackend reused (no double init),
FilesystemTool receives ai_helper at construction
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 16 Apr
|
Make profile switching autonomous: switch immediately, inform after
...
Previously Navi asked for permission before switching profiles.
Updated both the injected profiles block in the system prompt and the
switch_profile tool description to explicitly say: switch on your own
judgment, do not ask, then inform the user which profile is active and why.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 16 Apr
|
Add profile discoverability: list_profiles tool + system prompt injection
...
- AgentProfile: new short_description (1-line) and full_description (dict
with specialization / when_to_use / key_tools) fields
- All 3 profile configs: structured descriptions added; list_profiles added
to enabled_tools
- _build_system_prompt: now accepts full AgentProfile; injects compact
"Available profiles" block into every system prompt so Navi always knows
what other profiles exist and when to switch — dynamically, no hardcoding
- ListProfilesTool: new built-in; returns structured per-profile details
(specialization, when_to_use, key_tools); accepts optional profile_id
for single-profile lookup
- registry: register list_profiles_tool after profiles registry is built
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 16 Apr
|
Fix gmail auth: read credentials from settings, not os.environ
...
pydantic-settings loads .env only into the Settings object — it does not
populate os.environ. Added gmail_address and gmail_app_password fields to
Settings; gmail tool now reads from settings instead of os.environ.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 16 Apr
|
Persist context token count: return from API, restore on session load
...
- GET /sessions/{id} now returns context_token_count and max_context_tokens
(max pulled from settings.ollama_num_ctx)
- loadSession() in chat store sets contextTokens/maxContextTokens from the
response so ContextBar shows the last known fill level immediately on load,
not only after the first new message
- Restore v-if guard on ContextBar (hides for brand-new sessions with 0 tokens)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 16 Apr
|
Fix metrics: net token delta, subagent aggregation, ContextBar always visible
...
- run_stream: track _prev_tokens baseline before turn loop; compute net
token cost as (context_tokens - prev) + subagent_tokens for per-message cost
- run_stream: intercept SubagentComplete in sink drain loop to accumulate
subagent token and tool-call counts into the parent turn's totals
- run_ephemeral: already emitting SubagentComplete (from prior session)
- msg-meta-row: remove margin-left:auto from .msg-meta-time so time
groups inline with elapsed/tools/tokens instead of floating right
- ContextBar: remove v-if guard so bar is always visible (not only after
first LLM response with token data)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 16 Apr
|
Add response metrics: elapsed time, tool calls, token count
...
Server:
- Message model: elapsed_seconds, tool_call_count, token_count fields
(display-only, excluded from LLM context via exclude_none)
- StreamEnd event: carries same three fields
- agent.run_stream: tracks turn start time, counts ToolEvent completions,
writes metrics onto the final assistant Message before saving to DB
- WebSocket: forwards metrics in stream_end payload
Client:
- chat.onStreamEnd: attaches elapsed_seconds, tool_call_count, token_count
to the streaming message on completion
- buildMessageList: scans each assistant group for metrics from history
- AssistantMessage: renders .msg-meta-row below the response —
timer icon + Xs · wrench icon + N tools · coins icon + Nk tokens · time
(each item only shown if present; time pushed right via margin-left: auto)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 16 Apr
|

Add session name generation via LLM
...
Backend:
- Session model gets name: str | None field
- SQLite migration: ADD COLUMN name TEXT
- PostgreSQL: ADD COLUMN IF NOT EXISTS name TEXT (applied on pool init)
- SessionStore: add set_name() abstract method, implemented in all stores
- navi/core/name_generator.py: LLM worker that reads user messages and
returns a 3–6 word title or None if content isn't substantial yet
- POST /sessions/{id}/generate-name endpoint: fires LLM, saves and
returns name; skips if session already named or has no user messages
- GET /sessions and GET /sessions/{id} now include name field
Client:
- api.generateSessionName(id) — calls the new endpoint
- sessions store: updateName(id, name) mutation
- chat store: after stream_end, _tryGenerateName() runs fire-and-forget;
skips silently if session already has a name or if request fails
- SessionItem already displays session.name (falls back to id prefix)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 16 Apr
|
Migrate to Vue webclient; rename old client to old_webclient
...
- client/ → old_webclient/ (vanilla JS client preserved as reference)
- webclient/ — new Vue 3 + Pinia webclient (source + dist build)
- vite.config.js: outDir changed to webclient/dist/
- main.py: serve /assets and /images from webclient/dist/,
index.html from webclient/dist/index.html
- .gitignore: exclude webclient/node_modules/, include webclient/dist/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 16 Apr
|
Persist thinking and plan cards across session reloads
...
- Message: add thinking and is_plan fields (display-only, not sent to LLM)
- Agent main loop: accumulate thinking per iteration, save with assistant message
- _run_planning: also append plan to session.messages with is_plan=True so UI
can render plan cards after page reload (context already had the plan)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 16 Apr
|
| 2026-04-15 |
Fix Ollama connection leak and empty message bug in agent
...
- _iter_stream_guarded: track chunk_task as nullable, cancel in finally
block to prevent zombie HTTP connections accumulating under load
- Final turn: use `content or None` so empty text isn't saved to DB
- client/index.html: point to new Vue webclient build
- profiles: add email_manager tool
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 15 Apr
|
Add autonomous execution mode; clarify code_exec runs locally
...
persona.txt: EXECUTION MODES section — autonomous mode triggered by user phrase,
handles obstacles independently, only stops on fundamental blockers.
server_admin, developer profiles: explicit note that code_exec / terminal /
filesystem run on the LOCAL machine, never on remote hosts.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 15 Apr
|
Move orchestration from persona to profiles; tune per-profile delegation strategy
...
persona.txt now contains only: identity, profile switching, workspace,
response hygiene, memory, and documentation. All orchestration instructions
removed from the global scope.
Each profile gets its own orchestration model:
- secretary: full orchestrator — delegate any 2+ tool-call sub-task to agents,
scratchpad as blackboard, todo for milestone tracking
- server_admin: heavy orchestrator — one agent per host / per concern,
parallel delegation, diagnose-before-act discipline
- developer: builder + research delegation — implementation always inline,
spawn only for large API/codebase research tasks
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 15 Apr
|
Remove smart_home profile — to be re-added properly later
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 15 Apr
|