nemo_voice_agent.evaluation.sync_appliers
nemo_voice_agent.evaluation.sync_appliers
Cross-side sync-delta applier registry (bot-side).
This module is the bot-side endpoint of the cross-side state-propagation
pipeline introduced for dual-side scenarios (telecom and any future
domain that opts into Scenario.sync_state).
The pipeline at a glance:
- A write tool on bot A fires and calls
WriteScenarioTool._record_action, which (in addition to appending toshared_state["actions"]) emits anaction-appliedRTVI server message. - The bridge picks that up, replays the action onto an in-process shadow
copy of both DBs (using the scenario’s tool map + each tool’s sync
invokemethod), then callsscenario.sync_state(agent_db, user_db). sync_statereturns a per-sidedeltadict describing the cross-side field changes that must land on the OTHER bot. The bridge dispatches each delta via theapply_sync_deltaRTVI action.- The receiving bot’s handler calls into
apply_sync_delta(domain, db, delta)in this module to mutate its ownshared_state["db"].
The default applier handles “dotted path → value” deltas (e.g.
"surroundings.payment_request": {...}) and is sufficient for any
domain whose cross-side propagation is pure field assignment. Domains
needing more (list-by-id lookups, post-apply re-derivation hooks,
domain-specific validation) register a per-domain applier via
@register_sync_applier(domain="...").
This is structurally parallel to initialization_functions and
db_state_predicates — same registry-by-domain pattern, same
opt-in shape.
Module Contents
Functions
Data
API
Generic dotted-path field setter.
Each delta key is a dotted path into db; the corresponding
value is assigned at that path. The path components are followed
verbatim — no list-index or by-id-match support. Domains needing
those (e.g. bills[B1002].status) must register their own
applier.
Example::
delta = {“surroundings.payment_request”: {“bill_id”: “B1002”, …}}
→ db[“surroundings”][“payment_request”] = {“bill_id”: “B1002”, …}
Raises:
KeyError: if an intermediate path component doesn’t exist indb.
Dispatch a sync delta to the registered applier for domain.
Falls back to _default_sync_applier (dotted-path field set) when
no per-domain applier exists. The default suffices for any future
domain whose sync deltas are pure field assignments.
Parameters:
Scenario.domain value of the active scenario.
The bot’s live shared_state["db"] (mutated in place).
Cross-side delta from the bridge — shape is domain-defined.
Decorator: register a domain-specific applier.
The applier signature is func(db: dict, delta: dict) -> None
and must mutate db in place. The exact shape of delta is
a contract between the scenario’s sync_state (which produces
it) and the applier (which consumes it) — the bridge transports
it verbatim.
Usage::
@register_sync_applier(domain=“tau2_telecom”) def apply_telecom_sync_delta(db: dict, delta: dict) -> None: …