ConversationManager
Location: /inc/Engine/AI/ConversationManager.php
Since: v0.2.0 (Universal Engine Architecture)
Namespace: DataMachineEngineAI
Overview
ConversationManager provides standardized message formatting utilities for all AI agents (Pipeline and Chat). All methods are static with no state management, enabling consistent conversation structure across the Data Machine ecosystem.
Purpose
Centralizes conversation message building, tool call formatting, result messaging, and duplicate detection logic used by AIConversationLoop, RequestBuilder, and both Pipeline and Chat agents.
Core Methods
Message Building
buildConversationMessage()
Build standardized conversation message structure.
Signature:
public static function buildConversationMessage(string $role, string $content): array
Parameters:
$role(string) – Role identifier:user,assistant,system$content(string) – Message content
Returns: Array with role and content keys
Example:
$message = ConversationManager::buildConversationMessage('user', 'Create a pipeline');
// Returns: ['role' => 'user', 'content' => 'Create a pipeline']
Usage: Foundation for all message formatting methods
Tool Call Formatting
formatToolCallMessage()
Format tool call as conversation message with turn tracking.
Signature:
public static function formatToolCallMessage(
string $tool_name,
array $tool_parameters,
int $turn_count
): array
Parameters:
$tool_name(string) – Tool identifier (e.g.,google_search,wordpress_publish)$tool_parameters(array) – Tool call parameters$turn_count(int) – Current conversation turn (0 = no turn display)
Returns: Formatted assistant message with tool call details
Message Format:
AI ACTION (Turn {$turn_count}): Executing {Tool Display Name} with parameters: key: value, key2: value2
Parameter Truncation: String values over 50 characters are truncated to 50...
Example:
$message = ConversationManager::formatToolCallMessage(
'google_search',
['query' => 'WordPress best practices', 'num_results' => 5],
1
);
// Returns: ['role' => 'assistant', 'content' => 'AI ACTION (Turn 1): Executing Google Search with parameters: query: WordPress best practices, num_results: 5']
Integration: Used by AIConversationLoop during multi-turn conversation execution
Tool Result Formatting
formatToolResultMessage()
Format tool execution result as conversation message.
Signature:
public static function formatToolResultMessage(
string $tool_name,
array $tool_result,
array $tool_parameters,
bool $is_handler_tool = false,
int $turn_count = 0
): array
Parameters:
$tool_name(string) – Tool identifier$tool_result(array) – Tool execution result withsuccess,data,errorkeys$tool_parameters(array) – Original tool parameters$is_handler_tool(bool) – Whether tool is handler-specific (affects data inclusion)$turn_count(int) – Current conversation turn (0 = no turn display)
Returns: Formatted user message with tool result
Message Format:
TOOL RESPONSE (Turn {$turn_count}): {Success Message}
{JSON-encoded data for non-handler tools}
Data Inclusion:
- Handler tools: Success message only (no raw data)
- Non-handler tools: Success message + JSON-encoded
datafield
Example:
$result = [
'success' => true,
'data' => ['id' => 123, 'title' => 'New Post']
];
$message = ConversationManager::formatToolResultMessage(
'wordpress_publish',
$result,
['content' => 'Post content'],
true, // is_handler_tool
2
);
// Returns user message with success message only (no raw data)
$search_result = [
'success' => true,
'data' => ['results' => [...]]
];
$message2 = ConversationManager::formatToolResultMessage(
'google_search',
$search_result,
['query' => 'test'],
false, // not a handler tool
3
);
// Returns user message with success message + JSON data
Success Message Generation
generateSuccessMessage()
Generate success or failure message from tool result with filter-based customization.
Signature:
public static function generateSuccessMessage(
string $tool_name,
array $tool_result,
array $tool_parameters
): string
Parameters:
$tool_name(string) – Tool identifier$tool_result(array) – Tool execution result$tool_parameters(array) – Original tool parameters
Returns: Human-readable success/failure message
Default Success Message:
SUCCESS: {Tool Display Name} completed successfully. The requested operation has been finished as requested.
Failure Message:
TOOL FAILED: {tool_name} execution failed - {error}
Filter Hook: datamachine_tool_success_message allows handlers to customize success messages
Example:
// Success
$result = ['success' => true, 'data' => []];
$message = ConversationManager::generateSuccessMessage('twitter_publish', $result, []);
// Returns: "SUCCESS: Twitter Publish completed successfully. The requested operation has been finished as requested."
// Failure
$result = ['success' => false, 'error' => 'Invalid credentials'];
$message = ConversationManager::generateSuccessMessage('twitter_publish', $result, []);
// Returns: "TOOL FAILED: twitter_publish execution failed - Invalid credentials"
// Custom via filter
add_filter('datamachine_tool_success_message', function($message, $tool_name, $result, $params) {
if ($tool_name === 'wordpress_publish' && isset($result['data']['url'])) {
return "SUCCESS: Post published at {$result['data']['url']}";
}
return $message;
}, 10, 4);
generateFailureMessage()
Generate standardized failure message.
Signature:
public static function generateFailureMessage(string $tool_name, string $error_message): string
Parameters:
$tool_name(string) – Tool identifier$error_message(string) – Error details
Returns: Formatted failure message with guidance
Format:
TOOL FAILED: {Tool Display Name} execution failed - {error_message}. Please review the error and adjust your approach if needed.
Example:
$message = ConversationManager::generateFailureMessage(
'google_search',
'API quota exceeded'
);
// Returns: "TOOL FAILED: Google Search execution failed - API quota exceeded. Please review the error and adjust your approach if needed."
Duplicate Tool Call Detection
validateToolCall()
Validate if a tool call is a duplicate of the previous tool call in conversation history.
Signature:
public static function validateToolCall(
string $tool_name,
array $tool_parameters,
array $conversation_messages
): array
Parameters:
$tool_name(string) – Tool name to validate$tool_parameters(array) – Tool parameters to validate$conversation_messages(array) – Full conversation history
Returns: Array with is_duplicate (bool) and message (string) keys
Detection Logic:
- Search conversation history backwards for most recent assistant message with "AI ACTION" prefix
- Extract tool name and parameters from that message
- Compare with current tool call
- Return duplicate status and correction message if duplicate
Example:
$conversation = [
['role' => 'user', 'content' => 'Search for WordPress'],
['role' => 'assistant', 'content' => 'AI ACTION (Turn 1): Executing Google Search with parameters: query: WordPress, num_results: 5'],
['role' => 'user', 'content' => 'TOOL RESPONSE (Turn 1): ...']
];
$validation = ConversationManager::validateToolCall(
'google_search',
['query' => 'WordPress', 'num_results' => 5],
$conversation
);
// Returns: ['is_duplicate' => true, 'message' => 'You just called the google_search tool with the exact same parameters...']
$validation2 = ConversationManager::validateToolCall(
'google_search',
['query' => 'WordPress plugins', 'num_results' => 5],
$conversation
);
// Returns: ['is_duplicate' => false, 'message' => '']
Integration: Used by AIConversationLoop to prevent infinite loops from duplicate tool calls
extractToolCallFromMessage()
Extract tool call details from a conversation message.
Signature:
public static function extractToolCallFromMessage(array $message): ?array
Parameters:
$message(array) – Conversation message to parse
Returns: Array with tool_name and parameters keys, or null if not a tool call message
Recognition Pattern: Messages matching AI ACTION (Turn N): Executing {Tool} with parameters: ...
Parameter Parsing:
- Splits on
,delimiter - Parses
key: valuepairs - JSON-decodes values where possible
- Handles truncated values (appends
_truncated_{timestamp}to prevent false duplicates)
Example:
$message = [
'role' => 'assistant',
'content' => 'AI ACTION (Turn 1): Executing Google Search with parameters: query: WordPress, num_results: 5'
];
$extracted = ConversationManager::extractToolCallFromMessage($message);
// Returns: [
// 'tool_name' => 'google_search',
// 'parameters' => ['query' => 'WordPress', 'num_results' => 5]
// ]
Usage: Internal utility for duplicate detection
generateDuplicateToolCallMessage()
Generate a user message for duplicate tool call prevention.
Signature:
public static function generateDuplicateToolCallMessage(string $tool_name): array
Parameters:
$tool_name(string) – Tool name that was duplicated
Returns: Formatted user message with correction guidance
Example:
$message = ConversationManager::generateDuplicateToolCallMessage('google_search');
// Returns: ['role' => 'user', 'content' => 'You just called the Google Search tool with the exact same parameters as your previous action. Please try a different approach or use different parameters instead.']
Integration with Universal Engine
AIConversationLoop Integration
AIConversationLoop uses ConversationManager for:
- Tool Call Messages: Format each tool call with turn tracking
- Tool Result Messages: Format tool execution results with success/failure details
- Duplicate Detection: Validate tool calls before execution to prevent infinite loops
Conversation Flow:
// 1. Format tool call message
$tool_call_msg = ConversationManager::formatToolCallMessage($tool_name, $params, $turn_count);
$conversation[] = $tool_call_msg;
// 2. Execute tool via ToolExecutor
$result = ToolExecutor::executeTool(...);
// 3. Format tool result message
$result_msg = ConversationManager::formatToolResultMessage($tool_name, $result, $params, $is_handler_tool, $turn_count);
$conversation[] = $result_msg;
// 4. Validate next tool call for duplicates
$validation = ConversationManager::validateToolCall($next_tool, $next_params, $conversation);
if ($validation['is_duplicate']) {
$conversation[] = ConversationManager::buildConversationMessage('user', $validation['message']);
}
RequestBuilder Integration
RequestBuilder uses ConversationManager for:
- System Messages: Build directive messages with proper role assignment
- User Context: Format user-provided context as conversation messages
Handler Tool Integration
Publish/Update handlers use ConversationManager indirectly through:
- Success Message Filter: Customize tool result messages via
datamachine_tool_success_messagefilter
Custom Success Message Example:
add_filter('datamachine_tool_success_message', function($message, $tool_name, $result, $params) {
if ($tool_name === 'twitter_publish' && isset($result['data']['url'])) {
$tweet_url = $result['data']['url'];
return "SUCCESS: Tweet published successfully at {$tweet_url}. The content is now live on Twitter.";
}
return $message;
}, 10, 4);
Architecture Principles
Static Methods Only
All methods are static with no instance state:
- Benefit: No dependency injection required, simple utility usage
- Pattern: Pure functions for message transformation
- Thread Safety: No state mutations, safe for concurrent usage
Standardized Message Format
Consistent message structure across all agents:
- Role:
user,assistant,system - Content: String message content
- Turn Tracking: Explicit turn numbers in tool messages
- Result Clarity: Clear SUCCESS/FAILED prefixes
Filter-Based Extensibility
Handlers can customize messages via WordPress filters:
datamachine_tool_success_message: Override default success messages- Parameters:
$message,$tool_name,$tool_result,$tool_parameters - Use Cases: Platform-specific messaging, URL inclusion, custom formatting
Duplicate Prevention
Sophisticated duplicate detection prevents infinite loops:
- Backward Search: Finds most recent tool call in conversation history
- Exact Matching: Compares tool name and parameters
- Truncation Handling: Prevents false duplicates from truncated parameters
- Guidance Messaging: Provides clear correction instructions to AI
Usage Examples
Basic Message Building
// Simple user message
$msg = ConversationManager::buildConversationMessage('user', 'Create a pipeline');
// System directive
$directive = ConversationManager::buildConversationMessage('system', 'You are a helpful assistant');
Tool Call Workflow
// 1. Format tool call
$tool_call = ConversationManager::formatToolCallMessage(
'wordpress_publish',
['title' => 'My Post', 'content' => 'Post content'],
1
);
// 2. Execute tool (via ToolExecutor)
$result = ToolExecutor::executeTool(...);
// 3. Format result
$result_msg = ConversationManager::formatToolResultMessage(
'wordpress_publish',
$result,
['title' => 'My Post', 'content' => 'Post content'],
true, // is_handler_tool
1
);
Duplicate Detection
$conversation = [...]; // Full conversation history
// Validate before execution
$validation = ConversationManager::validateToolCall(
'google_search',
['query' => 'test'],
$conversation
);
if ($validation['is_duplicate']) {
$correction = ConversationManager::buildConversationMessage(
'user',
$validation['message']
);
$conversation[] = $correction;
// Skip tool execution, continue conversation with correction
}
Related Components
- AIConversationLoop – Multi-turn conversation execution using ConversationManager
- ToolExecutor – Tool discovery and execution
- RequestBuilder – AI request construction
- Parameter Systems – Tool parameter building and architecture
- Universal Engine Architecture – Shared AI infrastructure
Location: /inc/Engine/AI/ConversationManager.php
Namespace: DataMachineEngineAI
Type: Static utility class
Since: v0.2.0