feat: add email_blast tool for NEMO email sending #32
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "31-email-blast-tool"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Adds an
email_blasttool so NEMO can send branded emails to player groups via the basketball-api/admin/email/blastendpoint. Includes the confirmation flow (write operation requires "yes" reply) and test_email safety pattern.Changes
app/basketball.py— Added genericpost(path, body)method toBasketballClient, mirroring the existingget()pattern but with POST + JSON bodyapp/ai.py— Addedemail_blasttool definition to TOOLS list (tagged as write operation), execution handler in_execute_write_tool, human-readable action description in_ACTION_DESCRIPTIONS, and updatedSYSTEM_PROMPTwith email capabilities guidance (layouts, email_types, composition instructions, test_email safety)tests/test_ai.py— 11 new tests: tool existence, schema validation, execution dispatch, test_email/query inclusion, error handling, action descriptions, system prompt contenttests/test_basketball.py— 4 new tests: post with body, post without body, slash prepending, error raisingTest Plan
Review Checklist
Related Notes
None.
Related
Closes #31
Enables NEMO to send branded email blasts through the basketball-api /admin/email/blast endpoint, with confirmation flow and test_email safety. - Add generic post() method to BasketballClient - Add email_blast tool definition with layout/email_type/subject/data/test_email - Add execution handler dispatching to client.post("/admin/email/blast", body) - Update SYSTEM_PROMPT with email capabilities guidance - Add 15 new tests covering tool schema, execution, descriptions, and post() Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>PR #32 Review
DOMAIN REVIEW
Tech stack: Python / async / Anthropic tool-use pattern
The PR adds an
email_blasttool to the NEMO AI assistant, following established patterns in the codebase. Four files changed across two modules (app, tests) with 322 additions and 7 deletions (count adjustments).Pattern compliance: The new tool follows the exact same structure as existing write tools -- tool definition in
TOOLSlist withmetadata.operation = "write", execution branch in_execute_write_tool, action description lambda in_ACTION_DESCRIPTIONS, and system prompt guidance. This consistency is good.BasketballClient.post()method: Clean addition mirroring the existingget()pattern. Delegates to_request("POST", path, json=body). Path normalization (prepend/) matchesget(). Type hintbody: dict | None = Noneis correct for optional JSON payloads.Optional field handling:
queryandtest_emailare conditionally included in the POST body viatool_input.get(), which correctly excludes them when not provided. This avoids sendingnullvalues to the basketball-api endpoint.Safety: Tool is tagged as
writeoperation, triggering the confirmation flow before execution. System prompt instructs the model to suggesttest_emailbefore real blasts. These are appropriate guardrails for an email-sending tool.Test coverage: 15 new tests covering:
test_emailandqueryconditional inclusionRuntimeError-> error string)test_email)post(): with body, without body, slash prepending, error raisingThis is thorough coverage across happy path, edge cases, and error handling.
BLOCKERS
None.
NITS
Enum-style validation for
layout: Thelayoutfield accepts any string, but onlyaction,notification, andannouncementare valid. Consider adding anenumconstraint to the JSON schema so the LLM gets stronger guidance and invalid values are caught before hitting the API. This is non-blocking since basketball-api presumably validates on its end.test_emailnaming in system prompt: The system prompt says "setting test_email to the user's email address" but the tool name in the prompt is referenced as part of general guidance, not explicitly as theemail_blasttool parameter. Minor clarity improvement possible -- again non-blocking since the tool description itself is clear.SOP COMPLIANCE
31-email-blast-tool)Closes #31)PROCESS OBSERVATIONS
Clean, well-scoped PR. One issue, one feature, one PR. The 15 new tests maintain the repo's strong test culture (110 -> 125). The generic
post()method onBasketballClientcreates a reusable primitive for future write tools that need to POST to arbitrary endpoints, reducing future implementation cost.VERDICT: APPROVED