Generative Messaging — Technical Documentation
Last updated: February 2026
Table of Contents
- Overview
- Architecture
- Repository Map
- Core Flows
- Entities & Data Model
- API Endpoints
- Services & Business Logic
- AI Provider Integration
- QA Agent System
- Configuration
- Integration Points
1. Overview
Generative Messaging (AIM — AI Messaging) is Sopro's AI-powered email generation system. It assembles prospect + campaign data into prompts, calls AI providers (OpenAI, Anthropic, DeepSeek, Grok) to generate personalised emails, runs QA agents to validate quality, and stores generated emails for the sending pipeline. The AIM engine lives in the email-template-demo repo (hosted at aim.sopro.io), with integration points in sopro-sodastream, sopro-sodastream-core, and sopromasterdata.
2. Architecture
3. Repository Map
| Repository | Layer | Key Files |
|---|---|---|
| email-template-demo | Generation Controller | Controllers/GenerationController.cs |
| email-template-demo | Suitability Controller | Controllers/CompanySuitabilityController.cs |
| email-template-demo | Prompt Builder | Services/PromptBuilder.cs |
| email-template-demo | AI Provider Factory | Services/AIProviderFactory.cs |
| email-template-demo | QA Agent | Services/QAAgentService.cs |
| email-template-demo | Provider Adapters | Services/Providers/OpenAI/, Anthropic/, DeepSeek/, Grok/ |
| sopro-sodastream | GPT Controller | Controllers/GPTSpindleController.cs |
| sopro-sodastream | Entities | generative email entities and models |
| sopro-sodastream-core | HyperRequest | Services/HyperRequestService.cs |
| sopro-sodastream-core | Example Recipients | Services/GenerativeExampleRecipientService.cs |
| sopromasterdata | Company Suitability | CompanySuitabilityServices/CompanySuitabilityService.cs |
| sopromasterdata | EndpointManager | Shared/EndpointManager/EndpointManagerService.cs |
4. Core Flows
4.1 Email Generation Pipeline
4.2 Company Suitability Scoring (via AIM)
4.3 Prompt Assembly
5. Entities & Data Model
GenerativeEmail (sopro-sodastream)
| Column | Type | Description |
|---|---|---|
Id | int (PK) | Generated email identifier |
CampaignId | int (FK) | Campaign reference |
ProspectId | long (FK) | Prospect reference |
Subject | nvarchar(500) | Generated subject line |
Body | nvarchar(max) | Generated email HTML body |
AIProvider | nvarchar(50) | Provider used (OpenAI, Anthropic, etc.) |
QAScore | decimal? | Quality assessment score |
QAStatus | int (enum) | Pending, Passed, Failed, Regenerated |
EmailType | int (enum) | Initial, Chaser1, Chaser2, Chaser3 |
GeneratedAt | datetime | Generation timestamp |
ApprovedAt | datetime? | QA approval timestamp |
CompanySuitabilityResult (sopromasterdata)
| Column | Type | Description |
|---|---|---|
Id | int (PK) | Result identifier |
CampaignId | int (FK) | Campaign being scored for |
CompanyId | int (FK) | Company being scored |
Score | decimal | 0-100 suitability score |
Reasoning | nvarchar(max) | AI-generated explanation |
Provider | nvarchar(50) | AI provider used |
ScoredAt | datetime | Scoring timestamp |
6. API Endpoints
AIM Service Endpoints (email-template-demo at aim.sopro.io)
| Method | Endpoint | Description |
|---|---|---|
POST | /api/generate | Generate a personalised email |
POST | /api/generate/chaser | Generate a follow-up chaser email |
POST | /api/v5/company-suitability-v1 | Score company suitability for a campaign |
GET | /api/health | Health check |
Request Payload (/api/generate)
{
"campaignBrief": "...",
"valueProposition": "...",
"prospect": {
"firstName": "John",
"lastName": "Smith",
"jobTitle": "VP Marketing",
"seniority": "VP"
},
"company": {
"name": "Acme Corp",
"industry": "Technology",
"size": "200-500",
"website": "acme.com",
"description": "..."
},
"suitabilityScore": 85,
"suitabilityReasoning": "...",
"style": {
"tone": "professional",
"maxLength": 150,
"provider": "openai"
}
}
7. Services & Business Logic
GenerativeExampleRecipientService (sopro-sodastream-core)
Location: sopro-sodastream-core/Services/GenerativeExampleRecipientService.cs
Size: ~1477 lines
Purpose: Assembles all data needed for email generation — gathers prospect data, company information, campaign brief, suitability score, and example emails into a structured request.
This is the most complex service in the generation pipeline — it handles:
- Querying prospect and company data
- Fetching campaign configuration and brief
- Loading example emails for style reference
- Structuring the generation request payload
- Handling generation results and storage
HyperRequestService (sopro-sodastream-core)
Location: sopro-sodastream-core/Services/HyperRequestService.cs
Purpose: HTTP client for calling the AIM service endpoints.
PromptBuilder (email-template-demo)
Location: email-template-demo/Services/PromptBuilder.cs
Purpose: Assembles the structured prompt from the generation request:
| Method | Description |
|---|---|
BuildGenerationPrompt() | Creates system + user messages for email generation |
BuildChaserPrompt() | Creates prompt for follow-up chasers |
BuildSuitabilityPrompt() | Creates prompt for company suitability scoring |
AIProviderFactory (email-template-demo)
Location: email-template-demo/Services/AIProviderFactory.cs
Purpose: Factory pattern — selects the appropriate AI provider based on configuration.
public interface IAIProvider
{
Task<GenerationResult> GenerateAsync(PromptMessage[] messages, GenerationOptions options);
}
Implementations: OpenAIProvider, AnthropicProvider, DeepSeekProvider, GrokProvider
8. AI Provider Integration
Provider Configuration
Provider Selection Logic
The provider can be specified per request, or defaults are used per campaign/environment:
- Production: Primarily OpenAI and Anthropic
- Testing: DeepSeek or Grok for cost efficiency
- Fallback: If primary provider fails, factory falls back to secondary
9. QA Agent System
Architecture
The QA agent is a separate AI call that reviews the generated email:
QA Review Criteria
| Criterion | Weight | Description |
|---|---|---|
| Relevance | High | Does the email match the campaign brief? |
| Accuracy | High | Are company facts correct? |
| Tone | Medium | Professional yet approachable? |
| Length | Medium | Appropriate for the email type? |
| Compliance | High | No banned phrases, false claims, or spam triggers? |
| Personalisation | Medium | Does it reference specific prospect/company details? |
10. Configuration
AIM Service (email-template-demo)
{
"AIProviders": {
"OpenAI": { "ApiKey": "...", "DefaultModel": "gpt-4o" },
"Anthropic": { "ApiKey": "...", "DefaultModel": "claude-3-sonnet" },
"DeepSeek": { "ApiKey": "...", "DefaultModel": "deepseek-chat" },
"Grok": { "ApiKey": "...", "DefaultModel": "grok-2" }
},
"QA": {
"Enabled": true,
"PassThreshold": 0.7,
"MaxRegenerations": 2
}
}
EndpointManager in sopromasterdata
{
"EndpointManager": {
"CompanySuitability": {
"Url": "https://aim.sopro.io/api/v5/company-suitability-v1"
}
}
}
Hosting
| Setting | Value |
|---|---|
| AIM URL | https://aim.sopro.io |
| Hosting | ASP.NET Core (.NET 8) |
| Repo | email-template-demo |
11. Integration Points
Upstream (data flows in)
| Source | Data | Mechanism |
|---|---|---|
| sopro-sodastream | Campaign brief, prospect queue | Database + HTTP |
| sopro-sodastream-core | Assembled prospect + company data | HTTP to AIM |
| sopromasterdata | Company suitability scores | HTTP via EndpointManager |
Downstream (data flows out)
| Target | Data | Mechanism |
|---|---|---|
| sopro-sodastream | Generated emails (subject + body) | Stored in DB |
| Email Sending | Approved email content for delivery | Database read |
| Campaign Statistics | Generation counts, QA pass rates | Database |
Cross-Feature Dependencies
| Feature | Relationship |
|---|---|
| Campaign Management | Campaign brief drives email generation |
| Company Suitability | Suitability scores enrich the generation prompt |
| Email Sending | Approved generated emails are delivered by the sending pipeline |
| Email Finding | Prospect email addresses needed before sending generated content |