← all docs · north-os22 July 2026

NetDocs tips loop — mail intake, firm wiki, newsletters — design spec

Status: Planned
Author: Christophe
Date: 2026-07-22
Repo: north-os (apps/web, packages/agent-runtime, packages/knowledge, packages/db, apps/worker-notifications, apps/worker-automations)
Related: docs/superpowers/specs/2026-07-20-knowledge-retrieval-precision-design.html; weekly digest apps/worker-notifications/src/loops/weekly-digest.ts; automations tools packages/agent-runtime/src/tools/automations.ts

Context

Gill (HSE) asked for a test run of a multi-step agent loop: HSE staffers email NetDocs tips and tricks (text, screenshots, video links) to a dedicated intake address (netdocstips@hseny.com); an agent curates them into a coherent, referenceable resource; a periodic email goes to staff (every 2 days initially, weekly once settled). Explicit goals: nobody "manages" the intake, nobody's inbox gets flooded, and the loop demonstrates that agentic automation actually saves time. Gill notes many HSE administrative processes could follow the same rubric — this is the low-stakes pilot for that pattern.

This spec locks the architecture discussed on 2026-07-22. Three deliverables:

  1. The tips loop itself — intake mailbox → curated wiki → knowledge base → digest.
  2. A firm wiki surface in apps/web — new product surface, reusable beyond tips.
  3. Newsletters as a first-class capability — entity + agent tool family + UI, reusable beyond tips. This is the largest net-new piece.

The pattern being productized: North watches a source, keeps a living record, and tells the right people at the right moment. The next instance (new intake address, new wiki section, new periodic email) must be agent-doable configuration, not a project.

Decisions (locked)

D1 — Intake: licensed account, not a shared mailbox

connector-outlook is delegated per-user OAuth with every Graph call /me-anchored (subscriptions build me/mailFolders('Inbox')/messages; message/attachment fetch, folder listing — all /me). Scopes have no .Shared variants and there is no app-only (client_credentials) path anywhere in the codebase. True shared-mailbox support would mean new scopes (fresh tenant consent) plus parameterizing /me/users/{mailbox} across ~6 files in the package and worker-mail.

Decision: HSE creates netdocstips@hseny.com as a regular licensed account. We create a North service user for it and enroll through the standard connector OAuth signed in as that account (completeAuth binds whatever tenant account signs in to the initiating North user — no UPN match required). The entire existing machinery (subscription, webhook fan-out, attachment ingest, recent-mail import) works unchanged because the token is the mailbox. Christophe performs the connection himself given the account credentials.

The .Shared refactor is explicitly deferred; revisit only if HSE refuses a licensed seat.

Follow-up: exclude the service mailbox from the mail-intelligence realtime pipeline so tips mail doesn't pollute matter signals.

D2 — The pipeline is a prompt, not a system

No bespoke worker, no new pipeline code. A scheduled automation (existing automations + worker-automations automation.run executor) runs the agent with existing tools: read new mail in the tips mailbox since last run (search_email / read_email_thread as the service user), extract each tip, enrich via web_research, write wiki pages, ingest to knowledge. The next admin workflow is a new mailbox + a new automation prompt + a new category.

D3 — Reading surface: a wiki inside apps/web

Not a new app, not a Word document (unless Gill insists — asked in the reply; a doc export can be generated as a projection later). A route group in the existing shell ((app)/wiki, "Firm knowledge"): same sidebar, same Better Auth session, same org scoping. One login — North is the basecamp.

D4 — Knowledge ingestion: dedicated corpus category

Every wiki page is ingested into @workspace/knowledge via the existing pipeline/ingest-single-file.ts seam, under a dedicated corpus_category (e.g. firm-know-how / netdocs-tips), scope firm_global. This makes tips answerable in chat and over MCP (north__knowledge_search) — "how do I do X in NetDocs" returns the tip with its screenshot and video link.

Gaps to close (small): retrieval currently ignores corpus_category — add a category filter, expose it on the MCP search tool, and ensure firm-procedural content is excluded or down-ranked in matter contexts (firm know-how must never outrank matter documents in a matter thread — see the 2026-07-20 retrieval precision work).

Strategically this creates the second knowledge domain: firm operational know-how, alongside matter knowledge.

D5 — Newsletters: first-class entity, automation-backed via a facade

Verified posture: the agent cannot send mail autonomously todaymail-send.ts is the human-click path behind the ReplyDraftWidget ("never reached by the agent itself"), and the shipped weekly digest is a code-driven loop in worker-notifications. Autonomous newsletter send is therefore a deliberate, guardrailed posture change — a first-class capability, not a raw send tool.

Split of state:

Agent tool family (mirrors automations): create_newsletter, list_newsletters, update_newsletter (pause/resume, recipients, cadence), delete_newsletter. The agent can spin up a newsletter from chat — the tips digest is simply the first newsletter created through the tool.

Guardrails (what makes autonomous send acceptable):

  1. Newsletters send only from enrolled service mailboxes (e.g. netdocstips@) — never from a lawyer's own mailbox. The "agent never sends as you" invariant stands.
  2. Audience must be an explicit managed list or distribution-list address — no free-form recipients.
  3. Mandatory unsubscribe footer (route already exists: apps/web/app/api/newsletter/unsubscribe).
  4. Every newsletter starts gated: each issue pauses for one-click approval; promoted to autonomous explicitly after the first sends look right.

Sending rides worker-notifications (already the outbound-email domain, owns the weekly-digest precedent and the unsubscribe route). Composition rides worker-automations (headless run per issue). No new worker.

D6 — Newsletter UI: issue step timeline

A page alongside tasks/automations: newsletter list (next send, last send, recipients, pause/disable), and a per-issue detail view making the pipeline visible:

Issue #4 · due Jul 24, 9:00
  ● Gather      3 new tips since issue #3
  ● Compose     draft preview (rendered email)
  ◐ Approve     waiting  [Approve] [Edit] [Skip this issue]
  ○ Send        → 47 recipients ("HSE All Staff")
  ○ Report      delivered / bounced / unsubscribed

The approval gate sits between Compose and Send. Promoted newsletters show Approve as auto-passed and the timeline becomes a send log. Failures (sender token expired, Graph throttling) surface as a red step instead of a silently dead automation.

D7 — Loop niceties

D8 — Privacy

Architecture

HSE staffer ──mail──▶ netdocstips@hseny.com (licensed acct, enrolled via std OAuth)
                            │  worker-mail (existing, unchanged)
                            ▼
              scheduled automation (automation.run, headless)
                "process new tips since last run"
                            │
        ┌───────────────────┼──────────────────────┐
        ▼                   ▼                      ▼
  web_research        create/update           knowledge ingest
  (enrich, text       wiki pages              (ingest-single-file,
   only)              (canonical store)        corpus_category)
                            │                      │
                            ▼                      ▼
                     (app)/wiki in web       chat + MCP answers
                            │
                            ▼
              newsletter "NetDocs tips digest"
              (entity → hidden automation → compose run
               → gated approve → send via worker-notifications)

Single source of truth: wiki pages. Knowledge index, digest issues, and any future doc export are projections.

Net-new build (the honest shortlist)

#PieceSize
1North service user + mailbox enrollmentconfig, not code
2wiki_page schema + RLS + (app)/wiki route + 3 agent toolsmedium
3Knowledge: category filter in retrieval + MCP param + ingest tool wrapping ingest-single-filesmall
4Newsletter domain: tables + service + 4 agent tools + facade over automations + send seam in worker-notifications + UI with issue timelinelargest piece
5Automation prompts (intake processing, synthesis) + tips digest newslettercontent, not infra
6MI exclusion for service mailboxsmall

No new worker. No third-party wiki engine. Migrations via bun db:generate as always.

Open questions (pending Gill)

  1. Licensed account OK (vs shared mailbox)? Credentials shared with Christophe?
  2. Wiki in North confirmed vs. an explicit Word document requirement?
  3. Access rollout: all staff get North logins, or small group + digest carries content meanwhile?
  4. Digest audience: all staff or a distribution list HSE controls? Who holds the approval click during the gated phase?

Out of scope (v1)