showcase/shell-docs/src/content/docs/integrations/crewai-flows/advanced/exit-agent.mdx
After your agent has finished a workflow, you'll usually want to explicitly end that loop by calling the copilotkit_exit() method in your Python code.
Exiting the agent has different effects depending on mode:
Router Mode: Exiting the agent hands responsibility for handling input back to the router, which can initiate chat, call actions, other agents, etc. The router can return to this agent later (starting a new loop) to satisfy a user request.
Agent Lock Mode: Exiting the agent restarts the workflow loop for the current agent.
In this example from our email-sending app, the send_email node explicitly exits, then manually sends a response back to the user as a ToolMessage:
<Step>
### Exit the agent loop
This will exit the agent session as soon as the current CrewAI run is finished, either by a breakpoint or by reaching the `END` node.
<Tabs groupId="language_crewai-flows_agent" items={['Python']} default="Python" persist>
<Tab value="Python">
```python
from litellm import completion
from crewai.flow.flow import start
from copilotkit.crewai import copilotkit_exit
# ...
@start()
async def send_email(self):
"""Send an email."""
# get the last message and cast to ToolMessage
last_message = self.state["messages"][-1]
if last_message["content"] == "CANCEL":
text_message = "❌ Cancelled sending email."
else:
text_message = "✅ Sent email."
self.state["messages"].append({"role": "assistant", "content": text_message, "id": str(uuid.uuid4())})
# Exit the agent loop after processing
await copilotkit_exit() # [!code highlight]
```
</Tab>
</Tabs>
</Step>