The SDK builds every ad request from the conversation you feed it. Messages are the only contextual signal that changes during a session, so getting them right is the single most important thing for ad relevance and for the ad-cache mechanics to work.Documentation Index
Fetch the complete documentation index at: https://docs.kontext.so/llms.txt
Use this file to discover all available pages before exploring further.
The message shape
Every SDK accepts the same four fields per message (the exact type names differ per platform — see the SDK pages):| Field | Type | Required | Purpose |
|---|---|---|---|
id | string | yes | Stable, unique identifier for this message. The SDK keys the ad cache and routes events by this id. |
role | user or assistant | yes | Who sent the message. The SDK only triggers preloads on user messages but uses both roles for context. |
content | string | yes | The visible text of the message. |
createdAt | timestamp | yes | When the message was created. |
content should be the visible text of the message — what the user reads on screen. Don’t pre-process it (strip markdown, summarize, etc.) — the server uses the same text the user sees.
Stable IDs
id is the join key between everything else the SDK does:
- The ad cache stores returned ads under each assistant message’s
id(see Displaying ads for the pairing rules). - The ad component (
<InlineAd messageId="..." />or equivalent) looks up its ad by the sameid. - Ad lifecycle events (
filled,no-fill,viewed,clicked…) carry themessageIdso you know which slot they refer to.
Pass every message, both roles
Send both user and assistant messages throughaddMessage. The SDK uses the full conversation, not just the last message, to find a contextually relevant ad. Skipping assistant messages — or, conversely, only forwarding assistant messages — biases the context the server sees and degrades relevance.
Assistant messages are especially important. Kontext ads are generated to follow on directly from the preceding assistant reply — matching its tone and continuing its voice so the ad reads as a smooth continuation of the conversation rather than a hard ad break. If the SDK never sees your assistant messages, the ad has nothing to mimic and the transition becomes jarring.
This is true even when you don’t want an ad on a given turn. If you’d like to suppress ads but keep the conversation context intact (for example, only show ads every Nth turn, or for users on a free trial), pass the message normally with AddMessageOptions(trackOnly: true) — see Pacing.
When to call addMessage
Call addMessage once per message, when the message reaches its final form:
- User messages — call right after the user submits, before you forward the message to your LLM backend.
- Assistant messages — call when the assistant’s reply has finished streaming, not per token.
/preload when a newer addMessage arrives. Rapid back-to-back calls — a user message immediately followed by an assistant reply, several messages restored from history, or any other burst — are coalesced into a single request for the most recent state.
Restoring a conversation from your backend
When the user reopens a conversation, calladdMessage once per historical message in order. The same debounce coalesces them into a single preload for the most recent user message — you do not pay a network round-trip per restored message.
If your backend stores its own message ids, reuse them. If you have to generate fresh ones (because old ids were not persisted), be aware the SDK will see this as a fresh conversation — fine for context, but any ad the server might have served against the original ids will not be reusable.
Common mistakes
- Regenerating
idon every render. Use a stable id per message. UUIDs created in the component body during rendering will not survive a re-render and will break ad lookup. - Skipping assistant messages. Both roles go through
addMessage. Skippingassistantrows weakens contextual targeting. - Skipping messages “because they don’t need an ad”. Use
trackOnly: trueinstead — see Pacing.
Where to next
Ad lifecycle events
The
filled, no-fill, and render-time events that flow back per messageId.Pacing
Keeping conversation context intact while suppressing the ad for a turn.
Session lifecycle
Where
addMessage fits in the broader session lifecycle.