fix: handle UserCustomSent in history and LLM message builder#188
fix: handle UserCustomSent in history and LLM message builder#188TajPelc wants to merge 1 commit intocartesia-ai:mainfrom
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
400e829 to
3abb73d
Compare
## Problem
When UserCustomSent is included in run_filter to enable client-to-agent
custom events (e.g. billing signals, purchase notifications), the agent
crashes on the NEXT user turn with:
ValueError: Unknown event type in history: UserCustomSent
## Root Cause
The ConversationRunner records ALL input events into its raw history,
including UserCustomSent. When the next UserTurnEnded arrives, the
framework passes this history to LlmAgent via event.history. Three code
paths don't handle UserCustomSent:
1. _to_history_event() in history.py — no branch, raises ValueError
2. _HISTORY_EVENT_TYPES tuple — missing UserCustomSent, so
_validate_history() and _validate_context() reject it with TypeError
3. _build_messages() in llm_agent.py — no serialization for the type
## Our Workaround (without SDK fix)
In our agent wrapper, we strip UserCustomSent from event.history before
delegating to inner.process():
if hasattr(event, 'history') and event.history:
clean = [e for e in event.history if not isinstance(e, UserCustomSent)]
event = event.model_copy(update={"history": clean})
async for output in self.inner.process(env, event):
yield output
This prevents the crash but loses the custom event context from history,
meaning the LLM has no memory of client-side events in subsequent turns.
## SDK Fix
- Add UserCustomSent to the InputEvent pass-through block in
_to_history_event() so it's preserved in history
- Add UserCustomSent to _HISTORY_EVENT_TYPES so validation passes
- Add serialization in _build_messages() that converts UserCustomSent to
a system message with the event metadata as JSON, giving the LLM
useful context about client-side events across turns
With this fix, our workaround becomes unnecessary and the LLM naturally
sees context like [Client event: {"kind": "diamonds_purchased"}] in its
conversation history.
3abb73d to
720fb73
Compare
|
Hey @TajPelc, thanks for taking the time to fix this bug! While the crash on If you do wish to send a custom event to the LLM, we recommend you use the LlmAgent#history API to do so. For this specific case, I'd recommend I realize this is slightly inelegant, and we hope to have a better long-term solution soon. We've fixed issues 1 and 2 in a separate PR, and will publish the changes shortly. |

Problem
When
UserCustomSentis included inrun_filterto enable client-to-agent custom events (e.g. billing signals, purchase notifications), the agent crashes on the next user turn with:Root Cause
The
ConversationRunnerrecords ALL input events into its raw history, includingUserCustomSent. When the nextUserTurnEndedarrives, the framework passes this history toLlmAgentviaevent.history. Three code paths don't handleUserCustomSent:_to_history_event()inhistory.py— no branch, falls through toraise ValueError_HISTORY_EVENT_TYPEStuple — missingUserCustomSent, so_validate_history()and_validate_context()reject it withTypeError_build_messages()inllm_agent.py— no serialization for the typeReproduction
agent.process()(works fine)LlmAgent.process()crashesFix
UserCustomSentto the InputEvent pass-through block in_to_history_event()UserCustomSentto_HISTORY_EVENT_TYPESso validation passes_build_messages()that convertsUserCustomSentto a system message with the event metadata as JSONUserCustomSentin_build_full_historyWith this fix, the LLM naturally sees context like
[Client event: {"kind": "diamonds_purchased"}]in its conversation history.Current Workaround
Without this fix, agents must strip
UserCustomSentfromevent.historybefore delegating toLlmAgent.process():This prevents the crash but loses the custom event context from history.
Note
Medium Risk
Changes history validation/normalization and message-building to include
UserCustomSent, which can affect prompt content and downstream LLM behavior; risk is moderate but scoped and covered by new tests.Overview
Prevents crashes when
UserCustomSentappears inevent.historyby allowing it through history validation and_to_history_event()conversion.Extends
_build_messages()to serializeUserCustomSentinto asystemmessage containing the eventmetadata(JSON or a fallback marker), so client-side custom signals become part of the LLM context.Adds unit tests covering
UserCustomSentpassthrough in_build_full_historyand its serialization behavior in_build_messages().Written by Cursor Bugbot for commit 720fb73. This will update automatically on new commits. Configure here.