Add email_blast tool for NEMO to send branded emails via basketball-api #31

Closed
opened 2026-04-03 22:34:08 +00:00 by forgejo_admin · 2 comments

Type

Feature

Lineage

Standalone — part of westside-email-agent capability (2026-04-04). NEMO needs to call basketball-api's /admin/email/blast endpoint to send branded emails on behalf of Marcus.

Repo

forgejo_admin/westside-ai-assistant

User Story

As an admin messaging NEMO on GroupMe, I want to say "remind parents to sign contracts" and have NEMO compose and send the email through the blast endpoint, so that email campaigns are a conversation, not code.

Context

basketball-api has POST /admin/email/blast which accepts layout, email_type, query, subject, data, and optional test_email. The endpoint requires Keycloak JWT auth. westside-ai-assistant already authenticates to basketball-api via Keycloak (see config.py keycloak settings and basketball.py client).

The existing tool pattern: api_get does GET requests. Write tools use the confirmation system (confirmation.py) — agent proposes action, user says "yes", then it executes. Email blast should follow this same pattern since it's a write operation with real-world impact.

NEMO should know:

  • Available layouts: action, notification, announcement
  • Available queries: unsigned_contracts, incomplete_profiles (coming)
  • The approval chain: compose → confirm with user → send test → user approves → blast
  • How to compose email content (subject, headline, body, cta_text, cta_url)

File Targets

Files to modify:

  • app/ai.py — add email_blast tool to TOOLS list, add execution handler, update SYSTEM_PROMPT with email capabilities
  • app/basketball.py — add post method to BasketballClient (currently only has get)

Files NOT to touch:

  • app/confirmation.py — existing confirmation system works as-is for email blast
  • app/groupme.py — webhook handler unchanged
  • app/config.py — keycloak auth already configured

Acceptance Criteria

  • email_blast tool exists in TOOLS list with input schema: layout, email_type, query, subject, data, test_email (optional)
  • Tool is tagged as write operation (metadata: operation=write) — triggers confirmation flow
  • BasketballClient.post() method exists and sends authenticated POST to basketball-api
  • SYSTEM_PROMPT includes email capability description: available layouts, available queries, approval chain
  • When user says "remind parents to sign contracts" → NEMO proposes an email_blast tool call → user confirms "yes" → blast executes
  • test_email parameter works for safe testing before full blast

Test Expectations

  • Unit test: email_blast tool call builds correct POST body
  • Unit test: confirmation flow triggers for email_blast (write operation)
  • Unit test: BasketballClient.post() sends authenticated request
  • Run: pytest tests/ -v

Constraints

  • Follow existing tool pattern in ai.py — same structure as update_player, assign_player_to_team
  • Use existing confirmation.py for the approve/cancel flow — don't build new state management
  • SYSTEM_PROMPT additions should be concise — NEMO is a small model, keep instructions short and structured
  • Auth: use existing Keycloak client credentials flow in basketball.py

Checklist

  • PR opened
  • Tests pass
  • No unrelated changes
  • arch-email — email architecture
  • sop-email-send — email send workflow (the SOP NEMO should follow)
  • project-westside-agency — agent capability buildout
  • basketball-api #295 — the blast endpoint NEMO calls
### Type Feature ### Lineage Standalone — part of westside-email-agent capability (2026-04-04). NEMO needs to call basketball-api's /admin/email/blast endpoint to send branded emails on behalf of Marcus. ### Repo `forgejo_admin/westside-ai-assistant` ### User Story As an admin messaging NEMO on GroupMe, I want to say "remind parents to sign contracts" and have NEMO compose and send the email through the blast endpoint, so that email campaigns are a conversation, not code. ### Context basketball-api has `POST /admin/email/blast` which accepts layout, email_type, query, subject, data, and optional test_email. The endpoint requires Keycloak JWT auth. westside-ai-assistant already authenticates to basketball-api via Keycloak (see `config.py` keycloak settings and `basketball.py` client). The existing tool pattern: `api_get` does GET requests. Write tools use the confirmation system (`confirmation.py`) — agent proposes action, user says "yes", then it executes. Email blast should follow this same pattern since it's a write operation with real-world impact. NEMO should know: - Available layouts: action, notification, announcement - Available queries: unsigned_contracts, incomplete_profiles (coming) - The approval chain: compose → confirm with user → send test → user approves → blast - How to compose email content (subject, headline, body, cta_text, cta_url) ### File Targets Files to modify: - `app/ai.py` — add `email_blast` tool to TOOLS list, add execution handler, update SYSTEM_PROMPT with email capabilities - `app/basketball.py` — add `post` method to BasketballClient (currently only has `get`) Files NOT to touch: - `app/confirmation.py` — existing confirmation system works as-is for email blast - `app/groupme.py` — webhook handler unchanged - `app/config.py` — keycloak auth already configured ### Acceptance Criteria - [ ] `email_blast` tool exists in TOOLS list with input schema: layout, email_type, query, subject, data, test_email (optional) - [ ] Tool is tagged as write operation (metadata: operation=write) — triggers confirmation flow - [ ] BasketballClient.post() method exists and sends authenticated POST to basketball-api - [ ] SYSTEM_PROMPT includes email capability description: available layouts, available queries, approval chain - [ ] When user says "remind parents to sign contracts" → NEMO proposes an email_blast tool call → user confirms "yes" → blast executes - [ ] test_email parameter works for safe testing before full blast ### Test Expectations - [ ] Unit test: email_blast tool call builds correct POST body - [ ] Unit test: confirmation flow triggers for email_blast (write operation) - [ ] Unit test: BasketballClient.post() sends authenticated request - Run: `pytest tests/ -v` ### Constraints - Follow existing tool pattern in ai.py — same structure as update_player, assign_player_to_team - Use existing confirmation.py for the approve/cancel flow — don't build new state management - SYSTEM_PROMPT additions should be concise — NEMO is a small model, keep instructions short and structured - Auth: use existing Keycloak client credentials flow in basketball.py ### Checklist - [ ] PR opened - [ ] Tests pass - [ ] No unrelated changes ### Related - `arch-email` — email architecture - `sop-email-send` — email send workflow (the SOP NEMO should follow) - `project-westside-agency` — agent capability buildout - basketball-api #295 — the blast endpoint NEMO calls
Author
Owner

Scope Review: NEEDS_REFINEMENT

Review note: review-759-2026-04-03

Template is complete and file targets are verified. One traceability gap blocks advancement.

  • [SCOPE] story:WA-S1 label has no matching entry in project-westside-ai-assistant user-stories section. The project page lists: read-ops, write-ops, safety. Either create a new user story for email/agent-driven-comms, or relabel to an existing story (e.g., story:write-ops).
  • arch:email note verified (id 1102, active).
  • basketball-api #295 blast endpoint dependency is merged and deployed.
  • 2 files, 6 AC, single-agent pass — no decomposition needed.
## Scope Review: NEEDS_REFINEMENT Review note: `review-759-2026-04-03` Template is complete and file targets are verified. One traceability gap blocks advancement. - **[SCOPE]** `story:WA-S1` label has no matching entry in `project-westside-ai-assistant` user-stories section. The project page lists: `read-ops`, `write-ops`, `safety`. Either create a new user story for email/agent-driven-comms, or relabel to an existing story (e.g., `story:write-ops`). - `arch:email` note verified (id 1102, active). - basketball-api #295 blast endpoint dependency is merged and deployed. - 2 files, 6 AC, single-agent pass — no decomposition needed.
Author
Owner

Scope Review: READY

Review note: review-759-2026-04-03-r2
Re-review after story label fix. Previous finding (story:WA-S1 had no matching project page entry) resolved — now story:write-ops, verified on project-westside-ai-assistant. All template sections present, all file targets verified, traceability complete (arch-email note confirmed), dependencies satisfied. Ready for execution.

## Scope Review: READY Review note: `review-759-2026-04-03-r2` Re-review after story label fix. Previous finding (story:WA-S1 had no matching project page entry) resolved — now story:write-ops, verified on project-westside-ai-assistant. All template sections present, all file targets verified, traceability complete (arch-email note confirmed), dependencies satisfied. Ready for execution.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
forgejo_admin/westside-ai-assistant#31
No description provided.