Skip to content

docs: add email agent packaging integration spike design doc#1852

Open
theonlychant wants to merge 3 commits into
amd:mainfrom
theonlychant:design/email-agent-ui-integration
Open

docs: add email agent packaging integration spike design doc#1852
theonlychant wants to merge 3 commits into
amd:mainfrom
theonlychant:design/email-agent-ui-integration

Conversation

@theonlychant

@theonlychant theonlychant commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Summary

Concerning #1765
Adds a design spike doc deciding how the packaged email agent (REST sidecar + MCP server, per #1713) should reach the Agent UI for Phase 6 of the email-agent-packaging plan, given that the frozen contract is triage-centric while the desired UI experience covers the full capability set in #1691.

Why

The Agent UI currently runs email in-process (constructing EmailTriageAgent directly), bypassing the packaged sidecar entirely. A literal "swap in-process for the frozen REST/MCP contract" would silently drop capabilities the contract doesn't carry yet - batch archive, pre-scan, calendar, search, preferences - since those live only in the agent loop today. Before any rip-out-and-repoint work happens, we need an explicit, reviewed decision on which packaged interface (REST, MCP, extended REST, or agent-loop-over-sidecar) serves each capability, and which UI surface (chat vs. dedicated screens) delivers it - so Phase 6 has something concrete to execute against instead of discovering the gap mid-implementation.

Linked issue

Closes #N

Changes

  • Added docs/plans/email-agent-packaging-spike.md:
    • Capability → packaged-interface → UI-surface table for all six headline capabilities (Email Agent — capability completion tracker (live status vs. spec) #1691) plus the agent-loop-only set (pre-scan, batch archive, quarantine/undo, calendar, search, preferences/memory)
    • Recorded decision: hybrid of A (structured Inbox view over the frozen REST contract, ships immediately) + C (agent loop proxied through the sidecar, preserves conversational UX) + selective B (additive, apiVersion-bumped contract extensions where REST/MCP genuinely need to grow - e.g. batch archive, calendar)
    • Inventory of in-process wiring to remove (_chat_helpers.py, sse_handler.py pre_scan_inbox mapping, routers/sessions.py eviction), confirmed against current main
    • Note on how the sidecar reads connector tokens from the shared OS keyring, with the cross-process refresh-race caveat written up as an explicit test step
    • 7 sequenced, independently-shippable follow-up issues (transport swap, contract/MCP extensions, new UI surfaces)
  • No changes to the email agent's logic, tool behavior, or the frozen-binary build/sign/publish pipeline.

Test plan

  • Doc reviewed for accuracy against current main (in-process wiring list, packaged contract surfaces in gaia_agent_email/{api_routes,mcp_server,contract}.py)
  • Capability table cross-checked against Email Agent — capability completion tracker (live status vs. spec) #1691 and gaia-agent.yaml interface declarations
  • Follow-up issues filed and linked from the doc
  • (Optional) Node script using hub/agents/npm/agent-email spawns the sidecar and runs a triage round-trip, request/response pasted into the doc as a smoke test of the structured surface

Checklist

  • I have linked a GitHub issue above (Closes #N / Fixes #N / Refs #N).
  • I have described why this change is being made, not just what changed.
  • I have run linting and tests locally (python util/lint.py --all, pytest tests/unit/).
  • I have updated documentation if user-visible behavior changed

@github-actions github-actions Bot added the documentation Documentation changes label Jun 25, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Verdict: Approve with suggestions — a design-only spike doc; no code changes, and its claims about current main hold up well.

This adds docs/plans/email-agent-packaging-spike.md recording the Phase 6 decision (hybrid: Inbox over frozen REST + agent-loop proxy + selective additive endpoints) for wiring the packaged email agent into the Agent UI. I spot-checked the doc's file/symbol references against the repo and they're accurate — _session_mail_provider, the pre_scan_inbox SSE mapping, the mail_provider column, the grants/formatting helpers, and the frozen /v1/email/{triage,draft,send,health,version} endpoints all exist as described.

One thing to fix before implementers run with this: the doc repeatedly says to bump apiVersion in gaia-agent.yaml, but that's the wrong location — the manifest only carries the package version (0.2.2). The REST/contract apiVersion actually lives in the agent code. Pointing implementers at the wrong file would send a follow-up PR editing the manifest and leaving the real contract version stale. Otherwise this is well-scoped and ready.

(Process nit, not blocking: the PR body still has the Closes #N placeholder unfilled.)

🔍 Technical details

Issues

🟢 apiVersion location is wrong (email-agent-packaging-spike.md, the "API versioning and re-freeze impact" + "Interface assignment" + follow-up #4 sections) — the doc says contract bumps go to apiVersion in gaia-agent.yaml, e.g. "bump apiVersion in gaia-agent.yaml (e.g., from v1v1.1 or v2)". There is no apiVersion field in that manifest — it only has version: 0.2.2. The contract version is API_VERSION in hub/agents/python/email/gaia_agent_email/version.py:35 (API_VERSION = SCHEMA_VERSION), where SCHEMA_VERSION = "2.0" (contract.py:60), and it's served by the REST /version route as apiVersion (api_routes.py:982). The example v1 → v1.1 also doesn't match the live 2.0 scheme. Suggest rewording to: "bump API_VERSION/SCHEMA_VERSION in gaia_agent_email/version.py (currently 2.0), surfaced via /v1/email/version" — the gaia-agent.yaml version is the package version and tracks separately.

🟢 "eviction" framing (in-process wiring inventory) — the doc lists "email-agent eviction / special-case agent handling in routers/sessions.py" as something to remove. evict_session_agent (sessions.py:170,225,367) is the generic session-agent lifecycle hook, not email-specific; what's email-specific there is the mail_provider-driven model rebuild. Minor wording precision so the removal PR doesn't rip out generic session teardown.

Strengths

  • Genuinely verified against main — the in-process-wiring inventory (_chat_helpers.py, sse_handler.py _RENDER_TOOL_TO_LANG["pre_scan_inbox"], the mail_provider column) matches real symbols, which is exactly what a spike doc needs to be actionable.
  • Clean separation of "remove" vs "keep (transport-agnostic)" pieces, and the keyring cross-process refresh-race called out as a concrete test step rather than hand-waved.
  • Follow-ups are scoped to one PR each with titles/tests, so Phase 6 can execute incrementally.

@itomek itomek left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is very good, but based on external circumstances, we are trying to figure out which way to go with the integration, so if you don't mind, can we hold on this for a bit?

@theonlychant

Copy link
Copy Markdown
Contributor Author

This is very good, but based on external circumstances, we are trying to figure out which way to go with the integration, so if you don't mind, can we hold on this for a bit?

yea sure let me know what else you need!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Documentation changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants