diff --git a/website/docs/reference/cli-commands.md b/website/docs/reference/cli-commands.md index b6062454c4..bc9e3afca1 100644 --- a/website/docs/reference/cli-commands.md +++ b/website/docs/reference/cli-commands.md @@ -67,7 +67,7 @@ Common options: | `-q`, `--query "..."` | One-shot, non-interactive prompt. | | `-m`, `--model ` | Override the model for this run. | | `-t`, `--toolsets ` | Enable a comma-separated set of toolsets. | -| `--provider ` | Force a provider: `auto`, `openrouter`, `nous`, `openai-codex`, `copilot`, `copilot-acp`, `anthropic`, `huggingface`, `zai`, `kimi-coding`, `minimax`, `minimax-cn`, `kilocode`. | +| `--provider ` | Force a provider: `auto`, `openrouter`, `nous`, `openai-codex`, `copilot`, `copilot-acp`, `anthropic`, `huggingface`, `alibaba`, `zai`, `kimi-coding`, `minimax`, `minimax-cn`, `kilocode`. | | `-s`, `--skills ` | Preload one or more skills for the session (can be repeated or comma-separated). | | `-v`, `--verbose` | Verbose output. | | `-Q`, `--quiet` | Programmatic mode: suppress banner/spinner/tool previews. | diff --git a/website/docs/reference/environment-variables.md b/website/docs/reference/environment-variables.md index 939a02132f..315b6a39bb 100644 --- a/website/docs/reference/environment-variables.md +++ b/website/docs/reference/environment-variables.md @@ -42,7 +42,7 @@ All variables go in `~/.hermes/.env`. You can also set them with `hermes config | `ANTHROPIC_API_KEY` | Anthropic Console API key ([console.anthropic.com](https://console.anthropic.com/)) | | `ANTHROPIC_TOKEN` | Manual or legacy Anthropic OAuth/setup-token override | | `DASHSCOPE_API_KEY` | Alibaba Cloud DashScope API key for Qwen models ([modelstudio.console.alibabacloud.com](https://modelstudio.console.alibabacloud.com/)) | -| `DASHSCOPE_BASE_URL` | Custom DashScope base URL (default: international endpoint) | +| `DASHSCOPE_BASE_URL` | Custom DashScope base URL (default: `https://coding-intl.dashscope.aliyuncs.com/v1`) | | `DEEPSEEK_API_KEY` | DeepSeek API key for direct DeepSeek access ([platform.deepseek.com](https://platform.deepseek.com/api_keys)) | | `DEEPSEEK_BASE_URL` | Custom DeepSeek API base URL | | `OPENCODE_ZEN_API_KEY` | OpenCode Zen API key — pay-as-you-go access to curated models ([opencode.ai](https://opencode.ai/auth)) | diff --git a/website/docs/reference/toolsets-reference.md b/website/docs/reference/toolsets-reference.md index bb1813379f..7e8651b54f 100644 --- a/website/docs/reference/toolsets-reference.md +++ b/website/docs/reference/toolsets-reference.md @@ -19,10 +19,14 @@ Toolsets are named bundles of tools that you can enable with `hermes chat --tool | `file` | core | `patch`, `read_file`, `search_files`, `write_file` | | `hermes-acp` | platform | `browser_back`, `browser_click`, `browser_close`, `browser_console`, `browser_get_images`, `browser_navigate`, `browser_press`, `browser_scroll`, `browser_snapshot`, `browser_type`, `browser_vision`, `delegate_task`, `execute_code`, `memory`, `patch`, `process`, `read_file`, `search_files`, `session_search`, `skill_manage`, `skill_view`, `skills_list`, `terminal`, `todo`, `vision_analyze`, `web_extract`, `web_search`, `write_file` | | `hermes-cli` | platform | `browser_back`, `browser_click`, `browser_close`, `browser_console`, `browser_get_images`, `browser_navigate`, `browser_press`, `browser_scroll`, `browser_snapshot`, `browser_type`, `browser_vision`, `clarify`, `cronjob`, `delegate_task`, `execute_code`, `ha_call_service`, `ha_get_state`, `ha_list_entities`, `ha_list_services`, `honcho_conclude`, `honcho_context`, `honcho_profile`, `honcho_search`, `image_generate`, `memory`, `mixture_of_agents`, `patch`, `process`, `read_file`, `search_files`, `send_message`, `session_search`, `skill_manage`, `skill_view`, `skills_list`, `terminal`, `text_to_speech`, `todo`, `vision_analyze`, `web_extract`, `web_search`, `write_file` | +| `hermes-api-server` | platform | _(same as hermes-cli)_ | +| `hermes-dingtalk` | platform | _(same as hermes-cli)_ | | `hermes-discord` | platform | _(same as hermes-cli)_ | | `hermes-email` | platform | _(same as hermes-cli)_ | | `hermes-gateway` | composite | Union of all messaging platform toolsets | | `hermes-homeassistant` | platform | _(same as hermes-cli)_ | +| `hermes-matrix` | platform | _(same as hermes-cli)_ | +| `hermes-mattermost` | platform | _(same as hermes-cli)_ | | `hermes-signal` | platform | _(same as hermes-cli)_ | | `hermes-slack` | platform | _(same as hermes-cli)_ | | `hermes-sms` | platform | _(same as hermes-cli)_ | diff --git a/website/docs/user-guide/configuration.md b/website/docs/user-guide/configuration.md index 3ebe0f2686..17f15dc5c4 100644 --- a/website/docs/user-guide/configuration.md +++ b/website/docs/user-guide/configuration.md @@ -216,7 +216,7 @@ hermes chat --provider minimax-cn --model MiniMax-M2.7 # Requires: MINIMAX_CN_API_KEY in ~/.hermes/.env # Alibaba Cloud / DashScope (Qwen models) -hermes chat --provider alibaba --model qwen-plus +hermes chat --provider alibaba --model qwen3.5-plus # Requires: DASHSCOPE_API_KEY in ~/.hermes/.env ``` @@ -1026,6 +1026,7 @@ auxiliary: model: "" # e.g. "google/gemini-2.5-flash" base_url: "" api_key: "" + timeout: 30 # seconds # Dangerous command approval classifier approval: @@ -1033,8 +1034,17 @@ auxiliary: model: "" base_url: "" api_key: "" + timeout: 30 # seconds + + # Context compression timeout (separate from compression.* config) + compression: + timeout: 120 # seconds — compression summarizes long conversations, needs more time ``` +:::tip +Each auxiliary task has a configurable `timeout` (in seconds). Defaults: vision 30s, web_extract 30s, approval 30s, compression 120s. Increase these if you use slow local models for auxiliary tasks. +::: + :::info Context compression has its own top-level `compression:` block with `summary_provider`, `summary_model`, and `summary_base_url` — see [Context Compression](#context-compression) above. The fallback model uses a `fallback_model:` block — see [Fallback Model](#fallback-model) above. All three follow the same provider/model/base_url pattern. ::: @@ -1166,6 +1176,24 @@ You can also change the reasoning effort at runtime with the `/reasoning` comman /reasoning hide # Hide model thinking ``` +## Tool-Use Enforcement + +Some models (especially GPT-family) occasionally describe intended actions as text instead of making tool calls. Tool-use enforcement injects guidance that steers the model back to actually calling tools. + +```yaml +agent: + tool_use_enforcement: "auto" # "auto" | true | false | ["model-substring", ...] +``` + +| Value | Behavior | +|-------|----------| +| `"auto"` (default) | Enabled for GPT models (`gpt-`, `openai/gpt-`) and disabled for all others. | +| `true` | Always enabled for all models. | +| `false` | Always disabled. | +| `["gpt-", "o1-", "custom-model"]` | Enabled only for models whose name contains one of the listed substrings. | + +When enabled, the system prompt includes guidance reminding the model to make actual tool calls rather than describing what it would do. This is transparent to the user and has no effect on models that already use tools reliably. + ## TTS Configuration ```yaml diff --git a/website/docs/user-guide/features/api-server.md b/website/docs/user-guide/features/api-server.md index 3fab67441e..6739ad7abc 100644 --- a/website/docs/user-guide/features/api-server.md +++ b/website/docs/user-guide/features/api-server.md @@ -154,7 +154,7 @@ Lists `hermes-agent` as an available model. Required by most frontends for model ### GET /health -Health check. Returns `{"status": "ok"}`. +Health check. Returns `{"status": "ok"}`. Also available at **GET /v1/health** for OpenAI-compatible clients that expect the `/v1/` prefix. ## System Prompt Handling @@ -199,6 +199,12 @@ The default bind address (`127.0.0.1`) is for local-only use. Browser access is # config.yaml support coming in a future release. ``` +## Security Headers + +All responses include security headers: +- `X-Content-Type-Options: nosniff` — prevents MIME type sniffing +- `Referrer-Policy: no-referrer` — prevents referrer leakage + ## CORS The API server does **not** enable browser CORS by default. @@ -209,6 +215,11 @@ For direct browser access, set an explicit allowlist: API_SERVER_CORS_ORIGINS=http://localhost:3000,http://127.0.0.1:3000 ``` +When CORS is enabled: +- **Preflight responses** include `Access-Control-Max-Age: 600` (10 minute cache) +- **SSE streaming responses** include CORS headers so browser EventSource clients work correctly +- **`Idempotency-Key`** is an allowed request header — clients can send it for deduplication (responses are cached by key for 5 minutes) + Most documented frontends such as Open WebUI connect server-to-server and do not need CORS at all. ## Compatible Frontends diff --git a/website/docs/user-guide/features/fallback-providers.md b/website/docs/user-guide/features/fallback-providers.md index c149eee946..e46f69e35c 100644 --- a/website/docs/user-guide/features/fallback-providers.md +++ b/website/docs/user-guide/features/fallback-providers.md @@ -44,6 +44,7 @@ Both `provider` and `model` are **required**. If either is missing, the fallback | MiniMax | `minimax` | `MINIMAX_API_KEY` | | MiniMax (China) | `minimax-cn` | `MINIMAX_CN_API_KEY` | | Kilo Code | `kilocode` | `KILOCODE_API_KEY` | +| Alibaba / DashScope | `alibaba` | `DASHSCOPE_API_KEY` | | Hugging Face | `huggingface` | `HF_TOKEN` | | Custom endpoint | `custom` | `base_url` + `api_key_env` (see below) | diff --git a/website/docs/user-guide/features/hooks.md b/website/docs/user-guide/features/hooks.md index 272ea9ceaf..0ae8905dea 100644 --- a/website/docs/user-guide/features/hooks.md +++ b/website/docs/user-guide/features/hooks.md @@ -209,10 +209,10 @@ def register(ctx): |------|-----------|-------------------| | `pre_tool_call` | Before any tool executes | `tool_name`, `args`, `task_id` | | `post_tool_call` | After any tool returns | `tool_name`, `args`, `result`, `task_id` | -| `pre_llm_call` | Before LLM API request | *(planned — not yet wired)* | -| `post_llm_call` | After LLM API response | *(planned — not yet wired)* | -| `on_session_start` | Session begins | *(planned — not yet wired)* | -| `on_session_end` | Session ends | *(planned — not yet wired)* | +| `pre_llm_call` | Before LLM API request | `session_id`, `user_message`, `conversation_history`, `is_first_turn`, `model`, `platform` | +| `post_llm_call` | After LLM API response | `session_id`, `user_message`, `assistant_response`, `conversation_history`, `model`, `platform` | +| `on_session_start` | Session begins | `session_id`, `model`, `platform` | +| `on_session_end` | Session ends | `session_id`, `completed`, `interrupted`, `model`, `platform` | Callbacks receive keyword arguments matching the columns above: diff --git a/website/docs/user-guide/features/skills.md b/website/docs/user-guide/features/skills.md index d21c98885f..edd61f7396 100644 --- a/website/docs/user-guide/features/skills.md +++ b/website/docs/user-guide/features/skills.md @@ -277,9 +277,12 @@ hermes skills install well-known:https://mintlify.com/docs/.well-known/skills/mi Hermes can install directly from GitHub repositories and GitHub-based taps. This is useful when you already know the repo/path or want to add your own custom source repo. -- OpenAI skills: [openai/skills](https://github.com/openai/skills) -- Anthropic skills: [anthropics/skills](https://github.com/anthropics/skills) -- Example community tap source: [VoltAgent/awesome-agent-skills](https://github.com/VoltAgent/awesome-agent-skills) +Default taps (browsable without any setup): +- [openai/skills](https://github.com/openai/skills) +- [anthropics/skills](https://github.com/anthropics/skills) +- [VoltAgent/awesome-agent-skills](https://github.com/VoltAgent/awesome-agent-skills) +- [garrytan/gstack](https://github.com/garrytan/gstack) + - Example: ```bash diff --git a/website/docs/user-guide/messaging/email.md b/website/docs/user-guide/messaging/email.md index c302532b11..c1cf6f5f3f 100644 --- a/website/docs/user-guide/messaging/email.md +++ b/website/docs/user-guide/messaging/email.md @@ -104,6 +104,7 @@ The adapter polls the IMAP inbox for UNSEEN messages at a configurable interval - Documents (PDF, ZIP, etc.) → available for file access - **HTML-only emails** have tags stripped for plain text extraction - **Self-messages** are filtered out to prevent reply loops +- **Automated/noreply senders** are silently ignored — `noreply@`, `mailer-daemon@`, `bounce@`, `no-reply@`, and emails with `Auto-Submitted`, `Precedence: bulk`, or `List-Unsubscribe` headers ### Sending Replies diff --git a/website/docs/user-guide/security.md b/website/docs/user-guide/security.md index b38cdcb148..7c59a4aba0 100644 --- a/website/docs/user-guide/security.md +++ b/website/docs/user-guide/security.md @@ -43,6 +43,8 @@ The following patterns trigger approval prompts (defined in `tools/approval.py`) | `bash -c`, `python -e` | Shell/script execution via flags | | `find -exec rm`, `find -delete` | Find with destructive actions | | Fork bomb patterns | Fork bombs | +| `pkill`/`killall` hermes/gateway | Self-termination prevention | +| `gateway run` with `&`/`disown`/`nohup` | Prevents starting gateway outside service manager | :::info **Container bypass**: When running in `docker`, `singularity`, `modal`, or `daytona` backends, dangerous command checks are **skipped** because the container itself is the security boundary. Destructive commands inside a container can't harm the host. @@ -392,7 +394,7 @@ security: When `tirith_fail_open` is `true` (default), commands proceed if tirith is not installed or times out. Set to `false` in high-security environments to block commands when tirith is unavailable. -Tirith's verdict integrates with the approval flow: safe commands pass through, suspicious commands trigger user approval, and dangerous commands are blocked. +Tirith's verdict integrates with the approval flow: safe commands pass through, while both suspicious and blocked commands trigger user approval with the full tirith findings (severity, title, description, safer alternatives). Users can approve or deny — the default choice is deny to keep unattended scenarios secure. ### Context File Injection Protection