|
| 1 | +# Copyright(C) 2025-2026 Advanced Micro Devices, Inc. All rights reserved. |
| 2 | +# SPDX-License-Identifier: MIT |
| 3 | +"""GAIA Email Triage agent — standalone hub package. |
| 4 | +
|
| 5 | +Registers the ``email`` agent into the GAIA registry via the ``gaia.agent`` |
| 6 | +entry-point group (#1102). ``EmailTriageAgent`` / ``EmailAgentConfig`` are |
| 7 | +re-exported lazily (PEP 562) so that ``from gaia_agent_email.contract import |
| 8 | +...`` — the dependency-light request/response contract used by the REST surface |
| 9 | +(#1229) and the MCP stdio interface (#1104) — and registry discovery do NOT |
| 10 | +drag the agent and its Gmail / connector backends into the importing process. |
| 11 | +""" |
| 12 | + |
| 13 | +from typing import TYPE_CHECKING |
| 14 | + |
| 15 | +if TYPE_CHECKING: # pragma: no cover - import only for type checkers |
| 16 | + from gaia_agent_email.agent import EmailTriageAgent |
| 17 | + from gaia_agent_email.config import EmailAgentConfig |
| 18 | + |
| 19 | +__all__ = ["build_registration", "EmailTriageAgent", "EmailAgentConfig"] |
| 20 | + |
| 21 | +__version__ = "0.1.0" |
| 22 | + |
| 23 | +_LAZY = { |
| 24 | + "EmailTriageAgent": "agent", |
| 25 | + "EmailAgentConfig": "config", |
| 26 | +} |
| 27 | + |
| 28 | + |
| 29 | +def __getattr__(name: str): |
| 30 | + # PEP 562 lazy attribute access — keeps the heavy agent import off the path |
| 31 | + # of dependency-light consumers (the contract module) and registry discovery. |
| 32 | + if name in _LAZY: |
| 33 | + import importlib |
| 34 | + |
| 35 | + module = importlib.import_module(f"gaia_agent_email.{_LAZY[name]}") |
| 36 | + return getattr(module, name) |
| 37 | + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") |
| 38 | + |
| 39 | + |
| 40 | +def build_registration(): |
| 41 | + """Return the :class:`AgentRegistration` for the ``email`` agent. |
| 42 | +
|
| 43 | + Metadata is declared with literals (and connector requirements rebuilt from |
| 44 | + the dependency-light scope constants) so discovery stays cheap — the agent |
| 45 | + and its backends are imported only when an email agent is actually created. |
| 46 | + Values mirror ``EmailTriageAgent``'s class attributes exactly. |
| 47 | + """ |
| 48 | + import dataclasses |
| 49 | + |
| 50 | + from gaia.agents.registry import ( |
| 51 | + AgentRegistration, |
| 52 | + _wrap_factory_with_namespaced_id, |
| 53 | + ) |
| 54 | + from gaia.connectors.providers.base import ConnectorRequirement |
| 55 | + |
| 56 | + from gaia_agent_email.outlook_scopes import ( |
| 57 | + OUTLOOK_CALENDAR_SCOPES, |
| 58 | + OUTLOOK_MAIL_SCOPES, |
| 59 | + ) |
| 60 | + from gaia_agent_email.scopes import ALL_SCOPES |
| 61 | + |
| 62 | + def email_factory(**kwargs): |
| 63 | + from gaia_agent_email.agent import EmailTriageAgent |
| 64 | + from gaia_agent_email.config import EmailAgentConfig |
| 65 | + |
| 66 | + valid_fields = {f.name for f in dataclasses.fields(EmailAgentConfig)} |
| 67 | + config = EmailAgentConfig( |
| 68 | + **{k: v for k, v in kwargs.items() if k in valid_fields} |
| 69 | + ) |
| 70 | + return EmailTriageAgent(config=config) |
| 71 | + |
| 72 | + # Provider-superset connector list, mirrored from |
| 73 | + # EmailTriageAgent.REQUIRED_CONNECTORS so the AgentUI offers both the Google |
| 74 | + # and Microsoft tiles. Rebuilt from the light scope constants to avoid |
| 75 | + # importing the heavy agent module at discovery time. |
| 76 | + required_connections = [ |
| 77 | + ConnectorRequirement( |
| 78 | + connector_id="google", |
| 79 | + scopes=ALL_SCOPES, |
| 80 | + reason=( |
| 81 | + "Read and organize Gmail messages, send drafts on your " |
| 82 | + "behalf, and respond to Google Calendar invites." |
| 83 | + ), |
| 84 | + ), |
| 85 | + ConnectorRequirement( |
| 86 | + connector_id="microsoft", |
| 87 | + scopes=OUTLOOK_MAIL_SCOPES + OUTLOOK_CALENDAR_SCOPES, |
| 88 | + reason=( |
| 89 | + "Read and organize your personal Outlook.com mailbox, send " |
| 90 | + "messages on your behalf, and read/respond to your Outlook " |
| 91 | + "calendar via Microsoft Graph." |
| 92 | + ), |
| 93 | + ), |
| 94 | + ] |
| 95 | + |
| 96 | + return AgentRegistration( |
| 97 | + id="email", |
| 98 | + name="Email Triage", |
| 99 | + description=( |
| 100 | + "Read, triage, organize, and reply to email through your " |
| 101 | + "connected Google account. All email content is processed " |
| 102 | + "locally on your machine." |
| 103 | + ), |
| 104 | + source="installed", |
| 105 | + conversation_starters=[ |
| 106 | + "Run a pre-scan", |
| 107 | + "Triage my inbox", |
| 108 | + "Summarize my unread emails", |
| 109 | + "Draft a reply to my most recent message", |
| 110 | + "Show me today's calendar", |
| 111 | + ], |
| 112 | + factory=_wrap_factory_with_namespaced_id(email_factory, "installed:email"), |
| 113 | + agent_dir=None, |
| 114 | + models=[], |
| 115 | + required_connections=required_connections, |
| 116 | + namespaced_agent_id="installed:email", |
| 117 | + category="productivity", |
| 118 | + tags=["email", "gmail", "calendar", "triage"], |
| 119 | + icon="mail", |
| 120 | + tools_count=6, |
| 121 | + ) |
0 commit comments