How dynamic context works
Understand the states and events model, canonical context format, and how updates queue and flush before and during conversations.
Dynamic Context gives characters a live, structured view of what is happening in the scene. Instead of relying only on the static system prompt configured on the Convai dashboard, a character can reference a trainee's current location, the equipment they have collected, or an alarm that just triggered — because that information was injected directly into the session as it occurred. This page explains the underlying model: what the primitives are, how the SDK assembles them into a canonical context string, and why updates queue safely before a conversation starts.
States and events
Dynamic Context is built on two primitive types.
States are persistent, named key-value pairs. Each state has a name and a value. When you set a state, any previous value for that name is replaced. States are suitable for facts that change over time but have exactly one current value: the operator's current station, the hazard level in a zone, or whether a checklist item has been completed.
Events are chronological, one-time occurrences. Unlike states, events accumulate in sequence and are never replaced or deduplicated. Each call to AddEvent appends a new line to the character's context. Events are suitable for things that happened during a session and that the character should be able to reference in order: "Trainee bypassed the manual lockout procedure", "Chemical alarm triggered at Bay 7".
Both primitives feed into the character's awareness simultaneously. States provide a stable, queryable snapshot of current conditions; events provide a chronological record of what has happened.
Canonical context format
When the SDK sends an update to Convai, it assembles a canonical context string from all tracked states and events:
{StateName} is {Value}
{AnotherState} is {Value}
Event text line one
Event text line twoStates appear first, in the order they were first set — updating a state's value does not change its position. Events follow in call order after all states.
The reason states preserve insertion order across updates is to give the character a stable, predictable view of the world. If Station was the first thing set, it always appears first in the character's context, regardless of how many times the value has changed. This makes the context easier for the model to interpret consistently.
Example:
context.SetState("Station", "Bay 3"); // position 1
context.SetState("HazardLevel", "High"); // position 2
context.AddEvent("Operator bypassed interlock");
context.SetState("Station", "Bay 7"); // updates value; position stays at 1Canonical context after all four calls:
You supply only names, values, and event text. The SDK assembles and delivers the canonical string automatically.
Two entry points
Dynamic Context has two entry points that write to the same underlying tracker and produce identical network behavior.
Inspector — ConvaiDynamicContextCommand
Add this MonoBehaviour to the NPC's GameObject and configure the command type, fields, and reaction mode in the Inspector. Call Execute() from a UnityEvent, trigger collider, timeline marker, or UI button. No scripting required. One component encapsulates one command; for multiple commands per NPC, place each on a child GameObject.
Use this entry point when:
Context changes are tied to scene events that already fire
UnityEventcallbacksNon-programmers need to configure or modify context triggers
You want to prototype quickly without writing glue code
Scripting — IConvaiDynamicContext
Access character.DynamicContext to get the IConvaiDynamicContext interface and call methods directly from C#. This gives full control over timing, batching, and reaction mode.
Use this entry point when:
Context updates depend on runtime logic or data that cannot be expressed as static Inspector fields
Multiple states must change atomically (use
SetStates)You need to read state values back (
TryGetStateValue)The update source is an external system such as a state machine or analytics pipeline
Pre-conversation queueing
Updates made before a conversation begins are automatically queued by all tracked methods — SetState, SetStates, AddEvent, RemoveState, and Reset. When the session connects, the SDK delivers a single Replace message containing the full canonical context at that moment.
This means you can set initial context freely from Awake or Start without timing concerns. The SDK handles delivery.
The reason this collapses into one Replace rather than replaying individual messages is efficiency: the character receives one authoritative snapshot rather than a stream of incremental updates that could arrive out of order or create redundant LLM turns.
Apply() is the one exception: it does not queue. If called before a conversation starts, the update is discarded. Use SetState, AddEvent, or other tracked methods for pre-conversation context. See Dynamic context scripting API for details.
When to use which command type
Track one current condition
SetState
Track several conditions that change at the same moment
SetStates (one canonical rebuild, one network round-trip)
Record that something happened
AddEvent
Remove a condition that no longer applies
RemoveState
Clear all runtime context (for a new scenario phase)
Reset
Send externally constructed context text
Apply() — advanced; does not queue
Next steps
Dynamic context quick startCommand component referenceSync behavior and timingLast updated
Was this helpful?