Suggested Questions After Answer#
Suggested Questions After Answer is a Dify chat feature that automatically generates follow-up question suggestions after each AI response. When enabled, a client calls a dedicated API endpoint to retrieve a list of LLM-generated questions based on recent conversation history.
The feature is only available for chat-based app modes: CHAT, AGENT_CHAT, ADVANCED_CHAT, and AGENT . It is not supported for COMPLETION or WORKFLOW apps.
Configuration Schema#
The feature config is a SuggestedQuestionsAfterAnswerConfig TypedDict with these fields :
| Field | Type | Required | Description |
|---|---|---|---|
enabled | bool | Yes | Enables/disables the feature |
prompt | str | No | Custom instruction prompt (max 1000 chars) |
model | object | No | Override model β provider, name, optional completion_params |
Config is stored and read differently by app mode:
- Basic Chat / Agent-Chat: stored in
AppModelConfig.suggested_questions_after_answerDB column; read via thesuggested_questions_after_answer_dictproperty. - Advanced Chat: stored in
Workflow.features_dict["suggested_questions_after_answer"]; read throughAdvancedChatAppConfigManager.get_app_config(). - Agent: resolved at runtime via
AgentRuntimeConfigService(see Runtime Flow below).
Validation is handled by SuggestedQuestionsAfterAnswerConfigManager: validate_and_set_defaults() enforces types and length limits, defaulting the entire block to {"enabled": False} if absent.
Runtime Flow#
The feature uses a shared contract (MessageSuggestedQuestions) that supports both:
SuggestedQuestionsAccountβ for Console/debugger access withaccount_idSuggestedQuestionsEndUserβ for web-app/service-api access withend_user_id
The runtime validates the current app owner/mode and actor existence before delegating to the existing MessageService.get_suggested_questions_after_answer() method. This decouples the capability from specific app types while preserving existing behavior.
MessageService.get_suggested_questions_after_answer() orchestrates the request:
- Fetch & validate β confirms the message belongs to the requesting user.
- Read feature config β branches on
app_model.mode:- Advanced Chat: reads from the draft or published workflow's
features_dict. RaisesSuggestedQuestionsAfterAnswerDisabledErrorif absent. - Agent: resolves via
AgentRuntimeConfigServicein priority order β debug draft β bound snapshot β published soul β legacyAppModelConfig. - Chat / Agent-Chat: reads
AppModelConfig.suggested_questions_after_answer_dict. If the conversation hasoverride_model_configs, normalizes throughConversation.model_configto handle legacy config shapes .
- Advanced Chat: reads from the draft or published workflow's
- Generate β calls
LLMGenerator.generate_suggested_questions_after_answer()with conversation history. The generator uses the configured override model ifproviderandnameare valid strings, falling back to the tenant's default LLM on any exception . - Trace β emits a
SUGGESTED_QUESTION_TRACEto the ops trace queue.
LLM Invocation Details#
- The prompt is assembled by
SuggestedQuestionsAfterAnswerOutputParserusing the custom instruction or the built-in default prompt. - For the default model path, parameters are built by
_default_suggested_questions_model_parameters(): capsmax_tokensat 256, setstemperatureto 0.0, and attempts to disable reasoning by settingthinking=False/"disabled"or choosing the lowest availablereasoning_effort(noneβminimalβlow). - For the configured-model path,
completion_paramsfrom config are passed as-is after normalizingstopand dropping non-positive token limits . - The LLM call is wrapped with a hard 30-second plugin-daemon timeout via
use_plugin_daemon_request_timeout(30.0). Any exception returns[]β the feature degrades silently. - Output is parsed by
SuggestedQuestionsAfterAnswerOutputParser.parse(), which extracts a JSON array from the response text.
API Endpoints#
| Surface | Route | Controller |
|---|---|---|
| Service API | GET /messages/<message_id>/suggested | MessageSuggestedApi |
| Web API | GET /messages/<message_id>/suggested-questions | api/controllers/web/message.py |
| Console (app) | GET /apps/<app_id>/chat-messages/<message_id>/suggested-questions | api/controllers/console/app/message.py |
| Console (agent) | GET /agent/<agent_id>/chat-messages/<message_id>/suggested-questions | api/controllers/console/app/message.py |
| Trial App (Console) | GET /console/api/explore/apps/<trial_app_id>/messages/<message_id>/suggested-questions | api/controllers/console/explore/trial.py |
Trial App Endpoint β requires Console account admission and validates app ownership and mode in a short session. Supported modes: chat, agent-chat, advanced-chat. Actor is Console account with invoke_from: explore. Returns 401 Unauthorized (SuggestedQuestionsActorNotFoundError) if the account no longer exists.
All endpoints gate on app mode and return 400 bad_request with "Suggested Questions Is Disabled." if the feature is not enabled .
Known Issues & Fixes#
Reasoning models silently break the feature#
When the workspace System Model is a reasoning model (DeepSeek-R1, o1, etc.), the internal thinking process consumes all available output tokens, leaving nothing for the JSON array output. The feature returns an empty list with no user-facing error .
Fix (merged, PR #41705): _default_suggested_questions_model_parameters() now inspects the model schema and disables reasoning where supported, plus adds the 30-second hard timeout. If the configured/default model cannot be resolved, the service returns [] rather than raising .
An earlier open PR #34652 proposed stripping <think>β¦</think> blocks in the output parser as an additional guard, but the merged fix in PR #41705 addresses the root cause by disabling reasoning at the model parameter level.
Legacy override configs cause 500 errors#
Older conversations with override_model_configs missing newer required fields caused Pydantic 500 errors. Fixed (PR #36459) by routing through Conversation.model_config for compatibility normalization rather than parsing override_model_configs directly.
Agent apps: missing AppModelConfig#
Agent debug conversations intentionally store app_model_config_id = NULL. The prior code path (shared with Basic Chat) raised ValueError("did not find app model config") (HTTP 500). Fixed by introducing the AgentRuntimeConfigService resolution path (PR #40963).
Agent v2: legacy model shape rejected#
Agent v2 apps rejected the { provider, name, mode, completion_params } model shape in suggested_questions_after_answer.model. Fixed (PR #38370) by introducing AgentSuggestedQuestionsAfterAnswerModelConfig in api/models/agent_config_entities.py.