Skip to main content

addToAgentState

codebolt.cbstate.addToAgentState(key: string, value: string): Promise<AddToAgentStateResponse>

Adds a key-value pair to the agent's state on the server via WebSocket.

Parameters

  • key (string): The key to add to the agent's state.
  • value (string): The value associated with the key.

Returns

  • Promise<AddToAgentStateResponse>: A promise that resolves with the response to the addition request containing success status.

Response Structure

The method returns a Promise that resolves to an AddToAgentStateResponse object with the following properties:

  • type (string): Always "addToAgentStateResponse".
  • payload (object, optional): Contains the response data including:
    • success (boolean): Indicates if the operation was successful.
  • success (boolean, optional): Indicates if the operation was successful.
  • message (string, optional): A message with additional information.
  • error (string, optional): Error details if the operation failed.
  • messageId (string, optional): A unique identifier for the message.
  • threadId (string, optional): The thread identifier.

What is addToAgentState?

The addToAgentState function allows you to store temporary information that's specific to your current agent session. Think of it as a temporary storage system where you can save data that only needs to exist while your agent is running.

Key Points:

  • 🤖 Agent-specific storage - Data is only available to the current agent session
  • ⏱️ Temporary - Information is cleared when the agent session ends
  • 🔄 Session-based - Perfect for storing temporary settings and session data
  • 📝 String values only - All values must be stored as strings

When to Use This

Use addToAgentState when you need to:

  • Store temporary user preferences for the current session
  • Keep track of the agent's current status or progress
  • Save session-specific configuration
  • Store temporary data that doesn't need to persist after the agent stops

Basic Usage

Simple Example - Store User Preference

// Save a user's theme preference for this session
const result = await codebolt.cbstate.addToAgentState('user_preference', 'dark_theme');
console.log('Response:', result);
// Output: { type: 'addToAgentStateResponse', payload: { sucess: true } }

Store Different Types of Session Data

// Store session ID
await codebolt.cbstate.addToAgentState('session_id', 'sess_' + Date.now());

// Store user language preference
await codebolt.cbstate.addToAgentState('user_language', 'en');

// Store debug mode setting
await codebolt.cbstate.addToAgentState('debug_mode', 'true');

// Store current timestamp
await codebolt.cbstate.addToAgentState('last_activity', new Date().toISOString());

// Store current step in a process
await codebolt.cbstate.addToAgentState('current_step', '3');

Working with Complex Data

Since agent state only accepts strings, you'll need to convert objects and arrays to JSON strings:

// Store user preferences as JSON
const userPreferences = {
theme: 'dark',
notifications: true,
autoSave: false,
language: 'en'
};
await codebolt.cbstate.addToAgentState('user_preferences', JSON.stringify(userPreferences));

// Store a list of completed tasks
const completedTasks = ['task1', 'task2', 'task3'];
await codebolt.cbstate.addToAgentState('completed_tasks', JSON.stringify(completedTasks));

// Store configuration settings
const agentConfig = {
maxRetries: 3,
timeout: 5000,
enableLogging: true
};
await codebolt.cbstate.addToAgentState('agent_config', JSON.stringify(agentConfig));

Complete Example - Agent Session Setup

Here's how you might set up an agent session with various state data:

async function setupAgentSession() {
try {
// Basic session info
await codebolt.cbstate.addToAgentState('session_id', 'sess_' + Date.now());
await codebolt.cbstate.addToAgentState('user_language', 'en');
await codebolt.cbstate.addToAgentState('debug_mode', 'false');

// User preferences
const preferences = {
theme: 'dark',
notifications: true,
autoComplete: true
};
await codebolt.cbstate.addToAgentState('user_preferences', JSON.stringify(preferences));

// Track session start time
await codebolt.cbstate.addToAgentState('session_start', new Date().toISOString());

// Initialize progress tracking
await codebolt.cbstate.addToAgentState('current_step', '1');
await codebolt.cbstate.addToAgentState('total_steps', '5');

console.log('✅ Agent session setup complete!');
} catch (error) {
console.error('❌ Session setup failed:', error);
}
}

// Run the setup
setupAgentSession();

Error Handling

Always handle potential errors when adding to agent state:

async function addToAgentStateSafely(key, value) {
try {
const result = await codebolt.cbstate.addToAgentState(key, value);

if (result.payload.sucess) { // Note: 'sucess' is the actual field name
console.log(`✅ Successfully added ${key} to agent state`);
return true;
} else {
console.log(`⚠️ Unexpected response:`, result);
return false;
}
} catch (error) {
console.error(`❌ Failed to add ${key}:`, error.message);
return false;
}
}

// Usage
const success = await addToAgentStateSafely('user_status', 'active');
if (success) {
console.log('State update confirmed!');
}

Adding Multiple Items

When you need to add several items to agent state:

async function addMultipleToAgentState() {
const stateItems = [
{ key: 'session_id', value: 'sess_' + Date.now() },
{ key: 'user_language', value: 'en' },
{ key: 'debug_mode', value: 'true' },
{ key: 'last_activity', value: new Date().toISOString() }
];

console.log('Adding items to agent state...');

for (const item of stateItems) {
try {
const result = await codebolt.cbstate.addToAgentState(item.key, item.value);
if (result.payload.sucess) {
console.log(`${item.key}: ${item.value}`);
}
} catch (error) {
console.error(`❌ Failed to add ${item.key}:`, error.message);
}
}

console.log('Agent state setup complete!');
}

addMultipleToAgentState();

Response Format

When you call addToAgentState, you'll get back a response like this:

{
type: 'addToAgentStateResponse',
payload: {
sucess: true // Note: 'sucess' is the actual field name (not 'success')
}
}

Advanced Usage Patterns

Pattern 1: State Machine Implementation

class AgentStateMachine {
constructor() {
this.states = ['idle', 'processing', 'completed', 'error'];
}

async transition(newState, metadata = {}) {
if (!this.states.includes(newState)) {
throw new Error(`Invalid state: ${newState}`);
}

// Store state transition
await codebolt.cbstate.addToAgentState('current_state', newState);
await codebolt.cbstate.addToAgentState(
'state_metadata',
JSON.stringify({
...metadata,
timestamp: new Date().toISOString(),
previousState: await this.getCurrentState()
})
);

console.log(`State transitioned to: ${newState}`);
return newState;
}

async getCurrentState() {
const state = await codebolt.cbstate.getAgentState();
return state.payload.current_state || 'idle';
}

async executeInState(state, action) {
const currentState = await this.getCurrentState();

if (currentState !== state) {
throw new Error(`Cannot execute action in state: ${currentState}`);
}

return await action();
}
}

// Usage
const stateMachine = new AgentStateMachine();
await stateMachine.transition('processing', { taskId: 'task_123' });
await stateMachine.executeInState('processing', async () => {
console.log('Processing task...');
});

Pattern 2: Incremental Counter

async function incrementCounter(counterKey, increment = 1) {
// Get current value
const agentState = await codebolt.cbstate.getAgentState();
const currentValue = parseInt(agentState.payload[counterKey] || '0');

// Increment
const newValue = currentValue + increment;

// Store updated value
await codebolt.cbstate.addToAgentState(counterKey, newValue.toString());

return newValue;
}

// Usage
const retryCount = await incrementCounter('retry_count');
console.log(`Retry attempt: ${retryCount}`);

const processedItems = await incrementCounter('processed_items', 10);
console.log(`Processed items: ${processedItems}`);

Pattern 3: Transaction Log

async function logTransaction(type, data) {
// Get existing log
const agentState = await codebolt.cbstate.getAgentState();
const existingLog = JSON.parse(agentState.payload.transaction_log || '[]');

// Add new entry
const newEntry = {
type,
data,
timestamp: new Date().toISOString(),
sequence: existingLog.length + 1
};

existingLog.push(newEntry);

// Store updated log
await codebolt.cbstate.addToAgentState(
'transaction_log',
JSON.stringify(existingLog)
);

return newEntry;
}

// Usage
await logTransaction('api_call', { endpoint: '/users', method: 'GET' });
await logTransaction('data_fetch', { query: 'SELECT * FROM users' });
await logTransaction('cache_update', { key: 'user_123' });

Pattern 4: Scoped State Management

class ScopedAgentState {
constructor(scope) {
this.scope = scope;
}

async set(key, value) {
const scopedKey = `${this.scope}:${key}`;
return await codebolt.cbstate.addToAgentState(scopedKey, value);
}

async get(key) {
const scopedKey = `${this.scope}:${key}`;
const agentState = await codebolt.cbstate.getAgentState();
return agentState.payload[scopedKey];
}

async setMultiple(data) {
const promises = Object.entries(data).map(([key, value]) =>
this.set(key, value)
);
return await Promise.all(promises);
}

async getAll() {
const agentState = await codebolt.cbstate.getAgentState();
const prefix = `${this.scope}:`;

return Object.entries(agentState.payload)
.filter(([key]) => key.startsWith(prefix))
.reduce((acc, [key, value]) => {
acc[key.substring(prefix.length)] = value;
return acc;
}, {});
}
}

// Usage
const userState = new ScopedAgentState('user');
await userState.setMultiple({
id: 'user_123',
name: 'John Doe',
role: 'developer'
});

const allUserData = await userState.getAll();
console.log('User data:', allUserData);

Pattern 5: Expiring Data

async function setExpiringData(key, value, ttlSeconds) {
const expiryTime = Date.now() + (ttlSeconds * 1000);

// Store data with expiry
await codebolt.cbstate.addToAgentState(
`${key}:data`,
JSON.stringify(value)
);

await codebolt.cbstate.addToAgentState(
`${key}:expiry`,
expiryTime.toString()
);
}

async function getExpiringData(key) {
const agentState = await codebolt.cbstate.getAgentState();
const expiry = parseInt(agentState.payload[`${key}:expiry`] || '0');
const now = Date.now();

// Check if expired
if (now > expiry) {
// Clean up expired data
await codebolt.cbstate.addToAgentState(`${key}:data`, '');
await codebolt.cbstate.addToAgentState(`${key}:expiry`, '0');
return null;
}

// Return data if not expired
const data = agentState.payload[`${key}:data`];
return data ? JSON.parse(data) : null;
}

// Usage
await setExpiringData('session_token', 'abc123', 300); // Expires in 5 minutes
const token = await getExpiringData('session_token');
console.log('Token:', token);

Error Handling Strategies

Strategy 1: Retry with Exponential Backoff

async function addWithRetry(key, value, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const result = await codebolt.cbstate.addToAgentState(key, value);

if (result.payload.sucess) {
console.log(`✅ Added ${key} on attempt ${attempt}`);
return result;
}

// If not successful but no error, wait and retry
if (attempt < maxRetries) {
const delay = Math.pow(2, attempt) * 100; // Exponential backoff
console.log(`Retry ${attempt}/${maxRetries} after ${delay}ms`);
await new Promise(resolve => setTimeout(resolve, delay));
}
} catch (error) {
console.error(`Attempt ${attempt} failed:`, error.message);

if (attempt === maxRetries) {
throw error;
}

// Wait before retry
await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
}
}
}

Strategy 2: Validation Before Storage

const validators = {
email: (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value),
url: (value) => /^https?:\/\/.+/.test(value),
number: (value) => !isNaN(parseFloat(value)) && isFinite(value),
json: (value) => {
try {
JSON.parse(value);
return true;
} catch {
return false;
}
}
};

async function addValidated(key, value, validator) {
// Validate if validator provided
if (validator && !validator(value)) {
throw new Error(`Validation failed for key: ${key}`);
}

// Store validated value
const result = await codebolt.cbstate.addToAgentState(key, value);

if (result.payload.sucess) {
console.log(`✅ Validated and stored: ${key}`);
return result;
} else {
throw new Error(`Failed to store validated key: ${key}`);
}
}

// Usage
await addValidated('user_email', 'user@example.com', validators.email);
await addValidated('api_url', 'https://api.example.com', validators.url);
await addValidated('config', '{"theme":"dark"}', validators.json);

Strategy 3: Bulk Operations with Rollback

async function bulkAddWithRollback(items) {
const backup = [];

try {
// Store each item and keep backup
for (const item of items) {
// Get existing value as backup
const agentState = await codebolt.cbstate.getAgentState();
backup.push({
key: item.key,
oldValue: agentState.payload[item.key]
});

// Add new value
const result = await codebolt.cbstate.addToAgentState(item.key, item.value);

if (!result.payload.sucess) {
throw new Error(`Failed to add ${item.key}`);
}
}

console.log(`✅ Bulk operation completed: ${items.length} items`);
return true;

} catch (error) {
console.error('❌ Bulk operation failed, rolling back...');

// Rollback all changes
for (const backupItem of backup) {
if (backupItem.oldValue !== undefined) {
await codebolt.cbstate.addToAgentState(
backupItem.key,
backupItem.oldValue
);
}
}

throw error;
}
}

// Usage
await bulkAddWithRollback([
{ key: 'user_name', value: 'John Doe' },
{ key: 'user_email', value: 'john@example.com' },
{ key: 'user_role', value: 'admin' }
]);

Performance Considerations

Consideration 1: Batch Updates

// ❌ Slow: Sequential updates
for (let i = 0; i < 100; i++) {
await codebolt.cbstate.addToAgentState(`item_${i}`, `value_${i}`);
}

// ✅ Fast: Parallel updates
const updates = Array.from({ length: 100 }, (_, i) =>
codebolt.cbstate.addToAgentState(`item_${i}`, `value_${i}`)
);
await Promise.all(updates);

Consideration 2: String Length Limits

async function addLargeData(key, largeObject) {
const jsonString = JSON.stringify(largeObject);

// Check size before storing (assuming 1MB limit)
if (jsonString.length > 1_000_000) {
// Split into chunks
const chunks = [];
for (let i = 0; i < jsonString.length; i += 500_000) {
chunks.push(jsonString.substring(i, i + 500_000));
}

// Store chunk count
await codebolt.cbstate.addToAgentState(`${key}:chunks`, chunks.length.toString());

// Store each chunk
for (let i = 0; i < chunks.length; i++) {
await codebolt.cbstate.addToAgentState(`${key}:chunk_${i}`, chunks[i]);
}

console.log(`✅ Stored ${chunks.length} chunks`);
} else {
await codebolt.cbstate.addToAgentState(key, jsonString);
console.log('✅ Stored as single chunk');
}
}

Consideration 3: Memory Management

class StateBuffer {
constructor(maxSize = 50) {
this.maxSize = maxSize;
}

async add(key, value) {
const agentState = await codebolt.cbstate.getAgentState();
const currentKeys = Object.keys(agentState.payload).filter(k =>
!k.startsWith('system:')
);

// Check if buffer is full
if (currentKeys.length >= this.maxSize) {
// Remove oldest entry (FIFO)
const oldestKey = currentKeys[0];
await codebolt.cbstate.addToAgentState(oldestKey, '');
console.log(`Removed old key: ${oldestKey}`);
}

// Add new entry
await codebolt.cbstate.addToAgentState(key, value);
}
}

// Usage
const buffer = new StateBuffer(100);
for (let i = 0; i < 200; i++) {
await buffer.add(`entry_${i}`, `value_${i}`);
}

Common Pitfalls and Solutions

Pitfall 1: Race Conditions

// ❌ Problem: Race condition
await codebolt.cbstate.addToAgentState('counter', '1');
await codebolt.cbstate.addToAgentState('counter', '2'); // May overwrite first

// ✅ Solution: Use atomic operations with unique keys
await codebolt.cbstate.addToAgentState(`counter_${Date.now()}`, '1');
await codebolt.cbstate.addToAgentState(`counter_${Date.now()}`, '2');

Pitfall 2: Data Type Loss

// ❌ Problem: Numbers become strings
await codebolt.cbstate.addToAgentState('count', '42');
const count = agentState.payload.count; // '42' (string)
count + 1; // '421' (string concatenation!)

// ✅ Solution: Always convert types
const count = parseInt(agentState.payload.count || '0');
count + 1; // 43 (number)

Pitfall 3: Memory Leaks

// ❌ Problem: Accumulating data without cleanup
for (let i = 0; i < 1000; i++) {
await codebolt.cbstate.addToAgentState(`temp_${i}`, `data_${i}`);
}

// ✅ Solution: Clean up old data
async function cleanupTempData(maxAge = 3600000) { // 1 hour
const agentState = await codebolt.cbstate.getAgentState();
const now = Date.now();

for (const [key, value] of Object.entries(agentState.payload)) {
if (key.startsWith('temp_')) {
const timestamp = parseInt(value.split(':')[1] || '0');
if (now - timestamp > maxAge) {
await codebolt.cbstate.addToAgentState(key, '');
}
}
}
}

Integration Examples

With History Module

async function trackActionInHistory(action, details) {
// Store action in agent state
await codebolt.cbstate.addToAgentState(
'last_action',
JSON.stringify({ action, details, timestamp: new Date().toISOString() })
);

// Also add to history for timeline
const history = await codebolt.history.summarizeAll();

return history;
}

With Debug Module

async function debuggableStateUpdate(key, value) {
// Log the update attempt
await codebolt.debug.debug(`Updating agent state: ${key}`, 'info');

try {
const result = await codebolt.cbstate.addToAgentState(key, value);

if (result.payload.sucess) {
await codebolt.debug.debug(`Successfully updated: ${key}`, 'info');
} else {
await codebolt.debug.debug(`Failed to update: ${key}`, 'warning');
}

return result;
} catch (error) {
await codebolt.debug.debug(`Error updating ${key}: ${error.message}`, 'error');
throw error;
}
}