| name | ha-settings |
| description | Manage Hope Agent application settings through conversation. Use when the user wants to view or change any app configuration: theme, language, enhanced focus indicators, proxy, temperature, notifications, tool timeout, context compaction, automatic session titles, web search, GitHub issue reporting, memory, embedding, multimodal embedding, dreaming (offline memory consolidation), recap, behavior awareness, smart-mode approvals, plan mode, ask-user-question timeout, tool-result disk spill threshold, embedded server, ACP control plane, MCP subsystem (kill switch / concurrency / backoff), per-skill env vars, or any other setting visible in the Settings UI. Trigger phrases: 'change settings', 'configure proxy', 'set theme to dark', 'turn on enhanced focus indicators', 'turn off notifications', 'adjust temperature', 'show my settings', 'bind the server to all interfaces', 'enable smart mode', 'tune dreaming', 'disable mcp', 'show my channels'. Trigger even when the user doesn't explicitly say 'settings' — any intent to adjust app behavior qualifies. |
| always | true |
Settings — Application Configuration Management
Use get_settings and update_settings to read and modify settings. Never edit config files directly. Coverage matches the desktop Settings UI one-to-one for everything that doesn't carry secrets. The GUI-only zones — Providers / API Keys, IM Channel accounts (channels), MCP server configs (mcp_servers), the active model selection (active_model / fallback_models), the embedding model selection for both memory and knowledge-base vector search (memory_embedding / knowledge_embedding — model choice carries a background reembed side effect, like active_model), the knowledge-base chunking parameters (knowledge_chunk — changing chunk size/overlap re-chunks and re-embeds every space, same heavy reindex side effect; tuned under Settings → Knowledge → Advanced), the credential/model-selection parts of Speech-to-Text (stt_providers / active_stt_model / stt_fallback_models; the non-secret stt_language remains writable), and the Hooks system (hooks) — are configured only in the Settings UI (memory vector search under Settings → Memory; knowledge vector search under Settings → Knowledge) so credentials stay out of conversation logs and the model can't grant itself command execution.
Risk Levels & Dual-Confirmation
Every response from get_settings / update_settings includes a riskLevel field. Follow this workflow strictly:
| Risk | Required before calling update_settings |
|---|
low | One-line summary of what you'll change is enough |
medium | Show current value → new value, then proceed if the user has asked for it |
high | MUST explicitly ask the user to confirm (e.g. "Are you sure you want to change X from A to B? This affects …"). Wait for explicit yes before writing. |
get_settings({ category: "all" }) returns a riskLevels map grouping every category.
If the response includes sideEffect, surface it to the user (e.g. "this requires an app restart").
Workflow
- Understand intent — what does the user want to view or change?
- Read current —
get_settings(category). Note riskLevel and sideEffect.
- Confirm — low: brief summary. medium: diff. high: explicit yes/no prompt.
- Apply —
update_settings(category, values) with partial JSON.
- Report — show the updated values and any side-effect note (e.g. restart needed).
Tool Usage
get_settings
{ "category": "theme" }
{ "category": "all" }
update_settings
{ "category": "theme", "values": { "theme": "dark" } }
values uses partial merge — only include fields you want to change.
Full Category Reference
LOW risk — cosmetic / preference, trivially reversible
| Category | Fields |
|---|
user | name, avatar, gender, birthday, role, timezone, language, aiExperience, responseStyle, customInfo, autoSendPending, autoExpandThinking, autoCollapseCompletedTurns, enterToSend (bool, default true; when false, Enter inserts a newline and Ctrl+Enter sends), chatDisplayMode, serverMode, remoteServerUrl, weatherEnabled, weatherCity, weatherLatitude, weatherLongitude. remoteApiKey is credential-bearing, read-only/redacted here, and must be changed in Settings → Server |
theme | theme (auto/light/dark) |
language | language (auto/zh/en/…) |
focus_indicator | enhancedFocusIndicators (bool, default false). Enables the stronger 2px focus outline for all input methods. When disabled, pointer/touch focus stays visually quiet while keyboard navigation keeps the lightweight focus indicator. System prefers-contrast: more and forced-colors modes still take precedence automatically. |
ui_effects | uiEffectsEnabled |
prevent_sleep | preventSleep (bool, default false). When true, the primary process keeps the host awake by holding an OS sleep assertion (macOS caffeinate -i / Linux logind inhibitor / Windows ES_SYSTEM_REQUIRED) so long-running tasks, downloads, and background work aren't interrupted by idle sleep. The display may still turn off; takes effect immediately, no restart needed. |
MEDIUM risk — behavioral changes (cost, context, output quality)
| Category | Fields |
|---|
design | Design Space (侧边栏「设计空间」): enabled (master toggle), autoShow (auto-focus the preview after the agent generates an artifact), autoCritique (run a 5-dimension quality review before finalizing — incurs one extra model call, hence MEDIUM), selfCheck (anti-AI-slop heuristics), defaultSystemId (design-system id new artifacts fall back to when neither the artifact nor its project specifies one; empty = none), maxVersionsPerArtifact (default 50, [1,500]), panelWidth (default 480), maxExtractImageMb (image-size cap for screenshot reverse-extraction, MB; default 24, 0 = unlimited), exportScale (rasterization clarity multiplier for PNG/PDF/PPTX export; default 2, [1,4]), exportJpegQuality (JPEG quality for PDF pages, 1–100; default 92, clamped [40,100]), lastModel (the design model selector's last-picked vision model — behavioral memory updated implicitly by the picker, not normally hand-edited). Design generation / critique ride the shared function_models.automation chain; image paths (screenshot extraction, image-referenced generation) now use automation::run_vision with either the model picked in the design UI's selector or the default chain — decoupled from function_models.vision (that config is the chat vision bridge's alone now). Models are configured in Settings → Models; design systems, projects and artifacts are managed in the GUI, not here. |
compact | Master: enabled, cacheTtlSecs (default 300, max 900). Trim ratios: softTrimRatio (default 0.50), hardClearRatio (default 0.70), summarizationThreshold (default 0.85); load-time validation enforces soft < hard < summary. Reactive microcompact: reactiveMicrocompactEnabled (default true), reactiveTriggerRatio (default 0.75, range 0.50–0.95). Tool-result trimming: toolPolicies (HashMap mapping tool name → eager/protect), maxToolResultContextShare (default 0.3, range 0.1–0.6), (default 20000), / / (default 6000/2000/2000), , . Recent boundary: (default 4, range 1–12; protects recent message rounds, expands to the owning user turn only when that does not swallow prior execution rounds). Tier 3 summary: (provider:model override), (default 300, range 10–600), (default 4096, range 256–32768), (default 0.5), (default 16000, range 4000–64000), (default 0.5, clamped to ; combined budget for summary + ledger + recovery), (//), , . Recovery: , (default 5), (default 16384). |
HIGH risk — require explicit user confirmation
| Category | Fields | Why high risk |
|---|
proxy | mode, url | Affects ALL outgoing HTTP |
shortcuts | bindings (array) | Global OS keybindings, can collide |
skills | extraSkillsDirs, disabledSkills, skillEnvCheck, allowRemoteInstall | Disabling skills removes tools; allowRemoteInstall opens the HTTP /api/skills/{name}/install route that spawns brew/npm -g/go install/uv tool install — effectively RCE over the API Key |
acp_control | enabled, backends (each: id, name, binary, acpArgs, enabled, defaultModel, env), maxConcurrentSessions, defaultTimeoutSecs, runtimeTtlSecs, autoDiscover. Read responses redact non-empty backends[*].env to "[REDACTED]" because env frequently carries ANTHROPIC_API_KEY / OPENAI_API_KEY overrides. | Controls external agent delegation |
skill_env | Per-skill env vars (may contain secrets) | Stored plaintext in config.json |
security.ssrf | defaultPolicy (strict/default/allowPrivate), trustedHosts (array), per-tool overrides browserPolicy / webFetchPolicy / imageGeneratePolicy / urlPreviewPolicy | Controls whether tools can reach private networks / cloud metadata. Relaxing policy or adding untrusted hosts enables SSRF attack paths |
Read-only (cannot be modified via this tool)
| Category | Description |
|---|
active_model | Current primary model — use Settings UI |
fallback_models | Fallback chain — use Settings UI |
embedding | Active memory-embedding config. Read resolves the currently-selected model from the shared embedding_models library + memory_embedding selection (the same source the GUI and runtime use) and returns enabled / providerType / apiBaseUrl / apiModel / apiDimensions with apiKey redacted ("[REDACTED]"); a disabled selection reads as enabled:false. Writes are GUI-only (Settings → Memory) — the model choice carries an API key and a heavy background reembed side effect, same class as active_model / memory_embedding / knowledge_embedding. |
channels | IM Channel accounts (Telegram / WeChat / Feishu / QQ / Discord). Read returns the account list with credentials and settings fields redacted ("[REDACTED]"); structural metadata (id, channelId, label, enabled, agentId, autoApproveTools, security) is exposed so the model can reference accounts without seeing bot tokens. Writes must go through Settings → Channels so the registry can drop/re-establish listeners under user supervision and credentials stay out of conversation logs. |
mcp_servers | MCP server configs. Read returns the server list with env, headers, oauth fields redacted. Writes must go through Settings → MCP Servers UI which enforces "trust acknowledgement" for stdio servers and routes credentials through platform::write_secure_file (0600). |
server | Server bind/public URL metadata plus legacy apiKey state. Reads redact every non-empty as . Writes are GUI-only because the live Owner Token is stored separately in the 0600 credential store and must be changed through the dedicated rotate/save flow; writing the legacy config field would leak a credential into conversation history without rotating active authentication. |
Model / Provider / API Key / Server authentication / IM Channel accounts / MCP server configs / STT providers / per-session configs require the Settings UI.
Special: teams Semantics
Unlike every other category, teams does not live in AppConfig — it targets rows in the team_templates SQLite table. The update_settings payload is CRUD-shaped:
{
"category": "teams",
"values": {
"action": "save",
"template": {
"templateId": "fullstack-py-react",
"name": "Full-Stack (Py + React)",
"description": "Frontend (React expert) + Backend (Python expert) + Tester",
"members": [
{
"name": "Frontend",
"role": "worker",
"agentId": "react-expert",
"color": "#3B82F6",
"description": "You are the frontend specialist. Build React components with TS.",
"modelOverride":
read returns the full TeamTemplate[] — no values needed.
templateId must be non-empty and unique. Each member's agentId must point to an existing Agent (check list_agents in the Agents panel).
- Deleting a template does not touch any teams that were created from it;
teams.template_id is a historical reference only.
- EventBus broadcasts
template_saved / template_deleted so the UI refreshes live.
Special: skill_env Update Modes
Because per-skill env vars are a nested map, update_settings("skill_env", …) accepts three patch forms:
{ "skillEnv": { "my-skill": { "API_KEY": "xyz" } } }
{ "set": { "my-skill": { "API_KEY": "xyz", "OLD_VAR": null } } }
{ "remove": ["my-skill"] }
Prefer form 2 for targeted edits so you don't overwrite unrelated skills.
Rollback — Every Change Is Reversible
Every write to config.json / user.json — from this tool, the UI, or any other path — automatically snapshots the pre-change file under ~/.hope-agent/backups/autosave/. Last 50 snapshots retained.
list_settings_backups
{ "limit": 10 }
{ "kind": "config" }
Returns {id, timestamp, kind, category, source} newest first.
restore_settings_backup
{ "id": "2026-04-17T10-30-45-123__config__theme__skill" }
- Always HIGH risk — must confirm with the user before calling. Show them the entry's
timestamp, kind, and category.
- Creates a fresh snapshot of the current state first, so the rollback itself is reversible — you can "undo the undo" by restoring the newly-created entry.
- Restoring a
config entry reloads the in-memory cache immediately; server / shortcuts style side effects still apply and may need a restart.
When to proactively offer rollback
- User says "undo that", "revert", "go back", "you broke X" after a recent change.
- User complains about a specific behavior right after you changed a related setting.
- User asks "what did you change?" — list the last few entries to remind them.
Important Notes
- Read before write — always
get_settings first so you can show a diff.
- Confirm before write — especially HIGH risk. Include the risk level in your confirmation prompt.
- Field names are camelCase (e.g.
softRatio, toolTimeout, approvalTimeoutEnabled, askUserQuestionTimeoutEnabled, askUserQuestionTimeoutSecs).
- Security restrictions — cannot modify Providers or API Keys through this tool, including
user.remoteApiKey; guide the user to the Settings UI.
- Surface side effects — if the response has
sideEffect (e.g. "requires restart"), tell the user.
- Secrets in logs — never echo
apiKey, remoteApiKey, or skill_env values back in chat unless the user explicitly asks. Note that get_settings for user / server / web_search / media_generation / acp_control / embedding already redacts the credential fields to "[REDACTED]" — if you see that marker, the field is set but the value is hidden from the model intentionally.
- Rollback is built-in — if a change goes wrong, offer
restore_settings_backup instead of trying to reconstruct the old values manually.