# Agent Pipelines Each agent is selected via a "variant" in `overwrite/.../config/OpenRouter.yaml`, which maps to a model + endpoint + per-call parameters. Variants are referenced from the C++ DLL when it constructs each request. ## Variant routing table `[verified]` from `OpenRouter.yaml` + trace dump cross-check | Variant | Model alias | Endpoint (this install) | `max_tokens` | Purpose | |---|---|---|---|---| | `gamemaster_evaluation` | `claude-sonnet-4-5-20250929` | `127.0.0.1:8000` (local Claude proxy) | **256** | "Should I act and how?" — fires GM action selector | | `AgentDefault` (Dialogue) | `eva` (custom local alias) | `10.0.30.21:31000` | 4096 | NPC dialogue generation | | `meta` | `omega` | `10.0.30.22:31004` | 100 | Mood eval, memory query gen, classifiers, target selection | | `vision` | `Qwen3-VL-8B-Instruct-abliterated-v2.Q4_K_M.gguf` | `10.0.30.22:31005` | 4000 | OmniSight scene description from screenshot | | `combat` / `action_evaluation` | `eva` | same as AgentDefault | 500 | Combat-flavor dialogue / native action selection | | `gamemaster_scene_planner` | (no dedicated variant captured — likely uses `AgentDefault`) | — | — | Pre-plans 4-6-beat scenes (consumed by `gamemaster_action_selector.prompt:96-119` via `scene_plan` context var) | | `intel_story_dm` | `claude-sonnet-4-5-20250929` | local proxy | — | IntelEngine plugin's persistent narrative DM | | `gamemaster_evaluation` (TTON) | `claude-sonnet-4-5-20250929` | local proxy | — | OstimNet plugin's nearby-NPC GM | `[note]` Models can be reconfigured per-agent by editing `OpenRouter.yaml`. The aliases (`eva`, `omega`) are user-defined and resolved by the OpenRouter routing layer. --- ## Gamemaster (GM) **Prompt:** `prompts/gamemaster_action_selector.prompt` (action selector) + `prompts/gamemaster_scene_planner.prompt` (optional scene-plan generator). **When it fires** `[verified]` from trace dump: - Polling tick in continuous mode, roughly every `gamemaster.continuousSceneCooldownSeconds` (= 30s in this install). `[hypothesis]` exact timer source not isolated. - On player input arrival. - After a non-trivial in-game event (combat start, NPC death, location change) — though events are filterable via `Events.yaml`. **Input context:** - Recent events (`gamemaster.recentEventsCount: 25` controls volume). - Nearby actors (`gamemaster.nearbyActorRadius: 600`). - Eligible actions list (populated dynamically from C++; in continuous mode `ACTION: None` is allowed only if exposed by the prompt — see `bugs-and-fixes.md` Bug #1). - Optional `scene_plan` if scene planner has run. **Output:** exactly one line of the form ``` ACTION: ActionName PARAMS: {"key": "value", ...} ``` or `ACTION: None`. `max_tokens: 256` enforces this — no room for prose. **Consumers:** the C++ orchestrator parses the ACTION line and dispatches: - `StartConversation` / `ContinueConversation` → kicks the Dialogue pipeline for the named speaker/target with the given topic. - `Narrate` → triggers a narration-mode LLM call (no specific TTS speaker). - `None` → no-op, scene breathes. - Native actions (e.g. `OpenTrade`) when registered as eligible — fires the Papyrus/C++ callback. --- ## Dialogue Agent (`AgentDefault`) **Prompt:** `prompts/dialogue_response.prompt` (16-line wrapper) + `submodules/system_head/*` (load-ordered) + `submodules/user_final_instructions/*` (load-ordered) + `submodules/character_bio/*` (per-NPC). **When it fires:** - GM dispatches `StartConversation` or `ContinueConversation` with a target speaker. - Player provides text or voice input addressed to an NPC. - An NPC's AI Package activates one of SkyrimNet's custom packages (Player Dialogue, NPC Dialogue, TalkToPlayer). **Input context:** the NPC's full character bio (assembled from `character_bio/` submodules), the recent dialogue history (`event_history` component), the eligible actions list (if `embed_actions_in_dialogue: true`), the OmniSight scene description (if vision is enabled), and the topic from the GM (when GM-initiated). **Output:** the NPC's spoken line(s), optionally followed on a separate line by `ACTION: ActionName ...` if `embed_actions_in_dialogue: true`. **Consumers:** - `FilterActionLines` (in DLL, ~`ActionManager.cpp:1840`) strips any `ACTION:` line from the dialogue text before TTS. - `ParseEmbeddedAction` (in DLL, ~`ActionManager.cpp:1783`) extracts the action and dispatches it the same way as a GM-emitted action. - The remaining dialogue text is fed to the TTS pipeline (`tts_generation` span in trace). - After dialogue completes, **mood evaluation** and **memory search query generation** fire in parallel (both `meta` variant). --- ## Meta Agents (`meta` variant) A family of small classifier/helper calls, all capped at `max_tokens: 100`. **Prompts:** - `prompts/helpers/evaluate_mood.prompt` — post-dialogue mood update for the speaker - `prompts/helpers/generate_search_query.prompt` — turns a dialogue into a memory-retrieval query - `prompts/helpers/generate_profile.prompt` — generates/updates a character profile - `prompts/target_selectors/dialogue_speaker_selector.prompt` — picks who in a group should respond to player - `prompts/target_selectors/player_dialogue_target_selector.prompt` — picks the best NPC for player to address - `prompts/memory/generate_memory.prompt` and `memory_ranker.prompt` — memory creation/ranking - `prompts/transformers/native_dialogue_transformer.prompt` — text→text transformations - `prompts/transformers/universal_translator.prompt` — translation pipeline **When they fire:** mostly post-dialogue. `target_selection_llm` runs *before* dialogue when player input arrives. **Output:** small structured responses (mood enum, search query string, JSON profile, NPC UUID). --- ## Native Action Selector (`action_evaluation` variant) **Prompts:** `prompts/native_action_selector.prompt` (stage 1: pick category) + `prompts/native_action_selector_drilldown.prompt` (stage 2: pick leaf action under that category). **When it fires:** *after* the Dialogue agent produces text, asking "what in-game action does this dialogue imply?". `[hypothesis]` may not fire if `embed_actions_in_dialogue: true` and the Dialogue agent already emitted a valid `ACTION:` line — needs verification (see `open-questions.md`). **Input:** the NPC's just-spoken line + the eligible action list with category groupings. **Output:** `ACTION: CategoryName PARAMS: {"intent": "..."}` from stage 1, then `ACTION: LeafActionName PARAMS: {...}` from stage 2. **Why two stages:** with up to ~105 actions across contributor mods, asking the LLM to pick directly from a flat list is cognitively expensive. Categorizing first (Combat/Communication/Travel/Economy/etc.) narrows the choice set dramatically for stage 2. `[verified]` action firing pattern from `SkyrimNet.log:104547`: `ACTION: Communication PARAMS: {"intent": "express gratitude..."}`. --- ## Vision Agent (`vision` variant — OmniSight) **Prompts:** `prompts/omnisight/describe_actor.prompt`, `describe_scene.prompt`, `describe_item.prompt`, `describe_location.prompt`, `describe_furniture.prompt`, with rendering-mode submodules in `submodules/omnisight_*/`. **When it fires:** on `player_text_input` and `player_direct_input_voice` events. Captures a Skyrim screenshot via `omnisight_capture_image`, then feeds it to the local Qwen3-VL model. **Output:** scene description text (up to 4000 tokens), inserted into the Dialogue agent's context as the `omnisight` block. **Consumers:** the Dialogue agent uses this to ground its response in what's visually present (objects, characters, environment) — not just what's in event logs. --- ## How agents chain `[verified]` agent chains observed in trace `trace_1776469194689_100` (583 spans): ``` GM tick → ACTION: ContinueConversation → DialoguePipeline kicks └─ target_selection_llm (meta) → picks speaker └─ Dialogue agent generates text + optional ACTION line ├─ inline ACTION parsed → action dispatched ├─ remaining text → TTS ├─ mood_evaluation (meta) parallel └─ memory_search_query_generation (meta) parallel ``` For player input: ``` player_text_input → OmniSight (vision) capture → DialoguePipeline kicks └─ same downstream as above ``` ## Open questions about pipelines See [`open-questions.md`](open-questions.md) for unresolved items: - Does `native_action_selector` always fire, or only when `embed_actions_in_dialogue: false`? - What event types currently trigger non-GM agent firings? (`Events.yaml` lists ~40 event types with toggles.) - Does `gamemaster_scene_planner` ever fire in current config?