Workflow Engine · ac-python-api · outreach orchestration

AI Envoy

Envoy runs multi-step outreach sequences with a human gate on every send. The orchestrator advances each recipient through a step state machine, an Agno workflow drafts personalized emails from playbook, battlecard and signal context, a person approves them in the outbox, and replies thread back into a sentiment-scored inbox.

Steps message · delay · taskWriter gpt-5-mini draftGate human approvalChannel Nylas mailbox
Sequence + recipientsorchestrate · draft · approve·send via Nylasthreaded replies
00

What Envoy does

End users are sales teams and agencies running outreach at volume. Envoy takes a sequence — an ordered list of message, delay and task steps — plus a recipient list, and drives every recipient through it automatically. The defining choice: an LLM drafts every email, but a human approves every send. Automation handles the orchestration, scheduling and writing; the person keeps the judgement.

3
Step types
message · delay · task
1
Human gate
outbox approval
4
Context sources
signals · playbook · card · style
3
Sentiments
positive · neutral · negative
KEYDrafted by AI, sent by a human

The whole machine is automated except one transition. The orchestrator schedules steps, the workflow writes drafts, and Nylas sends — but a draft sits at pending_review until a person clicks approve. That single gate is what makes Envoy safe to run unattended: nothing reaches a prospect that a human did not see, and terminal states are enforced in the database so an approved send can never silently un-send.

01

System architecture

A host-side orchestrator drives the sequence, calls an Agno workflow to draft, persists everything to the outreach tables, and reaches the outside world only through Nylas. Click any box to trace its connections.

host-side ┃ Nylas is the only external hopEnvoy appsequences · outbox · inboxEnvoy routersFastAPI · sequences/outbox/inboxStep orchestratorCelery beat · state machineEmail draft workflowAgno · context → write → storeEmail writergpt-5-miniNylassend + reply webhookinbox_threadsreplies + sentimentoutreach_* tablessequences · steps · recipient_stepscrm_communicationsunified historyContext sourcesplaybook · battlecard · signals
02

Step state machine

Every recipient carries its own state on every step. Each step type runs a different ordered progression — only the message path has a human gate, and the last state of each is terminal. Switch the step type, then play the run or click any state to inspect it.

1

pending

recipient state
automated

The recipient is parked on this step. The orchestrator claims it on the next beat — no work has happened yet.

!Terminal means terminal

sent, task_created and skipped are terminal. A database trigger rejects any attempt to transition out of them, so a reconcile sweep or a retry can never resurrect and re-send a delivered email. The orchestrator retries failures up to five times with exponential backoff — but only from non-terminal states.

03

Context enrichment

Before the writer runs, the workflow assembles context. The prospect and the step prompt are always present; signals, playbook, battlecard and writing style are optional and each sharpens the draft. Toggle sources and watch the email — and the writer’s confidence — respond.

A note on Northwind’s London move

prospectHi Dana,

signalSaw Northwind just opened a London office — timely moment to talk.

offerWe help agencies turn cold lists into booked meetings without adding headcount.

CTAWorth a 15-minute look next week?

— sent from your connected mailbox

writer confidence84%

Workable — a clear offer, but no live signal to anchor the opener.

Weights here are illustrative of the relative lift each source gives. The point: a signal-anchored opener moves the needle most, the playbook supplies the offer and CTA, and the battlecard and style guide refine rather than carry the draft.

04

The approval gate

Generated drafts queue in the outbox at pending_review. A reviewer approves — the email sends via Nylas and dual-writes to crm_communications — or rejects, which sends the step back to regenerate. Work the queue below.

3 awaiting review0 approved + sent
Dana Okafor · VP Growth conf 91%

A note on Northwind’s London move

Saw Northwind just opened a London office — timely moment to talk about pipeline…

Marco Reyes · Founder conf 74%

Quick question

We help agencies turn cold lists into booked meetings without adding headcount…

Priya Nair · Head of Sales conf 58%

More meetings, fewer SDRs

Unlike the legacy sequencers, every send clears a human review first…

Why a gate, not autosend: the writer is good but not accountable. The approval click is where a human owns the message — and because it is the only path to a terminal sent state, an unattended sequence simply accumulates drafts rather than emailing prospects on its own.
05

Inbox & sentiment

When a prospect replies, Nylas webhooks the message in; it threads into inbox_threads and gets a sentiment score that routes the next action. Pick a reply to see how it is classified.

Keyword scoring here stands in for the sentiment pass that runs on every inbound message. The behaviour it drives is the real design: positive replies leave the cadence for a human, negatives pause it, and neutrals keep the thread open with an assisted reply.

06

Design decisions

Safety

A human gate on every send

Drafts are cheap and reversible; a sent email is neither. Approval is the only transition into a terminal sent state, so the system is safe to run unattended — it accumulates drafts, never rogue sends.

Cost

gpt-5-mini for volume

Outreach is high-volume and each draft is one short write. A small, fast model keeps per-draft spend low; the reviewer, not a bigger model, is the quality backstop.

Integrity

Terminal states in the database

sent / task_created / skipped are enforced by a DB trigger, not just app code. A reconcile sweep or retry physically cannot re-send a delivered email — correctness survives a buggy worker.

Continuity

Dual-write to crm_communications

Every send and reply also lands in the shared comms timeline keyed to the CRM person, so outreach is part of the contact relationship, not a siloed log.

Deferred, not blocking the design: campaign-level analytics rollups across sequences, confidence-threshold auto-approval for the highest-scoring drafts, and reply-intent classification richer than three-way sentiment. Each sits on top of the state machine and the gate, not inside them.
AgencyCore · Envoy design specAI outreach · human-gated sends