Skip to Content
Human-in-the-LoopHITL — UI Patterns

HITL — UI Patterns

How approvals are surfaced, displayed, and actioned across every interface — DM Portal, Dashboard, Mobile, and CLI.

See also: Approval Flow — full lifecycle | HITL Index — all touchpoints Screen specs: DM Portal Screens | Dashboard Screens | Mobile | CLI Commands


Where Approvals Surface

InterfacePrimary surfaceSecondary surface
DM PortalApproval Queue (P2) — cross-tenant listActivity Detail (P3) — inline review
DashboardApprovals Queue (D5) — tenant’s ownCampaign Detail (D4) — per-activity
MobileApprovals tab — push-notification entry point
CLI (lm)/queue — terminal table/stream + /approve — inline

DM Portal — The Primary Review Interface

The DM Portal is where the bulk of HITL decisions are made. Reviewers see work across all their assigned tenants in one place.

P2 — Approval Queue

┌─────────────────────────────────────────────────────────────────────┐ │ Approvals [Bulk select ▾] [Filter]│ ├─────────────────────────────────────────────────────────────────────┤ │ │ │ 🔴 HIGH RISK (2) │ │ ─────────────────────────────────────────────────────────────── │ │ ☐ Q2 Newsletter — April 2026 Globex Corp email 2h │ │ Content review · Email campaign · Expires in 22h │ │ ✅ Sarah K. approved · ⏳ Tenant admin pending │ │ [Review]│ │ │ │ ☐ Live Ad Push — Google Ads Campaign Acme Corp ads 45m │ │ Channel action · Google Ads · Expires in 23h │ │ [Review]│ │ │ │ 🟡 MEDIUM RISK (4) │ │ ─────────────────────────────────────────────────────────────── │ │ ☐ LinkedIn — Week 14 Acme Corp social 3h │ │ Content review · Social post │ │ [Review]│ │ ☐ Facebook — Week 14 Acme Corp social 3h │ │ Content review · Social post │ │ [Review]│ │ │ │ 🟢 LOW RISK (8) │ │ ─────────────────────────────────────────────────────────────── │ │ ☐ "Why Local SEO Matters" Acme Corp blog 18h │ │ ☐ "Top 5 Plumbing Tips" Acme Corp blog 18h │ │ ☐ "GBP Profile Optimisation" Acme Corp blog 17h │ │ ☐ + 5 more [Show all]│ │ │ │ ────────────────────────────────────────────────────────────────── │ │ Selected: 0 items [Approve all low]│ └─────────────────────────────────────────────────────────────────────┘

Visual conventions:

  • 🔴 / 🟡 / 🟢 risk badges are always shown — reviewers learn to scan by colour
  • High-risk items always appear at the top, regardless of age
  • Items approaching expiry show a countdown: Expires in 4h ⚠ with amber text
  • Expired items appear in a separate 🚨 EXPIRED section at the very top
  • Dual-approval items show which sign-offs are pending inline on the queue row
  • Bulk select + “Approve all low” is available for fast processing of large low-risk queues

Filtering options:

  • By tenant, risk level, type, agent role, age
  • “Assigned to me” vs “All reviewers”

P3 — Activity Detail (HITL review pane)

Opening a content_review approval for a blog post:

┌──────────────────────────┬──────────────────────────────────────────┐ │ ← Approvals │ Content Review │ │ │ "Why Local SEO Matters" │ │ Acme Corp │ blog_post · low risk · 18h ago │ │ "Why Local SEO ├──────────────────────────────────────────┤ │ Matters" │ Agent: blog-writer │ │ │ Model: claude-sonnet-4-6 │ │ ───────────────────── │ Tokens: 4,812 in / 1,204 out │ │ Validator results │ Cost: $0.018 │ │ │ Duration: 3m 40s │ │ ✅ Word count: 1,240 ├──────────────────────────────────────────┤ │ (min 800) │ ▸ Retrieved context (3 RAG queries) │ │ ✅ Sections: 5/5 │ client_docs · website_content │ │ ✅ Brand voice: 82/100 ├──────────────────────────────────────────┤ │ ✅ No banned words │ │ │ │ # Why Local SEO Matters for │ │ ───────────────────── │ Brisbane Plumbers │ │ Skills used │ │ │ client-context-file │ Local SEO is no longer optional for │ │ seo-brief │ businesses that rely on customers in │ │ │ a specific area. For a plumbing │ │ ───────────────────── │ business in Brisbane, ranking on page │ │ Approval expiry │ one for "plumber near me" can be the │ │ In 54 hours │ difference between… │ │ │ │ │ │ [full content scrollable] │ │ │ │ │ ├──────────────────────────────────────────┤ │ │ Reviewer notes (optional for approve, │ │ │ required for reject) │ │ │ ┌──────────────────────────────────┐ │ │ │ │ │ │ │ │ └──────────────────────────────────┘ │ │ │ │ │ │ [Edit content] │ │ │ [Reject ↩] [Approve ✓] │ └──────────────────────────┴──────────────────────────────────────────┘

“Edit content” flow:

  • Opens the content in an inline rich-text editor
  • Reviewer makes changes (typos, tone, factual fixes)
  • Clicks “Approve edited version” → edited content saved as final, no retry

For content_direction / brand_direction approvals with options:

Direction needed: "Should this blog target informational or commercial intent?" ○ Informational — "How to find a reliable plumber in Brisbane" Target: top-of-funnel, build authority ○ Commercial — "Best emergency plumber in Brisbane" Target: high-intent, conversion-focused [Reject ↩] [Approve selected option ✓]

For channel_action approvals (write-tool gate):

Channel Action Pending Action: Publish post to WordPress Site: acmecorp.com.au Post: "Why Local SEO Matters" Status: Will publish immediately on approval ⚠ This action cannot be undone once executed. [Cancel action ✗] [Approve & publish ✓]

Dashboard — Tenant Self-Approval

Tenants see their own approvals in the Dashboard. They cannot see approvals for other tenants.

D5 — Approvals Queue

Same layout as DM Portal P2 but scoped to the tenant’s content only. Tenants see:

  • content_review approvals for their deliverables
  • strategy_change and budget_authorization approvals that require their sign-off
  • The second sign-off prompt when a DM reviewer has already approved
┌──────────────────────────────────────────────────────┐ │ Approvals [Filter] │ ├──────────────────────────────────────────────────────┤ │ │ │ ACTION REQUIRED FROM YOU (1) │ │ ───────────────────────────────────────────────── │ │ Q2 Newsletter — April 2026 email high │ │ Sarah K. (DM team) has approved this. │ │ Your sign-off is also required before sending. │ │ [Review] │ │ │ │ PENDING DM REVIEW (3) │ │ ───────────────────────────────────────────────── │ │ "Why Local SEO Matters" blog low │ │ "Top 5 Plumbing Tips" blog low │ │ LinkedIn — Week 14 social medium │ │ │ └──────────────────────────────────────────────────────┘

Tenants see “Pending DM Review” items as read-only — they can see what is in the queue but cannot action items that are pending the DM reviewer’s turn.

D4 — Campaign Detail → Activity tab

Each activity card in the activity list shows its approval status inline:

┌──────────────────────────────────────────────────────────────┐ │ 🤖 Blog Writer — "Why Local SEO Matters" │ │ Status: ⏳ Awaiting approval · risk: low · 18h │ │ Cost: $0.018 · Duration: 3m 40s │ │ │ │ [View content] [Approve ✓] [Reject ↩] │ └──────────────────────────────────────────────────────────────┘

Clicking “View content” expands the card inline with the full output + validator results — no page navigation required for simple approvals.


Mobile — Push-First Approval Flow

Mobile is designed for the approval use case specifically. The primary entry point is a push notification, not the app.

📝 Blog post ready to review — Acme Corp "Why Local SEO Matters" · low risk

Tapping the notification deep-links directly to the review screen for that specific approval — not to the approvals list.

Mobile approval review screen

┌──────────────────────────────────────┐ │ ← Approvals ≡ │ │ │ │ Why Local SEO Matters │ │ blog post · low risk · 18h ago │ │ ──────────────────────────────── │ │ Acme Corp · blog-writer │ │ 1,240 words · $0.018 · 3m 40s │ │ │ │ ──────────────────────────────── │ │ Local SEO is no longer optional │ │ for businesses that rely on │ │ customers in a specific area. │ │ For a plumbing business in │ │ Brisbane, ranking on page one │ │ for "plumber near me" can be… │ │ │ │ [Read full post ↓] │ │ │ │ ──────────────────────────────── │ │ Notes (required to reject) │ │ ┌──────────────────────────────┐ │ │ │ │ │ │ └──────────────────────────────┘ │ │ │ │ ┌────────────┐ ┌────────────────┐ │ │ │ Reject ↩ │ │ Approve ✓ │ │ │ └────────────┘ └────────────────┘ │ │ │ │ Approving triggers haptic feedback │ └──────────────────────────────────────┘

Mobile-specific UX notes:

  • Action bar is pinned to the bottom — always visible without scrolling
  • Approve triggers haptic feedback (success pattern) + green flash
  • Rejection note entry uses a keyboard-aware bottom sheet so the input is never hidden
  • Swipe right on an approval card in the list = quick approve (with haptic + undo toast)
  • Swipe left = flag for later (snooze 2h)
  • Offline: decision is queued locally and submitted when connectivity returns. A banner shows: “Your approval will be submitted when you’re back online.”

Approvals tab (bottom bar)

The Approvals tab shows a badge with the count of pending items. The tab itself has two sub-sections:

[Needs your action] [Pending DM review]

“Needs your action” = approvals where the tenant admin is the blocker (strategy_change, budget_authorization, dual sign-off). These are sorted to the top and badged on the tab icon.


CLI — Terminal Approval Patterns

See CLI Commands — /approve, /reject, /bulk-approve for full command docs.

/queue output

lm [Acme Corp] › /queue 🔴 High Risk (1) ───────────────────────────────────────────────────────────────── A-1250 channel_action "Publish Q2 Newsletter to Mailchimp" 45m 🟡 Medium Risk (2) ───────────────────────────────────────────────────────────────── A-1253 social_post "LinkedIn — Week 14" 3h A-1254 social_post "Facebook — Week 14" 3h 🟢 Low Risk (3) ───────────────────────────────────────────────────────────────── A-1234 blog_post "Why Local SEO Matters" 18h A-1235 blog_post "Top 5 Plumbing Tips" 18h A-1236 blog_post "GBP Profile Optimisation" 17h

Inline review with /stream + /approve

lm [Acme Corp] › /stream A-1234 Content Review — "Why Local SEO Matters" blog_post · low risk · 18h ago · $0.018 Validator: ✅ word_count ✅ brand_voice:82 ✅ no_banned_words ────────────────────────────────────────────────────────────────── # Why Local SEO Matters for Brisbane Plumbers Local SEO is no longer optional for businesses… [full content] [/approve A-1234] [/reject A-1234 --reason "..."] lm [Acme Corp] › /approve A-1234 ✅ Approved. "Publish to WordPress" queued.

Bulk approve

lm [Acme Corp] › /bulk-approve --filter "risk=low" Preview — 3 blog posts will be approved: A-1234 "Why Local SEO Matters" A-1235 "Top 5 Plumbing Tips" A-1236 "GBP Profile Optimisation" Confirm? [y/N] › y ✅ 3 approved. Publish activities queued for all 3.

In-App Notifications (Web Bell)

The bell icon in the top navigation shows a badge count of unread notifications. Clicking it opens a dropdown:

┌──────────────────────────────────────────────┐ │ Notifications Mark all ✓ │ ├──────────────────────────────────────────────┤ │ 🔴 Q2 Newsletter needs your sign-off │ │ Globex Corp · email · 45 min ago │ │ [Review →] │ │ │ │ 📝 3 blog posts ready to review │ │ Acme Corp · low risk · 18h ago │ │ [Queue →] │ │ │ │ ✅ "LinkedIn Week 14" was approved │ │ by Sarah K. · 2h ago │ │ │ │ ⏱ Approval expiring in 4h │ │ "Live Ad Push" — Acme Corp │ │ [Review →] │ └──────────────────────────────────────────────┘

Notification types in the bell:

  • New approval requiring action (links to review screen)
  • Approval approved / rejected by someone else (informational)
  • Approval expiry warning (4h before expiry)
  • Budget cap alert
  • Channel disconnected (token expired)
  • Agent error / escalation

The bell updates in real time via SSE — no page refresh needed.


Notification Preferences

Users can configure which events trigger which channels in Settings → Notifications:

EventWeb (always)EmailSMSPush
New high-risk approval✅ on✅ onconfigurable✅ on
New medium-risk approval✅ on✅ onoff✅ on
New low-risk approval✅ ondigestoffconfigurable
Approval expiry warning✅ on✅ onoff✅ on
Approval resolved by colleague✅ onoffoffoff
Budget alert✅ on✅ onconfigurable✅ on
Agent error✅ on✅ onoff✅ on

Defaults shown above. Users can turn off any channel except web (in-app) for any event.

Notification delivery specs: Channels | Providers

© 2026 Leadmetrics — Internal use only