agent-mode-routing

star 0

Use when adding, editing, or debugging agent mode selection, LLM provider routing, Helix/heuristic fallback, the five-mode picker UI, or any code in bankingAgentLangGraphService, agentModeResolver, llmProviderResolver, or the agentMode.* / agentHelixUnconfigured tests. Also use when the agent appears to do nothing, returns "Advanced reasoning is temporarily unavailable", or ignores the selected mode. NOTE — this skill covers the BFF/Node.js agent only (demo_api_server). For the Python LangGraph agent (langchain_agent/, ports 8888–8890) use the langchain-agent skill instead.

curtismu7 By curtismu7 schedule Updated 6/7/2026

name: agent-mode-routing description: Use when adding, editing, or debugging agent mode selection, LLM provider routing, Helix/heuristic fallback, the five-mode picker UI, or any code in bankingAgentLangGraphService, agentModeResolver, llmProviderResolver, or the agentMode.* / agentHelixUnconfigured tests. Also use when the agent appears to do nothing, returns "Advanced reasoning is temporarily unavailable", or ignores the selected mode. NOTE — this skill covers the BFF/Node.js agent only (demo_api_server). For the Python LangGraph agent (langchain_agent/, ports 8888–8890) use the langchain-agent skill instead.

Agent Mode Routing — Architecture & Rules

Two separate agents exist in this repo:

  • BFF/Node.js agent (demo_api_server/services/bankingAgentLangGraphService.js) — this skill covers it. Runs inline in the BFF process.
  • Python LangGraph agent (langchain_agent/, ports 8888/8889/8890) — use the langchain-agent skill for that. Separate uvicorn process with its own LLM factory and MCP connections.

Do not confuse the two. A bug in "the LangGraph agent" might be in either one.

When to Use

  • Adding, editing, or debugging agent mode selection or the five-mode picker UI
  • Investigating LLM provider routing, Helix/heuristic fallback, or agentModeResolver/llmProviderResolver logic
  • Debugging when the agent does nothing, returns "Advanced reasoning is temporarily unavailable", or ignores the selected mode
  • Working with bankingAgentLangGraphService, agentMode.* tests, or agentHelixUnconfigured tests

When NOT to Use

  • The Python LangGraph agent (langchain_agent/, ports 8888–8890) — use langchain-agent instead
  • MCP server tool registration or WebSocket protocol — use mcp-server instead

The Five Modes (BFF Agent)

ID Label Provider Heuristic routing LLM fallback Shown in UI?
heuristics Heuristics only none none — catalog message on no-match
helix_google Helix (Google/Gemini) helix Helix always
heuristics_helix Heuristics + Helix helix Helix on no-match
chatgpt Just ChatGPT openai OpenAI Responses API (BFF or platform wiring) ❌ hidden
claude Just Claude anthropic Anthropic Messages API (BFF or platform wiring)

UI visibility: AgentModeSelector.jsx filters to CORE_MODE_IDS = ['heuristics', 'helix_google', 'heuristics_helix', 'claude']. The chatgpt mode exists in agentModeResolver.js and is selectable via API but is hidden from the UI. Do not add it back to the UI selector without an explicit decision.

anthropic-lmstudio provider: exists in langchainConfig.js for LM Studio's Anthropic-compatible endpoint (local dev). It is not a UI-selectable mode; it is a provider value that can be set via POST /api/langchain/config. The BFF's llmProviderResolver.js passes it through to :3006.

Single SSOT: demo_api_server/services/agentModeResolver.js — never inline a provider default anywhere else.

Default mode (DEFAULT_MODE): heuristics_helix — but agent_mode in configStore defaults to '' (empty string). An empty rawMode is falsy, so resolveAgentMode is never called for a fresh install. The heuristicEnabled path reads ff_heuristic_enabled instead.


The Helix-Unconfigured Fallback (ARCHITECTURE-TRUTH T-3b)

Rule: When the resolved provider is helix and no helix_api_key is present, the agent MUST return the heuristic catalog message (buildCatalogMessage()) with success: true. It must NOT call :3006 or return reasoning_unavailable.

Where it lives: bankingAgentLangGraphService.js — immediately before runReasonLoop, after resolveLlmProvider.

if (provider === 'helix') {
  const helixCfg = extractHelixConfig(langchainConfig);
  const helixApiKey = helixCfg.helix_api_key || configStore.getEffective('helix_api_key') || '';
  if (!helixApiKey) {
    // No Helix credentials — fall back to heuristics-only catalog
    if (req) req.agentPath = 'heuristic';
    return {
      reply: buildCatalogMessage(),
      success: true,
      toolsCalled: [], tokensUsed: 0, requiresConsent: false,
      agentConfigured: true, tokenEvents: req?.tokenEvents || [],
    };
  }
}

"Configured" definition: helix_api_key is present and non-empty. helix_base_url and helix_agent_id have FIELD_DEF defaults so they are always populated.


Provider Resolution Order

langchainConfig.provider
  'helix'   → helix
  'openai'  → openai (pass-through; :3006 enforces creds)
  'anthropic'→ anthropic (pass-through; :3006 enforces creds)
  <absent>  → helix  ← catch-all default

Never add a new default. llmProviderResolver.js is the single provider resolver — all catch-alls live there.


Mode Selector → configStore → Runtime Flow

UI selects mode
  → POST /api/langchain/config { agent_mode, external_wiring }
  → configStore.setConfig({ agent_mode: am.mode })
  → langchainConfig.provider = am.provider written to session

On message:
  rawMode = configStore.getEffective('agent_mode')  // '' on fresh install
  _agentMode = rawMode ? resolveAgentMode(rawMode, ...) : null
  heuristicEnabled = rawMode ? _agentMode.heuristicRouting
                             : ff_heuristic_enabled !== 'false'

Critical: rawMode = '' is falsy. resolveAgentMode is only called when agent_mode has been explicitly set via the UI or config POST. The default path reads ff_heuristic_enabled for the heuristic gate and langchainConfig.provider for the LLM provider.


Test Coverage Required

Every test that exercises processAgentMessage through the LLM/reason-loop path (i.e. it mocks agentReasoningClient.runReasonLoop) must include helix_api_key: 'test-key' in its TEST_CONFIG mock. Without it, the Helix-unconfigured check fires first and the mocked reason loop is never reached.

const TEST_CONFIG = {
  ff_heuristic_enabled: 'false', // force LLM path
  helix_api_key: 'test-key',    // satisfy Helix-configured check
};

Regression test: demo_api_server/tests/agentHelixUnconfigured.regression.test.js — must stay green. It asserts:

  • success: true when helix_api_key is absent
  • reply === buildCatalogMessage()
  • axios.post (:3006) is never called

UI Consistency Rule

The agent chat UI must display the catalog message as a normal assistant message when success: true — not as an error toast or "could not parse" message. The reasoning_unavailable error code (success: false) triggers reportNlFailure; the catalog reply does not.

Any UI path that receives response.success === true && response.reply must render it as an assistant message, regardless of whether an LLM was involved.


Common Mistakes

Mistake Fix
Adding a provider default outside llmProviderResolver.js Move it there; it's the single SSOT
Test expects reason loop to run but helix_api_key absent in mock Add helix_api_key: 'test-key' to TEST_CONFIG
Changing DEFAULT_MODE without updating agentModeResolver.regression.test.js Update the DEFAULT_MODE export test and the null/undefined/empty test
Treating agent_mode: '' the same as agent_mode: 'heuristics_helix' They behave differently: '' skips resolveAgentMode, 'heuristics_helix' calls it
Returning success: false / reasoning_unavailable when Helix is unconfigured Must return success: true + catalog message — the agent is responding, just in heuristics-only mode

Files to Read Before Editing

File Role
demo_api_server/services/agentModeResolver.js Five-mode SSOT + DEFAULT_MODE
demo_api_server/services/llmProviderResolver.js Provider catch-all — Helix default lives here
demo_api_server/services/bankingAgentLangGraphService.js Helix-unconfigured fallback + heuristic gate
demo_api_server/services/configStore.js (line ~287) agent_mode field def — default is '' not 'heuristics_helix'
demo_api_server/tests/agentHelixUnconfigured.regression.test.js Regression for the fallback
demo_api_server/tests/agentModeResolver.regression.test.js Mode SSOT regression
Install via CLI
npx skills add https://github.com/curtismu7/AI-demo --skill agent-mode-routing
Repository Details
star Stars 0
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator