Context updates
Push live storefront context — a client-created cart_id, available offers, the current page — into an open Buddy Assist session without spending an LLM turn.
The storefront often knows things mid-conversation that the agent should use: the shopper just created a cart client-side, there’s a coupon available, they’re looking at a specific product. Context updates let you push that into a live session without sending a message — no LLM turn, no chat bubble. The agent picks it up on the shopper’s next message.
There are two kinds of context, and they go to two different places:
| Kind | What it is | Example | Goes to |
|---|---|---|---|
| State | Identifiers the agent threads into tool calls — the shopper never reads them | cart_id, checkout_id, selected variant | agent_session_state.data |
| Facts | Ambient hints the model reasons over | available offers, cart summary, current page, locale | a clearly-delimited, untrusted context block |
Next-turn-only
The API
After the widget mounts it exposes the same control surfaces as the imperative API — a global, a DOM method, a CustomEvent, and postMessage. Every one of them funnels into the same context-push path.
window.BreezeAssist global
The recommended option for Shopify theme scripts, GTM custom HTML tags, and third-party snippets that don’t own the element reference:
// Full patch — state, facts, or both.
window.BreezeAssist.updateContext({
state: { cart_id: 'gid://shopify/Cart/abc123' },
facts: { offers: [{ code: 'WELCOME10', label: '10% off first order' }] }
});
// Sugar for the two common cases:
window.BreezeAssist.setCartId('gid://shopify/Cart/abc123');
window.BreezeAssist.setFacts({ offers: [{ code: 'WELCOME10' }] }); setCartId(id) is shorthand for updateContext({ state: { cart_id: id } }), and setFacts(facts) for updateContext({ facts }).
DOM method
If you hold the element reference, call the method directly:
const el = document.querySelector('breeze-buddy-assist');
el.updateContext({ state: { cart_id: 'gid://shopify/Cart/abc123' } }); CustomEvent (GTM / tag managers)
Dispatch a breeze-buddy-assist:context event on document — same pattern as the breeze-buddy-assist:command event:
document.dispatchEvent(
new CustomEvent('breeze-buddy-assist:context', {
detail: { state: { cart_id: 'gid://shopify/Cart/abc123' } }
})
); postMessage (iframes)
From a cross-origin context or an iframe:
window.parent.postMessage(
{
type: 'breeze-buddy-assist',
action: 'context',
detail: { facts: { offers: [{ code: 'WELCOME10' }] } }
},
'*'
); Pushed before the panel opens? No problem.
Patch shape
type ClientContextPatch = {
state?: Record<string, unknown>;
facts?: Record<string, unknown>;
merge?: 'shallow' | 'replace'; // default 'shallow'
placement?: 'user_tail' | 'system'; // default 'user_tail'
}; | Field | Default | Notes |
|---|---|---|
state | — | Identifiers shallow-merged into the session’s runtime state. Only keys on the template’s state_allowlist are accepted; everything else is dropped. |
facts | — | Ambient hints, allowlisted + size-capped server-side. Non-allowlisted keys are dropped (and reported back so you can see what landed). |
merge | 'shallow' | 'shallow' merges top-level keys (latest-wins per key); 'replace' swaps the whole namespace. |
placement | 'user_tail' | Where rendered facts land. 'user_tail' frames them as data; 'system' requests instruction-strength adherence — honored only for keys on the template’s trusted_facts list, so shopper-supplied data can never be elevated to instructions. |
Example — push a client-created cart_id
A shopper adds an item via the Storefront / Ajax API, which mints a cart_id on the page. Push it so the agent reuses that cart instead of creating a duplicate:
// After your add-to-cart call resolves:
async function onCartCreated(cart) {
window.BreezeAssist.setCartId(cart.id);
} The template’s tool-arg injection rule fills that cart_id into the next update_cart / checkout tool call automatically — the agent never has to ask “which cart?” and never creates a second one.
cart_id is safe to trust
cart_id is just a handle — the agent re-fetches the authoritative cart from Shopify before acting on it. That's why it's the canonical first entry on the state_allowlist.Example — push available offers
The page knows which coupons the shopper is eligible for. Surface them as facts so the agent can mention them:
window.BreezeAssist.setFacts({
offers: [
{ code: 'WELCOME10', label: '10% off your first order' },
{ code: 'FREESHIP', label: 'Free shipping over ₹2,000' }
],
cart_summary: { item_count: 3, subtotal_display: '₹4,500' },
current_page: { type: 'product', title: 'Cabin Trolley 55cm', handle: 'cabin-trolley-55' }
}); The agent now knows there’s a WELCOME10 offer and can bring it up when the shopper asks about discounts.
Facts are untrusted hints
facts are treated as untrusted data: allowlisted, size-capped, and rendered as a clearly-delimited block the model is told to consider, never obey. Anything money-related — offer eligibility, prices, discounts — is re-validated server-side against Shopify before the agent applies it. A pushed offer is a hint to surface, not authoritative truth. Which keys are allowed (and which may use system placement) is gated by the template's client_context config.Piggyback on a message
For the “create a cart, then immediately ask about it” flow, ride the patch along with the message so it applies to that turn — no separate round-trip. Pass context to send when using the SDK directly:
import { createBuddyChatStore } from '@juspay/breeze-buddy-client-sdk';
const chat = createBuddyChatStore({ publicWidgetKey, shopUrl });
await chat.send('Is my cart eligible for free shipping?', {
context: { state: { cart_id: 'gid://shopify/Cart/abc123' } }
}); The server merges the patch before building the turn, so the very message that references the cart already has it.
SDK reference
If you’re driving the session through the SDK rather than the widget element, updateContext lives on both the widget session and the store:
const result = await chat.updateContext({
state: { cart_id: 'gid://shopify/Cart/abc123' },
facts: { offers: [{ code: 'WELCOME10' }] }
});
// result echoes the keys the server actually accepted after filtering:
// { applied: true, stateKeys: ['cart_id'], factsKeys: ['offers'], revision?: number } updateContext does not mutate the message list — context updates don’t render. It maps the standard widget errors: 409 (another op holds the per-session lock — safe to retry), 410 (session ended), 413 (facts payload over the size cap), and 401 / 403 (auth).
Endpoint
/agent/voice/breeze-buddy/widget/session/{id}/context Called by the embed with the widget_token bearer — you don’t call it directly unless you’re building your own client. Request body is the ClientContextPatch shape above, plus an optional monotonic revision so stale writes are dropped when pushes race. The response echoes the accepted keys:
{
"applied": true,
"state_keys": ["cart_id"],
"facts_keys": ["offers", "cart_summary"],
"revision": 7
}