- Pull (
ContextStore) — your support AI agent callsenrich()at query time to fetch relevant context on demand. - Push (
AsyncAgentContextWriter) — actions are streamed to the agent destination as they arrive, and compressed with an LLM before the context window overflows.
What you own vs what the SDK handles
The SDK is built around plain callables — no base classes, no interfaces to implement. You supply functions; the SDK handles the orchestration.| You own | SDK owns |
|---|---|
llm(prompt) → str — any LLM callable | Accumulating actions per session |
embed(text) → list[float] — any embedding function | Detecting when the threshold is crossed |
upsert(id, vector, meta) — any vector store write | Calling your LLM at the right moment |
write_actions(session_id, text) — deliver raw context | Calling your callbacks in the right order |
overwrite_with_summary(session_id, summary) — replace with compressed context | Per-session task isolation (slow sessions never block others) |
on_connect / on_disconnect — lifecycle hooks | The “summary first, redact after” ordering guarantee |
The context window problem
Every user session produces a stream of actions. Left unmanaged, that stream grows unboundedly — eventually overwhelming any agent’s context window. The push model solves this with a two-step pattern:The overwrite requires an LLM step
overwrite_with_summary is not a simple in-memory swap. It is only called after AsyncSessionSummarizer has run your configured prompt through your LLM and produced a summary. The AsyncSessionSummarizer is required — without it there is no LLM call, no summary, and no overwrite.
Real-world example: Intercom
This is exactly how the event connector manages context in Intercom conversations.write_actions_cbposts each batch as an internal admin note to the conversation and records the returnedpart_id.- When K actions accumulate,
AsyncSessionSummarizercalls the LLM viacircuit_breaker_llm. overwrite_cbposts the summary note first, then redacts all old action notes in parallel.
The ordering guarantee
This contract mirrors whatsession_summary_worker.py enforces internally: write_summary (post the new note) runs before pre_write_summary (redact the old notes). The comment in that file reads: “no context gap is ever possible.”
Generic support AI agent example
For a support AI agent where you control the context directly, the pattern is simpler —set_context just overwrites the previous value:
Constructor
AsyncAgentContextWriter(summarizer, overwrite_with_summary, write_actions=None)
The summarizer that accumulates actions and triggers LLM summarisation. Its LLM, threshold, and prompt are configured on this object. The writer hooks into
summarizer.on_summary automatically — do not set on_summary separately.Called after each LLM summarisation. Must post the summary to the destination before removing any previous context. If this callback raises, the overwrite is logged and skipped — the raw action context remains in place.
Called on every new actions batch with the batch formatted as plain text. Use this to keep the destination current between summarisations. Optional — omit if you only want summaries pushed.
Per-session trailing-edge accumulation window in milliseconds. When
> 0,
multiple add() calls arriving within the window are merged into one
ActionsPayload before write_actions is called — reducing destination API
calls when events arrive in bursts.Set to 0 (default) if your write_actions callback already coalesces
internally, such as a BaseChatbotWriter subclass that applies its own
post_link_debounce_s window. Stacking both adds latency with no further
reduction in API calls.Debounce window
Whendebounce_ms > 0, the writer buffers ActionsPayload objects per session and merges them using ActionsPayload.merge() once the window expires with no new arrivals.
The merged payload carries the full combined action list, so AsyncSessionSummarizer threshold counting is unaffected — it sees every action regardless of how many were coalesced.
Avoid double-debouncing. If
write_actions already coalesces internally — for example a BaseChatbotWriter subclass with post_link_debounce_s — keep debounce_ms=0. Stacking both windows only adds latency.API reference
| Method | Description |
|---|---|
.add(payload) | Receive an ActionsPayload — wire to client.on_actions |
Related
- SessionSummarizer — configure the LLM, threshold, and prompt used for compression
- ContextStore — the pull model; fetch enriched context at query time instead of pushing it