Skip to main content

Configuration

Venice provisioning touches three files. Which file depends on active_agent; the third file is the same on both:

FileOwned byTouched by Venice
/root/.openclaw/openclaw.jsonopenclaw runtimewhen active_agent=openclaw
/root/.hermes/config.yamlhermes runtimewhen active_agent=hermes
/root/config/config.jsonintern-serveralways (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.apiKey is the Venice API key the install pasted in. It's how the runtime authenticates to api.venice.ai.
  • models.providers.venice.{baseUrl, api} are the values from venice.ai's own API. The api field is the hyphenated OpenClaw transport name (openai-completions), which differs from Hermes's underscore form (openai_completions).
  • models.providers.venice.models is 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. If agents is empty, bootstrap agents.defaults first.
  • agents.*.model.primary is set to venice/<model> under every agent only when $VENICE_MODEL is 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.models is a map keyed by model id, not an array. Existing keys are preserved across re-runs.
  • providers.venice.transport is the same transport you used on OpenClaw, with hyphens swapped for underscores — that's the convention Hermes itself uses (openai-completionsopenai_completions).
  • providers.venice.discover_models: false is always set. The runtime would otherwise try to auto-list models from the provider and end up with an empty picker.
  • model.default + model.provider at 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_length is what you typed in the install (contextLength), or 200000 as 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 uses pyyaml) — 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_key is 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.