Where the model is called
Both calls share the same provider — one decided at boot, retried under the same
deadline and backoff policy. See
the generative pipeline for how that works and
why.
What the model does not do
Under no circumstances is a model asked to compute or guess any of the following:- Customer counts, health, trends or “top customers” — these are SQL aggregates.
- Whether a customer matches a segment — that is a deterministic condition check.
- Customer imports or any write to the database.
- Campaign status. Drafting is the only model step; approving and sending are
domain rules (
draft → ready → sent).
What the model sees
Unusually for an AI feature, the model has no access to the database.- Campaign drafting receives the objective, segment name, audience size, channel and tone. It receives labels and aggregates, never raw customer rows.
- Chat receives the system prompt and the last 12 turns of the thread you are in — enough context to answer, bounded so a long conversation cannot grow past the model’s window. Stored history stays complete.
Guardrails on output
Drafts are the part that must be structurally correct, so they are treated that way:- The reply is parsed against the campaign schema. If a field is missing, the
adapter repairs it where it can, and refuses with
llm_errorif the reply is unreadable — a malformed draft never becomes a campaign with an empty title. - The prompt forbids inventing figures, fees or customer details, and tells the model what DME is (a software company doing marketing for its clients — not a bank), so copy does not drift into the wrong persona.
draft status and must be
reviewed by a person before it can leave that state. See
generate a campaign.
Providers, and what happens when one is missing
The provider is bound once at boot from configuration. With no key of any kind, the API binds the deterministic local generator (theScriptedModel) — the same
ports, the same streams, no network and no cost — so the entire application stays
reviewable offline. The boot log states which model is in use. See
run without a model key and the
configuration reference.