A dedicated namespace for your custom metadata. Use this namespace to:
Prevent conflicts with system properties.
Keep your custom data organized.
Ensure future platform updates do not break your code.
To use this namespace, create a new message_state object and a new user_defined object inside it. Add your custom properties inside user_defined.
If message_state or user_defined was previously sealed or made non-extensible, directly assigning a new nested property can throw an Object is not extensible error in strict mode. To make your code more robust and preserve existing properties, use the spread operator to create a fresh object reference before adding custom fields:
Set to true to persist client-side modifications to the backend database.When you modify message content in pre:receive, those changes only affect what displays in the UI. This triggers an automatic PATCH API call that persists your changes.
The system does not automatically set tracking properties. If you need to track whether modifications were applied, create a new message_state object and set the flag inside message_state.user_defined before enabling saveUpdate.
The following example demonstrates how to modify agent response text and add custom feedback controls before displaying the message to the user:
instance.on('pre:receive', (event, instance) => { // Log the incoming message for debugging purposes console.log('About to receive message:', event.message); // Modify response text by replacing specific words // This iterates through all content elements in the response event?.message?.content?.forEach((element) => { if (element?.text?.includes('assistant')) { // Replace 'assistant' with 'Agent' for brand consistency element.text = element.text.replace('assistant', 'Agent'); } }); // Add feedback controls to the last item in the response // This allows users to provide feedback on the agent's response const lastItem = event?.message?.content?.[event.message.content.length - 1]; if (lastItem) { lastItem.message_options = { feedback: { is_on: true, // Enable feedback controls show_positive_details: false, // Hide details form for positive feedback show_negative_details: true, // Show details form for negative feedback positive_options: { categories: ['Helpful', 'Accurate', 'Clear'], disclaimer: "Your feedback helps us improve." }, negative_options: { categories: ['Inaccurate', 'Incomplete', 'Confusing', 'Other'], disclaimer: "Please provide details to help us improve." } } }; }});
The following example demonstrates how to translate agent responses from English to the user’s preferred language before displaying them in the UI:
instance.on('pre:receive', async (event, instance) => { // Define the user's preferred language (could be dynamic based on user settings) const userLanguage = 'es'; // User's preferred language // Only translate if the user's language is not English if (userLanguage !== 'en' && event?.message?.content) { // Translate each text content item in the response // Agent responses can contain multiple content items for (const content of event.message.content) { if (content.response_type === 'text' && content.text) { // Translate from English to user's language // Note: translateText() is a placeholder - implement your own translation service const translatedText = await translateText(content.text, 'en', userLanguage); // Update the text that will be displayed in the UI content.text = translatedText; } } // Store custom metadata in user_defined namespace // Use the spread operator to preserve existing properties and avoid // issues with sealed or non-extensible objects in strict mode event.message.message_state = { ...event.message.message_state, user_defined: { ...(event.message.message_state?.user_defined || {}), translated_language: userLanguage } }; } else { // Mark as English (no translation needed) event.message.message_state = { ...event.message.message_state, user_defined: { ...(event.message.message_state?.user_defined || {}), translated_language: 'en' } }; } // Trigger automatic persistence to save the translated message // This makes a PATCH API call to update the message in the database event.saveUpdate = true;});
The following example demonstrates how to translate with streaming suppression. When using translation with streaming responses, suppress delta rendering in pre:stream:delta: