|
| 1 | +""" |
| 2 | +Slack Gmail Agent (DB-backed OAuth) |
| 3 | +==================================== |
| 4 | +
|
| 5 | +Slack bot that can read/send Gmail using DB-backed OAuth tokens. |
| 6 | +When a user asks about email, the agent checks the DB for stored tokens. |
| 7 | +If none exist, it returns an OAuth URL the user clicks to authenticate. |
| 8 | +
|
| 9 | +Setup: |
| 10 | + 1. Google Cloud: Create OAuth 2.0 Web Application credentials |
| 11 | + - Authorized redirect URI: https://<your-ngrok>/google/oauth/callback |
| 12 | + 2. Set env vars: |
| 13 | + - GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET |
| 14 | + - GOOGLE_REDIRECT_URI=https://<your-ngrok>/google/oauth/callback |
| 15 | + - SLACK_BOT_TOKEN, SLACK_SIGNING_SECRET |
| 16 | + - OPENAI_API_KEY |
| 17 | + 3. Start pgvector: ./cookbook/scripts/run_pgvector.sh |
| 18 | + 4. Start ngrok: ngrok http 7777 |
| 19 | + 5. Run: .venvs/demo/bin/python cookbook/05_agent_os/interfaces/slack/gmail_agent.py |
| 20 | +
|
| 21 | +Flow: |
| 22 | + User: "What are my latest emails?" |
| 23 | + Bot: Returns OAuth URL (first time) -> user clicks -> Google consent -> callback saves token |
| 24 | + User: Retries -> Bot reads Gmail via stored token |
| 25 | +""" |
| 26 | + |
| 27 | +from agno.agent import Agent |
| 28 | +from agno.db.postgres.postgres import PostgresDb |
| 29 | +from agno.models.openai import OpenAIChat |
| 30 | +from agno.os.app import AgentOS |
| 31 | +from agno.os.interfaces.slack import Slack |
| 32 | +from agno.tools.google.auth import GoogleAuth |
| 33 | +from agno.tools.google.gmail import GmailTools |
| 34 | + |
| 35 | +# --------------------------------------------------------------------------- |
| 36 | +# Database (shared between agent session storage and OAuth token storage) |
| 37 | +# --------------------------------------------------------------------------- |
| 38 | + |
| 39 | +db = PostgresDb( |
| 40 | + db_url="postgresql+psycopg://ai:ai@localhost:5532/ai", |
| 41 | +) |
| 42 | + |
| 43 | +# --------------------------------------------------------------------------- |
| 44 | +# Google Auth + Gmail |
| 45 | +# --------------------------------------------------------------------------- |
| 46 | + |
| 47 | +google_auth = GoogleAuth() |
| 48 | + |
| 49 | +gmail = GmailTools( |
| 50 | + google_auth=google_auth, |
| 51 | + get_latest_emails=True, |
| 52 | + get_emails_from_user=True, |
| 53 | + get_unread_emails=True, |
| 54 | + search_emails=True, |
| 55 | + send_email=True, |
| 56 | + create_draft_email=True, |
| 57 | +) |
| 58 | + |
| 59 | +# --------------------------------------------------------------------------- |
| 60 | +# Agent |
| 61 | +# --------------------------------------------------------------------------- |
| 62 | + |
| 63 | +gmail_agent = Agent( |
| 64 | + name="Gmail Agent", |
| 65 | + model=OpenAIChat(id="gpt-4o"), |
| 66 | + tools=[google_auth, gmail], |
| 67 | + db=db, |
| 68 | + add_history_to_context=True, |
| 69 | + num_history_runs=3, |
| 70 | + add_datetime_to_context=True, |
| 71 | + instructions=[ |
| 72 | + "You are a helpful email assistant connected to Gmail.", |
| 73 | + "When authentication is needed, share the OAuth URL and ask the user to click it.", |
| 74 | + "After they authenticate, retry the original request.", |
| 75 | + ], |
| 76 | +) |
| 77 | + |
| 78 | +# --------------------------------------------------------------------------- |
| 79 | +# AgentOS + Slack + OAuth callback |
| 80 | +# --------------------------------------------------------------------------- |
| 81 | + |
| 82 | +agent_os = AgentOS( |
| 83 | + agents=[gmail_agent], |
| 84 | + interfaces=[ |
| 85 | + Slack( |
| 86 | + agent=gmail_agent, |
| 87 | + reply_to_mentions_only=True, |
| 88 | + resolve_user_identity=True, |
| 89 | + ) |
| 90 | + ], |
| 91 | +) |
| 92 | + |
| 93 | +app = agent_os.get_app() |
| 94 | + |
| 95 | +# Attach the OAuth callback endpoint to the same FastAPI app |
| 96 | +# Google redirects here after user consents: /google/oauth/callback?code=...&state=... |
| 97 | +app.include_router(google_auth.get_oauth_router()) |
| 98 | + |
| 99 | + |
| 100 | +if __name__ == "__main__": |
| 101 | + agent_os.serve(app="gmail_agent:app", reload=True) |
0 commit comments