Execution Flow
This page describes the full lifecycle of a capability execution — from invocation to result.
Starting a capability
An agent starts a capability using the Codebolt JS SDK:
const result = await codebolt.capability.startCapability(
'frontend-refactor', // capabilityName
'skill', // capabilityType
{ file: 'src/App.tsx' }, // params (optional)
30000 // timeout in ms (optional)
);
Internally, this sends a message to the server which resolves to StartCapabilityOptions:
interface StartCapabilityOptions {
capabilityName: string; // name of the capability
capabilityType: string; // type (skill, power, talent, etc.)
threadId: string; // thread to execute in
parentAgentId: string; // parent agent ID
parentAgentInstanceId: string;// parent agent instance ID
params?: Record<string, any>;// additional parameters
timeout?: number; // timeout in ms (optional)
}
Execution lifecycle
startCapability()
│
├─ 1. Locate executor for the capability type
│ └─ capabilityRegistry.getExecutorForType(type)
│ └─ Error if not found: EXECUTOR_NOT_FOUND
│
├─ 2. Locate the capability
│ └─ capabilityRegistry.getCapability(name, type)
│ └─ Error if not found: CAPABILITY_NOT_FOUND
│
├─ 3. Generate unique execution ID
│ └─ Format: cap_<timestamp>_<uuid8>
│
├─ 4. Build thread context
│ └─ Chat history from the parent thread
│ └─ Project path, agent IDs, metadata
│
├─ 5. Launch executor via SideExecutionManager
│ └─ Spawns child process with env vars (SOCKET_PORT, IS_SIDE_EXECUTION, etc.)
│ └─ codeboltjs SDK auto-connects and receives params via actionBlockInvocation
│ └─ Same thread ID as parent agent
│
├─ 6. Emit "capabilityStarted" event
│
└─ 7. Return execution ID to caller
Execution statuses
| Status | Description |
|---|---|
starting | Execution is being set up |
running | Executor is actively processing |
completed | Execution finished successfully |
failed | Execution encountered an error |
timeout | Execution exceeded the time limit |
stopping | Stop requested, waiting for cleanup |
stopped | Execution was manually stopped |
Waiting for results
After starting a capability, the caller can await the result:
const executionId = await capabilityManager.startCapability(options);
const result = await capabilityManager.waitForCompletion(executionId);
if (result.success) {
console.log(result.result); // capability output
console.log(result.additionalContext); // extra context from executor
} else {
console.error(result.error);
}
The waitForCompletion() promise resolves when the underlying SideExecution completes, fails, or times out. There is no built-in timeout on the wait — capability executions can be long-running.
Result structure
interface CapabilityExecutionResult {
success: boolean;
executionId: string;
result?: any; // output data (on success)
additionalContext?: Record<string, any>;// extra context from executor
error?: string; // error message (on failure)
}
The result includes a capabilityPath field injected by the manager, allowing the client to resolve resource paths relative to the capability directory.
Thread context
The executor receives the full conversation context from the parent thread:
interface ThreadContext {
threadId: string;
messages: ThreadMessage[]; // chat history
projectPath: string;
agentId: string;
agentInstanceId: string;
metadata: Record<string, any>;
}
Each message includes: messageId, threadId, content, sender, timestamp, templateType, payload.
Stopping executions
// Stop a single execution
await capabilityManager.stopCapability(executionId);
// Stop all executions for a parent agent
await capabilityManager.stopAllForParent(parentAgentInstanceId);
Stopping sets the status to stopping, then delegates to SideExecutionManager to terminate the underlying process. After termination, resources are cleaned up.
Executor matching
When a capability is started, the manager looks up the executor using the capability's type:
capabilityType: "skill" → typeToExecutor map → skill-executor
The type-to-executor mapping is built during registry initialisation. If multiple executors support the same type, the last one registered wins (project-level overrides global, which overrides built-in).
Error codes
| Code | When |
|---|---|
CAPABILITY_NOT_FOUND | No capability with the given name and type exists |
EXECUTOR_NOT_FOUND | No executor is registered for the capability type |
INVALID_CAPABILITY_CONFIG | Capability configuration is malformed |
INVALID_EXECUTOR_CONFIG | Executor configuration is malformed |
EXECUTION_TIMEOUT | Execution exceeded the configured timeout |
EXECUTION_FAILED | Executor reported an error during execution |
DOWNLOAD_FAILED | Failed to download from marketplace |
EXTRACTION_FAILED | Failed to extract downloaded zip |
INVALID_REQUEST | Request parameters are invalid |
REGISTRY_NOT_INITIALIZED | Registry has not been initialised yet |