Background Agents Architecture

April 18, 2026

Specialized autonomous agents running in the background across morning briefings, meeting prep, reply generation, and more.

  • Agents: 8 specialized
  • Cost Savings: 5× vs boss agent
  • Safety Model: Read-only by default

01 — Why Dedicated Agents

The boss agent (Opus 4.6) can do anything. Give it a workflow and it will execute. But "can do anything" is the wrong architecture for recurring, high-frequency background tasks. It's expensive, slow, and carries the full tool surface. A morning briefing doesn't need Slack posting tools. A meeting prep doesn't need email sending. Loading unnecessary capabilities wastes context, increases cost, and creates risk.

01 — Specialized Storage Schemas

Each agent writes results through a terminal tool (DUMP_REPLY, DUMP_MEETING_PREP) into purpose-built database schemas. The reply generator stores suggested_reply, thread_summary, provider_draft_id, attachment metadata, and recipient lists. These schemas enable rich UIs that would be impossible with unstructured agent output.

02 — Read-Only Tool Sets

Background agents use build_tools_for_readonly_subagent() — a tool builder that only loads read-only MCP tools. No GMAIL_SEND_EMAIL, no SLACK_POST_MESSAGE. This is a hard architectural boundary, not a prompt instruction. The tools simply aren't available.

03 — Focused Prompts, Cheaper Models

The boss agent uses Opus 4.6 ($15/M input). Background agents use Sonnet 4.6 ($3/M input) — 5× cheaper — with tightly scoped system prompts. A 500-line general-purpose prompt dilutes attention. A 100-line task-specific prompt concentrates it.

A hallucinated "send this email" tool call fails with "tool not found" instead of sending an email. Safety through architecture, not instructions.


02 — The Background Agent Roster

Eight specialized agents run autonomously. Every agent follows the same pattern: NATS consumer receives event → agent graph runs → terminal tool writes structured output to DB → UI updates via Ably push.

AgentTriggerWhat It DoesModel
Morning BriefingDaily cron (pre-dawn)Day summary: calendar, emails, tasks. Parallel subgraphs for body + repliesSonnet 4.6
Evening BriefingDaily cron (end of day)Recaps completed items, pending threads, tomorrow's agendaSonnet 4.6
Reply GeneratorWebhook (new email / Slack DM)Drafts reply with tone matching. Creates Gmail draft. Opus refinement passS 4.6 + O 4.6
Meeting PrepCal sync + daily refresh + pre-meeting cronPrep notes: attendee context, relevant docs, talking pointsSonnet 4.6
Action ItemsWebhooks (Gmail, Linear, GitHub, Cal)Surfaces PR reviews, assigned issues, emails needing replySonnet 4.6
OnboardingUser signupResearches user on the web, generates profile, seeds memory graphSonnet 4.6
SkillsUser approves learned patternIndexes skill execution summary, stores reusable workflow patternSonnet 4.6
Begging AgentNear credit limitNudges user about usage, suggests upgrade path. Quality matters — converts free users to paidOpus 4.6

Shared Execution Pattern

NATS Event  Consumer  Agent Graph  DUMP_* Tool  DB + Ably Push

Note: From this point on, this document uses the Meeting Prep agent as a running example to illustrate how a background agent works end-to-end. The patterns shown — event-driven triggers, agent graph execution, structured output via DUMP tools — are the same across all eight agents.


03 — Meeting Prep — The Full Pipeline

One of our most loved background agents. Three consumers, a dedicated LangGraph agent, and multiple trigger paths.

Pipeline Stages

Stage 1 — SyncCalendarConsumer (webhooks app)
Fetch events via sync_token → normalize → match workflows → publish calendar events

Stage 2 — CalendarUpdateSuggestions (rag app)
Filter to next 2 days → separate cancelled/active → skip declined → route to prep or action item

Stage 3 — MeetingPrepConsumer (agent app)
Upsert skeleton → defer if not today → content diff → time shift detection (>20 min = regen) → skip RSVP-only → run agent → publish action item → send email

Stage 4 — meeting_prep_graph (LangGraph ReAct)

START  agent  tools  END

Tools: MEMORY_SEARCH, HYBRID_SEARCH, ADD_INTEGRATIONS, WEB_SEARCH, PEOPLE_SEARCH, Read-only MCP, DUMP_MEETING_PREP

Four Trigger Paths

  1. Calendar Sync — User connects Calendar. Skeleton upserted, deferred if not today.
  2. Webhook Update — Event changes (reschedule, new attendee). Content diff → regen only if material.
  3. Morning Refresh — Daily pre-dawn. Refreshes stale preps generated before today.
  4. Pre-Meeting Cron — ~20 min before meeting. Always regenerates. Sends email with prep notes.

The consumer decides whether to run the agent at all. RSVP changes, minor time shifts, and non-today events are handled without invoking the LLM.


04 — The Meeting Prep Agent

Classification Gate

  • Work meeting → proceed — Colleague sync, client call, sprint planning, 1:1s, standups
  • Not work → skip immediately — Haircut, gym, dentist, focus time. Calls DUMP_MEETING_PREP(skip=true)

Research Strategy — Domain Comparison

Internal (same domain):

  • Routine sync: Linear current cycle, blockers
  • Topic meeting: HYBRID_SEARCH for specs/docs
  • Vague title: MEMORY_SEARCH for patterns

External (different domain):

  • Known contact: Gmail threads, relationship history
  • New contact: PEOPLE_SEARCH, WEB_SEARCH
  • High-stakes: all of above + correspondence

The Agent's Prompt is Opinionated

Good: "Heads up: they mentioned response time concerns in their last email"

Bad: "Key Notes: Enterprise prospect. High-stakes call."

Tone: "Sharp colleague giving a heads-up, not a system generating a report." 100 lines of tone guidance and classification heuristics the boss agent's prompt can't carry for every task.

Update Intelligence

  • Content Change — Title, description, attendees → regenerate with fresh context
  • Time Shift >20 min — Regenerate + publish action item notification
  • RSVP-Only — Skip entirely, keep existing prep
  • Stale Prep — Generated before today → always regenerate

05 — Reply Generator

Demonstrates parallel pre-computation: expensive operations run before the agent's first LLM call, saving ReAct turns and latency.

LangGraph Execution Flow

START  ┌─ memory_search_node          ─┐
        ├─ preprocess_attachments_node  ─┤  agent  tools  END
        └─ prefetch_tone_skill_node    ─┘

Three nodes run in parallel before the agent's first LLM call.

Generates optimized queries from sender/subject/snippet, searches Zep for relationship context. The agent receives pre-computed memory instead of calling MEMORY_SEARCH itself — saves a full ReAct turn.

02 — Attachment Preprocessing

Extracts content from PDFs, images, and documents attached to the latest message. The agent sees extracted text, not raw attachments.

03 — Tone Skill Prefetch

Loads the user's learned email/Slack tone profile (if one exists). Both the Sonnet agent and the Opus refinement pass use this to match the user's natural voice.

Two-Model Architecture

Sonnet 4.6 (Research + draft)  Opus 4.6 (Tone refinement)  Gmail Draft (In user's account)

Production-quality replies at a fraction of the cost. Cheap model for research, expensive model for the final voice.


06 — Design Principles

01 — Each Agent is an Isolated Unit of Work

Every background agent runs on its own NATS consumer with independent retry semantics, cost tracking, and error handling. A failed meeting prep doesn't affect the morning briefing. A timed-out reply generator doesn't block the next email. They share infrastructure (NATS, Postgres, Zep, TurboPuffer) but never share state.

02 — Read-Only by Default

Background agents observe and summarize. They never take actions with real-world consequences — no emails sent, no messages posted, no issues created. The one exception (Gmail draft creation in the reply generator) is a deliberate, user-facing decision that creates a draft, not a sent email.

03 — Terminal Tools Enforce Schema

Every agent ends with a DUMP_* tool call that writes structured output to a purpose-built table. The schema is the API. Adding a field means updating the tool schema, the DB migration, and the UI component.

04 — Deferred Execution Saves Cost

Meeting prep defers non-today events. The morning briefing refreshes stale preps on the day of. Pre-meeting crons run 20 minutes before. This cascading deferral pattern means most events are only processed once, on the day they matter — not on every calendar sync.

05 — Consumer Decides, Agent Executes

The NATS consumer handles all "should we run?" logic — content diffs, time shift detection, RSVP filtering, staleness checks. The agent itself is stateless — it receives context and produces output. The LLM is never invoked for decisions that can be made deterministically.


This architecture powers dimension.dev's background agents — eight specialized agents handling recurring intelligence tasks for thousands of users daily.