Funnel Generator ExecModule
Overview
FunnelGeneratorModule produces a structured, review-only product funnel proposal through ValkyrAI's shared LlmAdapterFactory. One execution can return a product requirements document, landing-page sections, advertising variants, and a nurture email sequence.
The module does not publish content, launch advertising, send email, create a product, enroll contacts, or execute model-proposed actions. OpenAI credentials are read only from the IntegrationAccount bound to ExecModuleConfig.authConfig.integrationAccount. Prompt payloads and legacy direct-key fields are never credential sources.
Usage
- Bind a least-privilege OpenAI
IntegrationAccountwith status exactlyREADY, or select a loopback-only Ollama-compatible endpoint. - Add
FunnelGeneratorModuleto a workflow task. - Map the brand, offer, audience, pricing, delivery mode, and primary benefit inputs.
- Review the returned proposal for truthfulness, policy, brand, legal, and channel requirements.
- Use separately authorized modules for any later ContentData, campaign, email, enrollment, or publication action.
Every generated statement is untrusted draft content. The module instructs the model not to invent customers, testimonials, performance metrics, scarcity, endorsements, or compliance claims.
Inputs
| Name | Type | Requirement | Constraints |
|---|---|---|---|
brand | string | Required | 1–160 characters. |
offer | string | Required | 1–240 characters. |
targetAudience | string | Required | 1–500 characters. |
priceTier | string | Required | free, tripwire, core, or high_ticket. |
priceAmount | number | Optional | Finite value from 0 through 1,000,000,000. |
deliveryMode | string | Required | course, challenge, mentorship, consulting, service, or software. |
heroBenefit | string | Required | Primary customer outcome, 1–500 characters. |
templateId | string | Optional | UUID of an approved prompt template for downstream provenance. |
Raw openAiApiKey, apiKey, token, secret, and password-style inputs are rejected before any provider request.
Outputs
| Name | Type | When present | Description |
|---|---|---|---|
status | string | Always | success or error. |
provider | string | Always | Normalized provider name. |
model | string | Always | Requested model identifier. |
attempts | integer | Always | 0 before submission or 1 after the single provider attempt. |
prd | object | Success | Product requirements and funnel-stage proposal. |
landingPageSections | array | Success | At most 20 proposed landing-page section objects. |
adVariants | array | Success | At most 20 proposed advertising creative objects. |
emailSequence | array | Success | At most 20 proposed nurture email objects. |
generatedAt | integer | Success | Epoch-millisecond generation time. |
error | object | Failure | Bounded {code,message,retryable} details with credential-like values redacted. |
Provider output must be one JSON object containing exactly prd, landingPageSections, adVariants, and emailSequence. Partial or differently shaped content fails closed and is not exposed as a successful proposal.
IntegrationAccount Requirements
OpenAI mode requires an IntegrationAccount relationship on the module auth configuration.
| Field | Requirement |
|---|---|
accountName | Human-readable OpenAI automation identity. |
apiKey | Encrypted SecureField containing a scoped OpenAI API key. |
status | Exactly READY. |
Do not place a provider key in the input map, payload parameters, prompt text, environment-specific examples, or deprecated openAiApiKey configuration. Ollama mode does not use an OpenAI account, but the endpoint must be an HTTP or HTTPS loopback URL without embedded credentials or fragments.
Configuration
| Name | Type | Default | Constraints |
|---|---|---|---|
llmAccount | IntegrationAccount | None | Required for OpenAI; bind through the generated auth relationship. |
provider | select | OPENAI | OPENAI or OLLAMA; other generated provider values fail closed. |
openAiModel | text | gpt-4o | Provider model identifier used by the selected adapter. |
ollamaModelUrl | URL | None | Required for Ollama and limited to localhost, 127.0.0.1, or IPv6 loopback. |
temperature | number | 0.4 | 0 through 1. |
timeoutSeconds | integer | 90 | 1 through 300 seconds. |
Illustrative normalized configuration:
{
"authConfig": {
"authStrategy": 1,
"integrationAccount": "integration-account:openai-marketing-drafts"
},
"payloadConfig": {
"parameters": "{\"provider\":\"OPENAI\",\"openAiModel\":\"approved-model-id\",\"temperature\":0.4,\"timeoutSeconds\":90}"
}
}
The symbolic account reference is documentation only. Persisted workflows use the generated relationship and never a plaintext key.
Operations
The module has one operation: generate_proposal.
| Stage | Behavior | Side effect |
|---|---|---|
| Validate | Bounds every input, rejects raw secrets, checks the provider and account, and validates loopback Ollama URLs. | None. |
| Generate | Sends one system instruction and one serialized funnel input object through the shared adapter. | Outbound provider request and possible provider billing. |
| Normalize | Requires the exact four-field JSON contract and bounds each returned collection to 20 object entries. | None. |
| Return | Emits confidential draft content for human or policy-controlled review. | No publication or campaign action. |
Errors and Failure Modes
| Code | Typical cause | Retryable | Resolution |
|---|---|---|---|
VALIDATION_ERROR | Missing input, unsupported tier or mode, raw secret field, unsafe Ollama URL, invalid temperature/timeout, or malformed provider JSON. | No | Correct the named input or tighten the provider instruction. |
INTEGRATION_ACCOUNT_REQUIRED | OpenAI has no bound account. | No | Bind an OpenAI IntegrationAccount. |
INTEGRATION_ACCOUNT_NOT_READY | The account is not exactly READY. | No | Repair or reconnect the account. |
INTEGRATION_ACCOUNT_INVALID | The encrypted API key is absent or unreadable. | No | Store the key in the SecureField and verify decrypt authority. |
RESPONSE_TOO_LARGE | Provider content exceeds 1,000,000 characters. | No | Reduce scope or model output limits. |
PROVIDER_TIMEOUT | The completion exceeded timeoutSeconds. | Yes, after reconciliation | Check provider usage and health before manually retrying. |
EXECUTION_INTERRUPTED | Workflow cancellation or shutdown interrupted the wait. | Yes, after reconciliation | Inspect execution state and provider usage. |
PROVIDER_ERROR | Adapter, authentication, network, rate-limit, or provider failure. | Possibly | Inspect the sanitized error and provider status; avoid blind retries. |
No error path returns fabricated funnel content. Prompt, completion, and credential values are excluded from logs.
Example
Input:
{
"brand": "Valkyr Labs",
"offer": "Workflow Reliability Sprint",
"targetAudience": "engineering leaders operating production AI workflows",
"priceTier": "core",
"priceAmount": 499,
"deliveryMode": "consulting",
"heroBenefit": "Ship reliable AI workflows with evidence-backed release gates"
}
Expected normalized shape:
{
"status": "success",
"provider": "OPENAI",
"model": "approved-model-id",
"attempts": 1,
"prd": {
"productName": "Workflow Reliability Sprint",
"assumptions": ["Audience and price require validation"]
},
"landingPageSections": [
{"sectionType": "hero", "headline": "Ship reliable AI workflows"}
],
"adVariants": [
{"platform": "linkedin", "status": "draft"}
],
"emailSequence": [
{"sequenceOrder": 1, "status": "draft"}
],
"generatedAt": 1786380000000
}
The next workflow step must validate claims and obtain any required approval before acting on this draft.
Notes
- Pagination: not applicable. One execution returns one bounded proposal.
- Limits: the provider response is capped at 1,000,000 characters. Each returned collection is capped at 20 objects. Input strings, prices, temperature, and timeout are bounded before the request.
- Idempotency: LLM generation is not idempotent. A retry may consume more provider credits and produce different content, even with the same inputs.
- Rate limits: the module makes one attempt and does not automatically retry provider throttling or transient failures. Reconcile ambiguous provider usage before a manual retry.
- API constraints: OpenAI uses the shared adapter and READY IntegrationAccount key. Ollama is limited to the local loopback interface to avoid caller-selected outbound destinations.
- Destructive behavior: none. Generated content is a proposal only; later publication, advertising, enrollment, product, and email modules own their own authorization and safety contracts.
- Privacy: funnel inputs and generated content are classified confidential and sent externally in OpenAI mode. Choose provider, account, and data accordingly.
- Observability: logs contain only provider, model, safe result counts, and error code. They do not contain prompts, completions, API keys, or raw provider errors.
- Unverified boundary: deterministic tests cover input validation, account resolution, request construction, exact response mapping, loopback enforcement, redaction, and metadata discovery. Live model behavior, quotas, billing, and provider availability require a separately authorized account and are not exercised in repository tests.