> ## Documentation Index
> Fetch the complete documentation index at: https://developer.watson-orchestrate.ibm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# pre:receive

Triggered before chat receives a response from the agent. Use this event to inspect or modify the agent's response before it is rendered in the UI.

## Event properties

<ParamField path="type" type="string" required>
  Always `'pre:receive'`.
</ParamField>

<ParamField path="message" type="object" required>
  The agent's response payload.
</ParamField>

<ParamField path="message.content" type="array" required>
  Array of content items in the response.
</ParamField>

<ParamField path="message.content[].text" type="string">
  Text content of the response item. If you need to modify the displayed text only, update this property.
</ParamField>

<ParamField path="message.content[].response_type" type="string">
  Type of the response item, for example, `'text'`, `'user_defined'`.
</ParamField>

<ParamField path="message.message_state" type="object">
  State information for the message. You can create a new object with the spread operator before adding nested custom properties.
</ParamField>

<ParamField path="message.message_state.user_defined" type="object">
  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`.

  <Note>
    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:

    ```javascript theme={null}
    event.message.message_state = {
      ...event.message.message_state,
      user_defined: {
        ...(event.message.message_state?.user_defined || {}),
        my_custom_flag: true
      }
    };
    ```
  </Note>
</ParamField>

<ParamField path="saveUpdate" type="boolean">
  Set to `true` to persist client-side modifications to the backend database.

  When you modify message content in [`pre:receive`](preReceive), those changes only affect what displays in the UI. This triggers an automatic PATCH API call that persists your changes.

  <Warning>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`.</Warning>
</ParamField>

## Examples

The following example demonstrates how to modify agent response text and add custom feedback controls before displaying the message to the user:

```javascript [expandable] theme={null}
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:

```javascript [expandable] theme={null}
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`](preStreamDelta):

```javascript [expandable] theme={null}
// Suppress streaming deltas during translation
instance.on('pre:stream:delta', (event, instance) => {
    const userLanguage = 'es';
    
    if (userLanguage !== 'en') {
        // Suppress character-by-character rendering
        event.delta.content = [];
    }
});

// Translate complete message
instance.on('pre:receive', async (event, instance) => {
    const userLanguage = 'es';
    
    if (userLanguage !== 'en' && event?.message?.content) {
        for (const content of event.message.content) {
            if (content.response_type === 'text' && content.text) {
                content.text = await translateText(content.text, 'en', userLanguage);
            }
        }
        // Store custom metadata in user_defined namespace
        event.message.message_state = {
            ...event.message.message_state,
            user_defined: {
                ...(event.message.message_state?.user_defined || {}),
                translated_language: userLanguage
            }
        };
    } else {
        event.message.message_state = {
            ...event.message.message_state,
            user_defined: {
                ...(event.message.message_state?.user_defined || {}),
                translated_language: 'en'
            }
        };
    }
    
    event.saveUpdate = true;
});
```

## Considerations

### Persistence across sessions

Modifications made in [`pre:receive`](preReceive) might not run in all scenarios, for example:

* Users might close browser before response arrives.
* Users navigate away during response.
* Long-running flows return responses hours later.

To address persistence across sessions, you can implement the same logic in both events:

1. Use [`pre:receive`](preReceive) for new messages.
2. Use [`pre:threadLoaded`](preThreadLoaded) for historical messages.
3. Add a tracking flag in `message_state.user_defined` to avoid duplicate processing.

Example tracking flag: `message_state.user_defined.already_processed = true`

<Card title="Do you need practical examples?" icon="text-align-start" href="https://www.ibm.com/docs/SSAVQO/deploy/web_chat_agent/tutorials/tutorials_lp.html" arrow="true" cta="Learn with walk-throughs" horizontal>
  Learn how to apply the features available for embedded chat into your implementation with guidance and examples.
</Card>
