Conversation
📝 WalkthroughWalkthroughVersion 0.1.139 introduces conversation history propagation. A new optional property stores thread history on BubbleFlow instances. The runtime extracts thread histories from webhook payloads, formats them as conversation objects, and attaches them to flow contexts. AI agent bubbles auto-inject this history into their parameters. Changes
Sequence DiagramsequenceDiagram
actor Webhook
participant BubbleRunner
participant BubbleFlow
participant ParameterFormatter
participant AIAgentBubble
Webhook->>BubbleRunner: Receive payload with thread_histories
BubbleRunner->>BubbleRunner: Extract & format thread_histories
BubbleRunner->>BubbleFlow: Attach __triggerConversationHistory__
BubbleRunner->>ParameterFormatter: Prepare execution parameters
ParameterFormatter->>ParameterFormatter: Append triggerConversationHistory
ParameterFormatter->>AIAgentBubble: Pass params with history
AIAgentBubble->>AIAgentBubble: beforeAction: auto-inject if missing
AIAgentBubble->>AIAgentBubble: Execute with conversation context
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@packages/bubble-runtime/src/runtime/BubbleRunner.ts`:
- Around line 493-516: The code maps webhookPayload.thread_histories into
__triggerConversationHistory__ without validating each entry, so malformed items
produce entries like "[undefined]: undefined"; update the logic around
webhookPayload/thread_histories and historyWithoutCurrent to filter out entries
missing name or message (and skip non-objects), then map only valid items to {
role: 'user', content: `[${name}]: ${message}` } before assigning to
(flowInstance as any).__triggerConversationHistory__.
🧹 Nitpick comments (3)
packages/bubble-core/src/bubbles/service-bubble/ai-agent.ts (1)
590-602: The type assertion ontriggerConversationHistorybypasses validation.The source type (
context.triggerConversationHistory) hasrole: string, but the target type requiresrole: 'user' | 'assistant'. If upstream data ever includes unexpected roles (e.g.,'system','tool'), they'd pass through unchecked and could cause subtle issues downstream (e.g., when converting to LangChain messages inexecuteAgentat lines 1929-1949, unrecognized roles are silently dropped).Consider filtering to known roles instead of casting:
Suggested safer approach
if ( !this.params.conversationHistory?.length && this.context?.triggerConversationHistory ) { - this.params.conversationHistory = this.context - .triggerConversationHistory as Array<{ - role: 'user' | 'assistant'; - content: string; - }>; + this.params.conversationHistory = this.context.triggerConversationHistory + .filter( + (msg): msg is { role: 'user' | 'assistant'; content: string } => + msg.role === 'user' || msg.role === 'assistant' + ); }packages/bubble-runtime/src/runtime/BubbleRunner.ts (2)
497-502:user_idis declared in the type assertion but never read.The local type includes
user_id: stringbut it is unused in the mapping logic. If it's not needed, removing it keeps the type honest; if it will be needed later (e.g., for distinguishing bot vs. user messages), consider adding a TODO.
504-506: All history entries are hardcoded torole: 'user'.If thread histories could include bot/assistant responses in the future, this will produce incorrect conversation context for the AI agent. Worth noting as a known limitation or adding a comment about the assumption.
| if ( | ||
| webhookPayload && | ||
| Array.isArray((webhookPayload as any).thread_histories) | ||
| ) { | ||
| const threadHistories = (webhookPayload as any) | ||
| .thread_histories as Array<{ | ||
| user_id: string; | ||
| name: string; | ||
| message: string; | ||
| }>; | ||
| if (threadHistories.length > 0) { | ||
| // Convert to {role, content} format — all thread messages are "user" role | ||
| // The last entry is the current message that triggered the flow (already in `message` param), | ||
| // so we only include history up to but NOT including it to avoid duplication | ||
| const historyWithoutCurrent = threadHistories.slice(0, -1); | ||
| if (historyWithoutCurrent.length > 0) { | ||
| (flowInstance as any).__triggerConversationHistory__ = | ||
| historyWithoutCurrent.map((h) => ({ | ||
| role: 'user' as const, | ||
| content: `[${h.name}]: ${h.message}`, | ||
| })); | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Missing validation on individual thread history items.
If any entry in thread_histories has a missing or undefined name or message, the content will be [undefined]: undefined, which would produce confusing conversation history for the AI agent.
Consider adding a guard to filter out malformed entries:
🛡️ Proposed defensive filter
const historyWithoutCurrent = threadHistories.slice(0, -1);
if (historyWithoutCurrent.length > 0) {
(flowInstance as any).__triggerConversationHistory__ =
- historyWithoutCurrent.map((h) => ({
+ historyWithoutCurrent.filter((h) => h.message).map((h) => ({
role: 'user' as const,
content: `[${h.name}]: ${h.message}`,
}));
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if ( | |
| webhookPayload && | |
| Array.isArray((webhookPayload as any).thread_histories) | |
| ) { | |
| const threadHistories = (webhookPayload as any) | |
| .thread_histories as Array<{ | |
| user_id: string; | |
| name: string; | |
| message: string; | |
| }>; | |
| if (threadHistories.length > 0) { | |
| // Convert to {role, content} format — all thread messages are "user" role | |
| // The last entry is the current message that triggered the flow (already in `message` param), | |
| // so we only include history up to but NOT including it to avoid duplication | |
| const historyWithoutCurrent = threadHistories.slice(0, -1); | |
| if (historyWithoutCurrent.length > 0) { | |
| (flowInstance as any).__triggerConversationHistory__ = | |
| historyWithoutCurrent.map((h) => ({ | |
| role: 'user' as const, | |
| content: `[${h.name}]: ${h.message}`, | |
| })); | |
| } | |
| } | |
| } | |
| if ( | |
| webhookPayload && | |
| Array.isArray((webhookPayload as any).thread_histories) | |
| ) { | |
| const threadHistories = (webhookPayload as any) | |
| .thread_histories as Array<{ | |
| user_id: string; | |
| name: string; | |
| message: string; | |
| }>; | |
| if (threadHistories.length > 0) { | |
| // Convert to {role, content} format — all thread messages are "user" role | |
| // The last entry is the current message that triggered the flow (already in `message` param), | |
| // so we only include history up to but NOT including it to avoid duplication | |
| const historyWithoutCurrent = threadHistories.slice(0, -1); | |
| if (historyWithoutCurrent.length > 0) { | |
| (flowInstance as any).__triggerConversationHistory__ = | |
| historyWithoutCurrent.filter((h) => h.message).map((h) => ({ | |
| role: 'user' as const, | |
| content: `[${h.name}]: ${h.message}`, | |
| })); | |
| } | |
| } | |
| } |
🤖 Prompt for AI Agents
In `@packages/bubble-runtime/src/runtime/BubbleRunner.ts` around lines 493 - 516,
The code maps webhookPayload.thread_histories into
__triggerConversationHistory__ without validating each entry, so malformed items
produce entries like "[undefined]: undefined"; update the logic around
webhookPayload/thread_histories and historyWithoutCurrent to filter out entries
missing name or message (and skip non-objects), then map only valid items to {
role: 'user', content: `[${name}]: ${message}` } before assigning to
(flowInstance as any).__triggerConversationHistory__.
Summary
Related Issues
Type of Change
Checklist
pnpm checkand all tests passScreenshots (Required)
For New Bubble Integrations
.integration.flow.ts) covers all operationsAdditional Context
Summary by CodeRabbit
New Features
Chores