Skip to content

Core Concepts ​

AgentVM has five building blocks. Understanding how they fit together is the key to using it well.

Kernel ​

The Kernel is the central orchestrator. Everything goes through it.

typescript
const kernel = new Kernel({ name: 'my-app' });

The kernel manages the agent registry, process table, memory bus, tool router, message broker, and scheduler. It's the single object you pass around.

Agent ​

An Agent is a blueprint — a definition of what something can do. It's not running yet.

typescript
const agent = new Agent({
  name: 'analyzer',
  description: 'Analyzes data and produces reports',
  tools: ['http_fetch', 'file_read'],    // tools it can access
  memory: { persistent: true },           // memory config
  contract: {                             // input/output types
    input: { type: 'string' },
    output: { type: 'object' },
  },
  handler: async (ctx) => {               // what it actually does
    // ...
    return { analysis: 'done' };
  },
});

Think of an Agent like a class definition, not an instance.

Process ​

A Process is a running instance of an agent. You can have multiple processes from the same agent.

typescript
kernel.register(agent);

const proc1 = await kernel.spawn('analyzer');
const proc2 = await kernel.spawn('analyzer'); // separate instance

// Each has its own memory, its own lifecycle
await kernel.execute(proc1.id, { task: 'analyze sales' });
await kernel.execute(proc2.id, { task: 'analyze inventory' });

Processes have a lifecycle:

created → starting → running → paused → terminated
                        ↓
                     crashed

You can pause, resume, and terminate processes:

typescript
await kernel.pause(proc.id);
await kernel.resume(proc.id);
await kernel.terminate(proc.id);

ExecutionContext ​

When a process runs, its handler receives an ExecutionContext — the agent's window into the world:

typescript
handler: async (ctx) => {
  ctx.processId;           // this process's ID
  ctx.agentName;           // agent name
  ctx.input;               // the task input
  ctx.memory.get('key');   // read from memory
  ctx.memory.set('k', v); // write to memory
  ctx.useTool('name', {}); // call a tool
  ctx.publish('channel', data); // publish a message
  ctx.emit('event', data);      // emit an event
  ctx.signal;              // AbortSignal for cancellation
}

Everything an agent needs is in the context. No global state, no singletons.

ExecutionResult ​

Every kernel.execute() returns a result:

typescript
const result = await kernel.execute(proc.id, { task: 'work' });

result.processId;   // process that ran
result.agentName;   // agent name
result.output;      // whatever the handler returned
result.duration;    // wall-clock milliseconds
result.tokensUsed;  // LLM tokens (if applicable)
result.events;      // structured events emitted during execution

How They Fit Together ​

            register()              spawn()              execute()
Agent ──────────────→ Kernel ────────────→ Process ────────────→ Result
                        │                     │
                        ├── MemoryBus         ├── ExecutionContext
                        ├── ToolRouter        │     ├── memory
                        ├── MessageBroker     │     ├── useTool
                        └── Scheduler         │     ├── publish
                                              │     └── emit
                                              │
                                         handler(ctx)
                                              │
                                              ↓
                                         return output

Next Steps ​

  • Agents & Processes — Lifecycle management, metadata, events
  • Tools — Register, permission, rate limit
  • Memory — Backends, persistence, shared state

Released under the MIT License.