Nemo
Notes
Doc 1
-
Architecture: nemo-agent
arch-nemo-agentnemo-agent Architecture
Architecture ID used in board labels:
arch:nemo-agentComponents
Component Language Framework Responsibility Webhook server Python FastAPI Receive Postmark inbound POST, parse email, route to project agent Agent loop Python anthropic SDK Orchestrate workflow via Claude Opus 4.6 tool use Project configs Markdown — Workflow guides per client project Data Flow
Postmark inbound → FastAPI /inbound → parse email → route to project agent → Claude Opus 4.6 (tool use) → client API calls (Rails JSON API, Stripe) → Postmark outbound → email to admin/parentDeployment
- Namespace:
nemo - Image:
nemo/app(Harbor) - Port: 8000 (FastAPI/uvicorn)
- Exposed via Tailscale funnel for Postmark webhook delivery
- Overlay:
pal-e-deployments/overlays/nemo/prod
Authentication
Service Method Anthropic API API key (ANTHROPIC_API_KEY) Postmark Server token + webhook signature Rails API Bearer token (API_TOKEN) Stripe API key (STRIPE_SECRET_KEY) Related
project-nemo— project page- Repo docs:
docs/architecture.mdinldraney/nemo
- Namespace:
Project Page 1
-
Project: Nemo
project-nemoOverview
AI email agent. Receives inbound email via Postmark webhook, processes it with Claude (Opus 4.6) via the Anthropic API, and takes action through client project APIs.
Nemo is the brain layer — client apps (Rails, FastAPI, etc.) are the hands. Each client project gets a
projects/<project>/directory with a workflow guide that teaches Nemo how to use that project's API.Architecture
Python service (FastAPI + Anthropic SDK) deployed to the Hetzner k3s cluster. Two responsibilities:
- Webhook receiver — accepts Postmark inbound email POST, routes to project agent
- Agent loop — uses Claude Opus 4.6 to process emails and execute workflows with tool use
Email flow: Postmark inbound → Nemo webhook → Claude decides action → calls client API → sends via Postmark outbound.
Repos
ldraney/nemo— Python service repo (Forgejo)
User Stories
story:billing-follow-up
As Marcus (admin), I want an AI agent that emails me billing drafts for each player and waits for my approval before sending, so that I can process billing follow-ups via email without needing to log into any app.
First project. 17 remaining players owe money for tournament fees and monthly dues. Nemo pulls data from the westside-basketball Rails API, drafts emails, gets Marcus's approval via Postmark email thread, sends to parents.
Board
Board:
board-nemoKey People
- Lucas Draney — superadmin, monitors Nemo's operation, handles technical issues
- Marcus Draney — admin, approves/adjusts billing emails via email reply
Review 2
-
Review: Implement billing follow-up agent for Westside Basketball
review-1903-2026-07-25-r2Verdict: NEEDS_REFINEMENT
Re-review after refinement. Prior review:
review-1903-2026-07-25. All [BODY] issues from the prior review have been resolved. Remaining issues are [SCOPE] items only -- companion artifacts that need to be created.Prior Review Resolution
- [x] [BODY] Resolve data access approach -- RESOLVED. Issue now explicitly commits to JSON API on Rails with 5 named endpoints. Prerequisite documented in "What Must Be Built" section with code blocks, routes, and env var requirements.
- [x] [BODY] Resolve email sending approach -- RESOLVED. Issue explicitly states "Email sending uses Postmark outbound (not Gmail/ActionMailer). Nemo sends directly via Postmark API, not through the Rails app." Repeated in Constraints.
- [x] [BODY] Fix ParentMailer#billing_followup reference -- RESOLVED. Issue now correctly lists the 3 public mailer methods (announcement, payment_reminder, quick_send) and explicitly states "There is NO
billing_followupmethod. Nemo does NOT use Rails mailers." - [x] [BODY] AC vagueness for edge cases -- IMPROVED. AC #10 now enumerates specific edge cases: "no-show players, disputed charges, players who left program."
- [ ] [SCOPE] Create project-nemo page -- STILL MISSING (404)
- [ ] [SCOPE] Create arch-nemo-agent note -- STILL MISSING (404)
- [x] [DECOMPOSE] Owner explicitly chose to keep as single ticket -- ACKNOWLEDGED, respected
Template Completeness
- [x] Type -- Feature
- [x] Lineage -- Standalone, first ticket for Nemo project
- [x] Repo -- ldraney/nemo
- [x] User Story -- well-formed (As Marcus, I want an AI agent that emails me billing drafts...)
- [x] Context -- thorough, includes key architectural decisions and "What Exists Today" inventory
- [x] File Targets -- 13 files to create, 3 directories excluded with reasons
- [x] Feature Flag -- none
- [x] Acceptance Criteria -- 13 criteria
- [x] Test Expectations -- 5 test items + run command
- [x] Constraints -- 8 constraints listed
- [x] Checklist -- 4 items
- [x] Related -- 6 references
All required template sections present. The issue is notably thorough, with additional sections ("What Exists Today in the Rails App" and "What Must Be Built") that provide excellent context for the implementing agent.
Traceability
- [x] story:billing-follow-up label -- present on board item
- [ ] story note MISSING --
project-nemopage does not exist (404). [SCOPE] Create project pageproject-nemowith user-stories section containing the billing-follow-up story. - [x] arch:nemo-agent label -- present on board item
- [ ] arch note MISSING --
arch-nemo-agentnote does not exist (404). [SCOPE] Create architecture notearch-nemo-agent. The nemo repo'sdocs/architecture.mdhas detailed system diagrams and component descriptions to derive from. - [x] Forgejo issue -- ldraney/nemo#1, state: open
File Targets
- [x]
src/__init__.py-- to create; standard package init - [x]
src/webhook.py-- to create; repo currently docs-only, valid path - [x]
src/agent.py-- to create; consistent with architecture doc - [x]
src/tools.py-- to create; consistent with architecture doc - [x]
src/config.py-- to create; consistent with architecture doc - [x]
Dockerfile-- to create; standard containerized service - [x]
pyproject.toml-- to create; standard Python project - [x]
.pre-commit-config.yaml-- to create; matches platform convention - [x]
.woodpecker/ci.yaml-- to create; matches platform CI convention - [x]
tests/__init__.py-- to create; test package init - [x]
tests/test_webhook.py-- to create; webhook parsing tests - [x]
tests/test_approval.py-- to create; approval parser tests - [x]
tests/test_fixes.py-- to create; standard fixes logic tests - [x]
docs/-- excluded, already exists in repo (verified) - [x]
projects/-- excluded, workflow.md exists in repo (verified) - [x]
README.md-- excluded, already exists (verified)
All file targets valid for a greenfield service in a docs-only repo.
Rails App References Verified
The "What Exists Today" section makes specific claims about the westside-basketball codebase. All verified against the actual code:
- [x]
WebhooksControllerinherits fromActionController::Base-- confirmed - [x] No API controllers exist (
app/controllers/api/directory absent) -- confirmed - [x] No
API_TOKENenv references anywhere in the app -- confirmed - [x] Player model: has_many :orders, :payment_links, :player_tournaments; columns stripe_customer_id, subscription_status, monthly_fee, contract_status, parent_id -- all confirmed in schema
- [x] Parent model: has_many :players; columns name, email, phone -- confirmed
- [x] Order model: belongs_to :player, :parent, :product; columns amount_cents, status (orderstatus enum) -- confirmed. Minor: ticket says "pending/paid/canceled" but enum also includes "refunded"
- [x] PaymentLink model: belongs_to :player, :parent, :order (optional); columns description, amount_cents, status, stripe_payment_link_id, stripe_payment_link_url -- confirmed
- [x] PlayerTournament model: belongs_to :player, :tournament; validates payment_status against PAYMENT_STATUSES (pending/paid_stripe/paid_cash/paid_venmo/waived) -- confirmed
- [x] ParentMailer: 3 public methods (announcement, payment_reminder, quick_send), no billing_followup -- confirmed
- [x] jbuilder gem installed but unused -- confirmed
- [x] No rack-cors gem -- confirmed
- [x] TENANT_SLUG = "westside-kings-queens" in ApplicationController -- confirmed
- [x] StripeClient and GmailClient services exist -- confirmed
Repo Placement
Issue filed on
ldraney/nemo. All file targets are in the nemo repo. Cross-repo Rails API work is explicitly documented as a prerequisite in the "What Must Be Built" section with full controller code, route definitions, and env var requirements. The Checklist includes "Rails API prerequisite ticket created on westside-basketball repo." This is correct placement.However, the Rails API prerequisite ticket does NOT yet exist on westside-basketball (checked all 19 open issues -- none match).
Dependencies
- Only item on board-nemo; no board-level blockers or blocked items.
- Cross-repo prerequisite (documented but not created): 5 JSON API endpoints + BaseController + API_TOKEN env var on westside-basketball. The issue documents these thoroughly but the actual Forgejo issue has not been created yet.
- Operational dependencies (documented in Constraints): Postmark account, Anthropic API key, Stripe API key, k8s namespace -- not code dependencies, deployment prerequisites.
Acceptance Criteria
13 acceptance criteria. All are testable:
- [x] AC 1 (POST /inbound parses Postmark JSON) -- testable via webhook mock
- [x] AC 2 (Agent pulls billing data via Rails API) -- testable with mock; depends on Rails prerequisite
- [x] AC 3 (Standard fixes: rename dues, cancel dupes, add missing fees) -- testable with mock data
- [x] AC 4 (Draft billing email with itemized table) -- testable
- [x] AC 5 (Send test email to Marcus via Postmark) -- testable
- [x] AC 6 (Parse Marcus's approval reply) -- testable, approval language explicitly enumerated
- [x] AC 7 (Send to parent only after explicit approval) -- testable
- [x] AC 8 (One player at a time, sequential) -- testable
- [x] AC 9 (Resume from persistent state file) -- testable
- [x] AC 10 (Flag edge cases) -- testable, specific cases enumerated
- [x] AC 11 (Postmark error handling with retry/backoff) -- testable
- [x] AC 12 (Ruff lint + format in CI) -- testable
- [x] AC 13 (pytest tests pass) -- testable
One minor note: the approval parsing constraint is well-specified -- "send it"/"approved"/naming the recipient count as approval; "Push it"/"let's go"/"ASAP" do NOT. This is a critical safety gate that is clearly testable.
Blast Radius
- Nemo is a new standalone service; blast radius within its own repo is contained.
- Cross-repo impact on westside-basketball is limited to adding a new API namespace (no existing code modified).
- No existing Postmark integration in the infrastructure -- net-new.
- Documentation inconsistency in nemo repo:
projects/westside-billing-agent/workflow.mdstill references Gmail API,ParentMailer#billing_followup,POST /api/v1/emails/send, andkubectl execapproach.docs/architecture.mddiagram has stale "send email" label on the Rails connection and mentions "Gmail" in the intro. These contradict the issue's explicit Postmark approach. An implementing agent reading these docs could get confused.
Decomposition Assessment
Thresholds exceeded but owner chose single ticket:
- 13 file targets in 1 repo -- exceeds 3+ threshold (but single repo, not >2 repos)
- 13 acceptance criteria -- exceeds 5 AC threshold
- Estimated agent work far exceeds 5 minutes -- full greenfield service
- Owner explicitly chose to keep as single detailed ticket rather than decompose
The issue's level of detail (inline code blocks, exact routes, column-level model descriptions) partially compensates for its size. An agent has enough specificity to implement without ambiguity, even though the scope is large. Respecting owner's decision.
Recommendation
[SCOPE]Create project pageproject-nemowith user-stories section containing the billing-follow-up story entry. (Carried forward from prior review.)[SCOPE]Create architecture notearch-nemo-agentfor the agent component. Derive fromdocs/architecture.mdin the nemo repo. (Carried forward from prior review.)[SCOPE]Create the Rails API prerequisite ticket on westside-basketball. The issue body contains complete spec material (controller code, routes, env var) -- this should be extracted into a separate Forgejo issue before work starts.[SCOPE]Updateprojects/westside-billing-agent/workflow.mdanddocs/architecture.mdin the nemo repo to reflect the Postmark decision. Currently they reference Gmail API,ParentMailer#billing_followup, andPOST /api/v1/emails/send, which contradict the issue's Postmark approach. This should happen before an agent starts implementation to avoid confusion.
-
Review: Implement billing follow-up agent for Westside Basketball
review-1903-2026-07-25Verdict: NEEDS_REFINEMENT
Template Completeness
- [x] Type -- Feature
- [x] Lineage -- Standalone, first ticket for Nemo project
- [x] Repo -- ldraney/nemo
- [x] User Story -- well-formed (As Marcus, I want...)
- [x] Context -- thorough background on the 28-player billing campaign
- [x] File Targets -- 8 files to create, 2 files excluded
- [x] Feature Flag -- none
- [x] Acceptance Criteria -- 9 criteria
- [x] Test Expectations -- 4 test items + run command
- [x] Constraints -- 6 constraints listed
- [x] Checklist -- present
- [x] Related -- present
All required template sections are present.
Traceability
- [x] story:billing-follow-up label -- present on board item
- [ ] story note MISSING --
project-nemopage does not exist (404). [SCOPE] Create project pageproject-nemowith user-stories section containing the billing-follow-up story. - [x] arch:nemo-agent label -- present on board item
- [ ] arch note MISSING --
arch-nemo-agentnote does not exist (404). [SCOPE] Create architecture notearch-nemo-agentfor the agent component. - [x] Forgejo issue -- ldraney/nemo#1, state: open
File Targets
- [x]
src/webhook.py-- to create; repo is currently docs-only, path is valid - [x]
src/agent.py-- to create; consistent with architecture doc - [x]
src/tools.py-- to create; consistent with architecture doc - [x]
src/config.py-- to create; consistent with architecture doc - [x]
Dockerfile-- to create; standard for containerized service - [x]
pyproject.toml-- to create; standard Python project file - [x]
.woodpecker/ci.yaml-- to create; matches platform CI convention - [x]
.pre-commit-config.yaml-- to create; matches platform convention - [x]
docs/-- excluded (already exists in repo) - [x]
projects/westside-billing-agent/workflow.md-- excluded (exists in repo)
All file targets are valid for a greenfield service in a docs-only repo.
Repo Placement
Issue is filed on
ldraney/nemoand all file targets are in the nemo repo -- correct. However, there is an undocumented cross-repo dependency:- AC #2 references
GET /api/v1/players/:id/billingbut the westside-basketball Rails app has NO JSON API endpoints at all. The routes.rb has noapi/v1namespace and no API controllers exist. - The workflow doc (
projects/westside-billing-agent/workflow.md) explicitly lists "JSON API endpoints" under "What Is NOT Built" and proposes two options: (A) JSON API on Rails, or (B) Direct API access via kubectl/Stripe/Gmail. - The ticket implicitly assumes Option A without creating a companion westside-basketball ticket for the API endpoints.
- AC #4 references
ParentMailer#billing_followupbut that method does not exist. ParentMailer only hasannouncement,payment_reminder, andquick_send.
The ticket must either: (a) add a cross-repo dependency ticket on westside-basketball for JSON API + mailer work, or (b) rewrite the approach to use Option B (direct API access) and clarify which mailer method to use.
Dependencies
- Only item on board-nemo; no board-level blockers or blocked items.
- Cross-repo dependency (undocumented): Rails JSON API endpoints (
/api/v1/players/:id/billing,PATCH /api/v1/orders/:id,POST /api/v1/orders,POST /api/v1/emails/send,GET /api/v1/emails/inbox) do not exist in westside-basketball. No ticket exists to create them. - Cross-repo dependency (undocumented):
ParentMailer#billing_followupdoes not exist in westside-basketball. Onlyannouncement,payment_reminder,quick_sendexist. - Operational dependencies: Postmark account + DNS setup, Anthropic API key, Stripe API key, k8s namespace creation -- not code dependencies but need to exist before deployment.
Acceptance Criteria
9 acceptance criteria listed. Assessment:
- AC #1 (Postmark triggers agent) -- testable via webhook mock
- AC #2 (Agent pulls from Rails JSON API) -- BLOCKED: API does not exist in the Rails app
- AC #3 (Standard fixes) -- testable with mock data
- AC #4 (Draft billing email via Postmark) -- references nonexistent
billing_followupmailer; also, the architecture doc says Nemo sends via Postmark outbound, but the workflow doc referencesParentMailer(Rails Gmail delivery). These contradict each other. - AC #5-6 (Marcus approval flow) -- testable
- AC #7 (One player at a time) -- testable
- AC #8 (Persistent state on restart) -- testable
- AC #9 (Custom email handling for edge cases) -- vague; what edge cases specifically? "no-show, disputed, left program" are mentioned in Constraints but not mapped to specific AC behaviors
Blast Radius
- Nemo is a new standalone service, so blast radius within its own repo is contained.
- Cross-repo impact on westside-basketball is the primary concern: JSON API endpoints, mailer methods, and potentially auth token setup.
- No existing Postmark integration anywhere in the infrastructure -- this is net-new infrastructure.
- Email sending conflict: architecture.md says Nemo sends via Postmark outbound, workflow.md says emails go through
ParentMailer(Rails + Gmail). The ticket must pick one approach.
Decomposition Assessment
NEEDS DECOMPOSITION -- route to skill-decompose-ticket
- 8 file targets in 1 repo -- exceeds the 3+ file threshold
- 9 acceptance criteria -- exceeds the 5 AC threshold
- Estimated agent work far exceeds 5 minutes -- building an entire FastAPI service with Claude agent loop, Postmark webhook handling, tool definitions, persistent state, Dockerfile, CI pipeline, and pre-commit config is a multi-hour effort
- Cross-repo dependency -- Rails JSON API and/or mailer work needs a separate ticket on westside-basketball
Suggested decomposition axes:
- Skeleton service (FastAPI webhook + config + Dockerfile + CI + pre-commit) -- infra only, no agent logic
- Agent loop core (agent.py + tools.py) -- Claude API integration with tool use
- Postmark integration (inbound parsing + outbound sending + signature validation)
- Billing workflow logic (standard fixes, email drafting, approval parsing)
- State management (persistent state file, resume on restart)
- Cross-repo: westside-basketball JSON API endpoints (separate repo ticket)
Recommendation
[SCOPE]Create project pageproject-nemowith user-stories section containing the billing-follow-up story entry.[SCOPE]Create architecture notearch-nemo-agentfor the agent component. The architecture.md in the repo is detailed -- this can be derived from it.[BODY]Resolve the data access approach: either commit to Option A (JSON API on Rails, which requires a cross-repo dependency ticket on westside-basketball) or Option B (direct API access via Stripe/kubectl). Update AC #2 accordingly.[BODY]Resolve the email sending approach: architecture.md says Postmark outbound, workflow.md saysParentMailer(Rails + Gmail). Pick one and update AC #4 and the File Targets section.[BODY]Fix AC #4:ParentMailer#billing_followupdoes not exist. Either referenceannouncement/quick_sendor add a cross-repo dependency to create the method.[BODY]AC #9 (custom email handling) is too vague for agent verification. Enumerate the specific edge cases and expected agent behavior for each.[DECOMPOSE]8 file targets and 9 AC across a full greenfield service far exceed the 5-minute rule. Route toskill-decompose-ticketfor sub-ticket creation. Suggested decomposition: skeleton service, agent loop, Postmark integration, billing workflow, state management, and cross-repo Rails API work.
Board 1
-
Nemo
board-nemoNo content
Repos 1
-
nemoactive