Configuration
Venice provisioning touches three files. Which file depends on active_agent; the third file is the same on both:
| File | Owned by | Touched by Venice |
|---|---|---|
/root/.openclaw/openclaw.json | openclaw runtime | when active_agent=openclaw |
/root/.hermes/config.yaml | hermes runtime | when active_agent=hermes |
/root/config/config.json | intern-server | always (persists key + model id) |
All three values that describe Venice itself — baseUrl, transport (api), and the model list — are values you type during the SSH install; the device does not call any upstream catalog service to discover them. They come from venice.ai directly (their API docs or GET https://api.venice.ai/api/v1/models).
OpenClaw — openclaw.json
When active_agent=openclaw, the runtime config is /root/.openclaw/openclaw.json. Venice lands in two places:
{
"models": {
"providers": {
"venice": {
"apiKey": "vn-...",
"baseUrl": "https://api.venice.ai/api/v1",
"api": "openai-completions",
"models": [
{"id": "deepseek-v3.2", "contextWindow": 200000},
{"id": "qwen3.6-max", "contextWindow": 131072}
]
}
}
},
"agents": {
"defaults": {
"model": { "primary": "venice/deepseek-v3.2" },
"models": {
"venice/deepseek-v3.2": {},
"venice/qwen3.6-max": {}
}
}
}
}
Things to know:
models.providers.venice.apiKeyis the Venice API key the install pasted in. It's how the runtime authenticates toapi.venice.ai.models.providers.venice.{baseUrl, api}are the values from venice.ai's own API. Theapifield is the hyphenated OpenClaw transport name (openai-completions), which differs from Hermes's underscore form (openai_completions).models.providers.venice.modelsis an array merged by id. Existing entries on disk are preserved across re-runs; only new ids are appended. Fields the runtime doesn't know about pass through unchanged.agents.*.models["venice/<id>"]: {}is added under every agent. Ifagentsis empty, bootstrapagents.defaultsfirst.agents.*.model.primaryis set tovenice/<model>under every agent only when$VENICE_MODELis non-empty in the install. Skipping it leaves whatever primary was there before.
After editing, set ownership back to openclaw:openclaw (the runtime user) and mode 600, then systemctl restart openclaw.
Hermes — config.yaml
When active_agent=hermes, the runtime config is /root/.hermes/config.yaml. Venice lives at the top level under providers:
model:
default: 'deepseek-v3.2' # set when $VENICE_MODEL was non-empty
provider: venice
providers:
autonomous: # existing block from hermes setup, untouched
name: Autonomous
base_url: 'https://<llm-base-url>'
api_key: '<scoped-llm-key>'
transport: anthropic_messages
discover_models: false
models:
claude-opus-4-6: { context_length: 500000 }
claude-haiku-4-5: { context_length: 200000 }
venice: # block added by the SSH install
name: Venice
base_url: 'https://api.venice.ai/api/v1'
api_key: 'vn-...'
transport: openai_completions # hyphen → underscore vs OpenClaw
discover_models: false
models:
deepseek-v3.2: { context_length: 200000 }
qwen3.6-max: { context_length: 131072 }
Things to know:
providers.venice.modelsis a map keyed by model id, not an array. Existing keys are preserved across re-runs.providers.venice.transportis the same transport you used on OpenClaw, with hyphens swapped for underscores — that's the convention Hermes itself uses (openai-completions→openai_completions).providers.venice.discover_models: falseis always set. The runtime would otherwise try to auto-list models from the provider and end up with an empty picker.model.default + model.providerat the top of the file is only written when the install passed a non-empty$VENICE_MODEL. Skipping it leaves the existing default (set during Hermes setup) intact.context_lengthis what you typed in the install (contextLength), or200000as a fallback. Pick this from venice.ai's docs for each model.- The file is rewritten via a YAML roundtrip (Go uses
goccy/go-yaml, the install's Python helper usespyyaml) — string values are single-quoted, key order under each map is preserved when possible.
After editing, set the file mode to 600 and systemctl restart hermes-gateway.
config.json — persistence for agent swaps
Two fields in /root/config/config.json track the last successful install:
{
"venice_inference_api_key": "vn-...",
"venice_inference_model": "deepseek-v3.2"
}
These are written as step 3 of the SSH install. The model field should be overwritten — including with an empty string — every time you re-run the install, so the saved primary tracks the latest intent. Skipping this step leaves Venice working on the current runtime but breaks the auto-replay on a later agent swap.
Auto-replay on Hermes swap
When intern-server switches the device from OpenClaw → Hermes, the last step of the Hermes setup flow calls applyVeniceFromConfig:
- If
venice_inference_api_keyis empty → no-op. - Otherwise → re-applies the hermes-side venice block using the saved key + model.
This is the only way to get Venice onto a freshly-installed Hermes config without re-running the SSH install. It's best-effort: failure is logged + surfaced to the maintainer chat, but does not roll back the agent swap.
There is no symmetric auto-replay on Hermes → OpenClaw — if you swap back, the saved key stays in config.json, but you'd need to re-run the SSH install to get it back into openclaw.json. The plumbing exists, it just isn't wired into the OpenClaw setup path today.
Editing by hand
# Force the device to "forget" Venice for the next agent swap.
sudo jq '.venice_inference_api_key = "" | .venice_inference_model = ""' /root/config/config.json | \
sudo tee /root/config/config.json.tmp > /dev/null && \
sudo mv /root/config/config.json.tmp /root/config/config.json
sudo systemctl restart intern
Editing these fields does not retroactively touch openclaw.json or config.yaml — those keep whatever Venice block they already had. Clearing here only affects future agent swaps.
File-level checklist
A healthy Venice provisioning passes the relevant block below.
OpenClaw runtime:
sudo jq '.models.providers.venice | {has_key: (.apiKey != ""), baseUrl, model_count: (.models | length)}' \
/root/.openclaw/openclaw.json
# → {"has_key": true, "baseUrl": "https://api.venice.ai/api/v1", "model_count": N}
sudo jq '.agents | to_entries | map({agent: .key, has_venice: (.value.models | keys | map(startswith("venice/")) | any)})' \
/root/.openclaw/openclaw.json
# every agent should have "has_venice": true
Hermes runtime:
sudo grep -c '^ venice:' /root/.hermes/config.yaml # → 1
sudo grep -c 'context_length' /root/.hermes/config.yaml # → ≥ 2 (autonomous + venice models)
sudo grep -E '^ provider: venice' /root/.hermes/config.yaml || \
echo 'note: model.default not set to a Venice model (this is fine if no model was passed)'
Persistence (both runtimes):
sudo jq '{key_len: (.venice_inference_api_key | length), model: .venice_inference_model}' /root/config/config.json
# key_len ≥ 1; model is either empty or the id last passed to the install
If any of these fail, see the matching section above — every value on disk comes from what the install typed in, not from an upstream service.