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-login

v0.8.3

Published

Olane interface for agents to login to olane OS

Readme

@olane/o-login

Login interface for agents to connect to Olane OS.

o-login enables both human and AI agents to authenticate and interact with Olane OS by registering themselves as addressable nodes on the network. Once logged in, agents can receive intents, answer questions, and process streamed data.

TL;DR: Use oHumanLoginTool for human agents or oAILoginTool for AI agents. Provide callback functions to handle intents, questions, and streams.


Quick Start {#quick-start}

Installation

npm install @olane/o-login

Minimal Example: Human Agent Login

import { oHumanLoginTool } from '@olane/o-login';

// Create a human agent login
const humanAgent = new oHumanLoginTool({
  respond: async (intent: string) => {
    // Handle intents sent to this agent
    console.log('Received intent:', intent);
    return 'Intent resolved successfully';
  },
  answer: async (question: string) => {
    // Answer questions sent to this agent
    console.log('Received question:', question);
    return 'Here is my answer';
  },
  receiveStream: async (data: any) => {
    // Handle streamed data
    console.log('Received stream:', data);
  }
});

// Start the agent
await humanAgent.start();

// Now reachable at o://human
console.log('Human agent is online at:', humanAgent.address.toString());

Minimal Example: AI Agent Login

import { oAILoginTool } from '@olane/o-login';

// Create an AI agent login
const aiAgent = new oAILoginTool({
  respond: async (intent: string) => {
    // AI processes the intent
    const result = await processWithAI(intent);
    return result;
  },
  answer: async (question: string) => {
    // AI answers the question
    const answer = await aiAnswers(question);
    return answer;
  },
  receiveStream: async (data: any) => {
    // AI processes streamed data
    await processStream(data);
  }
});

// Start the AI agent
await aiAgent.start();

// Now reachable at o://ai
console.log('AI agent is online at:', aiAgent.address.toString());

How It Works {#how-it-works}

When you create and start a login tool, you're registering an agent node on Olane OS. This node:

  1. Becomes addressable - Gets an o:// address (default: o://human or o://ai)
  2. Exposes tools - Three built-in tools: intent, question, and receive_stream
  3. Handles requests - Routes incoming requests to your callback functions
  4. Maintains connection - Stays online and responsive until stopped

Visual Flow:

┌─────────────────────────────────────────────────────────────┐
│  Other Nodes/Agents                                         │
│  (anywhere on Olane OS)                                     │
└──────────────────┬──────────────────────────────────────────┘
                   │
                   │ Send intent/question/stream
                   ⬇
┌─────────────────────────────────────────────────────────────┐
│  o-login Node (o://human or o://ai)                        │
│                                                             │
│  ┌─────────────┐  ┌─────────────┐  ┌──────────────┐       │
│  │ _tool_intent│  │_tool_question│ │_tool_receive_ │       │
│  │             │  │              │  │   stream      │       │
│  └──────┬──────┘  └──────┬───────┘  └──────┬───────┘       │
│         │                │                  │               │
│         ⬇                ⬇                  ⬇               │
│  ┌──────────────────────────────────────────────────┐      │
│  │  Your Callback Functions                         │      │
│  │  • respond(intent)                               │      │
│  │  • answer(question)                              │      │
│  │  • receiveStream(data)                           │      │
│  └──────────────────────────────────────────────────┘      │
└─────────────────────────────────────────────────────────────┘

API Reference {#api-reference}

oHumanLoginTool

Creates a login node for human agents.

Constructor:

new oHumanLoginTool(config: oLoginConfig)

Parameters:

  • config (object, required): Configuration object
    • respond (function, required): Async function to handle intents
      • Signature: (intent: string) => Promise<string>
      • Returns: Resolution message
    • answer (function, required): Async function to answer questions
      • Signature: (question: string) => Promise<string>
      • Returns: Answer string
    • receiveStream (function, required): Async function to handle streams
      • Signature: (data: any) => Promise<any>
      • Returns: Processing result (optional)
    • address (oNodeAddress, optional): Custom address (default: o://human)
    • leader (oAddress, optional): Leader node address for network registration
    • parent (oAddress, optional): Parent node address

Example:

const humanAgent = new oHumanLoginTool({
  // Custom address
  address: new oNodeAddress('o://team/alice'),
  
  // Handle intents
  respond: async (intent: string) => {
    if (intent.includes('approve')) {
      return 'Request approved';
    }
    return 'Request pending review';
  },
  
  // Answer questions
  answer: async (question: string) => {
    return `Human response to: ${question}`;
  },
  
  // Handle streamed data
  receiveStream: async (data: any) => {
    console.log('Processing stream chunk:', data);
  }
});

await humanAgent.start();

oAILoginTool

Creates a login node for AI agents.

Constructor:

new oAILoginTool(config: oLoginConfig)

Parameters: Same as oHumanLoginTool, but with default address o://ai.

Example:

import { oAILoginTool } from '@olane/o-login';
import OpenAI from 'openai';

const openai = new OpenAI();

const aiAgent = new oAILoginTool({
  // AI processes intents
  respond: async (intent: string) => {
    const completion = await openai.chat.completions.create({
      model: 'gpt-4',
      messages: [{ role: 'user', content: intent }]
    });
    return completion.choices[0].message.content;
  },
  
  // AI answers questions
  answer: async (question: string) => {
    const completion = await openai.chat.completions.create({
      model: 'gpt-4',
      messages: [{ role: 'user', content: question }]
    });
    return completion.choices[0].message.content;
  },
  
  // AI processes streams
  receiveStream: async (data: any) => {
    // Process incoming data
    await processDataWithAI(data);
  }
});

await aiAgent.start();

oLoginTool (Base Class)

Base class for all login tools. Extends oLaneTool from @olane/o-lane.

You can extend this directly for custom agent types:

import { oLoginTool } from '@olane/o-login';
import { oNodeAddress } from '@olane/o-node';

class CustomAgentLogin extends oLoginTool {
  constructor() {
    super({
      address: new oNodeAddress('o://custom-agent'),
      respond: async (intent: string) => {
        // Custom intent handling
        return 'Custom response';
      },
      answer: async (question: string) => {
        // Custom question handling
        return 'Custom answer';
      },
      receiveStream: async (data: any) => {
        // Custom stream handling
      }
    });
  }
}

Built-in Tools {#built-in-tools}

Every login node exposes three tools:

_tool_intent

Handles intent-based requests.

Parameters:

  • intent (string, required): The intent to resolve

Returns:

{
  success: boolean;
  resolution: string;
}

Example Usage (from another node):

// Another node sends an intent to the human agent
const result = await humanAgent.use({
  method: 'intent',
  params: {
    intent: 'Please approve the budget request for Q4'
  }
});

console.log(result.resolution);
// "Request approved" (based on your respond callback)

_tool_question

Handles question-answer requests.

Parameters:

  • question (string, required): The question to answer

Returns:

{
  success: boolean;
  answer: string;
}

Example Usage (from another node):

// Another node asks a question
const result = await aiAgent.use({
  method: 'question',
  params: {
    question: 'What is the capital of France?'
  }
});

console.log(result.answer);
// "Paris" (based on your answer callback)

_tool_receive_stream

Handles streamed data.

Parameters:

  • data (any, required): The data to process

Returns:

{
  success: boolean;
}

Example Usage (from another node):

// Another node streams data
await humanAgent.use({
  method: 'receive_stream',
  params: {
    data: { type: 'notification', message: 'System update available' }
  }
});

Common Use Cases {#common-use-cases}

Use Case 1: Human-in-the-Loop Approval System

Create a human agent that approves or rejects automated actions.

import { oHumanLoginTool } from '@olane/o-login';
import readline from 'readline';

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

const humanApprover = new oHumanLoginTool({
  address: new oNodeAddress('o://approvals/human'),
  
  respond: async (intent: string) => {
    // Prompt human for approval
    return new Promise((resolve) => {
      rl.question(`Approve this action? "${intent}" (y/n): `, (answer) => {
        if (answer.toLowerCase() === 'y') {
          resolve('Approved by human operator');
        } else {
          resolve('Rejected by human operator');
        }
      });
    });
  },
  
  answer: async (question: string) => {
    return new Promise((resolve) => {
      rl.question(`${question}\nYour answer: `, resolve);
    });
  },
  
  receiveStream: async (data: any) => {
    console.log('[Human Dashboard] Received:', data);
  }
});

await humanApprover.start();
console.log('Human approver is online. Awaiting approval requests...');

Use Case 2: AI Assistant with Context

Create an AI agent that maintains conversation context.

import { oAILoginTool } from '@olane/o-login';
import OpenAI from 'openai';

const openai = new OpenAI();
const conversationHistory: any[] = [];

const aiAssistant = new oAILoginTool({
  address: new oNodeAddress('o://ai/assistant'),
  
  respond: async (intent: string) => {
    // Add to conversation history
    conversationHistory.push({
      role: 'user',
      content: intent
    });
    
    // Get AI response with context
    const completion = await openai.chat.completions.create({
      model: 'gpt-4',
      messages: conversationHistory
    });
    
    const response = completion.choices[0].message.content;
    
    // Store AI response in history
    conversationHistory.push({
      role: 'assistant',
      content: response
    });
    
    return response;
  },
  
  answer: async (question: string) => {
    // Similar to respond, but for direct questions
    conversationHistory.push({
      role: 'user',
      content: question
    });
    
    const completion = await openai.chat.completions.create({
      model: 'gpt-4',
      messages: conversationHistory
    });
    
    return completion.choices[0].message.content;
  },
  
  receiveStream: async (data: any) => {
    // Process streamed data (e.g., document chunks)
    conversationHistory.push({
      role: 'system',
      content: `Context data received: ${JSON.stringify(data)}`
    });
  }
});

await aiAssistant.start();

Use Case 3: Multi-Agent System

Create both human and AI agents working together.

import { oHumanLoginTool, oAILoginTool } from '@olane/o-login';
import { oNodeAddress } from '@olane/o-node';

// AI agent handles routine questions
const aiSupport = new oAILoginTool({
  address: new oNodeAddress('o://support/ai'),
  
  respond: async (intent: string) => {
    // Check if AI can handle this
    if (intent.includes('complex') || intent.includes('escalate')) {
      // Forward to human
      const humanResult = await humanSupport.use({
        method: 'intent',
        params: { intent }
      });
      return `Escalated to human: ${humanResult.resolution}`;
    }
    
    // AI handles routine intents
    return 'AI resolved the routine request';
  },
  
  answer: async (question: string) => {
    return 'AI answer to routine question';
  },
  
  receiveStream: async (data: any) => {
    console.log('[AI] Processing:', data);
  }
});

// Human agent handles escalations
const humanSupport = new oHumanLoginTool({
  address: new oNodeAddress('o://support/human'),
  
  respond: async (intent: string) => {
    console.log('[Human] Handling escalated request:', intent);
    // Human decides on action
    return 'Human resolved complex request';
  },
  
  answer: async (question: string) => {
    console.log('[Human] Answering complex question:', question);
    return 'Human answer to complex question';
  },
  
  receiveStream: async (data: any) => {
    console.log('[Human] Reviewing:', data);
  }
});

// Start both agents
await aiSupport.start();
await humanSupport.start();

console.log('Multi-agent support system is online');
console.log('AI Support:', aiSupport.address.toString());
console.log('Human Support:', humanSupport.address.toString());

Integration with Other Nodes {#integration}

Login nodes can interact with any other node on Olane OS.

Example: Agent Receives Work from Another Node

import { oHumanLoginTool } from '@olane/o-login';
import { oLaneTool } from '@olane/o-lane';
import { oNodeAddress } from '@olane/o-node';

// Create a task processor node
const taskProcessor = new oLaneTool({
  address: new oNodeAddress('o://tasks/processor')
});

// Create human agent that receives tasks
const humanWorker = new oHumanLoginTool({
  address: new oNodeAddress('o://workers/human'),
  
  respond: async (intent: string) => {
    console.log('New task:', intent);
    // Process the task
    return 'Task completed';
  },
  
  answer: async (question: string) => {
    return 'Status: Working';
  },
  
  receiveStream: async (data: any) => {
    console.log('Task update:', data);
  }
});

await taskProcessor.start();
await humanWorker.start();

// Task processor sends work to human
const result = await humanWorker.use({
  method: 'intent',
  params: {
    intent: 'Review and approve the financial report'
  }
});

console.log('Result:', result.resolution);

Advanced Configuration {#advanced-configuration}

Custom Address

Override the default address:

const agent = new oHumanLoginTool({
  address: new oNodeAddress('o://company/team/alice'),
  respond: async (intent) => 'resolved',
  answer: async (question) => 'answered',
  receiveStream: async (data) => {}
});

Network Registration with Leader

Connect to a leader node for service discovery:

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

const agent = new oHumanLoginTool({
  leader: new oAddress('o://network/leader'),
  respond: async (intent) => 'resolved',
  answer: async (question) => 'answered',
  receiveStream: async (data) => {}
});

await agent.start();

// Now discoverable by other nodes through the leader

Hierarchical Agents

Create agent hierarchies:

// Parent agent
const parentAgent = new oHumanLoginTool({
  address: new oNodeAddress('o://team/manager'),
  respond: async (intent) => 'Manager approved',
  answer: async (question) => 'Manager answered',
  receiveStream: async (data) => {}
});

await parentAgent.start();

// Child agent
const childAgent = new oAILoginTool({
  address: new oNodeAddress('o://team/assistant'),
  parent: parentAgent.address,
  respond: async (intent) => {
    // Escalate to parent if needed
    if (intent.includes('urgent')) {
      const result = await parentAgent.use({
        method: 'intent',
        params: { intent }
      });
      return result.resolution;
    }
    return 'Assistant handled';
  },
  answer: async (question) => 'Assistant answered',
  receiveStream: async (data) => {}
});

await childAgent.start();

Lifecycle Management {#lifecycle}

Starting an Agent

const agent = new oHumanLoginTool({
  respond: async (intent) => 'resolved',
  answer: async (question) => 'answered',
  receiveStream: async (data) => {}
});

// Start the agent (becomes addressable)
await agent.start();
console.log('Agent online at:', agent.address.toString());

Stopping an Agent

// Gracefully stop the agent
await agent.stop();
console.log('Agent offline');

Error Handling

const agent = new oHumanLoginTool({
  respond: async (intent: string) => {
    try {
      // Your logic
      return 'Success';
    } catch (error) {
      console.error('Error handling intent:', error);
      return 'Failed to process intent';
    }
  },
  
  answer: async (question: string) => {
    try {
      // Your logic
      return 'Answer';
    } catch (error) {
      console.error('Error answering question:', error);
      return 'Failed to answer question';
    }
  },
  
  receiveStream: async (data: any) => {
    try {
      // Your logic
    } catch (error) {
      console.error('Error processing stream:', error);
    }
  }
});

Troubleshooting {#troubleshooting}

Error: "Address already in use"

Cause: Another agent is already using the default address (o://human or o://ai).

Solution: Provide a custom address:

const agent = new oHumanLoginTool({
  address: new oNodeAddress('o://team/alice'),
  // ... other config
});

Error: "Cannot connect to leader"

Cause: Leader node is not reachable or not running.

Solution:

  1. Verify leader is running
  2. Check leader address is correct
  3. Or start without leader for local-only operation:
const agent = new oHumanLoginTool({
  leader: null,  // No leader needed for local testing
  // ... other config
});

Callback Function Not Called

Cause: Request is using wrong method name or parameters.

Solution: Verify the calling code uses correct method names:

  • Use method: 'intent' (not respond)
  • Use method: 'question' (not answer)
  • Use method: 'receive_stream' (not receiveStream)

TypeScript Type Errors

Cause: Missing peer dependencies.

Solution: Install all peer dependencies:

npm install @olane/o-core @olane/o-config @olane/o-protocol @olane/o-tool @olane/o-lane @olane/o-node

Comparison: Human vs AI Login {#comparison}

| Aspect | oHumanLoginTool | oAILoginTool | |--------|-------------------|----------------| | Default Address | o://human | o://ai | | Use Case | Human approval, oversight, decision-making | Automated processing, AI reasoning | | Response Time | Slower (human input required) | Faster (automated) | | Context Handling | Can interpret nuance | Requires context management | | Best For | Approvals, complex decisions | Routine questions, data processing |


Architecture {#architecture}

o-login nodes are complex nodes that use the o-lane capability loop for intent processing.

┌─────────────────────────────────────────────────────────────┐
│  o-login (extends oLaneTool)                                │
│                                                             │
│  Capabilities:                                              │
│  • Intent-driven interaction (via o-lane)                   │
│  • Addressable node (via o-node)                            │
│  • Tool discovery (via o-tool)                              │
│  • Network registration (via o-leader)                      │
│                                                             │
│  Three exposed tools:                                       │
│  • _tool_intent                                             │
│  • _tool_question                                           │
│  • _tool_receive_stream                                     │
└─────────────────────────────────────────────────────────────┘

Related Concepts:


TypeScript Support {#typescript}

Full TypeScript definitions included:

import { oLoginConfig } from '@olane/o-login';

// Config interface
interface oLoginConfig extends oNodeConfig {
  respond: (intent: string) => Promise<string>;
  answer: (intent: string) => Promise<string>;
  receiveStream: (data: any) => Promise<any>;
}

// Type-safe usage
const config: oLoginConfig = {
  respond: async (intent: string): Promise<string> => {
    return 'resolved';
  },
  answer: async (question: string): Promise<string> => {
    return 'answered';
  },
  receiveStream: async (data: any): Promise<any> => {
    console.log(data);
  }
};

Related Packages {#related-packages}


Next Steps {#next-steps}

Learn More:

Build an Agent System:

  1. Create AI agent for routine tasks
  2. Create human agent for escalations
  3. Implement escalation logic
  4. Connect to existing nodes

Integrate with Your App:

  1. Install @olane/o-login
  2. Create agent login for your app
  3. Handle intents and questions
  4. Connect to Olane OS network

Documentation {#documentation}

Support {#support}

License

ISC © Olane Inc.


Part of the Olane OS ecosystem - An agentic operating system where AI agents are the intelligent users, and you build the specialized tool nodes they use.