Files
nimmersky/skyrimnet/config-knobs.md

8.3 KiB

Config Knobs — load-bearing settings

YAML configs live in overwrite/SKSE/Plugins/SkyrimNet/config/ (with active edits) and mods/SkyrimNet/SKSE/Plugins/SkyrimNet/config/ (shipped baselines). 38 YAML files total, plus defaults_manifest.json.

This document focuses on the load-bearing settings — ones we've discovered have outsized effects on behavior. Full enumeration would be brittle and date-sensitive; the goal here is to capture the gotchas.

SkyrimNet.yaml — the central config

[verified] Direct observations from this install + log/trace correlation.

Setting This install What it controls Gotcha
dialogue.embedActionsInDialogue true Lets the Dialogue model emit ACTION: lines inline after speech. When true, the native_action_selector may be bypassed — and bug #2 (malformed markers) surfaces. When false, actions are strictly post-hoc via native selector.
dialogue.eligibilityCheckTimeoutMs 2500 Bounds the wait_eligibility_results span. Slow Papyrus eligibility callbacks (>2.5s) get dropped from the available action list for that turn.
dialogue.interruptDialogueOnVoiceStart true Player STT triggers a barge-in on the NPC. Distinct from TTS-side interrupts; affects whose voice cuts off whom.
dialogue.maxSegmentWords (tts.maxSegmentWords) 4 TTS chunk size for streaming. Was raised by us as part of the first-sentence-drop fix. Small chunks can amplify chunker race conditions; suspected innocent in NPC-NPC restatement.
gamemaster.enabled true Master switch for the GM.
gamemaster.agentEnabled true [unknown] Distinct from enabled? Both default true; toggling untested. See open-questions.md.
gamemaster.continuousSceneCooldownSeconds 30 Minimum gap between GM polling ticks in continuous mode. Lower = more LLM cost, more "alive" feel. Higher = cheaper, quieter scenes.
gamemaster.actionCooldownSeconds 180 Per-NPC action cooldown. Prevents the same NPC from being action-targeted repeatedly.
gamemaster.nearbyActorRadius 600 Radius around player the GM considers. Skyrim units (~10cm each, so ~60m).
gamemaster.recentEventsCount 25 How much event history goes into the GM prompt. Higher = more context, more tokens, more cost.
gamemaster.requestTimeoutSeconds 30 Per-call LLM timeout for the GM.
gamemaster.continuousSceneCooldownSeconds 30 (duplicate row — see above)
interaction.maxDistance 250 Default interaction distance. Affects who hears what.
interaction.normalMaxDistance 250 Normal speech audibility.
interaction.whisperMaxDistance 100 Whisper audibility.
events.preloadCount 1000 Events warmed at startup. Affects load time + initial memory query corpus.
narration.enabled false Suppresses asterisk-style narration globally. Referenced by is_narration_enabled() decorator in many prompts; toggling changes prompt content materially.
subtitles.enableNPCSubtitles true Whether NPC subtitles render.
dbvo.enabled true Dialogue Background Voice Over — routes TTS through vanilla Skyrim dialogue topics. The "first-sentence-dropped" bug we hit was traced to this. Disabling skips lip-sync and topic-coupling.
shouldSilenceActors true Silences actors before TTS plays (prevents vanilla audio overlap). Can race the first audio chunk and silence it.

[verified] enableNPCNodeUpdates: true and dbvo.fixSubtitleDuringTTS: true were the toggles that fixed the user's "first sentence not played" issue (see bugs-and-fixes.md historical context).

Agents.yaml

Defines per-agent variant assignments and behavior. Each agent has:

  • variant — which OpenRouter variant to use (cross-references OpenRouter.yaml)
  • enabled — master toggle for the agent
  • Possibly cooldown, timeout, model-specific overrides

[hypothesis] Editing Agents.yaml is how a user changes which model handles which agent (e.g., "use Claude for dialogue too, not just GM"). Confirm by inspection.

OpenRouter.yaml

Variant → model + endpoint + per-call defaults. See agent-pipelines.md for the full table extracted from this install.

Key sections:

  • default_params per variant — max_tokens, temperature, top_p, etc.
  • endpoint — the URL the OpenRouter routing layer sends to. In this install, mostly local IPs (10.0.30.x) plus a Claude proxy on 127.0.0.1:8000.
  • model — the OpenRouter alias or local model ID.

Actions.yaml

[hypothesis] Defines global action-system policies: which categories are enabled, default priorities, eligibility-check defaults. Doesn't define individual actions — those come from config/actions/*.yaml in contributing mods' folders (see action-system.md).

Events.yaml

~40 event types, each with toggles:

  • enabled — does SkyrimNet listen for this event at all
  • persistent — does the event get stored in the long-term log
  • shortLivedEnabled — short-lived event variant
  • allowNPCReaction — can NPCs react to this event via the GM
  • npcReactionCooldown — per-NPC cooldown for reacting
  • interrupt — does this event interrupt ongoing dialogue

Currently disabled in user's config [verified] from the user's install:

  • quest_stage
  • cell_attach_detach
  • quest_objective_state
  • scene* (multiple scene_* event types)

These were likely disabled to cut event noise. Re-enabling would feed more triggers to the GM and increase LLM call frequency.

Memory.yaml

Controls the vector memory system (semantic embeddings via all-MiniLM-L6-v2):

  • Embedding model selection
  • Memory retention windows
  • Number of memories retrieved per query
  • Memory generation thresholds

[hypothesis] These tune the RAG-for-NPCs behavior. Defaults probably reasonable for most users.

OmniSight.yaml

Vision-agent settings — when to capture screenshots, how often, scene description verbosity.

MCP.yaml

[hypothesis] Model Context Protocol integration? Not yet inspected. Could be relevant if SkyrimNet exposes MCP servers/clients for external tool integration.

Per-TTS provider configs

One YAML per supported TTS backend:

  • XTTS.yaml, Zonos.yaml, Chatterbox.yaml, Piper.yaml, PocketTTS.yaml, ElevenLabs.yaml, Inworld.yaml, VastAI.yaml

Active backend selected by tts.engine in SkyrimNet.yaml. This install uses pocket_tts.

Streaming params worth knowing (in PocketTTS.yaml):

  • streaming.max_words_to_process: 32 — max chunk size
  • streaming.min_words_to_process_initial: 16 — first-chunk minimum (was a suspect for the first-sentence-drop bug)
  • streaming.process_on_sentence_boundary: true
  • streaming.process_on_word_count: true
  • streaming.max_buffers_per_actor: 4

STT.yaml

Speech-to-text settings (whisper.cpp local). VAD thresholds, language, sample rate, voice activity gate.

defaults_manifest.json

[hypothesis] JSON dump of every config key with its default value, structured by section name. Looks like the schema the DLL seeds first-run config from — when a YAML doesn't exist, the DLL writes one populated from this manifest.

Sections present (28 total): ActorFilter, Agents, BardSinging, ChatUI, Chatterbox, DialogueFilter, Diary, DynamicBio, ElevenLabs, Entity, Events, Hotkey, Inworld, Memory, MemoryFilter, OmniSight, OpenRouter, Piper, PlayerDialogue, PocketTTS, STT, UniversalTranslator, VastAI, VirtualEntities, VoiceSamples, WebServer, XTTS, Zonos.

Each section name matches a YAML file. Verify role by deleting a YAML and watching what regenerates.

Plugins subtree

config/plugins/IntelEngine/ — the IntelEngine sibling plugin keeps its config under SkyrimNet's config root. Notable files: factions.yaml, settings.yaml. [unknown] exact contents.

Editing safety

  • Always edit overwrite/.../config/, never mods/.../config/ directly. The overwrite layer is what the game reads.
  • Most settings hot-reload. Restart only needed for backend swaps (TTS engine, STT) or fundamental architecture changes.
  • Backup before changes: cp foo.yaml foo.yaml.backup is the pattern we've used.
  • The in-game MCM (Mod Configuration Menu) writes back to these YAMLs — UI tweaks persist as YAML edits, which is convenient but means the UI is yet another writer to be aware of.