FinalResponse
Overview
FinalResponse is a special response type that tells the agent that your tool has fully handled the interaction. When a tool returns FinalResponse(), the agent stops — it will not generate or send any additional message to the contact after the tool finishes.
This is the key difference from TextResponse, where the agent receives the returned data and may compose a follow-up message to the contact based on it.
Why FinalResponse Matters
By default, when a tool returns TextResponse(data=...), the agent uses the returned data to generate a message to the user. This works well when the tool fetches information and the agent should interpret it and respond naturally.
However, there are scenarios where the tool itself already communicates with the user — for example, by sending a broadcast message, a product catalog, or an interactive quick reply. In these cases, having the agent send an additional message would be redundant or confusing. FinalResponse prevents this by telling the agent to stop.
Quick Start
from weni import Tool
from weni.context import Context
from weni.responses import FinalResponse
class MyTool(Tool):
def execute(self, context: Context) -> FinalResponse:
# Tool handles the interaction directly
return FinalResponse()
FinalResponse vs TextResponse
| Return Type | Agent sends a follow-up message? | When to use |
|---|---|---|
FinalResponse() |
No — the agent stops, no further message is sent | The tool already handled the user-facing communication |
TextResponse(data=...) |
Yes — the agent may generate a message based on the returned data | You want the agent to interpret the tool result and respond to the user |
When to Use FinalResponse
With Broadcasts
The most common use case for FinalResponse is when your tool sends messages to the contact via broadcasts. Since the broadcast already delivers the content to the user, the agent doesn't need to send anything else.
from weni import Tool
from weni.context import Context
from weni.responses import FinalResponse
from weni.broadcasts import Text, QuickReply
class NotifyUser(Tool):
def execute(self, context: Context) -> FinalResponse:
self.send_broadcast(Text(text="Your order has been confirmed!"))
self.send_broadcast(QuickReply(
text="What would you like to do next?",
options=["Track Order", "Continue Shopping"],
))
return FinalResponse()
With Catalog Messages
When sending product catalogs via broadcast, always use FinalResponse to avoid the agent sending a redundant text message on top of the catalog.
from weni import Tool
from weni.context import Context
from weni.responses import FinalResponse
from weni.broadcasts import WhatsAppCatalog, WhatsAppProductGroup
class SendCatalog(Tool):
def execute(self, context: Context) -> FinalResponse:
self.send_broadcast(WhatsAppCatalog(
text="Here are our products:",
products=[
WhatsAppProductGroup(
product="Featured",
product_retailer_ids=["12552#1#1", "12553#1#1"],
),
],
))
return FinalResponse()
Side-Effect-Only Tools
FinalResponse is also useful for tools that perform side effects (e.g., updating a database, triggering a webhook) where no response to the user is needed.
class UpdatePreferences(Tool):
def execute(self, context: Context) -> FinalResponse:
language = context.parameters.get("language")
self.save_user_preference("language", language)
return FinalResponse()
def save_user_preference(self, key, value):
# Persist the preference
...
Best Practices
- Use
FinalResponsewhen your tool already talks to the user: If you send broadcasts, catalogs, or any interactive message, returnFinalResponse()to prevent duplicate messages - Use
TextResponsewhen the agent should respond: If the tool fetches data that the agent needs to interpret and present, returnTextResponse(data=...)instead - Don't mix both intentions: If you send a broadcast and also return
TextResponse, the user may receive both the broadcast and an agent-generated message — which is usually not the desired behavior