Generative Prompt Parameters — Complete Parameters & Flow Reference
Audience: Developers & Operations Team
Updated: 2026-07-29
Key Files: TaskGenerativeTemplates.cs, HyperPersonaliseRequest.cs, HyperPersonaliseRequestModel.cs, HyperRequestService.cs, GenerativeTemplatesController.cs
Table of Contents
- Overview
- End-to-End Mermaid Flow
- Sender Parameters
- Recipient Parameters
- Template & Prompt Parameters
- Campaign & Client Metadata
- Additional Instructions (The
additionalDataDictionary) - Buyer Intent & Engagement Signals
- Previous Email Chain (Chasers)
- AI Provider & Model Selection
- Batch vs Single Processing
- Response & Logging
- Data Point Gating
Overview
The generative email pipeline builds AI-personalised emails by assembling a rich prompt payload from multiple data sources. The payload is constructed in TaskGenerativeTemplates (or TaskGenerativeTemplatesBulk for batch), serialised to JSON via HyperPersonaliseRequestModel, and POSTed to the AI Middleware service at {AIMUrl}/api/v5/generative/generate.
Every parameter passed to the AI is a property on HyperPersonaliseRequestModel. The model is built from HyperPersonaliseRequest (Dapper layer) via the GenerateHyperModel() helper.
End-to-End Mermaid Flow
Sender Parameters
These describe the sending company and the individual sender. All values are HTML-stripped before being sent to the AI.
| # | Parameter | Type | Source | Description |
|---|---|---|---|---|
| 1 | SenderCompany | string | Email Profile / Client | Name of the sending company |
| 2 | SenderCompanyDescription | string | Email Profile | What the company does; HTML-stripped |
| 3 | SenderOffering | string | Email Profile | Product/service offering description; HTML-stripped |
| 4 | SenderAngle | string | Email Profile | Value proposition / angle; HTML-stripped |
| 5 | SenderUSPs | string | Email Profile | Unique selling points; HTML-stripped |
| 6 | SenderTone | string | Email Profile | Desired email tone (e.g. "professional", "friendly"); HTML-stripped |
| 7 | SenderName | string | Email Profile | Full name of the sender (sales agent) |
| 8 | SenderJobTitle | string | Email Profile | Job title of the sender |
| 9 | SenderWebsite | string | Email Profile | Company website URL |
Brand & Market Context (in additionalData)
| # | Key | Type | Enum | Description |
|---|---|---|---|---|
| 10 | BrandFamiliarityId | string | BrandFamiliarityEnum | How well the recipient knows the brand (0 = not set) |
| 11 | BrandFamiliarityDescription | string | - | Human-readable label for brand familiarity |
| 12 | AudienceAwarenessOfOfferingId | string | MarketSaturationEnum | Market awareness of the offering (0 = not set) |
| 13 | AudienceAwarenessOfOfferingDescription | string | - | Human-readable label for market saturation |
Recipient Parameters
These describe the target prospect and their company.
| # | Parameter | Type | Source | Description |
|---|---|---|---|---|
| 14 | RecipientName | string | Prospect record | Full name of the recipient |
| 15 | RecipientFirstName | string | Prospect record | First name only |
| 16 | RecipientEmail | string | Prospect record | Email address |
| 17 | RecipientJobTitle | string | Prospect record | Current job title |
| 18 | RecipientLinkedIn | string | Prospect record | LinkedIn profile URL |
| 19 | RecipientCompany | string | Prospect record | Company name |
| 20 | RecipientCompanyDescription | string | Prospect record / enrichment | Description of the recipient's company |
| 21 | RecipientCompanyIndustry | string | Prospect record | Industry classification |
| 22 | RecipientCompanySize | string | Prospect record | Company employee count / size range |
| 23 | RecipientCompanyCountry | string | Prospect record | Country of the company |
| 24 | RecipientDomain | string | Prospect record | Company website domain |
Template & Prompt Parameters
These control how the AI generates the email — the prompt structure, style, and context.
| # | Parameter | Type | Required | Description |
|---|---|---|---|---|
| 25 | SettingId | int? | No | Master template / prompt setting ID. Determines the AI system prompt and output structure. |
| 26 | Intro | string? | No | Custom intro inserted at the top of the prompt. Supported only by certain settings. |
| 27 | AdditionalInstructions | string? | No | Template-level extra instructions appended to the prompt (e.g. "mention the upcoming webinar"). |
| 28 | IsManual | bool | Yes | If true, the email was manually triggered (portal preview). If false, automated via queue. |
| 29 | CommonTemplateId | int? | No | Shared template ID for consistent styling across stages. |
| 30 | FallbackEmail | string | No | The standard (non-AI) email used if generation fails. Stripped of signature and unsubscribe. |
| 31 | PreviousEmail | string? | No | Chasers only: Full text of previous emails in the thread. Format: Email N:\n"content"\n. |
| 32 | rtlTextDirection | bool | Yes | If true, generated HTML uses right-to-left text direction. |
| 33 | Tag | string | Yes | Stage tag, e.g. M1 (stage 1), M2 (stage 2). Used for AI routing. |
Campaign & Client Metadata
These provide contextual identifiers for logging, routing, and tracking.
| # | Parameter | Type | Description |
|---|---|---|---|
| 34 | ProspectId | int? | Prospect primary key |
| 35 | ClientId | int | Client account ID |
| 36 | CampaignId | int | Campaign ID |
| 37 | CampaignName | string | Campaign display name |
| 38 | ClientName | string | Client account display name |
| 39 | EmailProfileId | int | Email profile (sender identity) ID |
| 40 | EmailprofileName | string | Email profile display name |
| 41 | EmailTempalteId | int? | Email template (stage template) ID |
| 42 | ExternalId | int | ProspectGenerativeLogDetails.Id — links the AI request to the logging record |
| 43 | UnsubscribeContent | string | HTML unsubscribe footer (custom per client) |
| 44 | UnsubscribeContentText | string | Plain-text unsubscribe footer |
Additional Instructions (The additionalData Dictionary)
The additionalData dictionary carries key-value pairs that the AI Middleware interprets as additional instruction dimensions. These are not part of the main prompt body — they are sent as a structured dictionary that the AI provider settings consume.
Always Present
| Key | Value | Source | Description |
|---|---|---|---|
state | string | Prospect enrichment | US state of the prospect's company (e.g. "California") |
AudienceSpecificAdditionalInstructions | string? | Audience builder / Campaign | Campaign-level audience description (e.g. "CTOs at SaaS companies"). Gated by DataPointsEnum.AudienceSpecificAdditionalInstructions. Set to null if data point not enabled. |
ApproachLevelAdditionalInstructions | string? | Email Profile → Campaign settings | Campaign-level instructions set in the email profile (e.g. "Keep it under 150 words"). HTML-stripped. |
AudienceAwarenessOfOfferingId | string | Campaign settings | Enum value for market saturation (empty if 0). |
AudienceAwarenessOfOfferingDescription | string | Campaign settings | Friendly name for market saturation level. |
BrandFamiliarityId | string | Campaign settings | Enum value for brand familiarity (empty if 0). |
BrandFamiliarityDescription | string | Campaign settings | Friendly name for brand familiarity level. |
Conditionally Present
| Key | Value | Condition | Description |
|---|---|---|---|
ChaserType | string | Follow-up stages only | Chaser type ID selected by ChaserTypes.GetChaserType(). Determines the follow-up strategy (e.g. "case study", "social proof", "OOO response"). |
hasOOOReturnDate | "True"/"False" | Prospect has OOO response | Whether the prospect's OOO auto-reply included a return date. |
OOOReturnDays | string (int) | HasOOOReturnDate == true | Number of days until the prospect returns, calculated as OOOReturnDate - LastResponderDate. |
LinkedIn Prospect Parameters
When ProspectSource == "LinkedIn" and ProspectParametars is not empty, the JSON-deserialised parameters are added to additionalData with PascalCase keys. A blacklist (IsExcluded()) filters out sensitive/internal keys.
Example LinkedIn parameters injected:
CurrentCompany, CurrentPosition, Location, Industry, Connections, ...
Buyer Intent & Engagement Signals
These are optional fields — they are only populated if the email template's DataPoints field includes the corresponding DataPointsEnum flag. If the data point is not enabled, the field is set to null and excluded from the prompt.
| # | Parameter | Type | DataPointsEnum Flag | Description |
|---|---|---|---|---|
| 45 | RecipientCompanyAlternativeQualifiedProspects | string? | FutureAlternative (3) | Other prospects at the same company that could be contacted in future. |
| 46 | RecipientCompanyRecentlyContactedProspects | string? | RecentlyEngaged (2) | Other prospects at the same company recently contacted. |
| 47 | RecipientCompanyHasShownBuyerIntentLast30Days | bool? | RecentWebVisitCompany (6) | Whether the recipient's company visited the sender's website in the last 30 days. |
| 48 | RecipientCompanyHasShownBuyerIntentLast90Days | bool? | RecentWebVisitCompany (6) | Whether the recipient's company visited in the last 90 days. |
| 49 | RecipientHasShownBuyerIntentLast30Days | bool? | RecentWebVisitIndividual (5) | Whether the individual recipient visited the sender's website in the last 30 days. |
| 50 | RecipientHasShownBuyerIntentLast90Days | bool? | RecentWebVisitIndividual (5) | Whether the individual recipient visited in the last 90 days. |
Data Point Gating Logic
if DataPoints.CheckIfExist(emailTemplate.DataPoints, DataPointsEnum.FutureAlternative)
→ populate RecipientCompanyAlternativeQualifiedProspects
else
→ set to null
if DataPoints.CheckIfExist(emailTemplate.DataPoints, DataPointsEnum.AudienceSpecificAdditionalInstructions)
→ keep AudienceDescription populated
else
→ set AudienceDescription = null AND null out additionalData["AudienceSpecificAdditionalInstructions"]
Previous Email Chain (Chasers)
For follow-up emails (stages 2+), the AI receives the full chain of previous messages:
How PreviousEmail Is Built
- Query
EmailTemplateProspectfor all previous stages (stage - 1,stage - 2, ...) - For each previous message:
- Strip signature (
*|SALES_AGENT_SIGNATURE|*) and "From:" header - Format as:
Email {sendNumber}:\n"{textContent}"\n
- Strip signature (
- Concatenate all previous messages, newest last
- If the generated chaser contains
[PREVIOUS MESSAGE], it's replaced with the real content in the final saved template
Example chain sent to AI for stage 3:
Email 1:
"Hi John, noticed you're the CTO at Acme Corp..."
Email 2:
"Following up on my previous email about our DevOps solution..."
AI Provider & Model Selection
The AI provider and model are determined server-side by the AI Middleware (email-template-demo) based on the SettingId and prompt configuration. The Sopro core does not specify a model — it receives the model name back in the response.
Supported AI Providers
| Provider | Models (examples) |
|---|---|
| OpenAI | GPT-4o, GPT-4o-mini, GPT-4 Turbo |
| DeepSeek | DeepSeek-V3, DeepSeek-R1 |
| Grok | Grok-2 |
| Anthropic | Claude 3.5 Sonnet, Claude 3 Opus |
Model Tracking
The model used is recorded in:
ProspectGenerativeLogDetails.Model— per-prospectEndpointManagerLog(ClickHouse) — per-request in email-template-demo
Batch vs Single Processing
Single Prospect Path
TaskGenerativeTemplates
→ GenerateHyperModel()
→ HyperRequestService.HyperPersonaliseRequest(model)
→ POST {AIMUrl}/api/v5/generative/generate (JSON body: HyperPersonaliseRequestModel)
→ AI generates email synchronously
→ Returns HyperTemplateResponse immediately
Batch/Bulk Path
TaskGenerativeTemplatesBulk
→ Save all HyperPersonaliseRequestModel as JSONL to Azure Blob
→ HyperRequestService.CreateHyperBatch(fileName)
→ POST {AIMUrl}/api/v5/batch-processing/createHyperBatch
→ Creates BatchPromptRequest (GUID)
→ Hangfire processes batch asynchronously
→ Polls every ~10 min via ProcessAllPendingHyperBatch
→ On complete → WebHookProcessResponceHyperBatch
→ POST SoProCoreAPI/api/GenerativeTemplates/ProcessResponceHyperBatch
→ Enqueues ProcessResponceHyperBatch in SoProQueue
→ GenerativeTemplatesController.HyperBatch(Guid Id)
→ GetHyperBatch(batchId) → updates GenerativeBatchLog
→ For each TemplateResponse → processes same as single
Decision: Single vs Batch
emailProfile.IsBatch && canBatch(settingsId)
→ YES: GenerativeTemplatesBulk queue
→ NO: GenerativeTemplates queue
Response & Logging
HyperTemplateResponse (from AI)
| Field | Type | Description |
|---|---|---|
Success | bool | Whether generation succeeded |
Html | string | Full HTML email body |
Template | string | Plain-text version |
Subject | string | AI-generated subject line |
Model | string | AI model used (e.g. "gpt-4o") |
LogId | Guid? | AI log correlation ID |
Usage | UsageInfo | Token counts and estimated cost |
Errors | List<string> | Error messages if failed |
UsageInfo
| Field | Type | Description |
|---|---|---|
PromptTokens | int | Tokens consumed by the prompt |
CompletionTokens | int | Tokens generated in the response |
EstimatedCost | decimal | Estimated USD cost |
Post-Processing (on success)
- Signature (
*|SALES_AGENT_SIGNATURE|*) appended to HTML - Unsubscribe link appended (custom or default)
- Morning/Afternoon merge tags normalised to
*|SENDSCHEDULE_*|*format - For chasers: previous email chain variables (
*|SEND{N}_DATE|*,*|SEND{N}_SUBJECT|*,*|SEND{N}_HTML_CONTENT|*) injected - Final HTML uploaded to Azure Blob:
{container}/GPTSpindle/{emailTemplateProspectId} EmailTemplateProspectrecord created/updated withTextContentandSubjectProspectGenerativeLogDetailslogged with tokens, cost, model, success/failure
On Failure
EmailTemplateProspectis NOT createdProspectGenerativeLogDetails.Success = false,EmailTemplateProspectId = NULL- Error logged to
DapperApplicationsErrorLog - At send time, the system falls back to the standard
EmailTemplate.HTMLContent
Data Point Gating
Not all parameters are sent for every generation. The DataPoints field on the email template (a comma-separated string of DataPointsEnum values) determines which parameters are populated:
| DataPointsEnum | Value | Controls |
|---|---|---|
RecentlyEngaged | 2 | RecipientCompanyRecentlyContactedProspects |
FutureAlternative | 3 | RecipientCompanyAlternativeQualifiedProspects |
AudienceSpecificAdditionalInstructions | 4 | AudienceDescription + additionalData["AudienceSpecificAdditionalInstructions"] |
RecentWebVisitIndividual | 5 | RecipientHasShownBuyerIntentLast30Days, RecipientHasShownBuyerIntentLast90Days |
RecentWebVisitCompany | 6 | RecipientCompanyHasShownBuyerIntentLast30Days, RecipientCompanyHasShownBuyerIntentLast90Days |
Complete Parameters Summary
| # | Parameter | Category | Always Sent | Gated |
|---|---|---|---|---|
| 1 | SenderCompany | Sender | ✅ | - |
| 2 | SenderCompanyDescription | Sender | ✅ | - |
| 3 | SenderOffering | Sender | ✅ | - |
| 4 | SenderAngle | Sender | ✅ | - |
| 5 | SenderUSPs | Sender | ✅ | - |
| 6 | SenderTone | Sender | ✅ | - |
| 7 | SenderName | Sender | ✅ | - |
| 8 | SenderJobTitle | Sender | ✅ | - |
| 9 | SenderWebsite | Sender | ✅ | - |
| 10 | BrandFamiliarityId | additionalData | ✅ | - |
| 11 | BrandFamiliarityDescription | additionalData | ✅ | - |
| 12 | AudienceAwarenessOfOfferingId | additionalData | ✅ | - |
| 13 | AudienceAwarenessOfOfferingDescription | additionalData | ✅ | - |
| 14 | RecipientName | Recipient | ✅ | - |
| 15 | RecipientFirstName | Recipient | ✅ | - |
| 16 | RecipientEmail | Recipient | ✅ | - |
| 17 | RecipientJobTitle | Recipient | ✅ | - |
| 18 | RecipientLinkedIn | Recipient | ✅ | - |
| 19 | RecipientCompany | Recipient | ✅ | - |
| 20 | RecipientCompanyDescription | Recipient | ✅ | - |
| 21 | RecipientCompanyIndustry | Recipient | ✅ | - |
| 22 | RecipientCompanySize | Recipient | ✅ | - |
| 23 | RecipientCompanyCountry | Recipient | ✅ | - |
| 24 | RecipientDomain | Recipient | ✅ | - |
| 25 | SettingId | Template | ✅ | - |
| 26 | Intro | Template | ✅ | - |
| 27 | AdditionalInstructions | Template | ✅ | - |
| 28 | IsManual | Template | ✅ | - |
| 29 | CommonTemplateId | Template | ✅ | - |
| 30 | FallbackEmail | Template | ✅ | - |
| 31 | PreviousEmail | Template | Chasers only | - |
| 32 | rtlTextDirection | Template | ✅ | - |
| 33 | Tag | Template | ✅ | - |
| 34-44 | Metadata (ProspectId, ClientId, CampaignId, etc.) | Metadata | ✅ | - |
| 45 | RecipientCompanyAlternativeQualifiedProspects | Buyer Intent | - | ✅ FutureAlternative |
| 46 | RecipientCompanyRecentlyContactedProspects | Buyer Intent | - | ✅ RecentlyEngaged |
| 47 | RecipientCompanyHasShownBuyerIntentLast30Days | Buyer Intent | - | ✅ RecentWebVisitCompany |
| 48 | RecipientCompanyHasShownBuyerIntentLast90Days | Buyer Intent | - | ✅ RecentWebVisitCompany |
| 49 | RecipientHasShownBuyerIntentLast30Days | Buyer Intent | - | ✅ RecentWebVisitIndividual |
| 50 | RecipientHasShownBuyerIntentLast90Days | Buyer Intent | - | ✅ RecentWebVisitIndividual |
| 51 | AudienceSpecificAdditionalInstructions | additionalData | - | ✅ AudienceSpecificAdditionalInstructions |
| 52 | ApproachLevelAdditionalInstructions | additionalData | ✅ | - |
| 53 | ChaserType | additionalData | Chasers only | - |
| 54 | hasOOOReturnDate | additionalData | OOO only | - |
| 55 | OOOReturnDays | additionalData | OOO only | - |
| 56 | LinkedIn parameters | additionalData | LinkedIn source only | - |
| 57 | state | additionalData | ✅ | - |
Three Layers of "Additional Instructions"
The system supports three distinct layers of additional instructions, each applied at a different scope:
API Endpoint Reference
Single Generation
POST {AIMUrl}/api/v5/generative/generate
Headers: accept: application/json, auth: {AIMKey}
Body: HyperPersonaliseRequestModel (JSON)
Response: HyperTemplateResponse (JSON)
Batch Create
POST {AIMUrl}/api/v5/batch-processing/createHyperBatch?FileName={file}
Headers: accept: application/json, auth: {AIMKey}
Response: Guid (BatchRequestId)
Batch Status
POST {AIMUrl}/api/v5/batch-processing/getHyperBatch?Id={batchId}
Headers: accept: application/json, auth: {AIMKey}
Response: BatchHyperResult (JSON)
Callback (from AI Middleware → Sopro Core)
POST {SoProCoreUrl}/api/GenerativeTemplates/HyperBatch?Id={batchId}
Response: IActionResult
Can Batch Check
POST {AIMUrl}/api/v5/generative/canBatch?SettingsId={id}
Headers: accept: application/json, auth: {AIMKey}
Response: bool
End of Generative Prompt Parameters Reference