Reply Copilot guide
¶ Reply Copilot helps staff draft replies, not send them.
The released first slice lives inside the existing ReplyBox composer. It reads bounded same-organisation context, offers at most three drafts, and leaves the final message in a human's hands.
Suggest replies
¶ Compare drafts in place
Cards stack at mobile width, show the actual copy, and carry a short source label. Loading, disabled, empty, provider-error, and retry states must be visible.
Origin brief
¶ The ask was bigger than a reply button
The original request bundled staff reply help, follow-up lead replies, call-detected follow-ups, saved-message visibility, tone learning from staff or chat history, a connected-systems status page, and a bias toward shipped live work instead of unmerged prototypes.
Permanent boundary
¶ Suggestions become drafts. Staff remain the sender.
No suggestion endpoint, component, background job, or model call may send, queue, schedule, or start a message flow. Clicking a suggestion only stages editable text in the existing composer, and Enter still goes through the unchanged send path.
Suggest replies.
3ReplyBox returns three or fewer bounded suggestions.
4Staff clicks one to preview, edits it, and approves the send.
Design contract
¶ Small aid, never an AI showcase
¶ Conversation stays primary
Copilot is a compact composer aid. It must not become a competing dashboard, panel, carousel, or analytics display.
¶ Use ReplyBox primitives
Reuse existing Tailwind tokens, borders, radii, buttons, popovers, typography, focus styles, and dark-mode treatment.
¶ One quiet recognition cue
The existing AI accent and Sparkles icon are enough. Avoid generic AI claims, glass styling, gradients, oversized headings, and animation-heavy reveals.
¶ Works at 375px
Suggestion cards stack vertically, keep comfortable tap targets, and show readable generated copy without hiding it in a tooltip or modal.
Retrieval truth
¶ Tone priority is explicit
Reply Copilot prefers the current staff member's style. If that source is unavailable, the UI must say when it falls back to this conversation's style or same-organisation team style.
Resolved unknowns
¶ Ground truth from the build
¶ Existing composer path
ReplyBox already had an editable composer, slash-command saved-message picker, quick preview, flow-run audit trail, sender_user_id on human outbound messages, and a Gemini API integration.
¶ Completed use beats labels
Active organisations had hundreds of draft flows, and useful saved messages were not reliably marked approved. Retrieval ranks recently completed manual flow runs, with approved flows as fallback.
¶ Personal samples can be absent
In the 2026-09-05 snapshot, the signed-in administrator had no personal outbound samples in inspected organisations while teams had hundreds, so fallback labeling is required.
¶ Call summaries need substance
Call logs contain metadata only. ReplyBox cannot truthfully summarise call content until a recording, transcript, or staff-authored note exists with provenance.
¶ Call Tracker needs an adapter
The existing Call Tracker webhook payload and ReplyBox call-log ingest contract do not match. A signed adapter is required before call-trigger automation can activate.
¶ Separate gates fail closed
Reply suggestions use their own global kill switch and per-organisation opt-in, separate from the existing media-AI global switch and Gemini secret.
Product decisions
¶ The five decisions that keep the release safe
- Human approval is permanent for this first slice.
- Tone priority is staff member, then current conversation, then same-organisation team.
- Saved-message retrieval is based on real completed use, not status labels alone.
- No cross-organisation examples, no secret values in prompts, no training export, and no fine-tuning export.
- Customer auto-send, call-content summaries, and the cross-system status page remain planned next slices with their own proof and gates.
Explicitly not in slice one
¶ What stayed out
- Autonomous customer sends.
- Call summaries without recording, transcript, or staff-authored note evidence.
- Bulk rewriting or publishing hundreds of saved replies.
- A second outbound-message transport.
- Permanent prompt archives, fine-tuning, or copying chats across organisations.
- A new cross-company access/status product surface inside ReplyBox.
Success criteria
¶ What was verified before calling it shipped
The build started with no active fleet-board row or open pull request collision. The safe change was merged upward, deployed through the existing GitHub workflows, live-probed, and recorded in SHIPPED.md.
CLAUDE.md, and the saved-message coaching skill is installed and validated.
Delivery order
¶ How the first slice moved from proof to production
Feature gates, tenant-scoped retrieval, strict generation, and API tests.
Suggestion UI, staging semantics, source labels, and web tests.
Local checks plus mobile and desktop verification.
Saved-message coach skill installed and ReplyBox rule recorded.
Adversarial review, fixes, merge, deployment, and live verification.
Plan call adapter, transcripts or notes, and connected-systems status page.
Saved flows
¶ Approve an exact saved sequence from the IQ composer
¶ Search and preview
Staff can search and preview canonical Message Flows in the IQ reply composer, then explicitly approve them to send exact saved sequences. Preview is non-destructive and creates no outbound work.
¶ Server-verified on approval
Approving attaches a server-verified flow_reference, so the sent sequence matches the saved source exactly, preserving saved flow ordering and approved media.
¶ Same limits as the builder
The same unsupported actions are ignored, and the eight-item transport limit still applies. See the Message Flows guide for the full contract.
Channel firewall · issue #581, flag-gated
¶ Scope copilot knowledge to the conversation's line
An optional firewall scopes all Reply Copilot knowledge to the conversation's channel (line) to prevent cross-line leaks of saved replies and tone. The flag REPLY_COPILOT_CHANNEL_FIREWALL is off by default; when enabled, API routes pass the conversation's channel_id into the copilot context collector. This is a conversation-derived guard, not one based on staff permissions or organisation.
¶ What gets narrowed
Eligibility: a flow qualifies for a channel when it is tagged in message_flow_channels OR has actually run on a conversation of that channel. Saved replies narrow both the completed-manual-run ranking and the under-12 approved back-fill to the channel's eligible flows. Tone rows pin staff, conversation, and team fallback tiers to the channel, intersected with staff membership permissions.
¶ Fail closed
If a line has no eligible flow it receives no saved replies rather than falling back to organisation-wide results, and if the conversation cannot name its channel no suggestion is returned. Unsupported facts are scored against the narrowed context, so cross-trade claims become unsupported and those drafts are dropped.
¶ Validate-use
The snapshot's channel_id is re-asserted against the conversation's live channel and returns 409 reply_copilot_channel_firewall_mismatch on mismatch.
¶ Migration and rollout
Migration 0149_message_flow_channels adds one table (flow_id, channel_id, created_at). It is strictly additive and not backfilled, and the downgrade drops only that table. Set REPLY_COPILOT_CHANNEL_FIREWALL=true on the DigitalOcean api service and restart; turning it off needs no data change and restores byte-identical prior behaviour.
¶ Verification
The change includes an upgrade/downgrade migration test and eight unit tests in tests/test_reply_copilot_channel_firewall.py, asserting both flag states.
¶ Out of scope
There is no staff UI yet for writing message_flow_channels: today the tag table is populated by hand, and run-derived eligibility covers existing flows.
Declared rules · opt-in
¶ Drafts can obey the line's rules from Reply IQ
When enabled, the copilot performs a signed GET to Reply IQ's Learning Center before producing a Gemini draft, fetching the conversation's line-level DECLARED RULES and adding them to the model's SYSTEM prompt. Rules are fetched per line or channel, the same tenancy boundary other knowledge sources use, so one line never receives another line's rules. The feature is off by default: nothing changes until IQ_RULES_FEED_ENABLED=1 is set for the API service, and with the feed off no request is made at all.
¶ Where rules land
The fetched block goes in the SYSTEM prompt only, not the untrusted JSON payload. Rules are additive constraints: they never relax or override ReplyBox's safety guardrails, such as never promise, book, refund, or quote a new price.
¶ Fail-open
Any failure — timeout, 401, 500, malformed response, connect error, oversize — returns no rules and does not raise. The copilot continues with the line's saved flows, and the sparkle button is never blocked by IQ being slow or down.
¶ Caching
Successful rule responses are cached per line (default 60s) to reduce outbound probes. Failures are cached for a shorter window, which limits repeated latency while allowing quick recovery after transient blips. The copilot never holds a database connection while waiting for the remote request.
¶ Provenance
The rules revision used for each draft is recorded as rules_hash on the existing suggestion snapshot, so a complaint can be checked against the exact rules that applied.
¶ Security
Requests to IQ are HMAC-SHA256 signed over a canonical string including path and query, using a per-lane key id and key pair; that signature construction is an interop contract with Reply IQ. Keys are base64url-encoded 32-byte secrets without padding, and per-lane keys must be distinct.
Next live slices
¶ Keep expanding only where proof exists
The later roadmap keeps the same discipline: read-only review before changes, evidence before call summaries, and redacted status before any access surface claims health.
¶ Saved-message coach
Use the machine-local replybox-reply-coach skill to review one exact workspace's Message Flows. It ranks sampled completed human use, classifies flows by customer function, and proposes name, shortcut, text, reason, and risk flag.
No flow changes happen until CY approves exact rows. The skill re-fetches each row before editing and never runs or sends a flow.
¶ Call follow-up adapter
Add a signed duplicate-safe adapter from Call Tracker's batched HMAC event into ReplyBox's typed call-log contract, then require recording plus transcript or structured staff notes before generating a recap draft.
Customer recap remains preview, edit, and Enter first. Auto-send can only be evaluated later for a narrow approved class with a replayable test set and separate kill switch.
¶ Connected-systems status page
Recommended home is the internal Utopia Wall or ops surface, not ReplyBox, because customer conversations and company credential controls have different permission boundaries.
The registry should show system, capability, owner, environment, credential reference, probe freshness, status, redacted failure reason, and proof link without exposing secrets or customer data.
Status-page acceptance
¶ Healthy must mean freshly proven
The first acceptance test lists every registered system in the denominator, proves freshness for each healthy row, marks an intentionally disabled probe truthfully, and lets one removed credential degrade only that system.
unknown is different from healthy; stale probes age into unknown.