Skip to main content

Agent Builder — Developer Guide

The Agent Builder replaces the old BotConfigPage with an 8-tab configuration experience. It extends the BotConfiguration Prisma model with ~35 new fields and enhances the 3-step conversation brain pipeline to use all configured values.


Architecture​

┌─────────────────────────────────────────────┐
│ AgentBuilderPage.tsx (tab container) │
│ ┌──────┬──────┬──────┬──────┬──────┬────┐ │
│ │Ident │Know │Sales │Supp │Media │... │ │
│ └──┬───┴──┬───┴──┬───┴──┬───┴──┬───┴────┘ │
│ └──────┴──────┴──────┴──────┘ │
│ ▼ single state object │
│ BotConfiguration │
│ ▼ PUT /ice/bot-config │
└─────────────────────────────────────────────┘
▼
┌─────────────────────────────────────────────┐
│ conversation-brain.service.ts │
│ buildAgentContextSections(botConfig) │
│ ┌──────────┐ ┌──────────┐ ┌────────────┐ │
│ │decideAct │→│generateRe│→│compliance │ │
│ │ion │ │ply │ │Filter │ │
│ └──────────┘ └──────────┘ └────────────┘ │
└─────────────────────────────────────────────┘

Key design decisions:

  • Single state object: All 8 tabs modify one BotConfiguration. No intermediate saves.
  • No new API endpoints: The existing GET/PUT /ice/bot-config handles everything via generic upsert (Record<string, unknown> + as any cast).
  • Brain integration via buildAgentContextSections(): A typed helper extracts all config into prompt sections, keeping the pipeline functions clean.

Schema (Prisma)​

New fields added to the BotConfiguration model, organized by section:

Identity & Personality​

FieldTypeDescription
agentNameString?Display name for the AI agent
agentAvatarString?Avatar URL
systemPromptString?Master instruction prompt (up to 5000 chars)
personalityJson?AgentPersonality — humor, formality, emojiUsage, verbosity (0-100 each)
supportedLanguagesString[]ISO language codes the agent supports
autoDetectLanguageBooleanAuto-detect customer language (default: true)

Business Knowledge​

FieldTypeDescription
companyDescriptionString?Company story for context
businessPoliciesJson?AgentPolicies — return, refund, shipping, warranty
storeLocationsJson?StoreLocation[] — id, name, address, phone, hours, lat/lng
customInstructionsString?Additional directives
documentUrlsString[]URLs to external knowledge documents
pricingRulesJson?AgentPricingRules — canQuotePrices, currency, showTax

Sales & Commerce​

FieldTypeDescription
salesEnabledBooleanMaster sales toggle
connectedStoreIdsString[]Linked e-commerce store IDs
maxDiscountPercentFloat?Max autonomous discount
allowedPromoCodesString[]Whitelisted promo codes
upsellRulesJson?UpsellRule[] — trigger + message
bundleOffersJson?BundleOffer[] — name, discount, description
discountAuthorityJson?DiscountAuthority — enabled, max %, max fixed, currency
crossSellEnabledBooleanEnable cross-sell suggestions
cartBuildingEnabledBooleanEnable in-chat cart building
cartAbandonmentEnabledBooleanEnable cart abandonment follow-ups
commentToPurchaseFlowBooleanEnable comment-to-purchase
leadQualificationJson?LeadQualification — enabled, scoringThreshold
closingTechniquesJson?ClosingTechniques — urgency, socialProof, scarcity
objectionHandlingJson?ObjectionHandler[] — objection, response, category

Support & Problem Solving​

FieldTypeDescription
complaintFlowsJson?ComplaintFlow[] — trigger + step toggles
refundAuthorityJson?RefundAuthority — enabled, maxAmount, approvalAbove, currency
shippingIssueHandlingJson?ShippingIssueHandling — autoLookup, offerCompensation, maxCompensation
approvalWorkflowIdString?Linked approval workflow
handoffProtocolJson?HandoffProtocol — message, assignToRole, preserveTranscript
followUpSchedulingJson?FollowUpScheduling — enabled, delayHours, maxFollowUps
conversationGoalsString[]Goal tags (convert_to_sale, resolve_complaint, etc.)

Media & Rich Content​

FieldTypeDescription
voiceEnabledBooleanProcess voice messages
voiceLanguagesString[]Transcription language codes
voiceReplyFormatStringtext, voice, or both (default: text)
imageEnabledBooleanProcess images
imageUseCasesString[]product_lookup, damage_detection, receipt_parse, visual_search
videoEnabledBooleanProcess video
videoMaxDurationInt?Max video length in seconds
locationEnabledBooleanProcess location pins
documentEnabledBooleanProcess document attachments
documentTypesString[]receipt, invoice, warranty_card, id
unsupportedMediaMessageString?Fallback for unsupported media

Platform-Specific Behavior​

FieldTypeDescription
platformBehaviorsJson?Record<string, PlatformBehavior> — per-platform config

Each PlatformBehavior contains: enabled, toneOverride, maxReplyLength, features (object of boolean toggles).

Safety (Extended)​

FieldTypeDescription
neverSayPhrasesString[]Forbidden words/phrases
actionsRequiringApprovalJson?ApprovalAction[] — action, threshold, approverRole
dataPrivacyRulesJson?DataPrivacyRules — canReference flags, gdprMode, dataRetentionDays
industryComplianceJson?IndustryCompliance — type, restrictions, disclaimers
auditTrailEnabledBooleanEnable audit logging (default: true)

Shared Types​

All types are in packages/shared/src/types/ice.types.ts and exported from packages/shared/src/index.ts.

Key interfaces: AgentPersonality, AgentPolicies, StoreLocation, AgentPricingRules, UpsellRule, BundleOffer, DiscountAuthority, LeadQualification, ClosingTechniques, ObjectionHandler, ComplaintFlow, RefundAuthority, ShippingIssueHandling, HandoffProtocol, FollowUpScheduling, PlatformBehavior, ApprovalAction, DataPrivacyRules, IndustryCompliance.

Type aliases: VoiceReplyFormat, ImageUseCase, DocumentParseType.


Zod Validators​

Extended validators in packages/shared/src/validators/ice.schema.ts:

// Example: personality validator
personality: z.object({
humor: z.number().min(0).max(100),
formality: z.number().min(0).max(100),
emojiUsage: z.number().min(0).max(100),
verbosity: z.number().min(0).max(100),
}).optional(),

// Example: store location validator
storeLocations: z.array(z.object({
id: z.string(),
name: z.string(),
address: z.string(),
phone: z.string().optional(),
hours: z.string().optional(),
lat: z.number().optional(),
lng: z.number().optional(),
})).optional(),

All new fields are .optional() or .nullable() to maintain backward compatibility.


Brain Pipeline Integration​

The conversation-brain.service.ts uses a buildAgentContextSections() helper to extract all Agent Builder config into typed prompt sections:

function buildAgentContextSections(bc: Record<string, unknown>) {
const str = (key: string) => (typeof bc[key] === 'string' ? bc[key] as string : '');
const json = (key: string) => {
const v = bc[key];
return v && typeof v === 'object' ? JSON.stringify(v) : '';
};
// ... returns sections object
}

decideAction — Injected Sections​

  • System prompt and company description
  • Custom instructions
  • Business policies (JSON)
  • Upsell rules and discount authority
  • Objection handling playbook
  • Complaint flows and refund authority
  • Conversation goals
  • Media capabilities (voice, images, video)
  • Closing techniques

generateReply — Injected Sections​

  • Personality sliders (Humor=80/100, Formality=20/100, etc.)
  • Supported languages with auto-detect flag
  • Platform-specific tone override and max reply length
  • Handoff protocol
  • Closing techniques

complianceFilter — Injected Rules​

  • Never-say phrases with NEVER use these words directive
  • Data privacy rules (what data can/cannot be referenced)
  • Industry compliance restrictions and disclaimers
  • Three additional filter rules (Rules 7, 8, 9)

Frontend Architecture​

Tab Container — AgentBuilderPage.tsx​

apps/web/src/pages/conversation-engine/
├── AgentBuilderPage.tsx # Main container with 8 tabs
├── agent-builder/
│ ├── IdentityTab.tsx # Persona, personality, languages, settings
│ ├── KnowledgeTab.tsx # Company story, policies, FAQ, locations
│ ├── SalesTab.tsx # Commerce, discounts, upsell, bundles
│ ├── SupportTab.tsx # Objections, complaints, refunds, handoff
│ ├── MediaTab.tsx # Voice, images, video, documents
│ ├── PlatformsTab.tsx # Per-platform behavior cards
│ ├── PerformanceTab.tsx # Stats dashboard
│ └── SafetyTab.tsx # Blocked topics, privacy, compliance
└── __tests__/
└── AgentBuilderPage.test.tsx # 6 tests

State pattern: AgentBuilderPage loads the config once via iceApi.getBotConfig(), holds it in useState, and passes config + onChange to each tab. Tabs call onChange(partialUpdates) which merges into the parent state. A single Save button calls iceApi.updateBotConfig(config).

Dirty tracking: The page tracks whether any changes have been made since load, showing an unsaved indicator dot and disabling/enabling the save button accordingly.

Route Registration​

In apps/web/src/routes/index.tsx, the old BotConfigPage import was replaced:

import { AgentBuilderPage } from '@/pages/conversation-engine/AgentBuilderPage';
// Route element: <AgentBuilderPage />

API​

No new endpoints. The existing endpoints handle all Agent Builder data:

MethodEndpointDescription
GET/ice/bot-configFetch full BotConfiguration
PUT/ice/bot-configUpsert with partial updates

The updateBotConfig service uses Record<string, unknown> + as any for the Prisma upsert, so all new fields pass through automatically without backend changes.


i18n​

All strings use the ice namespace:

  • pages.ice.agentBuilder.tabs.* — Tab labels
  • pages.ice.agentBuilder.identity.* — Identity tab
  • pages.ice.agentBuilder.knowledge.* — Knowledge tab
  • pages.ice.agentBuilder.sales.* — Sales tab
  • pages.ice.agentBuilder.support.* — Support tab
  • pages.ice.agentBuilder.media.* — Media tab
  • pages.ice.agentBuilder.platforms.* — Platforms tab
  • pages.ice.agentBuilder.performance.* — Performance tab
  • pages.ice.agentBuilder.safety.* — Safety tab

Both en/ice.json and ar/ice.json are fully translated (~200 new keys each).


Tests​

Backend — conversation-brain.service.test.ts (9 tests)​

  1. Successful 3-step pipeline returns reply text
  2. Heuristic fallback when LLM call fails
  3. System prompt injection into decision prompt
  4. Company description injection
  5. Never-say phrases in compliance filter
  6. Objection handling in decision prompt
  7. Media capabilities in decision prompt
  8. Heuristic fallback for unparseable LLM response
  9. Personality sliders in generation prompt

Frontend — AgentBuilderPage.test.tsx (6 tests)​

  1. Renders agent builder with tabs
  2. All 8 tab buttons displayed
  3. Identity tab shown by default
  4. Master enable toggle present
  5. Save button present
  6. Back link present

Migration​

After deploying, run the Prisma migration to add all new fields:

cd apps/api
npx prisma migrate dev --name agent_builder_fields

All new fields are optional with sensible defaults, so existing BotConfiguration rows remain valid.