For the complete documentation index, see llms.txt. This page is also available as Markdown.

Sync behavior and timing

Understand how dynamic context payloads flush after debounce, how offline queueing works, and when immediate flushes bypass batching.

Dynamic context updates do not send to Convai on every Blueprint call. By default, the plugin waits briefly so rapid changes can merge into one send. This page explains when flushes happen, what each flush contains, and when to bypass the debounce timer.

When updates send

Situation
What happens

Default debounced call while connected

Updates stage locally; one Replace context-update sends after ContextDebounceWindow (default 0.5 s) with no new updates in the window

Rapid burst of updates

All changes in the burst coalesce into one flush; timer resets on each call but cannot exceed ContextMaxDebounceWindow (default 3.0 s) from the first update

bFlushImmediately = true after connect

FlushDynamicContext() runs in the current frame, bypassing debounce

Updates before session connects

Changes accumulate in PendingContextBatch; first flush after connect and debounce deadline

Reset Dynamic Context

Drains staged content first, then sends a Reset context-update, then clears the local tracker

Transport message shape

UConvaiSubsystem::UpdateContext sends a context-update message with a JSON data payload:

JSON field
Values (wire format)
When present

mode

append, replace, reset

Present on every message

run_llm

"auto", "true", "false"

Present on every message — maps from EC_RunLLMOption (Auto, Always, Never)

text

Context string

Omitted on Reset when text is empty

current_attention_object

Object name string

When attention is folded into the same message

Blueprint enum display names (Append, Replace, Reset, Auto, Always, Never) differ from the wire strings above.

Flush payload structure

Each flush that includes staged states or events builds one text payload:

{StateName} is {Value}
{AnotherState} is {Value}
Event text line one
{Key} changed from {OldValue} to {NewValue}
{NewKey} is {NewValue}

The first block is canonical context — states in insertion order ("{Key} is {Value}" per line) followed by events in chronological order. It is built by FConvaiDynamicContextTracker::BuildCanonicalContext().

When the batch's aggregate ShouldRespond is not Never and state delta lines exist, the plugin appends them on the next line after canonical context (one \n separator, not a blank line). Delta lines surface state changes at the tail of the prompt.

For state updates where the new value has more than three whitespace-separated words, the delta line uses "{Key} changed from {OldValue}" without repeating the long new value.

Scenarios during an active session

New state — aggregate ShouldRespond is Never

Triggering call: Set Context State or Set Context States with a key that has not been set before, and every staged item in the batch keeps aggregate ShouldRespond at Never.

The new key enters canonical immediately. No delta lines are added.

New state — aggregate ShouldRespond is Auto or Always

Triggering call: Set Context State or Set Context States with a new key, and at least one staged item raises aggregate ShouldRespond to Auto or Always.

On this flush, the new key is excluded from canonical. A delta line such as Health is 50 is appended after the canonical block.

On the next flush, the key enters canonical normally.

Update to existing state — aggregate ShouldRespond is Never

Triggering call: Set Context State with an existing key, and the batch keeps aggregate ShouldRespond at Never.

The updated value enters canonical. No delta lines are added.

Update to existing state — aggregate ShouldRespond is Auto or Always

Triggering call: Set Context State with an existing key, and at least one staged item raises aggregate ShouldRespond to Auto or Always.

The updated value enters canonical. A delta line describing the transition is appended.

Multiple states at once

Triggering call: Set Context States with a map of key-value pairs, potentially mixing new and existing keys.

All values are written to the tracker. First-appearance deferral applies per new key when aggregate is not Never. All changes share one flush — one Replace context-update.

Add context event

Triggering call: Add Context Event.

The event text is committed to the tracker's event list and appears in canonical. Regular context events are not duplicated into a separate delta line.

Identical event strings staged multiple times in the same debounce window are deduplicated — only the first occurrence is kept for that flush.

Remove context state

Triggering call: Remove Context State.

The key is removed from the tracker. bForceReplace is set so the flush sends canonical context without the removed key. No delta lines are added for removals.

Dynamic context reset

Triggering call: Reset Dynamic Context.

The plugin drains any staged context batch first, then sends a Reset context-update (mode: reset, run_llm: "false") with no text field for the empty Reset payload. The local tracker is cleared after the Reset message.

Queued triggers that already exist when Reset Dynamic Context is called are cleared immediately. Triggers queued after a pending offline Reset may still drain before the Reset during FlushDynamicContext().

When connected, Reset Dynamic Context calls the flush path immediately. When offline, the reset flag waits for the first post-connect flush.

Pre-session queueing

Default debounced mutation calls — Set Context State, Set Context States, Add Context Event, Remove Context State, and Reset Dynamic Context — accumulate in PendingContextBatch while IsChatbotConnected() is false.

TickDynamicContext() keeps accumulating until the session connects. When connected and the debounce deadline is reached, FlushDynamicContext() delivers the pending batch.

Offline updates collapse into the flush behavior described above — not replayed as a sequence of individual messages. After connection, on the first tick where the debounce deadline has elapsed, a batch whose aggregate ShouldRespond remains Never sends the current canonical snapshot from the tracker; batches with aggregate Auto or Always follow the canonical-plus-delta behavior described above. Any pending Reset clears context last.

If Reset Dynamic Context and subsequent updates are all pending offline, the flush sends staged content first, then Reset last.

bFlushImmediately

Each mutation function — Set Context State, Set Context States, Add Context Event, Remove Context State — exposes an Advanced parameter bFlushImmediately. When true, FlushDynamicContext() runs in the current frame.

Use bFlushImmediately for time-critical updates where the default debounce delay would cause perceptible lag. Each immediate call runs FlushDynamicContext() in the current frame and sends a context-update when the chatbot is connected with deliverable staged work. Avoid calling it every tick on continuously changing values.

Reset Dynamic Context calls the flush path immediately when connected. It has no bFlushImmediately parameter.

Next steps

Troubleshoot dynamic contextDynamic context Blueprint reference

Last updated

Was this helpful?