"""Built-in tool for switching the active agent profile mid-session."""
from navi.tools.base import Tool, ToolResult, current_event_sink, current_session_id
class SwitchProfileTool(Tool):
name = "switch_profile"
description = (
"Switch this session to a different agent profile. "
"Use when the task domain changes and another profile has better-suited tools or instructions. "
"The new profile (tools + system prompt) becomes active from the NEXT user message. "
"Always tell the user you switched and which profile is now active."
)
parameters = {
"type": "object",
"properties": {
"profile_id": {
"type": "string",
"description": "ID of the profile to switch to.",
}
},
"required": ["profile_id"],
}
def __init__(self, session_store, profile_registry) -> None:
self._sessions = session_store
self._profiles = profile_registry
async def execute(self, params: dict) -> ToolResult:
profile_id = (params.get("profile_id") or "").strip()
available = ", ".join(p.id for p in self._profiles.all())
try:
profile = self._profiles.get(profile_id)
except Exception:
return ToolResult(
success=False,
output="",
error=f"Profile '{profile_id}' not found. Available: {available}",
)
sid = current_session_id.get()
if not sid:
return ToolResult(success=False, output="", error="No active session context.")
session = await self._sessions.get(sid)
if session is None:
return ToolResult(success=False, output="", error="Session not found.")
if session.profile_id == profile_id:
return ToolResult(
success=True,
output=f"Already on profile '{profile.name}' — no change.",
)
session.profile_id = profile_id
await self._sessions.save(session)
# Notify the client immediately so it can update the UI.
sink = current_event_sink.get()
if sink is not None:
from navi.core.events import ProfileSwitched
await sink.put(ProfileSwitched(profile_id=profile_id, profile_name=profile.name))
return ToolResult(
success=True,
output=(
f"Switched to profile '{profile.name}' ({profile_id}). "
f"Its tools and system prompt are active from the next message."
),
)