{"slug": "run-hermes-fully-locally-with-qvac", "title": "Run Hermes Fully Locally with QVAC", "summary": "A developer guide explains how to run the Hermes agent fully locally using QVAC, an OpenAI-compatible server, enabling offline inference, persistent memory, and tool execution without cloud dependencies. The setup requires a Unix-like environment, Node.js, Python, and a local model, with an acceptance test that verifies generation, tool calling, durable memory, and offline operation.", "body_md": "Run Hermes Fully Locally with QVAC | Agent Lab Journal\n\n```\n  AL\n  Agent Lab Journal\n\n  Guides\n  Glossary\n```\n\nLOCAL AI AGENTS · PRACTICAL DEPLOYMENT\n\n```\n      Level: advanced\n      Reading time: 45 minutes\n      Result: local Hermes + QVAC + offline verification\n```\n\nBy the end of this guide, you will have a personal Hermes Agent that sends inference requests only to a model running on your machine, preserves memory between sessions, invokes a restricted set of local tools, and completes a repeatable task after the internet connection is disabled. No cloud API key is required during operation, although you must download the software and model files beforehand.\n\nHermes Agent is the agent layer around a language model. It manages conversations, state, memory, skills, tool descriptions, and the loop that connects a model request to an actual action. QVAC is responsible for running the model locally and exposing it through an OpenAI-compatible HTTP interface.\n\n```\nUser\n  │\n  ▼\nHermes Agent\n  ├── local sessions\n  ├── persistent memory\n  ├── skills and policies\n  └── restricted tools\n          │\n          │ HTTP over 127.0.0.1\n          ▼\n    QVAC OpenAI server\n          │\n          ▼\n      local model\n          │\n          ▼\n      CPU / GPU / RAM\n```\n\nThe roles must remain separate. The large language model produces a response or requests a function. Hermes controls the agent loop, memory, permissions, and function execution. QVAC loads the model weights, applies the model's chat template, and performs local inference.\n\nIn this guide, “fully local” has a precise and limited meaning:\n\nHermes and QVAC run on one computer, or inside an isolated local environment;\n\nmodel requests are sent only to 127.0.0.1;\n\nsessions, memory, skills, configuration, and logs remain on local storage;\n\nthe tools used by the acceptance test require no external services;\n\nafter dependencies and weights have been downloaded, the scenario passes without internet access.\n\nA local model does not automatically create a secure system. A tool can still execute a command, read an unrelated file, or contact an external address. Offline operation reduces one part of the attack surface; it does not replace operating-system permissions, path validation, or approval controls.\n\nA greeting is too weak to prove that an agent works. Our acceptance case therefore uses a small project directory and tests four independent layers: generation, tool calling, durable memory, and the absence of a required cloud route.\n\nHermes must:\n\nread a local meeting note;\n\nextract the project, decision, and next action;\n\nwrite a Markdown summary inside an allowed output directory;\n\nremember a harmless formatting preference;\n\nrecover that preference in a new session;\n\nrepeat a new file task after external networking is disabled.\n\nCreate a dedicated laboratory directory. Do not begin with your home directory, a repository containing credentials, or a cloud-synchronized folder.\n\n```\nmkdir -p \"$PWD/hermes-local-lab/inbox\"\nmkdir -p \"$PWD/hermes-local-lab/outbox\"\n\nprintf '%s\\n' \\\n  'Project: local assistant.' \\\n  'Decision: store final notes as Markdown.' \\\n  'Next action: verify operation without a network.' \\\n  > \"$PWD/hermes-local-lab/inbox/meeting.txt\"\n\nexport LAB_DIR=\"$PWD/hermes-local-lab\"\n\nfind \"$LAB_DIR\" -maxdepth 2 -type f -print\nprintf 'Laboratory directory: %s\\n' \"$LAB_DIR\"\n```\n\nKeep this terminal open or record the absolute value of LAB_DIR. Agent prompts should use an absolute path rather than relying on an uncertain working directory.\n\nYou need a Unix-like environment, Node.js and npm for QVAC, a Python environment supported by the Hermes release you install, Git, curl, and enough disk space for the selected model. On Windows, use WSL2 unless the current release explicitly documents another supported route.\n\nBefore changing the machine, record the software and available resources:\n\n```\nuname -a\nnode --version\nnpm --version\npython3 --version\ngit --version\ncurl --version | head -n 1\n\ndf -h .\nfree -h 2>/dev/null || true\n```\n\nCLI flags, model identifiers, and configuration formats can change between releases. Treat every command below as a configuration for the installed version, not as permission to ignore its built-in help. If a flag is rejected, stop and inspect --help instead of guessing a replacement.\n\nAfter installing QVAC, use its diagnostics to identify the available compute backend:\n\n```\nqvac doctor\n```\n\nA supported GPU backend can reduce latency, while CPU execution may still be adequate for a small model. The actual result depends on the machine, model build, context length, and runtime version; this article does not claim universal speed or memory measurements.\n\nBegin with a model variant using 4-bit quantization. Quantization reduces the storage and memory cost of weights, but it does not eliminate runtime buffers or the memory consumed by the context cache.\n\nThe QVAC model registry available in your installed release is the source of truth. List or inspect that registry before copying a model identifier into the configuration. If the following identifiers are not present in your release, select the corresponding supported instruct model and use its exact identifier.\n\n```\n          Deployment profile\n          Example model class\n          Use\n          QVAC identifier used below\n\n          Installation check\n          Qwen 4B, Q4\n          HTTP route and simple functions\n          QWEN3_5_4B_MULTIMODAL_Q4_K_M\n\n          Balanced laboratory\n          Qwen 9B, Q4\n          More reliable argument generation\n          QWEN3_5_9B_MULTIMODAL_Q4_K_M\n\n          Larger agent workload\n          Qwen 35B-A3B MoE, Q4\n          Longer multi-step work on capable hardware\n          QWEN3_6_35B_A3B_MULTIMODAL_Q4_K_M\n```\n\nA mixture-of-experts model activates only part of its expert network for each token, but its weights and working data still have to fit the runtime's memory strategy. Leave capacity for the operating system, Hermes, the context, and the KV cache.\n\nThe smallest model is useful for validating the route, but it may emit invalid function arguments or skip steps. A larger model can improve agent behavior, yet no model size guarantees correct tool use. First complete the whole test with a model that fits comfortably; compare alternatives only after the infrastructure is stable.\n\nInternet access is required at this stage to retrieve the package and, later, the model weights.\n\n```\nnpm install -g @qvac/cli\n\ncommand -v qvac\nqvac --help\nqvac doctor\n```\n\nIf global npm installation asks for administrator privileges, do not solve it by piping an unreviewed process into sudo. Configure a user-owned npm prefix or use a managed Node.js installation. Confirm that the discovered qvac binary belongs to the installation you intended.\n\nCreate a separate QVAC project directory:\n\n```\nmkdir -p \"$PWD/qvac-hermes\"\ncd \"$PWD/qvac-hermes\"\npwd\n```\n\nThe HTTP server loads models declared under serve.models. The object key becomes the model name visible to clients. Using a stable alias keeps Hermes independent of the underlying registry identifier.\n\nCreate qvac.config.json in the current directory:\n\n```\n{\n  \"serve\": {\n    \"models\": {\n      \"hermes-local\": {\n        \"model\": \"QWEN3_6_35B_A3B_MULTIMODAL_Q4_K_M\",\n        \"default\": true,\n        \"preload\": true,\n        \"config\": {\n          \"ctx_size\": 65536,\n          \"tools\": true\n        }\n      }\n    }\n  }\n}\n```\n\nFor a smaller model, change only the model value to an identifier verified in your installed QVAC registry, for example:\n\n```\n\"QWEN3_5_4B_MULTIMODAL_Q4_K_M\"\n```\n\nor:\n\n```\n\"QWEN3_5_9B_MULTIMODAL_Q4_K_M\"\n```\n\nctx_size is the maximum context the runtime attempts to hold. Hermes may send a large system instruction plus multiple tool schemas before the user's task begins. A small context can overflow early, while a large token limit increases KV-cache memory.\n\nIf 65,536 tokens do not fit, lower the value, expose fewer tools, and configure Hermes with the same effective limit. Do not advertise a larger context to Hermes than QVAC can actually serve.\n\nThe tools option enables function handling for the selected model. Without it, ordinary chat can succeed while the agent returns prose instead of a structured call.\n\nBind QVAC to the loopback interface so that other devices cannot reach the port through the LAN.\n\n```\ncd /absolute/path/to/qvac-hermes\n\nqvac serve openai \\\n  --config \"$PWD/qvac.config.json\" \\\n  --host 127.0.0.1 \\\n  --port 11434 \\\n  --verbose\n```\n\nKeep this process in a dedicated terminal. The first start may download weights before loading them into memory. Wait until server initialization has completed.\n\nFrom another terminal, inspect the model endpoint:\n\n```\ncurl --fail --silent --show-error \\\n  http://127.0.0.1:11434/v1/models\n```\n\nThe returned JSON should contain the client-facing identifier hermes-local. An empty list usually means the model is not ready. A 404 indicates a route, configuration, or CLI-version mismatch.\n\nNow send a minimal completion:\n\n```\ncurl --fail --silent --show-error \\\n  http://127.0.0.1:11434/v1/chat/completions \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"model\": \"hermes-local\",\n    \"messages\": [\n      {\n        \"role\": \"user\",\n        \"content\": \"Reply with exactly one word: ready\"\n      }\n    ],\n    \"temperature\": 0,\n    \"max_tokens\": 16\n  }'\n```\n\nValidate the response structure rather than punctuation or capitalization. It must contain a choices array with an assistant message. If HTTP succeeds but content is empty, inspect the verbose QVAC log and verify that the chosen registry entry is a chat-capable instruct model.\n\nThis test separates QVAC and model behavior from the agent runtime. The described function performs no action; the request only asks the model to return a structured intention.\n\n```\ncurl --fail --silent --show-error \\\n  http://127.0.0.1:11434/v1/chat/completions \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"model\": \"hermes-local\",\n    \"messages\": [\n      {\n        \"role\": \"user\",\n        \"content\": \"Find the size of /lab/inbox/meeting.txt. Do not guess; use the function.\"\n      }\n    ],\n    \"tools\": [\n      {\n        \"type\": \"function\",\n        \"function\": {\n          \"name\": \"get_file_size\",\n          \"description\": \"Return the size of an allowed local file\",\n          \"parameters\": {\n            \"type\": \"object\",\n            \"properties\": {\n              \"path\": {\n                \"type\": \"string\",\n                \"description\": \"Absolute path to the file\"\n              }\n            },\n            \"required\": [\"path\"],\n            \"additionalProperties\": false\n          }\n        }\n      }\n    ],\n    \"tool_choice\": \"auto\",\n    \"temperature\": 0,\n    \"max_tokens\": 256\n  }'\n```\n\nA successful result is not an alleged byte count. It is an item in message.tool_calls whose function name is get_file_size and whose arguments value contains valid JSON with the requested path.\n\nFail the test if:\n\nthe model says that it will call a function but returns no tool_calls;\n\nthe function name is changed;\n\narguments cannot be parsed as JSON;\n\nthe model invents a file size;\n\nthe requested path is replaced with another path.\n\nDo not install or debug Hermes until this boundary works. Confirm that \"tools\": true is active, restart QVAC after configuration changes, and test a more capable model if necessary. Successful chat completion is not evidence of successful function calling.\n\nReview remote installation scripts before executing them. One cautious sequence is:\n\n```\ncurl --fail --silent --show-error \\\n  https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh \\\n  -o /tmp/hermes-install.sh\n\nless /tmp/hermes-install.sh\nbash /tmp/hermes-install.sh\n```\n\nIf your environment prohibits remote installation scripts, follow the manual installation procedure for the release you selected. Avoid mixing system Python packages with unrelated virtual environments.\n\nOpen a new terminal if the installer changed PATH, then verify the command:\n\n```\ncommand -v hermes\nhermes --help\n```\n\nHermes commonly stores user state under ~/.hermes/. That directory can contain sessions, memory, skills, logs, and provider configuration. Do not publish it or commit it to Git.\n\n```\nfind \"$HOME/.hermes\" -maxdepth 2 -type d -print 2>/dev/null\n```\n\nUse Hermes' interactive model configuration so that the installed release writes its own supported configuration structure:\n\n```\nhermes model\n```\n\nSelect a custom OpenAI-compatible endpoint and enter:\n\n```\nAPI base URL: http://127.0.0.1:11434/v1\nAPI key: local-qvac\nModel name: hermes-local\nContext length: 65536\n```\n\nIf QVAC was started without an API-key requirement, local-qvac is merely a non-empty local placeholder for clients that require a value. It is not a cloud credential and must not be copied from a real account.\n\nThe corresponding configuration is conceptually equivalent to:\n\n```\nmodel:\n  default: hermes-local\n  provider: custom\n  base_url: http://127.0.0.1:11434/v1\n```\n\nThe exact YAML structure can change. Do not replace the entire Hermes configuration with this short example: the existing file may also contain memory, channel, and skill settings.\n\nConfirm the saved route without printing credential fields:\n\n```\ngrep -nE 'provider:|base_url:|default:' \\\n  \"$HOME/.hermes/config.yaml\"\n```\n\nThe base URL should begin with [http://127.0.0.1:11434/v1](http://127.0.0.1:11434/v1), and no cloud provider domain should appear in the active model configuration.\n\n```\nhermes\n```\n\nBegin with a generation-only request:\n\n```\nState the configured model name and base URL.\nDo not use tools and do not access the network.\n```\n\nThe model's answer is not authoritative. It can repeat prompt text or hallucinate configuration. The sources of truth are the Hermes configuration, QVAC request logs, and network observation.\n\nNext, establish an explicit working boundary:\n\n```\nWorking directory: /absolute/path/hermes-local-lab\nYou may read only from inbox.\nYou may write only to outbox.\nDo not modify source files.\nDo not make network requests.\nFirst present a plan, then wait for my next instruction.\n```\n\nIf the agent immediately changes files, stop it. A prompt influences model behavior but does not create an isolation boundary. File permissions and tool-level validation must enforce the same policy.\n\nThe precise skill and permission controls depend on the installed Hermes version, but the security rule does not: expose the smallest directory and the smallest set of operations required by the task.\n\nThe laboratory needs only these capabilities:\n\nread a file from the approved input directory;\n\nlist files inside the laboratory;\n\ncreate a new file in outbox;\n\nread and write Hermes' local memory through its dedicated interface;\n\nrequest approval for anything outside those boundaries.\n\nDo not enable a browser, email, messaging, unrestricted shell access, or external MCP servers for this test. If Hermes runs in a container, expose individual directories rather than the entire home directory:\n\n``` php\n/host/hermes-local-lab/inbox  -> /lab/inbox:ro\n/host/hermes-local-lab/outbox -> /lab/outbox:rw\n/host/hermes-state            -> /home/hermes/.hermes:rw\n```\n\nFor a native process, use a dedicated operating-system account or another isolation mechanism. Natural-language instructions remain useful, but the operating system must reject access that the agent should not have.\n\nAn allowlist must compare normalized absolute paths. A raw string-prefix check can be bypassed with .., alternate separators, or symbolic links.\n\n```\nrequested path\n      │\n      ▼\nresolve with realpath\n      │\n      ├── inside inbox  → read\n      ├── inside outbox → read and create\n      └── elsewhere     → deny\n```\n\nGive Hermes this task after replacing with the absolute laboratory path:\n\n```\nRead:\n<LAB_DIR>/inbox/meeting.txt\n\nCreate:\n<LAB_DIR>/outbox/meeting-summary.md\n\nThe new file must contain exactly these three sections:\n# Project\n# Decision\n# Next action\n\nDo not modify the source file. After writing the result,\nread the new file again and report its path and section names.\n```\n\nDo not accept the final chat message as evidence. Inspect the filesystem independently:\n\n```\ntest -f \"$LAB_DIR/outbox/meeting-summary.md\"\ntest -f \"$LAB_DIR/inbox/meeting.txt\"\n\nsed -n '1,80p' \"$LAB_DIR/outbox/meeting-summary.md\"\n\nfind \"$LAB_DIR\" -maxdepth 2 -type f \\\n  -printf '%p\\n' 2>/dev/null || \\\nfind \"$LAB_DIR\" -maxdepth 2 -type f -print\n```\n\nThe loop passes only if:\n\nthe agent reads the source instead of inventing its contents;\n\nthe write call targets a path inside outbox;\n\nexactly the expected output file is created;\n\nthe input file remains unchanged;\n\nthe agent rereads the output before completing;\n\nQVAC logs show local model requests only.\n\nRecord the source hash before and after a repeated run:\n\n```\nsha256sum \"$LAB_DIR/inbox/meeting.txt\"\n```\n\nA matching hash proves that this particular source file did not change. It does not prove that no file outside the laboratory was touched, which is why operating-system isolation remains important.\n\nAgent memory must be tested across independent sessions. A correct answer inside the original conversation may come from the active context rather than durable storage.\n\nIn the first session, store a harmless synthetic preference:\n\n```\nRemember this durable preference for the test project:\nfinal notes must contain no more than three sections.\nDo not store file paths, personal data, or secrets.\nConfirm exactly what you sent to persistent memory.\n```\n\nExit Hermes through its normal exit command. Start a new session and ask:\n\n```\nWhat formatting limit did I set for final notes?\nIf persistent memory does not contain the answer, say so plainly.\n```\n\nThe test passes when the new session recovers the three-section rule from persistent storage. Do not include the answer in the retrieval question.\n\nYou can inspect modification times without printing all memory contents:\n\n```\nfind \"$HOME/.hermes\" -type f \\\n  -printf '%TY-%Tm-%Td %TH:%TM %p\\n' 2>/dev/null \\\n  | sort \\\n  | tail -n 30\n```\n\nOn macOS, use its supported find options or file metadata tools. Do not infer the memory format from a directory name; internal storage can change between Hermes versions.\n\nRun the offline test only after the complete model has been downloaded. Otherwise, a startup failure merely proves that required files were never cached.\n\nBefore disconnecting, confirm that:\n\nQVAC starts without another download;\n\n/v1/models returns hermes-local;\n\nHermes sends completions through QVAC;\n\nthe restricted tools can read and write laboratory files;\n\nmemory survives a Hermes restart.\n\nStop Hermes and QVAC. Disable Wi-Fi and wired networking, or use a temporary network namespace or firewall policy that denies external connections while preserving loopback. Do not block 127.0.0.1, because Hermes needs it to reach QVAC.\n\nCold-start QVAC again:\n\n```\ncd /absolute/path/to/qvac-hermes\n\nqvac serve openai \\\n  --config \"$PWD/qvac.config.json\" \\\n  --host 127.0.0.1 \\\n  --port 11434 \\\n  --verbose\n```\n\nIn a second terminal:\n\n```\ncurl --fail http://127.0.0.1:11434/v1/models\nhermes\n```\n\nGive Hermes a new task that was not completed in the earlier session:\n\n```\nCreate offline-check.md in the allowed outbox.\nWrite this exact line: OFFLINE_ROUTE_OK\nAdd a short summary of inbox/meeting.txt.\nDo not use a browser, search, URL, or external source.\nAfter writing the file, read it again.\n```\n\nVerify the artifact independently:\n\n```\ntest -f \"$LAB_DIR/outbox/offline-check.md\"\n\ngrep -F 'OFFLINE_ROUTE_OK' \\\n  \"$LAB_DIR/outbox/offline-check.md\"\n\nsed -n '1,80p' \\\n  \"$LAB_DIR/outbox/offline-check.md\"\n```\n\nConfirm that QVAC listens only on loopback:\n\n```\nss -ltnp 2>/dev/null | grep ':11434' || \\\nlsof -nP -iTCP:11434 -sTCP:LISTEN\n```\n\nThe listening address should be 127.0.0.1:11434, not 0.0.0.0:11434. Disabling Wi-Fi alone may leave VPN, virtual-machine, container, or wired interfaces active. For a strict test, observe outbound connections or isolate the processes so that only loopback traffic is permitted.\n\nAcceptance criterion: after a cold restart with no external network, QVAC loads already downloaded weights, Hermes connects to 127.0.0.1, creates and rereads the requested file through a restricted tool, and recovers the synthetic preference from local memory.\n\nA small script can verify the HTTP boundary before every Hermes session. It checks model discovery and an ordinary completion; the earlier raw function test is still required.\n\n``` bash\n#!/usr/bin/env bash\nset -euo pipefail\n\nbase_url=\"${QVAC_BASE_URL:-http://127.0.0.1:11434/v1}\"\nmodel=\"${QVAC_MODEL:-hermes-local}\"\n\nmodels_json=\"$(curl --fail --silent --show-error \\\n  \"$base_url/models\")\"\n\nprintf '%s' \"$models_json\" |\n  grep -F \"\\\"id\\\":\\\"$model\\\"\" >/dev/null ||\nprintf '%s' \"$models_json\" |\n  grep -F \"\\\"id\\\": \\\"$model\\\"\" >/dev/null\n\nresponse_json=\"$(curl --fail --silent --show-error \\\n  \"$base_url/chat/completions\" \\\n  -H 'Content-Type: application/json' \\\n  -d \"{\n    \\\"model\\\": \\\"$model\\\",\n    \\\"messages\\\": [\n      {\\\"role\\\": \\\"user\\\", \\\"content\\\": \\\"Reply: LOCAL_OK\\\"}\n    ],\n    \\\"temperature\\\": 0,\n    \\\"max_tokens\\\": 32\n  }\")\"\n\nprintf '%s' \"$response_json\" |\n  grep -F 'choices' >/dev/null\n\nprintf '%s\\n' 'QVAC_HTTP_OK'\n```\n\nFor a maintained test, parse JSON with jq and validate exact fields. The two grep patterns are only a minimal portable check and do not validate the complete response.\n\n```\n          Symptom\n          Likely layer\n          First check\n\n          qvac: command not found\n          CLI installation\n          npm prefix -g and PATH\n\n          Server exits while loading\n          Model or memory\n          qvac doctor, free RAM, model identifier\n\n          /v1/models returns 404\n          HTTP configuration\n          CLI help, config path, and server mode\n\n          Model not found\n          Client alias\n          hermes-local must match in QVAC and Hermes\n\n          Chat works but tools do not\n          Function calling\n          \"tools\": true and the raw curl function test\n\n          Hermes contacts a cloud host\n          Provider routing\n          provider: custom and local base_url\n\n          A new session forgets the rule\n          Persistent memory\n          State path, write permissions, and memory-save operation\n\n          Offline startup attempts a download\n          Model cache\n          Whether every model file completed downloading\n\n          Responses are truncated\n          Context or output limit\n          ctx_size, active tool count, Hermes limit\n\n          The machine swaps heavily\n          Insufficient RAM\n          Smaller model, smaller context, fewer preloaded models\n```\n\nThe expected value in this setup includes /v1:\n\n```\nhttp://127.0.0.1:11434/v1\n```\n\nSome clients append /v1 themselves. A duplicated path will appear in QVAC's HTTP log. Change one parameter at a time so that an address problem is not confused with a model or provider problem.\n\nHermes sends the key declared under serve.models: hermes-local. The longer QVAC registry identifier tells the server which weights to resolve; it is not necessarily the name that the client should send.\n\nA configured value of 65,536 does not guarantee that the machine can allocate it efficiently. Reduce the context, expose only necessary tools, restart QVAC, and repeat the raw HTTP tests. Keep the effective limit consistent between server and client.\n\nText that resembles JSON is not a valid function call. Inspect the raw response. If message.tool_calls is absent, Hermes should not execute the text. Repairing this output with regular expressions can transform malformed model prose into unintended actions.\n\nSet a maximum number of agent steps and preserve the full message sequence. Verify that Hermes returns each tool result to the model with the expected role and call identifier. Give the task an explicit stopping condition: after one successful write and one verification read, finish.\n\nA long system prompt and multiple schemas require prompt processing before output begins. Watch QVAC logs and resource use. If generation never starts, reduce the model, context, or active tool set. Do not assign a universal timeout based on one machine.\n\nStore short, atomic, unambiguous preferences rather than full conversational transcripts. Test retrieval in a fresh session without embedding the answer in the question. Never place passwords, API tokens, or confidential document content in persistent memory.\n\nA disabled browser or Wi-Fi icon does not prove network isolation. Check listening sockets and outbound connections. VPNs, container bridges, virtual interfaces, and wired adapters can remain available. Use a firewall or network namespace when the proof matters.\n\nA local agent inherits the filesystem permissions of the account that runs it. The production boundary must therefore limit the consequences of an incorrect tool call, not merely its internet access.\n\nBind QVAC to 127.0.0.1 unless remote access is explicitly required.\n\nDo not expose the complete home directory to Hermes.\n\nMount or permission input data as read-only.\n\nUse a separate directory for generated artifacts.\n\nPrefer narrow file functions over a general-purpose shell.\n\nRequire an approval gate for deletion, sending, publication, or access outside the working directory.\n\nResolve symbolic links before applying path policy.\n\nKeep real credentials out of laboratory configuration and memory.\n\nRecord the model identifier, package versions, and configuration hash.\n\nBack up ~/.hermes before upgrading or changing memory storage.\n\n```\nsha256sum qvac.config.json\nnpm list -g @qvac/cli --depth=0\nhermes --help | head -n 5\n```\n\nHermes releases may expose version information through different commands. Record only information returned by the installed build; do not invent a version string when no version flag is available.\n\nA valid benchmark gives every model the same prompts, function schemas, permissions, context budget, and acceptance checks. Do not compare a 4B model with one small function against a 35B model loaded with every Hermes skill.\n\nUse five local tasks:\n\nread one file and return an exact fact;\n\ncreate a file that follows a three-section schema;\n\nselect the correct function from two similar functions;\n\nrepair an argument after the path allowlist rejects it;\n\nstop after receiving the successful result instead of calling the function again.\n\nFor each run, record:\n\nthe model registry identifier and context size;\n\nthe complete sanitized input;\n\nthe ordered sequence of tool calls;\n\nwhether names and JSON arguments are valid;\n\nthe number of unnecessary calls;\n\nwhether every path remained inside the boundary;\n\nwhether the filesystem result passed deterministic checks;\n\ncold-start and warmed-run times measured on your own machine.\n\nA fast, persuasive answer that does not create the required file is a failed run. A model that reaches the result but repeats a dangerous call also fails. Determine the number of repetitions and pass criteria before reviewing results, and preserve raw logs. This guide intentionally reports no success percentages or latency figures because none can be honestly transferred to the reader without the original hardware, tasks, versions, and logs.\n\nModel quality. A compact local model may select tools, plan long chains, and recover from errors less reliably than a larger model.\n\nHardware memory. Weight files are only part of consumption. The runtime needs working buffers, KV cache, Hermes memory, and operating-system capacity.\n\nLatency. Large system prompts and many function schemas make the first agent step expensive.\n\nContext. A model's advertised maximum does not prove that the selected runtime and device can use it efficiently.\n\nExternal tools. A local model does not make email, web search, SaaS APIs, or remote MCP servers local.\n\nUpdates. CLI flags, registries, model templates, and configuration formats change. Pinning a working setup creates an upgrade responsibility.\n\nSecurity. A malicious local document can contain a prompt injection. Removing cloud access does not prevent the model from requesting a dangerous local action.\n\nObservability. Without logs, model, template, server, agent, and tool failures are difficult to distinguish.\n\nBackups. Local memory can disappear with disk failure unless it is backed up separately.\n\nOffline autonomy is not the same as universal usefulness. Without a network, the agent cannot retrieve current news, use remote business systems, or synchronize data. This architecture is best suited to local documents, private knowledge collections, drafting, classification, and workflows where data locality matters more than live external information.\n\nqvac doctor recognizes an available backend.\n\nThe selected model exists in the installed QVAC registry.\n\nThe model is declared in qvac.config.json.\n\n\"tools\": true is enabled for that model.\n\nQVAC listens only on 127.0.0.1:11434.\n\n/v1/models returns hermes-local.\n\nA direct curl request returns a structured chat completion.\n\nThe direct function test returns structured tool_calls.\n\nHermes uses the custom provider and local /v1 URL.\n\nHermes can access only the laboratory directories.\n\nThe input directory is read-only at the system or container level.\n\nFilesystem results are checked independently of the agent's claims.\n\nPersistent memory is verified in a new session.\n\nBoth processes cold-start after external networking is disabled.\n\nThe offline task creates and rereads a new file.\n\nNo real credentials are present in configuration, prompts, logs, or memory.\n\nIf every item passes, you have more than a local chat interface. You have a minimal reproducible personal-agent environment: QVAC serves the model, Hermes manages memory and function execution, operating-system controls restrict access, and the offline test demonstrates that the working path does not require a cloud API.\n\nAdd one specialized skill and one narrowly defined tool, then repeat the complete test suite. Avoid enabling a browser, unrestricted shell, email, and messaging at the same time: when a failure occurs, you need to know which layer violated its contract.\n\nContinue with the practical material in Agent Lab Journal guides, and use the glossary for definitions of agents, language models, context, tool calling, memory, MCP, and related engineering terms.\n\n← All guides · Open the glossary →\n\n```\nAgent Lab Journal\nReal experiments. Verifiable conclusions.\n```\n\n", "url": "https://wpnews.pro/news/run-hermes-fully-locally-with-qvac", "canonical_source": "https://dev.to/_862f933aa9477a9d2d/run-hermes-fully-locally-with-qvac-125h", "published_at": "2026-07-29 05:10:39+00:00", "updated_at": "2026-07-29 05:31:11.322292+00:00", "lang": "en", "topics": ["artificial-intelligence", "large-language-models", "ai-agents", "developer-tools", "ai-infrastructure"], "entities": ["Hermes Agent", "QVAC", "Agent Lab Journal"], "alternates": {"html": "https://wpnews.pro/news/run-hermes-fully-locally-with-qvac", "markdown": "https://wpnews.pro/news/run-hermes-fully-locally-with-qvac.md", "text": "https://wpnews.pro/news/run-hermes-fully-locally-with-qvac.txt", "jsonld": "https://wpnews.pro/news/run-hermes-fully-locally-with-qvac.jsonld"}}