Design sophisticated agent personalities with dynamic attributes and behavioral patterns
const communicationAttributes = {
// Tone and Voice
formality: {
type: 'scale',
range: [0, 100],
description: 'How formal vs casual the agent communicates',
examples: {
0: "Hey! What's up? How can I help? 😊",
50: "Hello! How can I assist you today?",
100: "Good afternoon. How may I be of service?"
}
},
// Empathy and Emotional Intelligence
empathy_level: {
type: 'scale',
range: [0, 100],
description: 'How much emotional understanding the agent shows',
impact: {
low: 'Direct, solution-focused responses',
medium: 'Acknowledges feelings while solving problems',
high: 'Deeply validates emotions before addressing issues'
}
},
// Communication Preferences
verbosity: {
type: 'enum',
values: ['concise', 'balanced', 'detailed'],
description: 'How much detail to include in responses',
use_cases: {
concise: 'Quick answers for simple questions',
balanced: 'Standard customer service',
detailed: 'Technical support or complex issues'
}
},
// Language Complexity
language_level: {
type: 'enum',
values: ['simple', 'standard', 'professional', 'technical'],
description: 'Vocabulary and sentence complexity',
adapts_to: ['customer_profile', 'topic_complexity']
}
};
const behavioralAttributes = {
// Decision Making
autonomy_level: {
type: 'scale',
range: [0, 100],
description: 'How independently the agent makes decisions',
thresholds: {
0: 'Always asks for confirmation',
30: 'Handles routine tasks independently',
70: 'Makes most decisions autonomously',
100: 'Full autonomy within defined bounds'
}
},
// Problem Solving Approach
solution_style: {
type: 'enum',
values: ['step_by_step', 'quick_fix', 'comprehensive', 'educational'],
description: 'How the agent approaches problem resolution',
when_to_use: {
step_by_step: 'Complex technical issues',
quick_fix: 'Simple, common problems',
comprehensive: 'VIP customers or critical issues',
educational: 'First-time users or learning opportunities'
}
},
// Proactivity
proactivity: {
type: 'scale',
range: [0, 100],
description: 'How proactive vs reactive the agent is',
behaviors: {
low: 'Answers only what is asked',
medium: 'Suggests related solutions',
high: 'Anticipates needs and offers preventive advice'
}
}
};
const expertiseAttributes = {
// Domain Knowledge
domain_expertise: {
type: 'multi_select',
values: ['product', 'technical', 'billing', 'shipping', 'legal'],
description: 'Areas where the agent has deep knowledge',
confidence_modifiers: {
expert: 1.0,
familiar: 0.7,
basic: 0.4
}
},
// Technical Depth
technical_level: {
type: 'scale',
range: [0, 100],
description: 'How technical the agent can get',
auto_adjust: true,
based_on: ['customer_technical_level', 'topic_complexity']
},
// Industry Specialization
industry_focus: {
type: 'enum',
values: ['retail', 'saas', 'healthcare', 'finance', 'general'],
description: 'Industry-specific knowledge and compliance',
includes: ['terminology', 'regulations', 'best_practices']
}
};
import { StateSetClient } from 'stateset-node';
const client = new StateSetClient({
apiKey: process.env.STATESET_API_KEY
});
async function createBasicAttribute(agentId) {
const attribute = await client.attributes.create({
agent_id: agentId,
type: 'personality',
name: 'friendliness',
description: 'How warm and friendly the agent appears',
value_type: 'scale',
default_value: 75,
range: {
min: 0,
max: 100
},
impact: {
greeting: 'Affects warmth of initial greeting',
sign_off: 'Influences closing statements',
emoji_usage: 'Controls emoji frequency'
}
});
return attribute;
}
async function createConditionalAttribute(agentId) {
const attribute = await client.attributes.create({
agent_id: agentId,
type: 'behavioral',
name: 'urgency_response',
description: 'How the agent responds to urgent situations',
// Dynamic value based on conditions
value_logic: {
type: 'conditional',
conditions: [
{
if: 'ticket.priority === "critical"',
then: { urgency: 100, response_time: 'immediate' }
},
{
if: 'customer.tier === "vip" && ticket.priority === "high"',
then: { urgency: 90, response_time: '5_minutes' }
},
{
if: 'ticket.age > 24_hours',
then: { urgency: 'urgency + 20', response_time: '30_minutes' }
}
],
default: { urgency: 50, response_time: '2_hours' }
},
// How this affects behavior
behaviors: {
high_urgency: [
'Skip pleasantries',
'Get to solution immediately',
'Offer immediate escalation option',
'Follow up proactively'
],
low_urgency: [
'Full greeting and rapport building',
'Thorough explanation',
'Educational approach'
]
}
});
return attribute;
}
class PersonalityBuilder {
async createPersonalityProfile(agentId, profileType) {
const profiles = {
technical_expert: {
formality: 70,
empathy: 50,
technical_depth: 95,
verbosity: 'detailed',
solution_style: 'educational',
proactivity: 80,
emoji_usage: 0,
code_examples: true
},
friendly_support: {
formality: 20,
empathy: 90,
technical_depth: 40,
verbosity: 'balanced',
solution_style: 'step_by_step',
proactivity: 70,
emoji_usage: 80,
humor_allowed: true
},
enterprise_account_manager: {
formality: 90,
empathy: 70,
technical_depth: 60,
verbosity: 'concise',
solution_style: 'comprehensive',
proactivity: 95,
business_focus: true,
upsell_awareness: 80
},
crisis_manager: {
formality: 60,
empathy: 85,
urgency: 100,
verbosity: 'concise',
solution_style: 'quick_fix',
escalation_threshold: 20,
calm_reassurance: true
}
};
const profile = profiles[profileType];
const attributes = [];
for (const [name, value] of Object.entries(profile)) {
const attr = await client.attributes.create({
agent_id: agentId,
name,
value,
profile_group: profileType
});
attributes.push(attr);
}
return attributes;
}
}
class DynamicPersonality {
constructor(agentId) {
this.agentId = agentId;
this.baselineAttributes = {};
this.currentAttributes = {};
}
async adaptToContext(context) {
const adjustments = this.calculateAdjustments(context);
for (const [attribute, adjustment] of Object.entries(adjustments)) {
await this.updateAttribute(attribute, adjustment);
}
}
calculateAdjustments(context) {
const adjustments = {};
// Adjust formality based on customer
if (context.customer.age > 60) {
adjustments.formality = 20; // More formal
} else if (context.customer.age < 25) {
adjustments.formality = -20; // Less formal
}
// Adjust empathy based on sentiment
if (context.sentiment === 'angry') {
adjustments.empathy = 30;
adjustments.patience = 40;
}
// Adjust technical level based on customer knowledge
if (context.customer.technical_score > 80) {
adjustments.technical_depth = 30;
adjustments.verbosity = 'detailed';
}
// Adjust urgency based on issue type
if (context.issue.type === 'outage') {
adjustments.urgency = 50;
adjustments.solution_style = 'quick_fix';
}
return adjustments;
}
async updateAttribute(name, adjustment) {
const current = this.currentAttributes[name] || this.baselineAttributes[name];
let newValue;
if (typeof adjustment === 'number') {
newValue = Math.max(0, Math.min(100, current + adjustment));
} else {
newValue = adjustment;
}
await client.attributes.update({
agent_id: this.agentId,
name,
value: newValue
});
this.currentAttributes[name] = newValue;
}
}
class EvolvingPersonality {
async learnFromInteraction(agentId, conversation) {
const feedback = await this.analyzeConversation(conversation);
// Identify successful patterns
if (feedback.satisfaction_score > 4.5) {
await this.reinforceAttributes(agentId, conversation.attributes);
}
// Identify areas for improvement
if (feedback.escalated || feedback.satisfaction_score < 3) {
await this.adjustWeakAttributes(agentId, feedback.issues);
}
// Update long-term personality trends
await this.updatePersonalityTrends(agentId, feedback);
}
async reinforceAttributes(agentId, successfulAttributes) {
for (const [attr, value] of Object.entries(successfulAttributes)) {
await client.attributes.updateTrend({
agent_id: agentId,
attribute: attr,
trend_direction: 'towards',
target_value: value,
learning_rate: 0.1
});
}
}
async analyzeConversation(conversation) {
return {
satisfaction_score: conversation.rating,
escalated: conversation.escalated,
resolution_time: conversation.duration,
sentiment_progression: this.analyzeSentiment(conversation),
successful_tactics: this.identifySuccessfulTactics(conversation)
};
}
}
const industryTemplates = {
healthcare: {
attributes: {
compliance_awareness: 100,
empathy: 85,
privacy_consciousness: 100,
medical_terminology: true,
formality: 70
},
restricted_behaviors: ['humor', 'medical_advice'],
required_confirmations: ['patient_identity', 'consent']
},
financial_services: {
attributes: {
accuracy_focus: 100,
regulatory_compliance: 100,
formality: 80,
numerical_precision: true,
security_awareness: 95
},
audit_trail: true,
pii_handling: 'strict'
},
e_commerce: {
attributes: {
sales_awareness: 70,
product_knowledge: 90,
friendliness: 80,
urgency_creation: 60,
visual_description: true
},
upsell_enabled: true,
abandoned_cart_recovery: true
},
saas_technical: {
attributes: {
technical_depth: 85,
problem_solving: 'systematic',
documentation_reference: true,
code_literacy: 90,
patience: 80
},
integration_knowledge: true,
api_fluency: true
}
};
async function applyIndustryTemplate(agentId, industry) {
const template = industryTemplates[industry];
if (!template) {
throw new Error(`Unknown industry: ${industry}`);
}
// Apply all attributes
for (const [name, value] of Object.entries(template.attributes)) {
await client.attributes.create({
agent_id: agentId,
name,
value,
category: 'industry_standard',
locked: true // Prevent accidental changes
});
}
// Apply behavioral restrictions
if (template.restricted_behaviors) {
await client.agents.updateRestrictions({
agent_id: agentId,
restrictions: template.restricted_behaviors
});
}
return template;
}
class PersonalityTester {
async testConsistency(agentId, scenarios) {
const results = [];
for (const scenario of scenarios) {
const response = await this.runScenario(agentId, scenario);
const analysis = await this.analyzeResponse(response, scenario.expected_attributes);
results.push({
scenario: scenario.name,
consistency_score: analysis.consistency,
attribute_alignment: analysis.alignment,
deviations: analysis.deviations
});
}
return {
overall_consistency: this.calculateOverallConsistency(results),
recommendations: this.generateRecommendations(results)
};
}
async runScenario(agentId, scenario) {
return client.agents.test({
agent_id: agentId,
input: scenario.input,
context: scenario.context,
expected_attributes: scenario.expected_attributes
});
}
analyzeResponse(response, expectedAttributes) {
const analysis = {
consistency: 0,
alignment: {},
deviations: []
};
// Check each expected attribute
for (const [attr, expected] of Object.entries(expectedAttributes)) {
const actual = this.measureAttribute(response, attr);
const deviation = Math.abs(actual - expected);
analysis.alignment[attr] = {
expected,
actual,
deviation
};
if (deviation > 20) {
analysis.deviations.push({
attribute: attr,
severity: 'high',
recommendation: `Adjust ${attr} baseline or add conditional logic`
});
}
}
analysis.consistency = 100 - (analysis.deviations.length * 10);
return analysis;
}
}
class PersonalityABTest {
async runTest(agentId, variantA, variantB, duration) {
const test = await client.experiments.create({
type: 'personality_test',
agent_id: agentId,
variants: {
control: variantA,
treatment: variantB
},
metrics: ['satisfaction_score', 'resolution_time', 'escalation_rate'],
duration,
traffic_split: 50
});
// Monitor results
const monitor = setInterval(async () => {
const results = await client.experiments.getResults(test.id);
if (results.significant) {
await this.applyWinner(agentId, results.winner);
clearInterval(monitor);
}
}, 3600000); // Check hourly
return test;
}
async applyWinner(agentId, winningVariant) {
await client.attributes.bulkUpdate({
agent_id: agentId,
attributes: winningVariant.attributes,
source: 'ab_test_winner'
});
}
}
// Good: Clear hierarchy and relationships
const attributeHierarchy = {
communication: {
parent: null,
children: ['tone', 'formality', 'verbosity'],
weight: 1.0
},
tone: {
parent: 'communication',
children: ['friendliness', 'professionalism', 'empathy'],
weight: 0.8
},
friendliness: {
parent: 'tone',
children: ['emoji_usage', 'casual_language'],
weight: 0.6,
constraints: {
max_if: { formality: '> 80', value: 30 }
}
}
};
// Bad: Conflicting flat attributes
const flatAttributes = {
friendly: 100,
formal: 100, // Conflicts with friendly
professional: 0 // Conflicts with formal
};
// Good: Dynamic defaults based on context
const contextAwareDefaults = {
getDefaultAttributes(context) {
const defaults = { ...this.baseDefaults };
// Time-based adjustments
const hour = new Date().getHours();
if (hour < 9 || hour > 17) {
defaults.formality -= 10;
defaults.brevity += 20;
}
// Channel-based adjustments
if (context.channel === 'sms') {
defaults.verbosity = 'concise';
defaults.emoji_usage = 0;
} else if (context.channel === 'chat') {
defaults.response_speed = 'quick';
defaults.emoji_usage = 40;
}
return defaults;
}
};
class AttributeValidator {
validateAttributes(attributes) {
const errors = [];
// Check for conflicts
if (attributes.friendliness > 80 && attributes.formality > 80) {
errors.push({
type: 'conflict',
message: 'High friendliness conflicts with high formality',
suggestion: 'Consider professional_warmth instead'
});
}
// Check for missing required attributes
const required = ['empathy', 'clarity', 'helpfulness'];
for (const req of required) {
if (!(req in attributes)) {
errors.push({
type: 'missing',
attribute: req,
message: `Required attribute ${req} is missing`
});
}
}
// Check value ranges
for (const [attr, value] of Object.entries(attributes)) {
if (typeof value === 'number' && (value < 0 || value > 100)) {
errors.push({
type: 'range',
attribute: attr,
message: `${attr} value ${value} is out of range [0-100]`
});
}
}
return errors;
}
}
async function trackAttributePerformance(agentId) {
const metrics = await client.attributes.getPerformanceMetrics({
agent_id: agentId,
timeframe: '30d',
group_by: 'attribute'
});
const insights = {
high_impact: metrics.filter(m => m.correlation_with_satisfaction > 0.7),
low_impact: metrics.filter(m => m.correlation_with_satisfaction < 0.3),
optimal_ranges: {},
recommendations: []
};
// Find optimal ranges
for (const metric of metrics) {
const optimal = metric.satisfaction_by_value.reduce((best, current) =>
current.satisfaction > best.satisfaction ? current : best
);
insights.optimal_ranges[metric.attribute] = {
range: optimal.value_range,
satisfaction: optimal.satisfaction
};
}
return insights;
}