npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@olane/o-core

v0.8.10

Published

Olane addressable p2p node used to host tools, data or anything else your heart can dream of.

Downloads

1,759

Readme

@olane/o-core

The kernel layer of Olane OS - an agentic operating system where AI agents are the users, and you build tool nodes as applications.

npm version License: ISC

What is o-core?

o-core is the kernel layer of Olane OS - the foundational runtime for building tool nodes that AI agents use. Think of it as the Linux kernel: it defines how processes work (lifecycle, IPC, addressing, routing) but doesn't implement specific transport layers.

The Three-Layer Model

AI Agents (LLMs|Humans) → use → Tool Nodes (you build) → run on → Olane OS (o-core)
  • Agents (Users): GPT-4, Claude, Humans, etc. - the intelligent users
  • Tool Nodes (Applications): Domain-specific capabilities you build
  • o-core (OS Kernel): The runtime infrastructure that makes it all work

This is NOT a network framework or API library - it's the abstract operating system layer that makes inter-process communication (IPC), resource addressing, and hierarchical organization possible.

Key Features

  • 🏗️ Tool Node Runtime: Base infrastructure for creating tool node processes that agents use
  • 📍 Hierarchical Addressing: o:// protocol for filesystem-like tool node addressing
  • 🔀 Intelligent Routing: Automatic request routing through tool node hierarchies
  • 🔌 Transport-Agnostic: Abstract layer - works with any communication layer (libp2p, HTTP, custom)
  • 🌳 Hierarchy Management: Built-in parent-child relationships between tool nodes
  • 🔄 Lifecycle Management: Complete process state management and graceful shutdown
  • 📊 Observable: Built-in metrics, logging, and request tracking
  • 🛡️ Fault-Tolerant: Error handling, graceful degradation, and automatic cleanup

Installation

pnpm install @olane/o-core @olane/o-protocol

Quick Start

Creating Your First Tool Node

Note: oCore is an abstract base class. For production use, extend higher-level packages like oNodeTool (from @olane/o-node), oLaneTool (from @olane/o-lane), or McpTool (from @olane/o-mcp). The example below demonstrates the core concepts.

import { oCore, oAddress, NodeType, NodeState } from '@olane/o-core';
import { oRequest, oResponse } from '@olane/o-core';

// Extend oCore to create your tool node
class MyToolNode extends oCore {
  constructor(config: { address: oAddress }) {
    super({
      address: config.address,
      type: NodeType.AGENT, // Type remains AGENT for now (legacy naming)
      description: 'My first tool node',
      methods: {
        greet: {
          name: 'greet',
          description: 'Greets the user',
          parameters: {
            name: { type: 'string', required: true }
          }
        }
      }
    });
  }

  // Implement required abstract methods
  async execute(request: oRequest): Promise<any> {
    const { method, params } = request;

    if (method === 'greet') {
      return { message: `Hello, ${params.name}!` };
    }

    throw new Error(`Unknown method: ${method}`);
  }

  configureTransports(): any[] {
    // Configure your transport layer (libp2p, HTTP, etc.)
    return [];
  }

  async connect(nextHop: oAddress, target: oAddress) {
    // Implement connection logic
    return this.connectionManager.connect({ nextHop, target });
  }

  initializeRouter(): void {
    // Initialize routing logic
    this.router = new MyRouter();
  }

  async register(): Promise<void> {
    // Register with parent or leader node
    console.log('Tool node registered');
  }

  async unregister(): Promise<void> {
    // Cleanup registration
    console.log('Tool node unregistered');
  }
}

// Create and start your tool node
// IMPORTANT: Use simple (non-nested) addresses in constructors.
// Nested addresses like 'o://company/customer-service' are created
// automatically at runtime during parent-child registration.
const toolNode = new MyToolNode({
  address: new oAddress('o://customer-service')
});
await toolNode.start();

// AI agents can now use this tool node via its o:// address
const response = await toolNode.use(
  new oAddress('o://customer-service'),
  {
    method: 'greet',
    params: { name: 'Alice' }
  }
);

// Response follows the standard wrapping structure:
// response.result.success - boolean indicating success/failure
// response.result.data    - the returned data on success
// response.result.error   - error details on failure
if (response.result.success) {
  console.log(response.result.data); // { message: "Hello, Alice!" }
}

// Stop the tool node gracefully
await toolNode.stop();

Tool Node Communication (IPC)

// Tool Node A can communicate with Tool Node B using o:// addresses
// Use simple addresses in constructors; nested addresses are created at runtime
const salesTool = new MyToolNode({ address: new oAddress('o://sales') });
const analyticsTool = new MyToolNode({ address: new oAddress('o://analytics') });

await salesTool.start();
await analyticsTool.start();

// Sales tool calls analytics tool (inter-process communication)
const result = await salesTool.use(
  new oAddress('o://analytics'),
  {
    method: 'analyze',
    params: { data: salesData }
  }
);

Hierarchical Organization

// Create a parent-child hierarchy of tool nodes
// Use simple addresses in constructors - nested addresses are created at runtime
const parent = new MyToolNode({ address: new oAddress('o://company') });

// Children use simple addresses with a parent reference
// During registration, child addresses become nested (e.g., 'o://company/sales')
const child1 = new MyToolNode({ address: new oAddress('o://sales') });
const child2 = new MyToolNode({ address: new oAddress('o://marketing') });

await parent.start();
await child1.start();
await child2.start();

// Register children with parent - this creates the nested addresses
parent.addChildNode(child1);
parent.addChildNode(child2);

// After registration:
// child1.address -> 'o://company/sales'
// child2.address -> 'o://company/marketing'
// Routing happens automatically through the hierarchy

Core Concepts

Tool Node Lifecycle States

Tool nodes (processes) transition through the following states:

  • STOPPED - Initial state, tool node is not running
  • STARTING - Tool node is initializing
  • RUNNING - Tool node is active and processing requests
  • STOPPING - Tool node is shutting down gracefully
  • ERROR - Tool node encountered an error
console.log(toolNode.state); // NodeState.RUNNING

await toolNode.stop();
console.log(toolNode.state); // NodeState.STOPPED

The o:// Protocol

Addresses in Olane OS follow a hierarchical filesystem-like pattern:

// Hierarchical addresses exist at runtime after parent-child registration.
// They are created by the system, not by constructors directly.
// For example, after registration a child address may become:
const address1 = new oAddress('o://company/finance/accounting');
const address2 = new oAddress('o://users/alice/inbox');

// Address operations
console.log(address1.paths);        // "company/finance/accounting"
console.log(address1.root);         // "o://company"
console.log(address1.validate());   // true

// Static vs dynamic addresses
const staticAddr = address1.toStaticAddress();
console.log(staticAddr.toString()); // "o://accounting"

// IMPORTANT: When creating nodes in constructors, always use simple
// (non-nested) addresses. Nested addresses are created automatically
// during parent-child registration at runtime.
// ✅ new oAddress('o://my-tool')
// ❌ new oAddress('o://parent/my-tool')  -- violates validateNotNested()

📖 For complete details on address resolution, routing algorithms, and custom resolvers, see the Router System documentation.

Request/Response Pattern

All inter-process communication (IPC) follows a request/response pattern using JSON-RPC 2.0:

// Making a request from one tool node to another
// Full signature: use(address: oAddress, data?: { method: string, params: any, id?: string }, options?: UseOptions)
const response: oResponse = await toolNode.use(
  new oAddress('o://target-toolnode'),
  {
    method: 'processData',
    params: { key: 'value' },
    id: 'unique-request-id'
  }
);

// Always check the response structure
if (response.result.success) {
  console.log('Data:', response.result.data);
} else {
  console.error('Error:', response.result.error);
}

// Transport-level errors throw exceptions
try {
  const response = await toolNode.use(targetAddress, requestData);
  // Check response.result.success for application-level errors
} catch (error) {
  if (error instanceof oError) {
    console.error(`Transport error ${error.code}: ${error.message}`);
  }
}

📖 Learn more about JSON-RPC messaging, request states, and connection lifecycle in the Connection System documentation.

Response Structure

When you call use(), the response follows a standard wrapping structure created by the ResponseBuilder. In higher-level packages (@olane/o-node, @olane/o-tool, @olane/o-lane), responses are wrapped with success, data, and error fields:

const response = await toolNode.use(targetAddress, {
  method: 'processData',
  params: { key: 'value' }
});

// Standard response structure:
// {
//   jsonrpc: "2.0",
//   id: "request-id",
//   result: {
//     success: boolean,    // Whether the operation succeeded
//     data: any,           // The returned data (on success)
//     error?: string       // Error details (on failure)
//   }
// }

// Always check success before accessing data
if (response.result.success) {
  const data = response.result.data;
  console.log('Result:', data);
} else {
  console.error('Error:', response.result.error);
}

Important: Access data via response.result.data, not response.result directly. The result object contains the wrapping fields (success, data, error), not the raw return value.

Metrics and Observability

Every tool node tracks metrics automatically:

// Access tool node metrics
console.log(toolNode.metrics.successCount);
console.log(toolNode.metrics.errorCount);

// Built-in logging
toolNode.logger.debug('Debug message');
toolNode.logger.info('Info message');
toolNode.logger.warn('Warning message');
toolNode.logger.error('Error message');

Architecture

Abstract Base Class

oCore is an abstract base class that provides:

  • Lifecycle Management: start(), stop(), initialize(), teardown()
  • Communication: use(), useDirect(), connect()
  • Routing: router, initializeRouter()
  • Hierarchy: addChildNode(), removeChildNode(), hierarchyManager
  • State Management: state, NodeState enum
  • Observability: metrics, logger, requestManager

Key Components

1. Router System (oAddress & oRouter)

Hierarchical addressing and intelligent routing for tool nodes

const addr = new oAddress('o://domain/subdomain/resource');
addr.validate();           // Check if address is valid
addr.toStaticAddress();   // Convert to static address
addr.toCID();             // Convert to Content ID

// Router determines the next hop in the network
const { nextHopAddress, targetAddress } = await router.translate(
  address,
  node
);

📚 View detailed Router System documentation →

2. Connection System (oConnection & oConnectionManager)

Inter-Process Communication (IPC) layer for tool-node-to-tool-node messaging

// Connections are cached and reused
const connection = await connectionManager.connect({
  nextHop: nextHopAddress,
  target: targetAddress
});

// Send data over the connection
const response = await connection.send({
  address: 'o://target/service',
  payload: { key: 'value' }
});

📚 View detailed Connection System documentation →

3. oHierarchyManager

Manages parent-child relationships between tool nodes

toolNode.hierarchyManager.addChild(childAddress);
toolNode.hierarchyManager.removeChild(childAddress);
console.log(toolNode.hierarchyManager.children);

Advanced Usage

Custom Transport & Connection Implementation

import { oTransport, TransportType, oConnection, oConnectionConfig } from '@olane/o-core';

class MyCustomTransport extends oTransport {
  constructor() {
    super(TransportType.CUSTOM);
  }

  async send(data: any): Promise<any> {
    // Implement your transport logic (HTTP, WebSocket, etc.)
  }
}

// Custom connection implementation
class MyConnection extends oConnection {
  async transmit(request: oRequest): Promise<oResponse> {
    // Implement your connection logic
    const response = await fetch(this.nextHopAddress.toString(), {
      method: 'POST',
      body: request.toString()
    });
    return new oResponse(await response.json());
  }
}

class MyToolNode extends oCore {
  configureTransports(): any[] {
    return [new MyCustomTransport()];
  }
}

📖 For connection pooling, retry logic, middleware, and transport-specific implementations, see the Connection System documentation.

Custom Router Implementation

import { oRouter, RouteResponse } from '@olane/o-core';

class MyRouter extends oRouter {
  async translate(address: oAddress, node: oCore): Promise<RouteResponse> {
    // Implement custom routing logic
    return {
      nextHopAddress: calculatedNextHop,
      targetAddress: address
    };
  }

  isInternal(address: oAddress, node: oCore): boolean {
    // Determine if address is internal to this node
    return address.root === node.address.root;
  }

  async route(request: oRouterRequest, node: oCore): Promise<RouteResponse> {
    // Handle routing requests
  }
}

📖 For advanced routing patterns, custom resolvers, and hierarchical routing strategies, see the Router System documentation.

Error Handling

import { oError, oErrorCodes } from '@olane/o-core';

// In your execute method
async execute(request: oRequest): Promise<any> {
  if (!isValid(request.params)) {
    throw new oError(
      oErrorCodes.INVALID_PARAMS,
      'Invalid parameters provided'
    );
  }

  try {
    return await processRequest(request);
  } catch (error) {
    throw new oError(
      oErrorCodes.EXECUTION_ERROR,
      error.message
    );
  }
}

Graceful Shutdown

import { setupGracefulShutdown } from '@olane/o-core';

const toolNode = new MyToolNode({ address: new oAddress('o://my-toolnode') });
await toolNode.start();

// Setup graceful shutdown handlers
setupGracefulShutdown(async () => {
  console.log('Shutting down gracefully...');
  await toolNode.stop();
});

// Tool node will automatically stop on SIGINT/SIGTERM

API Reference

oCore Class

Abstract base class for building tool nodes.

Properties

  • address: oAddress - The tool node's hierarchical address
  • state: NodeState - Current lifecycle state
  • metrics: oMetrics - Performance and usage metrics
  • hierarchyManager: oHierarchyManager - Manages child nodes
  • router: oRouter - Routing logic
  • connectionManager: oConnectionManager - Connection pooling

Methods

  • async start(): Promise<void> - Start the tool node
  • async stop(): Promise<void> - Stop the tool node gracefully
  • async use(address: oAddress, data?: UseDataConfig, options?: UseOptions): Promise<oResponse> - Communicate with another tool node (IPC). The options parameter supports noRouting, isStream, onChunk, readTimeoutMs, drainTimeoutMs, and abortSignal.
  • async useDirect(address: oAddress, data?: UseDataConfig): Promise<oResponse> - Send a request without routing (equivalent to use() with { noRouting: true })
  • async useStream(address: oAddress, data: UseDataConfig, options: UseStreamOptions): Promise<oResponse> - Send a streaming request to another tool node
  • async execute(request): Promise<any> - Execute a request (abstract - you implement this)
  • addChildNode(node): void - Add a child tool node
  • removeChildNode(node): void - Remove a child tool node
  • async whoami(): Promise<any> - Get tool node information

oAddress Class

Methods

  • validate(): boolean - Validate address format
  • toStaticAddress(): oAddress - Convert to static address
  • toString(): string - Get string representation
  • equals(other): boolean - Compare addresses
  • async toCID(): Promise<CID> - Convert to Content ID

oError Class

Constructor

new oError(code: oErrorCodes, message: string, data?: any)

Methods

  • toJSON(): object - Serialize error
  • static fromJSON(json): oError - Deserialize error

Testing

# Run tests
pnpm test

# Run tests in Node.js
pnpm run test:node

# Run tests in browser
pnpm run test:browser

Development

# Install dependencies
pnpm install

# Build the package
pnpm run build

# Run in development mode
pnpm run dev

# Lint the code
pnpm run lint

Use Cases

o-core enables you to:

  1. Build Specialized Tool Nodes with unique o:// addresses and capabilities
  2. Create Hierarchical Tool Networks that AI agents discover and use
  3. Route Requests Intelligently through tool node hierarchies
  4. Manage Tool Node Lifecycles with automatic cleanup and error handling
  5. Share Knowledge and Capabilities across tool networks through addressable resources

What o-core is NOT

  • Not a network framework - It's the OS kernel for tool nodes
  • Not an orchestration tool - It enables emergent coordination, not explicit workflows
  • Not a REST API - It's a runtime for inter-process communication (IPC)
  • Not a complete solution - It's an abstract foundation; use o-node for production
  • Not what you use directly - Extend it or use higher-level packages (o-node, o-tool, o-lane)

Related Packages

  • @olane/o-protocol - Protocol definitions and types
  • @olane/o-node - Complete node implementation (extends o-core)
  • @olane/o-tool - Tool system for agent capabilities
  • @olane/o-storage - Storage layer for agent state
  • @olane/o-network-cli - CLI for managing agent networks

Component Documentation

For in-depth documentation on specific o-core components, see:

  • Router System - Deep dive into the o:// protocol, address resolution, routing logic, and custom resolvers
  • Connection System - Complete guide to IPC, JSON-RPC messaging, connection pooling, and transport implementations

Documentation

Support

Contributing

We welcome contributions! Please see our Contributing Guide for details.

License

ISC © Olane Inc.


Part of the Olane OS ecosystem - An agentic operating system where AI agents are the users and you build tool nodes as applications.