Skip to content

Canned Responses

Canned Responses enable agents to use pre-defined message templates for common queries, improving response time and consistency.

User Story: As a support agent, I want to use pre-defined response templates so that I can respond quickly to common customer questions.

Acceptance Criteria:

  • ✅ Browse available canned responses
  • ✅ Search canned responses by keyword
  • ✅ Insert canned response into message input
  • ✅ Preview response before sending
  • ✅ Filter by category/tags
  • ✅ Support variable interpolation

Inputs:

  • Search query
  • Selected canned response

Outputs:

  • Filtered list of canned responses
  • Formatted response text with variables replaced
User Opens Chat Screen
Dispatch: fetchCannedResponses()
API Request: GET /canned_responses
Transform Response Data
Store in Redux (cannedResponses.byId, allIds)
Ready for Use in Message Input
User Types '/' in Message Input
Show Canned Response Picker
User Types Search Query
Filter Canned Responses by Short Code or Content
Display Matching Responses
User Selects Response
Replace Variables ({{contact.name}}, {{agent.name}})
Insert into Message Input
User Reviews and Sends

Request:

GET /api/v1/accounts/{accountId}/canned_responses

Response:

{
data: CannedResponse[]
}
interface CannedResponse {
id: number;
short_code: string;
content: string;
account_id: number;
}

Supported Variables:

const VARIABLES = {
'contact.name': () => contact.name,
'contact.email': () => contact.email,
'agent.name': () => currentUser.name,
'agent.email': () => currentUser.email,
};
export const CannedResponsePicker = ({
onSelect,
}: {
onSelect: (response: CannedResponse) => void;
}) => {
const [search, setSearch] = useState('');
const cannedResponses = useAppSelector(selectAllCannedResponses);
const filteredResponses = useMemo(() => {
return cannedResponses.filter(
response =>
response.shortCode.includes(search) ||
response.content.toLowerCase().includes(search.toLowerCase())
);
}, [cannedResponses, search]);
return (
<View>
<TextInput
value={search}
onChangeText={setSearch}
placeholder="Search canned responses..."
/>
<FlatList
data={filteredResponses}
renderItem={({ item }) => (
<TouchableOpacity onPress={() => onSelect(item)}>
<View style={tailwind('p-3 border-b border-gray-3')}>
<Text style={tailwind('text-blue-9 font-inter-semibold-20')}>
/{item.shortCode}
</Text>
<Text style={tailwind('text-gray-11 text-xs mt-1')} numberOfLines={2}>
{item.content}
</Text>
</View>
</TouchableOpacity>
)}
/>
</View>
);
};