Quorentra

Quorentra CRM Creating Opportunities from ChatGPT: Building from Zero — Part 19

Series: Building Quorentra CRM from Zero — A Modular, ChatGPT-Native AI CRM

Building conversational Opportunity creation with server-side drafts, missing-field detection, business defaults, Company resolution, validation, confirmation, idempotency, transactions, and audit.

Quorentra Creating Opportunities from ChatGPT: Building from Zero — Part 19
Quorentra Creating Opportunities from ChatGPT: Building from Zero — Part 19

1. Introduction

In Part 18, Quorentra crossed an important boundary.

For the first time, ChatGPT could participate in changing authoritative CRM state.

A user could say:

Move the Microsoft 365 Migration opportunity to negotiation.

Quorentra did not immediately execute the request.

Instead, we built a governed mutation pipeline:

User Intent
Entity Resolution
Prepare Mutation
Validate Current State
Confirmation
Execute
Audit
Authoritative Result

That architecture gave us a safe first mutation.

But updating an existing Opportunity was relatively simple.

We already knew:

Opportunity
Current Stage
Requested Stage

Creating a new Opportunity is fundamentally differen

Consider:

Create an opportunity for Contoso.

What should Quorentra create?

We know the Company.

But we may not know:

Opportunity Name
Amount
Currency
Expected Close Date
Probability
Description

ChatGPT must not invent those facts merely to complete the operation.

Part 19 therefore introduces a new concept:

Conversational CRM drafts.

Instead of converting incomplete natural language directly into database writes, Quorentra will progressively construct a structured Opportunity draft.

Only when the draft is complete and valid can it become a prepared creation mutation.

And only after confirmation can that mutation create an authoritative CRM record.


2. What Are We Building?

Our target interaction begins simply:

Create a new opportunity for Contoso.

ChatGPT resolves:

Company:
Contoso

but determines that required information is missing.

It may ask:

What should the opportunity be called?

The user replies:

Microsoft Copilot Deployment.

Then:

What is the estimated value?

User:

€120,000.

Then:

What is the expected close date?

User:

November 30.

Quorentra progressively builds:

Opportunity Draft
Company:
Contoso
Name:
Microsoft Copilot Deployment
Amount:
€120,000
Currency:
EUR
Stage:
Qualification
Probability:
20%
Expected Close:
30 November 2026

When all required information is available, Quorentra presents:

┌────────────────────────────────────────────┐
│ QUORENTRA │
│ Create Opportunity │
│ │
│ Company │
│ Contoso │
│ │
│ Opportunity │
│ Microsoft Copilot Deployment │
│ │
│ Value │
│ €120,000 │
│ │
│ Stage │
│ Qualification │
│ │
│ Probability │
│ 20% │
│ │
│ Expected Close │
│ 30 November 2026 │
│ │
│ This will create a new CRM record. │
│ │
│ [Cancel] [Create Opportunity] │
└────────────────────────────────────────────┘

Only after:

Create Opportunity

does Quorentra insert the record into PostgreSQL.


3. Why Creation Is Harder Than Updating

Part 18 changed:

One existing entity
+
One known field
+
One requested value

Part 19 must solve:

Entity relationship
+
Multiple fields
+
Potentially missing values
+
Defaults
+
User-provided facts
+
Ambiguity
+
Validation
+
Duplicate awareness
+
Confirmation
+
Creation

That is a much richer workflow.


4. The Central Rule

The most important principle in Part 19 is:

ChatGPT must not silently invent missing CRM facts.

If the user says:

Create an opportunity for Contoso.

ChatGPT should not invent:

Name = Cloud Transformation Project
Amount = €100,000
Probability = 70%
Close Date = next quarter

just because those values sound plausible.

Those are business facts.

They must come from:

The user
Authoritative CRM data
Explicit business rules
Deterministic defaults

not model imagination.


5. Defaults Are Different From Guesses

This distinction is critical.

Suppose Quorentra defines:

New Opportunity Stage:
Qualification
Default Qualification Probability:
20%

Then:

stage = qualification
probability = 20

are legitimate business defaults.

They are deterministic.

By contrast:

amount = €75,000

because ChatGPT believes that sounds reasonable is a guess.

Quorentra must distinguish:

Business Default

from:

AI Guess

6. The New Creation Architecture

Our new workflow becomes:

User
│ "Create an opportunity for Contoso."
ChatGPT
Resolve Company
Create Opportunity Draft
Quorentra
├── Apply Business Defaults
├── Validate Known Fields
└── Identify Missing Fields
Draft Status
├── incomplete → ask user
└── complete
Prepare Creation
Confirmation UI
User Confirms
Execute Creation
Transaction
├── Create Opportunity
├── Create AuditEvent
└── Mark Mutation Executed
Authoritative Opportunity
ChatGPT + Widget

This extends the Part 18 mutation model rather than replacing it.


7. Reuse the Mutation Architecture

Part 18 gave us:

MutationRequest
AuditEvent
Confirmation
Expiry
Idempotency
RBAC
Tenant Isolation
Transactions

We should reuse all of that.

Do not create a separate safety architecture just for record creation.

Our general mutation pattern remains:

Prepare
Confirm
Execute
Audit

Part 19 adds a new phase before preparation:

Draft

So the full creation pattern becomes:

Draft
Prepare
Confirm
Execute
Audit

8. Starting Checkpoint

Before implementing Part 19, verify Part 18.

Run:

cd backend
python -m pytest

Then:

cd ..\chatgpt-ui
npm run build

Verify:

Show my EUR pipeline.

Open an Opportunity.

Then request:

Move Microsoft 365 Migration to negotiation.

Verify:

Prepare
Confirmation
Execution
Audit
Updated Opportunity

all work.

Part 19 depends directly on that mutation infrastructure.


9. Define the Create Permission

Part 18 introduced:

opportunities.update

Part 19 requires:

opportunities.create

Again:

read
update
create

must remain separate capabilities.


10. Example Role Matrix

Conceptually:

RoleReadCreateUpdate
Viewer
Member
Manager
Admin
Owner

The exact role model can evolve later.

The important point is capability separation.


11. What Fields Does an Opportunity Need?

Our current Opportunity domain contains approximately:

id
organization_id
company_id
name
description
stage
amount
currency
probability
expected_close_date
version
created_at
updated_at

Some are system-managed.

Others must be provided or defaulted.


12. Classify Every Field

Before building conversational creation, classify each field.

For example:

FieldSource
idSystem generated
organization_idTenantContext
company_idResolved CRM entity
nameUser required
descriptionOptional user input
stageBusiness default
amountUser required
currencyUser or contextual default
probabilityStage business rule
expected_close_dateUser required
versionSystem default
created_atSystem generated
updated_atSystem generated

This classification is extremely useful.


13. Never Ask the User for Tenant ID

The user should never need to provide:

organization_id

The authenticated:

TenantContext

supplies it.

Likewise, ChatGPT should not send it.

This rule remains unchanged.


14. Never Ask the User for Record ID

The Opportunity:

id

is generated by Quorentra.

It is not conversational input.

The same applies to:

version
created_at
updated_at

These are system-managed fields.


15. Stage as a Business Default

For the MVP, define:

New Opportunity Stage:
qualification

unless the user explicitly provides another allowed stage.

This means:

Create an opportunity for Contoso.

does not require ChatGPT to ask:

Which stage?

unless the user wants something different.


16. Probability as a Stage Default

We can define:

qualification = 20%
discovery = 40%
proposal = 60%
negotiation = 80%

Then new:

Qualification

Opportunities default to:

20%

This is deterministic business logic.


17. Should Users Override Probability?

Eventually, yes.

Sales organizations often customize probability independently of stage.

For the MVP, we can allow an explicitly supplied probability.

Otherwise use the stage default.

The rule becomes:

Explicit valid user value
Use it
No explicit value
Use stage default

18. Currency Default

Currency is more interesting.

If the user’s active organization has:

default_currency = EUR

then Quorentra can safely default:

currency = EUR

That is an organization setting.

It is not an AI guess.


19. Avoid Locale Guessing

Do not infer:

EUR

solely because the user appears to be in Europe.

A user in Europe may be creating:

USD
GBP
CHF
JPY

Opportunities.

Currency should come from:

Explicit user input
or
Organization business configuration

20. Expected Close Date

Should Quorentra default the expected close date?

Probably not.

This is a meaningful sales forecast.

The model should not invent:

30 days from today

unless Quorentra explicitly defines that as organizational policy.

For the MVP:

expected_close_date

is required user information.


21. Opportunity Name

Likewise:

name

should be required.

If the user says:

Create an opportunity for Contoso for their Microsoft Copilot deployment.

ChatGPT may reasonably extract:

Microsoft Copilot Deployment

from the user’s explicit wording.

That is extraction.

It is not invention.


22. Extraction Versus Generation

This distinction matters.

User says:

We have a €120,000 Microsoft Copilot deployment opportunity with Contoso expected to close November 30.

ChatGPT can extract:

Company:
Contoso
Name:
Microsoft Copilot Deployment
Amount:
120000
Currency:
EUR
Expected Close:
30 November

All of those facts came from the user.

ChatGPT merely structured them.


23. Natural Language Is Input

This is one of the strengths of a ChatGPT-native CRM.

Traditional CRM:

Open form
Fill company
Fill name
Fill amount
Select currency
Select stage
Enter probability
Choose date
Save

Quorentra:

Create a €120,000 Microsoft Copilot deployment opportunity for Contoso closing November 30.

The same structured data can be captured conversationally.

But the backend still validates everything.


24. Introduce OpportunityDraft

We now need a server-side representation of an incomplete proposed Opportunity.

Conceptually:

OpportunityDraft
├── id
├── organization_id
├── user_id
├── company_id
├── name
├── description
├── stage
├── amount
├── currency
├── probability
├── expected_close_date
├── status
├── expires_at
├── created_at
└── updated_at

This is not yet an Opportunity.


25. Why Persist the Draft?

We could keep draft state entirely in ChatGPT conversation context.

But that would make the model responsible for preserving authoritative creation state.

A better design is:

Conversation
Draft updates
Quorentra
Authoritative draft

ChatGPT can help build the draft.

Quorentra owns it.


26. Conversation Context Is Not a Database

This principle is worth making explicit:

Chat history is context, not authoritative application state.

A conversation may be:

trimmed
summarized
restarted
interrupted
continued elsewhere

The CRM draft should survive independently where appropriate.


27. Draft Status

Possible statuses:

incomplete
complete
prepared
cancelled
expired
converted

Initially:

incomplete

Once all required fields exist:

complete

After a MutationRequest is prepared:

prepared

After successful Opportunity creation:

converted

28. Draft Expiry

Drafts should not live forever.

For example:

expires_at =
last_updated_at + 24 hours

or another configurable duration.

A longer lifetime than confirmation requests makes sense because conversational data collection may take time.


29. Draft Is Tenant-Scoped

Every draft belongs to:

organization_id
user_id

All reads and updates must enforce both.

A draft is not a globally accessible temporary record.


30. Create the Draft Model

Conceptually:

class OpportunityDraft(Base):
__tablename__ = "opportunity_drafts"
id = ...
organization_id = ...
user_id = ...
company_id = ...
name = ...
description = ...
stage = ...
amount = ...
currency = ...
probability = ...
expected_close_date = ...
status = ...
expires_at = ...
created_at = ...
updated_at = ...

Most business fields are nullable because the draft may be incomplete.


31. Draft Fields May Be Null

This is intentionally different from the authoritative Opportunity model.

For example:

Opportunity.amount

may be required.

But:

OpportunityDraft.amount

may be:

NULL

until the user supplies it.

That is the purpose of the draft.


32. Authoritative Records Remain Strict

Do not weaken the real Opportunity schema just because conversational drafts can be incomplete.

Keep:

Opportunity

strict.

Allow incompleteness only in:

OpportunityDraft

This maintains domain integrity.


33. Draft Creation Tool

Introduce:

create_opportunity_draft

This tool does not create an Opportunity.

It creates a working draft.

Conceptually:

Permission:
opportunities.create
Mutation:
Draft state only
CRM Business Record Created:
No

34. Draft Tool Input

The input should allow known fields.

Conceptually:

class CreateOpportunityDraftInput(BaseModel):
company_reference: str | None = None
name: str | None = None
description: str | None = None
stage: OpportunityStage | None = None
amount: Decimal | None = None
currency: str | None = None
probability: int | None = None
expected_close_date: date | None = None

However, Company resolution deserves special attention.


35. Do Not Trust a Company Name as an ID

The user says:

Contoso.

The database needs:

company_id

ChatGPT should not manufacture a UUID.

Instead:

"Contoso"
Company Resolution
company_id

The server owns this resolution process.


36. Company Resolution

We already have Company capabilities from earlier parts.

We can introduce or reuse:

search_companies

or equivalent Company lookup logic.

The resolution must be:

Tenant-scoped
Case-aware
Predictable
Ambiguity-aware

37. Exact Company Match

Suppose Tenant A contains:

Contoso
Fabrikam
Northwind

The user says:

Contoso.

Quorentra finds one exact tenant-scoped match.

Then:

company_id = Contoso.id

can safely enter the draft.


38. Ambiguous Company Match

Suppose the tenant contains:

Contoso Ltd
Contoso Europe
Contoso Consulting

The user says:

Create an opportunity for Contoso.

Do not arbitrarily choose one.

Return:

Multiple companies match "Contoso".

Then ChatGPT can ask:

Which Contoso company do you mean?


39. Ambiguity Is Better Than Guessing

This will become a recurring Quorentra principle:

When authoritative entity resolution is ambiguous, ask rather than guess.

This applies later to:

Contacts
Opportunities
Tasks
Users
Documents
Meetings

40. Company Not Found

If no Company exists:

Company "Contoso" was not found.

Do not silently create the Company as a side effect of creating an Opportunity.

That would combine two business operations.

Later we can support:

Create Company
then
Create Opportunity

as an explicit multi-step workflow.


41. Why Not Auto-Create Missing Companies?

Because:

Create an opportunity for Acme.

could contain:

Typo
New company
Existing company under different name
Trading name
Subsidiary

Automatic creation can produce duplicate CRM records.

Explicit Company creation deserves its own governed operation.


42. Apply Business Defaults Server-Side

After Company resolution, the server applies:

stage = qualification

if no stage was provided.

Then:

probability = 20

if no probability was provided.

Then:

currency = organization.default_currency

if no currency was provided.

These rules belong in Quorentra.


43. Why Not Apply Defaults in ChatGPT?

Because business defaults should work identically from:

ChatGPT
Widget
REST
Future mobile client
Automation
AI Agent

Therefore:

Application Service

owns defaults.

Not the interface.


44. Draft Result

After creation, the tool might return:

{
"draft_id": "...",
"status": "incomplete",
"values": {
"company": {
"id": "...",
"name": "Contoso"
},
"name": null,
"amount": null,
"currency": "EUR",
"stage": "qualification",
"probability": 20,
"expected_close_date": null
},
"missing_fields": [
"name",
"amount",
"expected_close_date"
]
}

This is extremely useful to ChatGPT.


45. Missing Fields Are Server-Determined

Do not make ChatGPT independently decide which fields are required.

Quorentra returns:

missing_fields

based on current business rules.

This allows requirements to evolve without rewriting prompts.


46. Example Conversation

User:

Create an opportunity for Contoso.

Quorentra creates:

Company: Contoso
Currency: EUR
Stage: Qualification
Probability: 20%
Missing:
Name
Amount
Expected Close Date

ChatGPT can then ask:

What should the opportunity be called?


47. Why Ask One Thing at a Time?

Conversationally, one concise question often works better than presenting a large form.

But ChatGPT may combine questions when appropriate.

For example:

What should the opportunity be called, what is its estimated value, and when do you expect it to close?

The important part is that missing fields come from Quorentra’s structured result.


48. Updating the Draft

Introduce:

update_opportunity_draft

Conceptually:

class UpdateOpportunityDraftInput(BaseModel):
draft_id: UUID
name: str | None = None
description: str | None = None
stage: OpportunityStage | None = None
amount: Decimal | None = None
currency: str | None = None
probability: int | None = None
expected_close_date: date | None = None

The server applies only provided fields.


49. Draft Update Is Not Final CRM Mutation

Updating:

OpportunityDraft

does not create or change an authoritative Opportunity.

Therefore it has a lower business impact.

Still, it must be:

Authenticated
Tenant-scoped
User-scoped
Validated

because drafts may contain business information.


50. User Supplies the Name

ChatGPT asks:

What should the opportunity be called?

User:

Microsoft Copilot Deployment.

The tool calls:

update_opportunity_draft

with:

{
"draft_id": "...",
"name": "Microsoft Copilot Deployment"
}

Quorentra returns the updated draft.


51. Missing Fields Shrink

Now:

{
"missing_fields": [
"amount",
"expected_close_date"
]
}

ChatGPT knows what remains.


52. User Supplies Amount

User:

€120,000.

ChatGPT can extract:

amount = 120000
currency = EUR

Then update the draft.

Because the user explicitly provided the currency symbol:

this is legitimate extraction.


53. Amount Validation

The backend validates:

amount >= 0

and whatever upper bounds or precision rules Quorentra defines.

Do not trust the model to validate monetary values.


54. Decimal, Not Float

For monetary values, continue using:

Decimal

rather than binary floating-point arithmetic.

For example:

Decimal("120000.00")

This keeps monetary calculations deterministic.


55. Currency Validation

Normalize currency to ISO-style codes:

EUR
USD
GBP
CHF
JPY

Do not store:

Euro
EURO
euros

as the authoritative currency field.

Presentation can use symbols.

Persistence should use a stable code.


56. Date Resolution

User:

November 30.

What year?

If the context makes the year unambiguous according to defined rules, ChatGPT may resolve it.

But date interpretation can be risky.

A safer interaction is:

November 30, 2026?

The user can confirm if necessary.

For authoritative forecasting dates, explicit dates are preferable.


57. Relative Dates

The user may say:

End of next month.

ChatGPT can interpret that into a date.

But Quorentra should receive the normalized:

YYYY-MM-DD

value.

The structured tool input should not contain vague text such as:

"end of next month"

unless a dedicated date-resolution layer exists.


58. Complete Draft

Eventually:

missing_fields = []

and:

status = complete

The draft may look like:

Company:
Contoso
Name:
Microsoft Copilot Deployment
Amount:
€120,000
Stage:
Qualification
Probability:
20%
Expected Close:
30 November 2026

Now it is eligible for preparation.


59. Complete Does Not Mean Created

This distinction is essential.

Draft status = complete

means:

All required information is available
and structurally valid.

It does not mean:

Opportunity exists.

No Opportunity row has been inserted yet.


60. Duplicate Awareness

Before preparing creation, Quorentra should check for obvious potential duplicates.

For example:

Company:
Contoso
Opportunity:
Microsoft Copilot Deployment

may already exist.

We do not necessarily block creation.

But we should detect relevant matches.


61. Duplicate Check

A simple MVP duplicate query can search the active tenant for:

same company
+
similar or exact opportunity name
+
open opportunity

An exact normalized name match is a good starting point.


62. Example Duplicate Warning

Quorentra may return:

Potential existing opportunity:
Microsoft Copilot Deployment
Contoso
Proposal
€110,000

Then the user can decide whether to:

Open existing opportunity
or
Continue creating new opportunity

63. Do Not Overbuild Fuzzy Matching Yet

We do not need:

Embeddings
Vector similarity
AI duplicate scoring

for the MVP.

Start with deterministic:

normalized company
normalized opportunity name

Later AI can improve duplicate detection.


64. Prepare Creation Tool

Once the draft is complete, introduce:

prepare_opportunity_creation

Input:

{
"draft_id": "..."
}

The server then:

Loads draft
Checks tenant
Checks user
Checks permission
Checks expiry
Revalidates Company
Revalidates all fields
Checks missing fields
Checks duplicates
Creates MutationRequest
Marks draft prepared

No Opportunity is created yet.


65. Mutation Type

The Part 18 MutationRequest can now support:

mutation_type =
opportunity.create

Its proposed values contain the complete Opportunity data.

For example:

{
"company_id": "...",
"name": "Microsoft Copilot Deployment",
"amount": "120000.00",
"currency": "EUR",
"stage": "qualification",
"probability": 20,
"expected_close_date": "2026-11-30"
}

66. No Old Values for Creation

Part 18 recorded:

old value
new value

For creation there is no prior entity state.

Therefore:

old_values = null

or:

{}

while:

new_values

contains the created record’s relevant business state.


67. Confirmation Result

prepare_opportunity_creation returns something like:

{
"mutation_request_id": "...",
"draft_id": "...",
"requires_confirmation": true,
"opportunity": {
"company_name": "Contoso",
"name": "Microsoft Copilot Deployment",
"amount": "120000.00",
"currency": "EUR",
"stage": "qualification",
"probability": 20,
"expected_close_date": "2026-11-30"
},
"warnings": [],
"expires_at": "..."
}

This drives the confirmation UI.


68. Build the Creation Confirmation UI

Create:

chatgpt-ui/src/mutations/
└── OpportunityCreationConfirmation.tsx

It should clearly show every material business field.

For example:

┌────────────────────────────────────────────┐
│ QUORENTRA │
│ Create Opportunity │
│ │
│ Company │
│ Contoso │
│ │
│ Opportunity │
│ Microsoft Copilot Deployment │
│ │
│ Value │
│ €120,000 │
│ │
│ Stage │
│ Qualification │
│ │
│ Probability │
│ 20% │
│ │
│ Expected Close │
│ 30 November 2026 │
│ │
│ This will create a new CRM record. │
│ │
│ [Cancel] [Create Opportunity] │
└────────────────────────────────────────────┘

69. Confirmation Should Show Defaults

Suppose:

Stage = Qualification
Probability = 20%
Currency = EUR

came from business defaults.

They should still appear in the confirmation.

The user should see the actual record that will be created.


70. Do Not Hide AI Interpretation

Likewise, if ChatGPT extracted:

Microsoft Copilot Deployment

from a longer sentence, show it.

Confirmation is the point where structured interpretation becomes visible to the user.


71. Edit Before Creation

What if the user notices:

€120,000

should actually be:

€125,000

?

They should not need to create the wrong record and fix it later.

The confirmation workflow should support returning to the draft.

For example:

[Edit] [Cancel] [Create Opportunity]

72. Editing Invalidates the Prepared Mutation

This is important.

Once:

MutationRequest

has been prepared for:

€120,000

and the user changes the draft to:

€125,000

the old MutationRequest must no longer be executable.

The prepared action no longer matches the draft.


73. Mutation Request Supersession

When a prepared draft changes:

old MutationRequest
→ cancelled or superseded

Then a new:

prepare_opportunity_creation

must create a fresh confirmation.

This ensures the user confirms exactly what will be executed.


74. Execute Creation Tool

Introduce:

create_opportunity

as the execution capability.

But like Part 18, it should not accept arbitrary record fields.

Input:

{
"mutation_request_id": "..."
}

That is all.


75. Why Not Accept Opportunity Data Directly?

Avoid:

{
"company_id": "...",
"name": "...",
"amount": "...",
"confirmed": true
}

because the client could modify the record after confirmation.

Instead:

MutationRequest

contains the exact confirmed proposed record.

The execution tool merely references it.


76. Execution Flow

create_opportunity performs:

Load MutationRequest
Verify Tenant
Verify User
Verify Permission
Verify Pending
Verify Not Expired
Load Draft
Verify Draft Still Matches
Revalidate Company
Revalidate Fields
Recheck Duplicate Policy
Create Opportunity
Create AuditEvent
Mark Mutation Executed
Mark Draft Converted
Commit

Again, validation happens at execution time.


77. Why Revalidate the Company?

The Company may have been:

deleted
archived
moved
made unavailable

between draft preparation and execution.

The fact that it existed earlier does not guarantee creation is still valid.


78. Why Revalidate the Draft?

We need to ensure:

confirmed values

still correspond to the draft state.

If the draft changed after preparation, reject the old MutationRequest.

Never create something different from what the user confirmed.


79. Transaction Boundary

The creation transaction should include:

BEGIN
create Opportunity
create AuditEvent
mark MutationRequest executed
mark OpportunityDraft converted
COMMIT

If any required step fails:

ROLLBACK

No partial business state should remain.


80. Generate Opportunity ID Server-Side

The new:

opportunity.id

is generated inside Quorentra.

Neither ChatGPT nor the widget chooses it.

The authoritative result returns it afterward.


81. Initial Version

New Opportunities begin with:

version = 1

This immediately makes them compatible with the optimistic concurrency architecture from Part 18.


82. Creation Audit Event

Create:

action =
opportunity.created

The event records:

organization_id
actor_user_id
entity_id
new_values
invocation_source
mutation_request_id
created_at

There are no old Opportunity values because the record did not previously exist.


83. Example Audit Event

Conceptually:

{
"action": "opportunity.created",
"entity_type": "opportunity",
"entity_id": "...",
"new_values": {
"company_id": "...",
"name": "Microsoft Copilot Deployment",
"amount": "120000.00",
"currency": "EUR",
"stage": "qualification",
"probability": 20,
"expected_close_date": "2026-11-30"
},
"invocation_source": "chatgpt_model"
}

Again, avoid storing unnecessary sensitive information.


84. Authoritative Result

After commit, return:

{
"success": true,
"mutation_request_id": "...",
"opportunity": {
"id": "...",
"company_id": "...",
"company_name": "Contoso",
"name": "Microsoft Copilot Deployment",
"amount": "120000.00",
"currency": "EUR",
"stage": "qualification",
"probability": 20,
"expected_close_date": "2026-11-30",
"version": 1
}
}

This is the record ChatGPT and the UI should trust.


85. Never Announce Creation Early

ChatGPT must not say:

I’ve created the opportunity.

after:

Draft complete

or:

Confirmation shown

It can only say that after:

create_opportunity

returns successful authoritative data.


86. Success UI

After successful creation:

┌────────────────────────────────────────────┐
│ QUORENTRA │
│ Opportunity Created │
│ │
│ Microsoft Copilot Deployment │
│ Contoso │
│ │
│ €120,000 │
│ Qualification · 20% │
│ │
│ Expected Close │
│ 30 November 2026 │
│ │
│ [View Opportunity] │
└────────────────────────────────────────────┘

This gives the user immediate confirmation and navigation.


87. Refresh Affected Views

Creating an Opportunity affects:

Opportunity List
Pipeline Summary
Stage Lists
Company Opportunity Count

At minimum, mark:

pipeline
opportunity list

as stale.

Reload them when the user returns.


88. Pipeline Changes Immediately

Unlike Part 18’s stage-only update, creating an Opportunity directly changes:

Open Opportunity Count
Total Pipeline
Weighted Pipeline

Therefore the old pipeline summary is definitely stale.

It must not remain presented as current indefinitely.


89. Example Pipeline Change

Before:

4 Opportunities
€385,000 Total
€161,000 Weighted

Create:

Microsoft Copilot Deployment
€120,000
20%

After:

5 Opportunities
€505,000 Total
€185,000 Weighted

because:

€120,000 × 20% = €24,000

and:

€161,000 + €24,000
= €185,000

The backend remains responsible for those calculations.


90. ChatGPT Follow-Up

After creation, ChatGPT can say:

Microsoft Copilot Deployment has been created for Contoso at €120,000, with an expected close date of November 30, 2026.

The user can then ask:

Show me the updated pipeline.

Quorentra retrieves fresh authoritative data.


91. One-Shot Creation

The conversational draft architecture does not mean every creation requires several turns.

Suppose the user says:

Create a €120,000 Microsoft Copilot Deployment opportunity for Contoso, expected to close November 30, 2026.

ChatGPT extracts all required information.

Quorentra creates a draft.

The draft immediately returns:

missing_fields = []

Then Quorentra can proceed directly to preparation and confirmation.


92. Best-Case Workflow

User gives complete intent
Create Draft
Draft Complete
Prepare Creation
Confirmation
Create

Only one user confirmation is required.

This makes conversational CRM faster than traditional form entry.


93. Incomplete Workflow

If information is missing:

User gives partial intent
Create Draft
Missing Fields
Ask User
Update Draft
Still Missing?
┌───┴────┐
Yes No
│ │
└─loop ▼
Prepare

The same architecture handles both simple and incomplete requests.


94. User Corrections

Suppose the user says:

Actually make that €125,000.

ChatGPT updates:

amount

in the draft.

It does not create a second draft unless necessary.

Conversational correction is one of the advantages of this model.


95. Explicit Field Provenance

A useful future enhancement is tracking where each draft value came from.

For example:

name
source = user
amount
source = user
currency
source = organization_default
stage
source = business_default
probability
source = stage_default

This can improve transparency and debugging.


96. Should We Add Provenance Now?

A lightweight provenance map is worthwhile.

Conceptually:

{
"field_sources": {
"name": "user",
"amount": "user",
"currency": "organization_default",
"stage": "business_default",
"probability": "stage_default",
"expected_close_date": "user"
}
}

This makes AI-assisted data capture more explainable.


97. Why Provenance Matters

Later we may want to know:

Which values did the user explicitly provide?
Which were defaults?
Which were extracted from CRM data?
Which were suggested by AI?
Which were confirmed?

For enterprise AI systems, provenance becomes increasingly valuable.


98. Do Not Treat AI Suggestions as Facts

Later, ChatGPT might suggest:

Based on similar opportunities, you may want to use a 40% probability.

That can be helpful.

But if accepted, the system should distinguish:

AI suggested
+
User accepted

from:

AI silently inserted

Part 19 avoids AI-generated business values entirely unless explicitly accepted.


99. Description Field

description can remain optional.

If the user supplies:

This is a 500-seat Copilot deployment including adoption services.

ChatGPT can capture that as:

description

If no description is supplied:

NULL

is acceptable.

Do not generate marketing prose just to fill the field.


100. Validation Layer

The draft service should validate each supplied value as soon as possible.

For example:

name
→ length validation
amount
→ Decimal validation
currency
→ supported currency validation
stage
→ OpportunityStage validation
probability
→ 0–100
expected_close_date
→ valid date

Early validation makes conversational correction easier.


101. Invalid Amount Example

User:

The opportunity is worth minus €20,000.

If negative Opportunities are not supported:

amount = -20000

fails.

ChatGPT can explain:

Quorentra requires the opportunity amount to be zero or greater. What amount should I use?

The backend produced the rule.

ChatGPT produced the conversational explanation.


102. Invalid Probability

User:

Set the probability to 130%.

Quorentra rejects it because:

0 <= probability <= 100

ChatGPT asks for a valid value.

Again, the model does not decide the business rule.


103. Unsupported Currency

If Quorentra only supports configured currencies and receives:

XYZ

the server returns a structured validation error.

The user can correct it.


104. Past Close Date

Should:

expected_close_date

be allowed in the past?

For open Opportunities, probably not.

Define this as a business rule.

For example:

new open Opportunity
expected_close_date >= today

unless importing historical data through another workflow.


105. Creation Rules Belong in the Domain

The ChatGPT interface should not contain:

if close_date < today

as the authoritative rule.

The application/domain layer validates it.

This ensures REST and future integrations behave identically.


106. Draft Validation Errors

Return structured errors such as:

{
"field": "expected_close_date",
"code": "DATE_IN_PAST",
"message": "Expected close date must not be in the past."
}

ChatGPT can turn this into a natural follow-up question.


107. Field-Level Errors Are Valuable

Instead of:

Invalid draft

return:

amount → required
expected_close_date → required
probability → invalid

This makes both UI and conversational repair much easier.


108. Draft UI

Although the workflow is conversation-first, the widget can also show the current draft.

For example:

┌────────────────────────────────────────────┐
│ QUORENTRA │
│ New Opportunity Draft │
│ │
│ Company Contoso │
│ Name Microsoft Copilot Deployment│
│ Amount — │
│ Currency EUR │
│ Stage Qualification │
│ Probability 20% │
│ Close Date — │
│ │
│ Missing: Amount, Close Date │
└────────────────────────────────────────────┘

This gives the user visual grounding.


109. Conversation and Widget Can Cooperate

The user might type:

€120,000, closing November 30.

ChatGPT updates the draft.

The widget automatically reflects:

Amount €120,000
Close Date 30 Nov 2026

This is an excellent example of:

Conversation
+
Structured UI

working together.


110. Do Not Build a Full Form Yet

We could make every draft field editable directly in React.

But that would move us back toward a conventional CRM form.

For the MVP, keep the widget focused on:

Review
Progress
Confirmation

while conversation handles most data entry.

Later we can add selective inline editing where useful.


111. Draft Tool Logging

Log:

tool_name
draft_id
organization_id
user_id
fields_changed
status
duration_ms

Avoid logging entire descriptions or sensitive business content unless operationally necessary.


112. Creation Mutation Logging

For final execution, log:

mutation_request_id
entity_id
actor_user_id
organization_id
invocation_source
result
duration_ms

The AuditEvent remains the authoritative business audit trail.

Operational logs and audit logs have different purposes.


113. Draft Repository Tests

Test:

create tenant-scoped draft
load own draft
cannot load other tenant draft
cannot load another user's draft
update draft
expire draft
cancel draft

114. Default Tests

Verify:

stage defaults to qualification
probability defaults correctly
currency defaults from organization
explicit stage overrides default
explicit probability overrides default
explicit currency overrides default

provided those explicit values are permitted.


115. Missing-Field Tests

Create a draft with only:

company_id

Expected:

missing_fields:
name
amount
expected_close_date

Then add:

name

Expected:

missing_fields:
amount
expected_close_date

Then complete the draft.

Expected:

missing_fields = []
status = complete

116. Company Resolution Tests

Test:

exact Company match
Company not found
ambiguous Company match
cross-tenant Company inaccessible
archived Company rejected if policy requires

These tests are important because entity resolution is part of creation safety.


117. Duplicate Tests

Create existing:

Contoso
Microsoft Copilot Deployment

Then prepare another draft with the same normalized name.

Expected:

potential duplicate warning

according to policy.

Do not silently create duplicates without awareness.


118. Permission Tests

Viewer:

create draft → denied
prepare creation → denied
execute creation → denied

Authorized Member:

create draft → allowed
prepare → allowed
execute → allowed

119. Permission Change Test

Authorized user creates and prepares a draft.

Before confirmation, permission changes to Viewer.

Execution:

denied

No Opportunity is created.

Again, authorization is checked at execution.


120. Tenant Isolation Tests

Tenant A must not:

use Tenant B Company
read Tenant B draft
update Tenant B draft
prepare Tenant B draft
execute Tenant B MutationRequest

Test every boundary.


121. Draft Ownership Tests

User A creates a draft.

User B in the same organization should not automatically be able to mutate or execute it.

Our MVP keeps drafts user-owned.

Collaborative drafts can come later.


122. Preparation Tests

Verify:

incomplete draft cannot prepare
expired draft cannot prepare
cancelled draft cannot prepare
invalid Company cannot prepare
complete valid draft can prepare
prepared MutationRequest matches exact draft

123. Edit-After-Prepare Test

Prepare:

Amount = €120,000

Then change the draft:

Amount = €125,000

Expected:

old MutationRequest invalidated

A new preparation is required.

This test protects confirmation integrity.


124. Execution Tests

Successful execution must:

create exactly one Opportunity
assign active tenant
assign resolved Company
use confirmed values
set version = 1
create AuditEvent
mark MutationRequest executed
mark Draft converted
return authoritative Opportunity

125. Idempotency Test

Execute the same MutationRequest twice.

Expected:

one Opportunity
one AuditEvent
one logical result

Never:

two duplicate Opportunities

This is particularly important for creation.


126. Transaction Failure Test

Simulate failure while creating AuditEvent.

Expected:

Opportunity creation rolled back
MutationRequest not executed
Draft not converted

The database remains consistent.


127. Company Deletion Race Test

Prepare creation for:

Contoso

Then make Contoso unavailable before execution.

Expected:

creation rejected

Do not create an Opportunity pointing at an invalid Company.


128. Duplicate Race

Two users may simultaneously prepare the same Opportunity.

If exact duplicates must be prohibited, enforce a suitable database/domain uniqueness strategy.

If duplicates are merely discouraged, warn but permit.

This is a product decision.

For the MVP, duplicate awareness without strict uniqueness is usually more practical.


129. Why Not Enforce Unique Opportunity Names?

A Company may legitimately have:

Microsoft 365 Migration

Opportunities in different years or business units.

Therefore:

company_id + opportunity_name

should not automatically become a database unique constraint.

Duplicate detection and uniqueness are not the same thing.


130. End-to-End Scenario 1

User:

Create a new opportunity for Contoso.

Expected:

Company resolved
Draft created
Defaults applied
Missing fields returned

No Opportunity exists yet.


131. Scenario 2: Complete the Draft

User:

Microsoft Copilot Deployment.

Then:

€120,000.

Then:

November 30, 2026.

Expected draft:

Company:
Contoso
Name:
Microsoft Copilot Deployment
Amount:
€120,000
Currency:
EUR
Stage:
Qualification
Probability:
20%
Expected Close:
30 November 2026
Status:
Complete

132. Scenario 3: Prepare

Quorentra calls:

prepare_opportunity_creation

Expected:

MutationRequest created
Confirmation rendered

Still:

0 new Opportunity rows

133. Scenario 4: Cancel

Click:

Cancel

Expected:

No Opportunity created
MutationRequest cancelled
Draft retained or cancelled according to policy

The user can safely abandon the operation.


134. Scenario 5: Confirm

Prepare again.

Click:

Create Opportunity

Expected:

1 Opportunity created
1 AuditEvent created
Draft converted
MutationRequest executed

The success widget renders.


135. Scenario 6: Verify Pipeline

Ask:

Show my EUR pipeline.

The new Opportunity must be reflected in:

Open Opportunity Count
Total Pipeline
Weighted Pipeline

This proves integration with the existing CRM.


136. Scenario 7: Complete One-Shot Request

User:

Create a €75,000 Azure Landing Zone opportunity for Fabrikam closing December 15, 2026.

Expected:

Company = Fabrikam
Name = Azure Landing Zone
Amount = 75000
Currency = EUR
Close Date = 2026-12-15
Stage = Qualification
Probability = 20%

The draft is complete immediately.

Quorentra proceeds to confirmation.


137. Scenario 8: Ambiguous Company

User:

Create an opportunity for Contoso.

Database:

Contoso Europe
Contoso Consulting

Expected:

No Company chosen
No final draft preparation
User clarification requested

Never select one arbitrarily.


138. Scenario 9: Missing Company

User:

Create an opportunity for Adventure Works.

No Company exists.

Expected:

Company not found

Quorentra can explain that the Company must first exist.

Later we will make Company creation conversational too.


139. Scenario 10: User Correction

User:

Create a €120,000 Copilot project for Contoso closing November 30.

Draft complete.

Then:

Actually make it €125,000.

Expected:

Draft amount updated
Any prepared mutation invalidated
New confirmation required

This proves conversational correction works safely.


140. The Emerging Conversational Data Entry Pattern

We now have a reusable pattern:

Natural Language
Extract Known Facts
Resolve References
Create Structured Draft
Apply Deterministic Defaults
Detect Missing Fields
Ask User
Update Draft
Validate
Prepare
Confirm
Execute

This pattern will later work for:

Companies
Contacts
Tasks
Activities
Meetings
Notes

141. Why This Is Better Than Giving the Model CRUD

A naive AI CRM might expose:

create_record(
table,
fields
)

and let the model decide what to send.

Quorentra instead exposes:

create_opportunity_draft
update_opportunity_draft
prepare_opportunity_creation
create_opportunity

These capabilities encode business semantics.

That is more verbose architecturally.

It is also far safer.


142. Domain-Specific Tools Beat Generic CRUD

Compare:

create_record
update_record
delete_record

with:

prepare_opportunity_creation
create_opportunity
update_opportunity_stage

The second group makes it easier to implement:

Business rules
Permissions
Confirmation
Audit
Tool descriptions
Testing
Observability

This is the direction Quorentra should continue taking.


143. ChatGPT Becomes an Intent Layer

At this stage, ChatGPT’s primary job is becoming clear.

It translates:

"Create a €120k Copilot deal for Contoso
closing at the end of November."

into:

Structured Business Intent

Quorentra then handles:

Identity
Tenant
Permissions
Defaults
Validation
Persistence
Audit

This division of responsibility is powerful.


144. The CRM Database Remains Authoritative

Even though the user may experience the workflow almost entirely through ChatGPT, authoritative state still lives in:

PostgreSQL

not:

Conversation history
Widget state
Model memory
Prompt context

That separation makes the system dependable.


145. Drafts Are Application State

This deserves emphasis.

A draft is:

temporary application state

but still application state.

It belongs in Quorentra.

This is different from merely remembering that the user mentioned:

€120,000

earlier in a conversation.


146. Future Draft Reuse

Later, users may be able to say:

Continue the Contoso opportunity I started yesterday.

Because drafts are persisted, Quorentra can find:

incomplete OpportunityDraft

and continue.

That would be difficult if all state existed only in conversation history.


147. Future Draft List

We may eventually expose:

list_my_opportunity_drafts

so ChatGPT can answer:

Do I have any unfinished opportunities?

But that is not required for Part 19.


148. Future AI Assistance

Once the basic workflow is safe, AI can provide optional assistance.

For example:

Based on the opportunity description, would you like me to suggest a concise opportunity name?

or:

Similar opportunities typically use the Proposal stage. Would you like to change it?

The key phrase is:

Would you like...

AI suggestions remain proposals until accepted.


149. Future CRM Intelligence

Eventually Quorentra may calculate:

Recommended probability
Expected close risk
Opportunity quality
Next best action
Stakeholder coverage
Competitive risk

But these belong to later intelligence modules.

Part 19 deliberately keeps creation deterministic and transparent.


150. Version Update

Part 19 adds conversational record creation.

Update:

app/core/constants.py

from:

APP_VERSION = "0.5.0"

to:

APP_VERSION = "0.6.0"

Quorentra now supports both:

Governed CRM updates

and:

Governed CRM creation

from ChatGPT.


151. Quorentra 0.6.0

Our MVP status becomes:

Platform
├── FastAPI ✓
├── PostgreSQL ✓
├── SQLAlchemy ✓
└── Alembic ✓
Identity
├── Organizations ✓
├── Users ✓
├── Memberships ✓
├── Authentication ✓
└── JWT ✓
Security
├── TenantContext ✓
├── Tenant Isolation ✓
├── RBAC ✓
├── Read Permissions ✓
├── Create Permissions ✓
└── Update Permissions ✓
CRM
├── Companies ✓
├── Contacts ✓
└── Opportunities ✓
Sales
├── Pipeline ✓
├── Opportunity Stages ✓
├── Probability ✓
└── Weighted Pipeline ✓
Interfaces
├── REST ✓
├── MCP ✓
└── ChatGPT ✓
ChatGPT UI
├── Pipeline Widget ✓
├── Opportunity List ✓
├── Opportunity Detail ✓
├── Mutation Confirmation ✓
├── Creation Confirmation ✓
└── Creation Result ✓
Mutation Governance
├── Mutation Requests ✓
├── Confirmation ✓
├── Expiry ✓
├── Cancellation ✓
├── Idempotency ✓
├── Transactions ✓
├── Optimistic Concurrency ✓
└── Audit Events ✓
Conversational Creation
├── Opportunity Drafts ✓
├── Company Resolution ✓
├── Missing-Field Detection ✓
├── Business Defaults ✓
├── Draft Validation ✓
├── Field Provenance ✓
├── Duplicate Awareness ✓
├── Multi-Turn Completion ✓
├── Draft Correction ✓
├── Prepared Creation ✓
└── Safe Opportunity Creation ✓
ChatGPT CRM Operations
├── Read Pipeline ✓
├── Read Opportunities ✓
├── Filter Opportunities ✓
├── View Opportunity ✓
├── Update Opportunity Stage ✓
├── Create Opportunity ✓
├── Create Company -
├── Create Contact -
├── Create Task -
└── Create Activity -
Activities -
Tasks -
AI Intelligence -

152. Acceptance Criteria

Part 19 is complete when:

✓ Part 18 regression suite remains green
✓ opportunities.create permission exists
✓ Viewer cannot create Opportunities
✓ authorized role can create drafts
✓ OpportunityDraft model exists
✓ OpportunityDraft migration applies
✓ drafts are tenant-scoped
✓ drafts are user-scoped
✓ drafts expire
✓ drafts support incomplete fields
✓ create_opportunity_draft exists
✓ update_opportunity_draft exists
✓ draft tools do not create Opportunities
✓ Company references resolve server-side
✓ exact Company match works
✓ ambiguous Company is not guessed
✓ missing Company is not auto-created
✓ cross-tenant Company cannot be used
✓ organization default currency is applied
✓ default stage is applied
✓ stage probability default is applied
✓ explicit valid values override defaults
✓ defaults are server-side
✓ required fields are server-defined
✓ missing_fields is returned
✓ incomplete draft remains incomplete
✓ complete draft becomes complete
✓ amount uses Decimal
✓ amount validation works
✓ currency normalization works
✓ probability validation works
✓ date validation works
✓ field-level errors are structured
✓ field provenance exists
✓ user values are distinguishable from defaults
✓ AI does not silently invent required business facts
✓ duplicate awareness exists
✓ potential duplicates can be surfaced
✓ duplicate awareness remains tenant-scoped
✓ prepare_opportunity_creation exists
✓ incomplete draft cannot prepare
✓ complete valid draft can prepare
✓ preparation does not create Opportunity
✓ MutationRequest contains exact proposed values
✓ confirmation expiry exists
✓ confirmation UI displays Company
✓ confirmation UI displays Opportunity name
✓ confirmation UI displays amount
✓ confirmation UI displays currency
✓ confirmation UI displays stage
✓ confirmation UI displays probability
✓ confirmation UI displays expected close date
✓ business defaults are visible
✓ CRM side effect is explicit
✓ Cancel does not create Opportunity
✓ editing after prepare invalidates old confirmation
✓ new confirmation is required after draft changes
✓ create_opportunity accepts mutation_request_id
✓ arbitrary client fields cannot replace confirmed values
✓ authentication is rechecked
✓ tenant is rechecked
✓ permission is rechecked
✓ MutationRequest status is rechecked
✓ expiry is rechecked
✓ draft is rechecked
✓ Company is rechecked
✓ values are revalidated
✓ Opportunity is created transactionally
✓ version starts at 1
✓ AuditEvent is created transactionally
✓ MutationRequest becomes executed
✓ OpportunityDraft becomes converted
✓ failure rolls everything back
✓ duplicate execution creates only one Opportunity
✓ duplicate execution creates only one AuditEvent
✓ retry returns the original logical result
✓ authoritative Opportunity is returned
✓ ChatGPT reports creation only after server success
✓ success UI uses authoritative result
✓ Opportunity list is invalidated after creation
✓ Pipeline summary is invalidated after creation
✓ fresh pipeline includes new Opportunity
✓ weighted pipeline reflects new Opportunity
✓ one-shot complete creation works
✓ multi-turn incomplete creation works
✓ user correction works
✓ ambiguous Company workflow works
✓ missing Company workflow works
✓ permission-change-before-execution is respected
✓ cross-tenant creation attempts fail
✓ Quorentra reports version 0.6.0

Most importantly:

A user can now describe a sales opportunity naturally, provide missing information conversationally, review the exact structured record Quorentra intends to create, explicitly confirm it, and create an authoritative tenant-safe CRM record without giving ChatGPT unrestricted CRUD authority.


153. What We Have Achieved

The Quorentra creation path now looks like:

Natural Language
ChatGPT
Extract Explicit Facts
Quorentra Draft
Resolve CRM References
Apply Business Defaults
Detect Missing Fields
Conversation
Complete Draft
Validate
Prepare Mutation
Confirmation
Create Opportunity
Audit
PostgreSQL
Authoritative Result

This is a major step toward a genuinely ChatGPT-native CRM.


154. The Difference From a Traditional CRM

Traditional CRM creation is primarily:

Navigate
Open Form
Populate Fields
Save

Quorentra can support:

Describe Intent
Review Structured Interpretation
Confirm

The underlying CRM discipline does not disappear.

In fact, it becomes more important.

Natural language is flexible.

Business data must remain precise.


155. Conversation Replaces Navigation, Not Governance

This distinction captures the architecture well:

Quorentra uses conversation to reduce navigation and data-entry friction, not to remove validation, authorization, or business rules.

The user should experience less CRM bureaucracy.

The backend should become more rigorous, not less.


156. The Next Missing Piece

We can now:

Create Opportunity
Update Opportunity Stage
Read Opportunity
List Opportunities
Analyze Pipeline

But the Opportunity must belong to an existing:

Company

If the Company does not exist, the workflow stops.

For a useful CRM MVP, that is the next limitation to remove.


157. Example

User:

Create a €90,000 Azure migration opportunity for Adventure Works.

Quorentra searches Companies.

Result:

Adventure Works
not found

Today we must stop.

But the natural next experience is:

Adventure Works isn’t in Quorentra yet. Would you like me to create the company first?

That introduces chained business operations.


158. Company Creation Has Different Fields

A Company might require:

Name
Website
Industry
Phone
Address
Country
Notes

But unlike an Opportunity, perhaps only:

Name

is mandatory for the MVP.

This gives us an opportunity to design a much lighter conversational creation workflow.


159. Chained Operations

Once Company creation exists, the original request:

Create a €90,000 Azure migration opportunity for Adventure Works.

could become:

Resolve Company
Not Found
Prepare Company Creation
Confirm
Create Company
Resume Opportunity Draft
Prepare Opportunity
Confirm
Create Opportunity

That is the beginning of multi-step conversational CRM workflows.


160. Next Article

In Part 20, we will build:

Creating Companies from ChatGPT — Entity Resolution, Duplicate Prevention, Conversational Creation, and Chained CRM Workflows

We will introduce:

Company creation permission
CompanyDraft
Company name normalization
Exact-match detection
Duplicate detection
Website/domain normalization
Optional Company enrichment
Missing-field detection
Business validation
Company creation confirmation
Prepared Company mutations
Idempotent Company creation
Creation audit events
Company result widgets
Tenant isolation
RBAC
Resume-after-create context
Opportunity draft dependency handling
Chained Company → Opportunity workflow

The target interaction will be:

User:
"Create a €90,000 Azure migration
opportunity for Adventure Works."

Quorentra determines:

Adventure Works
not found

and asks:

Adventure Works isn't currently in Quorentra.
Would you like to create the company first?

After confirmation:

Create Company
Company ID
Resume Opportunity Draft
€90,000 Azure Migration
Opportunity Confirmation
Create Opportunity

The resulting experience becomes:

Natural Language Request
Resolve Dependencies
Create Missing CRM Entity
Resume Original Intent
Create Dependent CRM Entity
Audit Both Operations

That will be our first multi-entity conversational business workflow in Quorentra.

And it will move us one step closer to the central vision of the series:

A modular CRM where ChatGPT provides the conversational operating layer, while Quorentra remains the secure, deterministic, tenant-aware system of record underneath.

Quorentra

Contact

Menu

Designed with WordPress

Discover more from Quorentra

Subscribe now to keep reading and get access to the full archive.

Continue reading