The qckfx Agent SDK provides a comprehensive event system that allows you to monitor and respond to various agent activities in real-time. This includes processing lifecycle events, tool execution events, environment status changes, and more.
Event Categories
The event system is organized into several categories, each with specific event types and data structures.
Processing Lifecycle Events
These events track the overall processing lifecycle of agent queries.
ProcessingEvents.STARTED
Fired when the agent begins processing a new query.
interface ProcessingStartedData {
sessionId : string ; // Unique session identifier
query : string ; // The user query being processed
model : string ; // LLM model being used
}
ProcessingEvents.COMPLETED
Fired when the agent successfully completes processing a query.
interface ProcessingCompletedData {
sessionId : string ; // Unique session identifier
response : string ; // The agent's response
executionTime ?: number ; // Total execution time in milliseconds
}
ProcessingEvents.ERROR
Fired when an error occurs during query processing.
interface ProcessingErrorData {
sessionId : string ;
error : {
message : string ; // Error message
stack ?: string ; // Stack trace (if available)
};
}
ProcessingEvents.ABORTED
Fired when query processing is aborted (e.g., user interrupt).
interface ProcessingAbortedData {
sessionId : string ; // Unique session identifier
}
These events provide detailed information about individual tool executions.
Fired when a tool begins execution.
Fired when a tool completes execution successfully.
Fired when a tool execution encounters an error.
All tool execution events use the ToolExecutionState
interface:
interface ToolExecutionState {
sessionId : string ;
toolId : string ;
executionId : string ;
status : ToolExecutionStatus ;
args : Record < string , unknown >;
result ?: ToolResult ;
error ?: string ;
startTime : number ;
endTime ?: number ;
}
Environment Events
These events track the status of the execution environment.
EnvironmentEvents.STATUS_CHANGED
Fired when the environment status changes (e.g., connecting, connected, error).
interface EnvironmentStatusData {
sessionId : string ;
environmentType : 'local' | 'docker' | 'remote' ;
status : 'initializing' | 'connecting' | 'connected' | 'disconnected' | 'error' ;
isReady : boolean ;
error ?: string ;
}
Checkpoint Events
These events are related to the agent’s checkpoint and rollback system.
CheckpointEvents.READY
Fired when a new checkpoint is created and ready for potential rollback.
interface CheckpointData {
sessionId : string ;
toolExecutionId : string ;
hostCommits : Map < string , string >; // repo path -> commit sha
shadowCommits : Map < string , string >; // repo path -> shadow commit sha
bundles : Map < string , Uint8Array >; // repo path -> bundle
repoCount : number ;
timestamp : string ;
}
Rollback Events
These events track rollback operations.
RollbackEvents.COMPLETED
Fired when a rollback operation completes.
interface RollbackData {
sessionId : string ;
commitSha : string ; // First repo's commit SHA (backwards compatibility)
restoredCommits : Map < string , string >; // repo path -> commit sha
repoCount : number ;
}
Permission Events
These events are fired when tools request user permission.
PermissionEvents.REQUESTED
Fired when a tool requires user permission before execution.
interface PermissionData {
sessionId : string ;
toolId : string ;
args : Record < string , unknown >;
}
Event Bus Integration
The Agent SDK uses a typed event bus system that provides type-safe event handling.
BusEvent Enum
enum BusEvent {
PROCESSING_STARTED = 'processing:started' ,
PROCESSING_COMPLETED = 'processing:completed' ,
PROCESSING_ERROR = 'processing:error' ,
PROCESSING_ABORTED = 'processing:aborted' ,
TOOL_EXECUTION_STARTED = 'tool:execution:started' ,
TOOL_EXECUTION_COMPLETED = 'tool:execution:completed' ,
TOOL_EXECUTION_ERROR = 'tool:execution:error' ,
ENVIRONMENT_STATUS_CHANGED = 'environment:status_changed' ,
CHECKPOINT_READY = 'checkpoint:ready' ,
ROLLBACK_COMPLETED = 'rollback:completed' ,
PERMISSION_REQUESTED = 'permission:requested' ,
}
Event Listening
You can listen to events using the agent’s event system:
Callback-based Listening
Event Bus Listening
const agent = new Agent ({
defaultModel: 'claude-3-5-sonnet-20241022' ,
systemPrompt: 'You are a helpful coding assistant.' ,
callbacks: {
onProcessingStarted : ( data ) => {
console . log ( `Started processing: ${ data . query } ` );
},
onProcessingCompleted : ( data ) => {
console . log ( `Completed in ${ data . executionTime } ms` );
},
onProcessingError : ( data ) => {
console . error ( `Error: ${ data . error . message } ` );
},
onToolExecutionStarted : ( data ) => {
console . log ( `Tool ${ data . toolId } started` );
},
onEnvironmentStatusChanged : ( data ) => {
console . log ( `Environment ${ data . environmentType } is ${ data . status } ` );
}
}
});
Event Patterns
agent . on ( BusEvent . TOOL_EXECUTION_STARTED , ( data ) => {
console . log ( `🔧 ${ data . toolId } started with args:` , data . args );
});
agent . on ( BusEvent . TOOL_EXECUTION_COMPLETED , ( data ) => {
const duration = data . endTime ! - data . startTime ;
console . log ( `✅ ${ data . toolId } completed in ${ duration } ms` );
});
agent . on ( BusEvent . TOOL_EXECUTION_ERROR , ( data ) => {
console . error ( `❌ ${ data . toolId } failed:` , data . error );
});
Tracking Processing Lifecycle
let processingStartTime : number ;
agent . on ( BusEvent . PROCESSING_STARTED , ( data ) => {
processingStartTime = Date . now ();
console . log ( `🚀 Started processing: " ${ data . query } "` );
});
agent . on ( BusEvent . PROCESSING_COMPLETED , ( data ) => {
const totalTime = Date . now () - processingStartTime ;
console . log ( `🎉 Completed in ${ totalTime } ms: " ${ data . response . substring ( 0 , 100 ) } ..."` );
});
Environment Monitoring
agent . on ( BusEvent . ENVIRONMENT_STATUS_CHANGED , ( data ) => {
switch ( data . status ) {
case 'initializing' :
console . log ( '🔄 Environment initializing...' );
break ;
case 'connected' :
console . log ( '✅ Environment ready' );
break ;
case 'error' :
console . error ( '❌ Environment error:' , data . error );
break ;
}
});
Permission Handling
agent . on ( BusEvent . PERMISSION_REQUESTED , ( data ) => {
console . log ( `🔐 Permission requested for ${ data . toolId } ` );
console . log ( 'Args:' , data . args );
// You could implement custom permission logic here
// Note: The actual permission response is handled by the agent's permission system
});
Best Practices
Event Handler Organization
class AgentMonitor {
constructor ( private agent : Agent ) {
this . setupEventHandlers ();
}
private setupEventHandlers () {
// Group related event handlers
this . setupProcessingHandlers ();
this . setupToolHandlers ();
this . setupEnvironmentHandlers ();
}
private setupProcessingHandlers () {
this . agent . on ( BusEvent . PROCESSING_STARTED , this . onProcessingStarted . bind ( this ));
this . agent . on ( BusEvent . PROCESSING_COMPLETED , this . onProcessingCompleted . bind ( this ));
this . agent . on ( BusEvent . PROCESSING_ERROR , this . onProcessingError . bind ( this ));
}
private setupToolHandlers () {
this . agent . on ( BusEvent . TOOL_EXECUTION_STARTED , this . onToolStarted . bind ( this ));
this . agent . on ( BusEvent . TOOL_EXECUTION_COMPLETED , this . onToolCompleted . bind ( this ));
}
private setupEnvironmentHandlers () {
this . agent . on ( BusEvent . ENVIRONMENT_STATUS_CHANGED , this . onEnvironmentChanged . bind ( this ));
}
private onProcessingStarted ( data : ProcessingStartedData ) {
// Handle processing started
}
// ... other handlers
}
Error Handling in Event Listeners
agent . on ( BusEvent . PROCESSING_ERROR , ( data ) => {
try {
// Log error details
console . error ( 'Processing failed:' , {
sessionId: data . sessionId ,
message: data . error . message ,
stack: data . error . stack
});
// Notify external systems
notifyErrorTrackingService ( data . error );
// Update UI state
updateUIErrorState ( data . error . message );
} catch ( handlerError ) {
console . error ( 'Error in event handler:' , handlerError );
}
});
const performanceMetrics = new Map < string , number >();
agent . on ( BusEvent . TOOL_EXECUTION_STARTED , ( data ) => {
performanceMetrics . set ( data . executionId , data . startTime );
});
agent . on ( BusEvent . TOOL_EXECUTION_COMPLETED , ( data ) => {
const startTime = performanceMetrics . get ( data . executionId );
if ( startTime && data . endTime ) {
const duration = data . endTime - startTime ;
console . log ( `Tool ${ data . toolId } took ${ duration } ms` );
// Track slow tools
if ( duration > 5000 ) {
console . warn ( `Slow tool execution: ${ data . toolId } took ${ duration } ms` );
}
}
performanceMetrics . delete ( data . executionId );
});
Event handlers should be lightweight and avoid blocking operations. For heavy processing, consider using async handlers or queuing work for later processing.
Be careful with error handling in event listeners. Unhandled errors in event handlers can cause the agent to become unstable.