UOM Assistant Frontend: State Synchronization & LangGraph Runtime
This document explains the runtime state machine integration, event stream adapters, checkpoint backtracking logic, and manual checkpoint recovery routines utilized in the UOM Assistant frontend dashboard.1. The Runtime Wrapper & Local State Machine
The interface communicates with the LangGraph backend via theuseLangGraphRuntime hook, which is wrapped in a provider component to distribute state across the workspace:
- File Path:
frontend/uom-translator-ui/components/assistant-ui/runtime/assistant-runtime-provider.tsx - Component:
AssistantRuntimeProviderWrapper
graphState: APartial<BackendState>containing the active translation data, validation errors, and equivalence diff logs.errorandrunError: Diagnostic models logging compilation failures and stream aborted triggers.activeNode: Identifies the current executing python node in the backend (e.g., input extraction, schema inspection, compilation validation, equivalence checks, and evaluations).
2. Configurable Context Injection (stream)
When a user submits a query via the Composer input, the custom stream callback triggers. This method loads credentials and database configuration settings from localStorage under the "uom_translator_config" key and injects them as a structured payload into the run execution context. For more information on LanGraph SDK client methods/options (streamMode, streamSubgraphs, context), see the LangGraph SDK documentation.
assistant-ui runtime, which are passed through the config argument of the stream method:
abortSignal: AnAbortControllersignal that can be triggered to cancel the stream.command: An optional command object (e.g.{ resume: ... }), used by theInterruptHandlercomponent to resume a suspended graph. Itsresumevalue is forwarded verbatim to the backendinterrupt()call (see §6).checkpointId: An optional string identifier for resuming from a specific checkpoint in the thread history.
2.1 LLM Backend Switcher
This injection logic allows users to swap models and providers on-the-fly:- Local Ollama Deployment: Directs requests to a local daemon (e.g.,
http://localhost:11434) running open-weights models likeqwen2.5-coder. - Remote Metacentrum e-INFRA CZ: Routes calls through Metacentrum’s OpenAI-compatible APIs, providing access to larger models like
einfra/kimi-k2.6oreinfra/deepseek-v4-pro-thinking.
3. Sub-graphs, Event Handlers, & Custom Telemetry
The runtime adapter processes LangGraph events to sync backend execution details with the UI.3.1 Sub-graph State Merging
To track execution parameters inside nested validation or equivalence test subgraphs, the runtime processes sub-graph values and merges them into the main state object. See LangGraph Subgraph Docs how multi-agent orchestration works.3.2 Custom Event Logs (onCustomEvent)
The Python orchestrator streams container log details and validation updates as custom events, which are processed by the runtime for debugging:
3.3 Noise Reduction Error Filtering
To prevent system warnings or connection resets from flooding the user console, the error handler implements a filtering system that ignores known harmless messages:5. Thread List Synchronization (RemoteThreadListAdapter)
Note: The adapter definitions in this section are simplified conceptual representations of the actual implementation.
The frontend maps UI actions (like creating or deleting threads) to the backend database using a thread list adapter:
5.1 Adapter Methods
list(): Queries the thread catalog usingclient.threads.search(returning up to 50 threads sorted by creation date descending):rename(remoteId, newTitle): Updates metadata tags stored on the server:delete(remoteId): Removes the thread from server persistence:initialize(): Provisions a new thread identifier on the server, initialized with a timestamped title:fetch(threadId): Retrieves the current state and messages for the selected thread:
6. Interrupt & User Decision Flow (InterruptHandler)
- File Path:
frontend/uom-translator-ui/components/assistant-ui/interrupt-handler.tsx - Component:
InterruptHandler
human_intervention_node suspends execution using LangGraph’s native interrupt() API (not a tool call). The interrupt payload carries an instruction plus the current translation state:
InterruptHandler reads this payload, renders the explanation and the query-equivalence deep diffs, and presents the Accept / Reject decision controls.
6.1 State Transitions during Suspends
The component uses hooks from@assistant-ui/react-langgraph to resume the graph:
-
useLangGraphInterruptState(): Accesses the active suspend payload viainterrupt.value. The card renders whenever a payload is present.Do not gate on
interrupt.resumable. That field is deprecated in@langchain/langgraph-sdk(≥ 1.x) and omitted by recent servers, so guarding on it hides the card entirely (both live and on reload). -
useLangGraphSendCommand(): Resumes execution by posting the decision object back to the suspended node. The value becomes the return value of the backendinterrupt()call and is validated against theHumanInterventionResponsePydantic model, so both fields are required and it must be an object — not a bare string or a JSON-encoded string:
6.2 Persistence across reloads
Because the backend uses a nativeinterrupt(), the suspension is part of the thread’s server-side checkpoint. The runtime’s load() callback returns it so the card reappears when an interrupted conversation is reopened from the thread list:
Why nativeFor more information on interrupt handling and human-in-the-loop patterns, see the LangGraph Interrupts Documentation and the assistant-ui LangGraph Interrupts guide.interrupt()rather than the tool-message approval pattern? The assistant-ui Approval UI tutorial resumes by appending aToolMessage(viaaddResult) to a pending tool call. That mechanism is incompatible withinterrupt()+Command(resume):addResultsends new input rather than a resume command, and it would require the backend graph to be rebuilt around a pending tool call. The native interrupt keeps the human-in-the-loop gate as a first-class checkpoint that persists and restores cleanly.