Agent tools and MCP
Agent tools are managed by AgentService and used by ChatController when the Agent toggle is enabled.
Agent service
AgentService owns:
- A
SkillRegistry. - The selected skill set.
- Custom skills added by the user.
- A
SecretStorefor skills that require secrets. - Persisted MCP server configs.
- Per-session executor construction.
It is created once during app startup and injected through agentServiceProvider.
Skills
Bundled skills load from AssetSkillSource. Custom skills can be added from a URL that returns a SKILL.md file. The settings page fetches the content, parses it with parseSkillMd, and registers the skill.
Skill selections persist through SharedPreferences:
StorageKeys.selectedSkillsStorageKeys.customSkills
Secrets are stored through the agent secret store and are not injected into prompts.
Agent context
When agent tools are enabled, ChatController._buildAgentContext injects a compact tool instruction block into the system prompt.
The block includes:
- Selected skill names and descriptions.
- Instructions to call
loadSkillbefore using a skill. - Available MCP tools from enabled servers.
- JSON fence formats for tool calls.
If no selected skills and no enabled MCP tools exist, the agent context is empty.
Tool call format
The model requests tools with a fenced JSON block:
{"tool":"loadSkill","skillName":"<name>"}Other supported calls:
{"tool":"runSkill","skillName":"<name>","data":"<json>"}{"tool":"runIntent","intent":"<action>","parameters":"{}"}{"tool":"runMcp","toolName":"<name>","input":"{}"}The visible assistant message is cleaned before execution continues. The tool result is fed back into a continuation generation.
Skill execution
runSkill dispatches through an executor selected from AgentService.buildExecutors():
TextSkillExecutorNativeIntentExecutorJsSkillExecutorMcpSkillExecutor
Errors are shown in the agent progress panel and fed back to the model as tool failure text.
Native intents
runIntent uses NativeIntentExecutor from the agent package. Chat also has direct deterministic device routing for common commands such as timers, alarms, app launch, media control, and ringer mode.
Device actions run through DeviceActions and platform channels. Message, email, SMS, and calendar actions open system composer or confirmation surfaces instead of silently sending content.
MCP server configuration
The MCP settings page lets the user add a server URL and optional auth header. AgentService.addServer connects with McpClient, discovers tools, persists the connected config, and registers the server with the MCP executor.
Users can:
- Remove a server.
- Enable or disable each discovered tool.
- Enable
alwaysAllowper tool.
Server configs persist through StorageKeys.mcpServers.
MCP permission model
MCP tools do not execute by default just because the model asks for them. In chat, _dispatchMcpTool checks:
- The requested tool exists on an enabled server.
- The tool is enabled.
- The tool has
alwaysAllowset.
If alwaysAllow is not enabled, the controller returns a permission message that tells the user to enable the tool in Settings and retry the message. This avoids runtime permission dialogs from a controller that has no BuildContext.
Tool loop limit
The ReAct continuation loop is limited to two tool hops per assistant turn. This keeps local inference bounded and prevents uncontrolled tool chains.