Skip to main content

The proactive outreach evaluation model

An ambient agent answers one question per segment crossing: should I reach out to this contact? Every answer, sent or not, lands as exactly one audit row. This page is the model behind that loop: what triggers an evaluation, what an answer can become, how goal state carries between runs, and how the plane stacks on the same tenant-owned send gates your campaigns walk. For setup and a worked example, see Ambient agents: proactive outreach from setup to audit. For the per-field contract of the settings block, the trigger flow, and the audit API, see Ambient agents.

The evaluation lifecycle

One crossing, one question, one row. The lifecycle has four stages:
  1. Trigger. A contact enters a CDP segment bound to an agent, producing a segment.entered event. Your track events feed segment membership in real time, and the crossing itself is the trigger: Orbit enqueues one evaluation job per crossing. In v1, segment.entered is the only trigger. Segment exits and raw track events shape membership but do not fire an evaluation on their own.
  2. Prechecks. The cheap gates run before any model call is spent: is ambient outreach enabled for your organization, is there a well-formed binding for this segment, is the contact suppressed, and is there a reachable address on the bound channel? A failed precheck ends the evaluation as a skip before the agent is asked. This is the same discipline the journey enrollment fan-out applies at its entry chain: the shared offboard precheck stops a suppressed contact before any work is done, and a re-entry guard makes a repeat crossing a no-op. For ambient outreach the guard is the contact+segment idempotency row: a contact that leaves a segment and later re-enters it is not re-asked, because the row from the first crossing already exists and wins.
  3. Decision. The bound agent receives a prompt summarizing the contact, the segment, and any active goals, and answers send (one drafted message on the bound channel) or decline (with its reasoning recorded).
  4. Admission. A send decision is a draft, not a dispatch. Between “the agent said send” and “the message went out,” your tenant policy gates re-run exactly as they do for a campaign: consent and opt-in checks, quiet hours, the suppression list, and your frequency caps. A gate that stops a send the agent wanted to make lands the row as Blocked and names the gate.
Every evaluation writes one audit row keyed by contact + segment, so the idempotency record and the audit trail are the same row. Retried or duplicated background jobs short-circuit against it instead of asking the agent twice, and a worker crash-and-retry cannot double-send. Follow-up check-ins (below) enter the same lifecycle at stage 3’s context: they are evaluations like any other, with their own row and their own pass through the admission gates.

The outcome taxonomy

Every row resolves to one of three outcomes: The per-agent rollup at the top of Agents → Proactive Outreach (and the summary block of the audit API) counts sent / agent-declined / blocked per agent over the recent-activity window, sorted by sends. The three shapes read differently:
  • Decline-heavy means the binding is working as prompted: the agent is examining every crossing and judging most of them not worth a message. If the decline rate surprises you, the decline criteria in the prompt are swallowing the segment; tune the prompt, not the segment.
  • Block-heavy means the agent wants to send more than your policy posture allows. Review the consent, quiet-hours, and frequency-cap settings the rows name.
  • All three near zero means the trigger never fires: check segment membership and the enable flag.
Because declines and blocks are recorded rather than silent, a binding that produces nothing but declines is visible on day one, not invisible forever.

Goal-state continuity

Entry-triggered evaluations are self-contained by default. Goals add memory between runs so a second message to the same contact continues the thread instead of restarting it. When a run establishes an outreach goal for a contact, Orbit persists it per contact: a free-text description, a status (active, paused, completed, or abandoned), the agent’s checkpoint notes from its last run, and the next check-in time the agent picked. One contact can hold more than one goal, and each is tracked separately. On every later evaluation for that contact, active goals are handed to the agent as extra context with the instruction to continue from the last checkpoint rather than re-pitch the contact as a stranger. The platform bounds the follow-up clock on both sides: never sooner than an hour ahead, so a confused model cannot busy-loop a contact, and never farther than a year ahead, so a goal cannot park forever. If the agent picks no time, the goal goes dormant and is never treated as due; only active goals whose chosen time has arrived are picked up for a follow-up run. A follow-up check-in is an evaluation like any other. It lands in the dashboard and in the audit API with its own row (segment, agent, decision, outcome, and cost), passes the same consent, quiet-hours, suppression, and frequency-cap gates as an entry-triggered send, and never duplicates the original crossing’s send, because the send-once row is still keyed by contact + segment. The v1 boundary, stated plainly: goal state persists across runs, but goals surface only through the follow-up rows they produce. There is no goals panel, nothing to configure per goal, and no structured goal schema or sub-goal tree. The follow-up rows are the surface; the persisted status, notes, and next check-in are the continuity behind them.

Audit and read-back

Two surfaces read the same rows:
  • Dashboard: Agents → Proactive Outreach shows one row per evaluation with the segment that fired, the agent asked, its decision, and the outcome, plus the per-agent rollup. The route /agents/ambient-outreach exists solely to redirect into that tab inside /agents; it hosts no separate page.
  • API: GET /api/v1/agents/ambient-outreach/audit returns the same rows for pull-based reporting, readable by any authenticated tenant user. Filter with agent_id, decision (sent or skip), and limit (1–200, default 50).
Each entry carries the contact, the segment, the agent, the channel, the decision, the outcome (with the policy reason when blocked), messageId and costUsd when a send happened, and createdAt. The response also carries count and the per-agent summary, computed over the same bounded window of the most recent 500 decisions as the entries, so the list and the rollup can never disagree. A tenant with no ambient activity yet gets empty lists, not an error. The audit is also your evidence surface for the controls below: when one of your gates stops a draft, the row says Blocked and names the gate, so volume you cannot reach is visible rather than silent.

How the plane composes

Proactive outreach is a trigger and a decision layer on top of gates that already exist; it owns none of them.
  • Consent, opt-out, and suppression supplies the recipient state the prechecks and admission gates read. An opted-out contact is stopped before or at admission, and the row records which.
  • Frequency caps count ambient sends like any other send. A proactive send claims a cap slot against the same counters your campaigns use, so an ambient send can both be denied by a cap and consume the budget a campaign wanted.
  • Outbound send gating and quiet hours is the admission chain a drafted message walks in order; ambient outreach adds no gate of its own and bypasses none.
  • Journey enrollment fan-out is the closest sibling: segment entry also enrolls contacts into journeys, and both planes share the offboard-precheck and re-entry-guard discipline. The difference is the verb: a journey moves a contact through your steps, while an evaluation asks an agent one question and records the answer.
  • The cross-campaign send allocator is where ambient outreach differs most. A campaign sweeps an audience on your schedule and the allocator spreads that volume across eligible slots; an ambient agent sends no sweeps and has no spread window. It is one contact, one question, at the moment of crossing, so there is nothing to allocate. Both planes still draw on the same caps and quiet hours.
On billing: the send leg of a Sent outcome bills against your wallet at the standard rate for the bound channel, and costUsd on the audit entry is that debit. The model inference behind each evaluation is agent spend that reads back through LLM spend attribution, and organizations that have opted into outcome-based agent billing read agent conversations under that model; wherever a send has a cost, it is priced like any other outbound message on the channel. One boundary is structural: ambient outreach sends on sms, whatsapp, or email and never places an outbound voice call. Outbound voice lives on its own termination plane, and the voice dialing-window guards that apply to voice campaigns simply have no ambient voice traffic to evaluate.