LLM-powered task execution engine with tool calling, checkpointing, and state persistence.
Runtime Engine
The runtime module is the core execution engine for autonomous agent tasks. It provides an LLM-driven loop that processes goals, calls tools, manages state, and supports checkpointing for resumable long-running tasks.
npm install @codmir/sdkQuick Start
import { DefaultRunnerEngine } from '@codmir/sdk/runtime';
const engine = new DefaultRunnerEngine({
llm: myLlmAdapter,
tools: myToolRegistry,
state: myStateStore,
maxIterations: 60,
onEvent: (event) => console.log(event.type, event.payload),
});
const task = {
id: 'task_001',
goal: 'Fix the failing login test',
state: 'queued' as const,
createdAt: Date.now(),
updatedAt: Date.now(),
steps: [],
};
const completed = await engine.run(task);
console.log(completed.state); // 'completed' | 'failed' | 'paused'
console.log(completed.result); // Output from the LLMArchitecture
The runtime uses an iterative loop:
- LLM decides — The adapter receives the task, history, and available tools, then returns a decision
- Engine acts — Based on the decision: call a tool, finish, or pause
- State persists — Each step is recorded; checkpoints are saved for resumability
- Loop continues — Until the LLM finishes, max iterations are hit, or the task is cancelled
Task Lifecycle
queued → assigned → running → completed
→ failed
→ paused (checkpoint)
→ cancelled (abort signal)
→ awaiting_approvalTask Structure
interface RunnerTask {
id: string;
goal: string;
projectId?: string;
workspace?: string;
state: RunnerTaskState;
createdAt: number;
updatedAt: number;
metadata?: Record<string, unknown>;
steps: RunnerTaskStep[];
result?: unknown;
error?: string;
}Task Steps
Every action taken by the engine is recorded as a step:
interface RunnerTaskStep {
id: string;
type: 'thinking' | 'tool_call' | 'tool_result' | 'step_pending' | 'state_change' | 'result';
timestamp: number;
payload: Record<string, unknown>;
}LLM Adapter
Implement the RunnerLlmAdapter interface to connect any LLM provider.
interface RunnerLlmAdapter {
nextAction(input: {
task: RunnerTask;
history: RunnerTaskStep[];
availableTools: Array<{ name: string; description?: string }>;
context: RunnerExecutionContext;
}): Promise<RunnerDecision>;
}The adapter returns one of three decisions:
type RunnerDecision =
| { kind: 'tool_call'; toolName: string; args: Record<string, unknown>; thinking?: string }
| { kind: 'finish'; output?: unknown; summary?: string }
| { kind: 'pause'; reason?: string };Example Adapter
import Anthropic from '@anthropic-ai/sdk';
import type { RunnerLlmAdapter } from '@codmir/sdk/runtime';
const adapter: RunnerLlmAdapter = {
async nextAction({ task, history, availableTools }) {
const anthropic = new Anthropic();
const response = await anthropic.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 4096,
system: `You are an agent. Your goal: ${task.goal}`,
messages: historyToMessages(history),
tools: availableTools.map(t => ({
name: t.name,
description: t.description || '',
input_schema: { type: 'object' },
})),
});
// Parse response into RunnerDecision
return parseDecision(response);
},
};Tool Registry
Register tools that the LLM can call during execution.
interface RunnerToolRegistry {
listTools(): Array<{ name: string; description?: string }>;
executeTool(
name: string,
args: Record<string, unknown>,
context: RunnerExecutionContext,
): Promise<unknown>;
}Example Registry
const tools: RunnerToolRegistry = {
listTools: () => [
{ name: 'read_file', description: 'Read a file from disk' },
{ name: 'write_file', description: 'Write content to a file' },
{ name: 'run_tests', description: 'Run the test suite' },
],
executeTool: async (name, args) => {
switch (name) {
case 'read_file': return await fs.readFile(args.path as string, 'utf-8');
case 'write_file': return await fs.writeFile(args.path as string, args.content as string);
case 'run_tests': return await exec('npm test');
default: throw new Error(`Unknown tool: ${name}`);
}
},
};State Store and Checkpointing
Implement RunnerStateStore for persistent checkpointing. Tasks can be resumed from checkpoints after crashes or restarts.
interface RunnerStateStore {
saveCheckpoint(checkpoint: LocalTaskCheckpoint): Promise<void>;
loadCheckpoint(taskId: string): Promise<LocalTaskCheckpoint | null>;
deleteCheckpoint(taskId: string): Promise<void>;
}Resume from Checkpoint
// Resume a previously paused or crashed task
const resumed = await engine.resume('task_001');Execution Context
Pass an AbortSignal to cancel tasks, and metadata for runtime context.
const controller = new AbortController();
const task = await engine.run(myTask, {
signal: controller.signal,
metadata: { userId: 'u_123', environment: 'staging' },
});
// Cancel from outside
controller.abort();Events
Subscribe to runtime events for monitoring, logging, or UI updates.
const engine = new DefaultRunnerEngine({
llm: adapter,
tools: registry,
state: store,
onEvent: async (event) => {
console.log(`[${event.type}] Task ${event.taskId}: ${JSON.stringify(event.payload)}`);
// Send to monitoring dashboard, WebSocket, etc.
},
});TypeScript Support
import type {
RunnerTask,
RunnerTaskState,
RunnerTaskStep,
RunnerEvent,
RunnerDecision,
RunnerEngine,
RunnerLlmAdapter,
RunnerToolRegistry,
RunnerStateStore,
RunnerExecutionContext,
} from '@codmir/sdk/runtime';
import { DefaultRunnerEngine } from '@codmir/sdk/runtime';