conversational 5-workflow flow on chat-ui + telegram · agent-runtime native
Sales rep chats freely across channels and days. The agent holds work-in-progress draft state in our Postgres; pushes the finalized proposal to Twendee ERP as a versioned ProposalDraft only when the rep attaches to a Deal. ERP also owns per-tenant config (rates, currency, T&C) via a new /settings/proposal-config endpoint.
Channels feed messages into a single API path. The proposal-builder skill mediates between
our durable draft store and ERP, with file blobs in a separate store and a manager-approval channel via
ConfirmationLedger.
Ctrl/Cmd + wheel = zoom · drag = pan · double-click = fit
addProposalDraft bumps a version each call — pushing on every W1–W4 save would create noisy versions. So the agent holds working state until W5 finalize, then pushes a single coherent draft. Subsequent revisions (post-feedback) push as new versions.
Hard line between agent-side state (volatile, conversational, attachment-heavy) and ERP-side records (canonical business entities, versioned artifacts, tenant policy).
| Concern | Our Postgres (agent) | Twendee ERP |
|---|---|---|
| WIP per-phase content | proposal_drafts.requirements_jsonscope_json · technical_json · cost_json |
— |
| Workflow phase & version | proposal_drafts.phase enum.version (optimistic lock) |
— |
| Owners / share access | proposal_drafts.owners[] (rep + invited co-owners/manager) |
— |
| Chat session → draft binding | chat_sessions.active_proposal_draft_id (nullable fk) |
— |
| Conversation history | messages (existing) |
— |
| RFP / brief uploads | attachments + blob in our store, signed URL |
— (no native file storage) |
| Final rendered docs | proposal_drafts.final_md / .final_docx_url / .final_pdf_url |
ProposalDraft.pdfUrl (reference only) |
| Company / Deal (canonical) | — | Companies, Deals |
| Published proposal versions | — | deals.addProposalDraft() · tagged JSON in deal comment · auto-inc version |
| Tenant config (rates, T&C, currency, approvers) | 5-min in-memory cache only | GET /settings/proposal-config (new this sprint) |
| Manager approval flow | approval_state + ConfirmationLedger pause/resume |
ProposalDraft.status moves: pending_rep_review → approval_required → sent |
One sales rep, multiple chat sessions (chat-ui Mon → Telegram Tue → fresh chat-ui Wed), one durable
proposal_drafts row, one ERP push at finalize.
Ctrl/Cmd + wheel = zoom · drag = pan
proposal_drafts is independent; chat_sessions.active_proposal_draft_id is a pointer), the rep can continue on Telegram, in a new chat-ui session, or even pass to a co-owner via shareProposal(). First turn of a new session detects intent and calls resumeProposal().