Gmail Draft Reply Agent
Reads a conversation thread and drafts a contextual reply.
Read a conversation thread and prepare a reply draft for review.
"""
Gmail Draft Reply Agent
=======================
Reads a conversation thread and drafts a contextual reply.
The agent never sends -- it only creates drafts for human review.
Key concepts:
- Thread-aware drafting: thread_id + message_id link the draft to the conversation
Setup:
1. Create OAuth credentials at https://console.cloud.google.com (enable Gmail API)
2. Export GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, GOOGLE_PROJECT_ID env vars
3. pip install openai google-api-python-client google-auth-httplib2 google-auth-oauthlib
4. First run opens browser for OAuth consent, saves token.json for reuse
"""
from agno.agent import Agent
from agno.models.openai import OpenAIResponses
from agno.tools.google.gmail import GmailTools
# ---------------------------------------------------------------------------
# Create Agent
# ---------------------------------------------------------------------------
agent = Agent(
name="Draft Reply Agent",
model=OpenAIResponses(id="gpt-5.5"),
tools=[GmailTools()],
instructions=[
"Match the tone and formality of the existing conversation.",
"Keep replies concise and professional unless instructed otherwise.",
"Always create a draft -- never send directly.",
"Summarize the thread context so the user knows what the reply addresses.",
],
markdown=True,
)
# ---------------------------------------------------------------------------
# Run Demo
# ---------------------------------------------------------------------------
if __name__ == "__main__":
agent.print_response(
"Find the most recent thread about 'project update' and draft a reply "
"acknowledging the update and asking about next steps",
stream=True,
)
# Draft a reply to a specific sender
# agent.print_response(
# "Find the latest email from john@example.com and draft a polite follow-up reply",
# stream=True,
# )Expose draft tools only
Replace GmailTools(...) with the following selection to enforce the drafting scope; the default toolkit also exposes sending methods:
GmailTools(
include_tools=["search_threads", "get_thread", "get_message", "create_draft_email"],
max_results=15,
)search_threads returns IDs and snippets. Load each selected thread before deciding whether a reply is needed. The current readers omit the original RFC Message-ID header, while create_draft_email(message_id=...) copies its argument directly into reply headers. Do not substitute the Gmail API resource ID. To satisfy Gmail's threading requirements, obtain the original header through the Gmail API and supply it with the thread ID and matching subject. Otherwise create a standalone draft by omitting thread_id and message_id, then review it in Gmail.
Run the Example
Set up your virtual environment
uv venv --python 3.12
source .venv/bin/activateInstall dependencies
uv pip install -U agno google-api-python-client google-auth google-auth-httplib2 google-auth-oauthlib openaiConfigure Google OAuth
Enable the Google API used by this example, configure the consent screen, and create a Desktop OAuth client in your Cloud project. Export its GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, and GOOGLE_PROJECT_ID, or place the downloaded client JSON at credentials.json in the directory where you run Python. Google's Python quickstart shows the Desktop client setup.
The first tool call opens a browser for consent and caches credentials in token.json. Use a separate token_path when switching accounts. Passing an Agno user_id does not switch the authenticated Google account.
Export environment variables
export GOOGLE_CLIENT_ID="your_google_client_id_here"
export GOOGLE_CLIENT_SECRET="your_google_client_secret_here"
export GOOGLE_PROJECT_ID="your_google_project_id_here"
export OPENAI_API_KEY="your_openai_api_key_here"Run the example
Save the code above as draft_reply.py, then run:
python draft_reply.pyFull source: cookbook/91_tools/google/gmail/draft_reply.py