Runtime engine

How Convoship executes assistant flows — node types, intent matching, knowledge fallback, and instruction agents.

The runtime is a stateless flow walker in apps/studio-api/app/runtime/engine.py. Each turn loads the published ConversationFlow (or draft in simulator), walks nodes until awaiting input or session end, and returns bot messages plus debug metadata.

Intent matching order

  1. Welcome event on session start when enabled.
  2. Small talk topics — pattern score before intents.
  3. Substring match on training phrases.
  4. LLM verify — confirm keyword match semantically (fails open on LLM outage).
  5. LLM match — full intent classifier when substring misses.
  6. Knowledge fallback — hybrid search when no intent; synthesize answer if score clears threshold.
  7. Fallback event / fallback intent.

Node types (assistant sub-flows)

TypeBehavior
start / endSession entry and termination
intentEntry node for matched intent sub-flow
messageBot text; {{ session.var }} templates; rich UI blocks
entitySlot capture with reprompt and max_attempts
decisionExpression branch on edges
serviceHTTP tool — real httpx call, JSONPath outputs
pythonSandboxed script — session read/write
setAssign session variable
handoffHuman agent transfer
fallbackDefault branch
subflowInvoke another flow graph
knowledgeHybrid retrieval + optional LLM synthesis from chunks
instruction_agentAgenticLoop — multi-step LLM + tool calls

instruction_agent nodes

Configured in flow JSON with instructions, tools[], optional model, temperature, max_steps, greeting. Uses AgenticLoop with OpenAI-compatible or Anthropic provider from settings.effective_agent_*. Memory persists under session variable _agent_memory_{nodeId}. ToolBridge executes workspace/agent tools registered on the node.

Knowledge nodes

  • Query from static template, last user message, and/or conversation summary (LLM summary when configured).
  • Retriever — vector + keyword hybrid (pgvector + tsvector).
  • synthesize_answer — uses extraction provider LLM (Groq/OpenAI/Anthropic).
  • Respects knowledge_fallback_min_score when used as runtime fallback path.

Service nodes

  • Template URL, headers, body with {{ variables }}.
  • Workspace secrets resolved at runtime — never stored in flow JSON.
  • Retries, timeout, JSONPath mapping to session.*.
  • response_body stored on session for simulator trace.

Safety limits

  • 64 steps per turn cycle guard.
  • Python node wall-clock timeout (PYTHON_NODE_TIMEOUT_SECONDS).
  • Free-tier session/import rate limits via usage_events (429 + X-RateLimit-*).
  • Monthly LLM spend cap per assistant — blocks enrichment and intent LLM matcher.

Agent-level orchestration

agent_runtime.py sits above engine.py for multi-intent assistants: tracks _active_intent_id, routes utterances to intent sub-flows, returns to root when sub-flow completes, handles welcome/fallback at agent scope.

Workflow graph runtime

Legacy workflows use workflow_graph_runtime.py plus runtime route handlers (not engine.py intent matching). The simulator walks nodes from triggers/root_agent through agents, knowledge, router/decision branches, tool nodes, nested workflow handoffs, and end nodes.

  • Routing — select_workflow_successor_node evaluates edge condition.expr against last user text and variables.
  • Tool nodes — ToolBridge executes workspace tools; trace event workflow.tool.executed.
  • Sub-workflow — workflow nodes load the referenced graph and enter its first runnable node.
  • Publish validation — rejects script, datastore, set, human, parallel, wait; requires reachable agent/knowledge/end from entries.
  • Chain runtime — workflow_chain_runtime.py runs primitive chains (assistant, agent, webhook, human, decide, notify, schedule) with persisted WorkflowChainRun steps.