Quickstart
- SDK Installation & Setup Guide
- Platform Quickstarts
StateSet One
- Guides
StateSet Response
- Core Concepts
- Guides
- Getting Started
- Agent Development
- Features
- Integrations
- Advanced Features
- E-commerce Workflows
StateSet Commerce
- Guides
Agent Attributes & Personality
Design sophisticated agent personalities with dynamic attributes and behavioral patterns
Prerequisites
Before creating agent attributes, ensure you have:
Account & Setup
- StateSet account with API access
- At least one agent created in your StateSet workspace
- API credentials from the StateSet Dashboard
Technical Requirements
- Node.js 16+ installed (for SDK examples)
- Basic understanding of JavaScript and REST APIs
- Text editor or IDE for development
Domain Knowledge
- Familiarity with personality modeling and behavioral psychology concepts
- Understanding of your brand voice and customer interaction requirements
- Knowledge of customer service best practices and communication styles
Introduction
Agent Attributes are the building blocks of personality in StateSet. They define not just how your agents communicate, but who they are—their tone, expertise level, decision-making style, and behavioral patterns. This guide shows you how to create agents with distinct, adaptable personalities that align with your brand and customer needs.
What are Agent Attributes?
Agent Attributes are dynamic parameters that shape your agent’s behavior, communication style, and decision-making. Unlike static prompts, attributes can change in real-time based on context, allowing your agents to adapt their personality to different situations.
Core Concepts
Personality Traits
Define communication style, empathy level, and formality
Behavioral Patterns
Control decision-making, proactivity, and problem-solving approach
Dynamic Adaptation
Adjust attributes in real-time based on context and customer needs
Attribute Categories
1. Communication Style Attributes
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']
}
};
2. Behavioral Attributes
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'
}
}
};
3. Expertise Attributes
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']
}
};
Creating Dynamic Attributes
Basic Attribute Creation
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;
}
Advanced Attribute with Conditions
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;
}
Composite Personality Profiles
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;
}
}
Dynamic Attribute Adjustment
Real-time Adaptation
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;
}
}
Learning and Evolution
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)
};
}
}
Attribute Templates
Industry-Specific Templates
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;
}
Testing and Validation
Personality Consistency Testing
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;
}
}
A/B Testing Personalities
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'
});
}
}
Best Practices
1. Attribute Hierarchies
// 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
};
2. Context-Aware Defaults
// 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;
}
};
3. Attribute Validation
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;
}
}
Monitoring and Analytics
Attribute Performance Tracking
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;
}
Next Steps
Personality Templates
Pre-built personalities for common use cases
Emotional Intelligence
Build agents that understand and respond to emotions
Pro Tip: Start with a base personality and use conditional attributes to adapt to specific situations. This provides consistency while allowing flexibility.
For personality examples and templates, visit our GitHub repository or contact support@stateset.com.
- Prerequisites
- Introduction
- What are Agent Attributes?
- Core Concepts
- Attribute Categories
- 1. Communication Style Attributes
- 2. Behavioral Attributes
- 3. Expertise Attributes
- Creating Dynamic Attributes
- Basic Attribute Creation
- Advanced Attribute with Conditions
- Composite Personality Profiles
- Dynamic Attribute Adjustment
- Real-time Adaptation
- Learning and Evolution
- Attribute Templates
- Industry-Specific Templates
- Testing and Validation
- Personality Consistency Testing
- A/B Testing Personalities
- Best Practices
- 1. Attribute Hierarchies
- 2. Context-Aware Defaults
- 3. Attribute Validation
- Monitoring and Analytics
- Attribute Performance Tracking
- Next Steps