How to Implement Custom Site-Specific Learnings in ego-lite: A Complete Developer Guide

You implement custom site-specific learnings in ego-lite by creating a folder under skills/ego-browser/learnings/<site-id>/ containing a manifest.json that declares the site's domains and available tools, plus JavaScript files for node-tools and optional browser-tools that the AI agent can execute.

ego-lite is an open-source browser automation framework that lets AI agents extend their capabilities through self-contained, site-specific learning packages. These learnings live in the filesystem as declarative modules requiring no core runtime changes, allowing developers to add new site integrations simply by populating a directory with a manifest and tool scripts.

What Are Site-Specific Learnings in ego-lite?

A site-specific learning is a self-contained package that extends the ego-lite agent's browser automation capabilities for a particular domain. Each learning lives under skills/ego-browser/learnings/<site-id>/ and consists of:

  • A manifest (manifest.json) declaring domains, tool definitions, and metadata
  • Node-tools (tools/*.js) executed in the Node.js runtime side of the agent
  • Browser-tools (browser-tools/*.js) executed inside the actual browser page context
  • Documentation (notes/*.md) for human reference and the help() command

Because the architecture is manifest-driven, you can add new sites without modifying the core runtime—only the new learning folder and its files are required.

The Learning Subsystem Architecture

When the ego-lite runtime starts, it automatically discovers and registers all learnings through a three-phase process:

Discovery Phase

The learningsRoot() function in [src/learning/check-domain-learning.ts](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/learning/check-domain-learning.ts) returns the absolute path to skills/ego-browser/learnings. The system walks this directory to find all available site folders.

Validation Phase

Each discovered manifest.json undergoes schema validation via validateLearnings() in [src/learning/validate-learning-format.ts](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/learning/validate-learning-format.ts). Required fields include id, name, domains, and either nodeTools or browserTools. Malformed manifests emit clear errors preventing runtime loading.

Indexing Phase

The loadLearnings() function in [src/learning/index.ts](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/learning/index.ts) reads every valid manifest and builds lookup tables that helper functions later use to resolve tool calls.

Execution Phase

When an agent script invokes runSiteTool(), the helper layer in [src/helpers.ts](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts) resolves the request, loads the referenced JavaScript file, and executes it. Node-tools are required as modules (require(path)), while browser-tools are sent to the page via await browserFetch and executed with await js(...).

Step-by-Step: Creating a Custom Learning

Follow these seven steps to implement a new site-specific learning:

  1. Create the learning directory under skills/ego-browser/learnings/ using a unique ID (e.g., my-site).

  2. Add the manifest at skills/ego-browser/learnings/my-site/manifest.json to declare domains and expose tools.

  3. Write node-tool scripts in tools/. Each file must export a single async function matching the callable name defined in the manifest.

  4. (Optional) Write browser-tool scripts in browser-tools/. These execute inside the browser context for DOM manipulation.

  5. Add markdown notes in notes/ to describe the learning for humans and the help() command.

  6. Validate the learning by running npm run validate:site-skills or npm test, which exercises the validation code in validateLearnings.

  7. Use the tool from an agent script via await runSiteTool('my-site', '<tool-id>', args).

Code Implementation Examples

Minimal Manifest Configuration

Create skills/ego-browser/learnings/my-site/manifest.json:

{
  "id": "my-site",
  "name": "My Site",
  "domains": ["mysite.com", "*.mysite.com"],
  "notes": ["notes/overview.md"],
  "nodeTools": {
    "extract_info": {
      "description": "Extract title and description from the current page.",
      "path": "tools/extract-info.js",
      "callable": "extractInfo",
      "args": {},
      "returns": {
        "type": "object",
        "description": "Object with `title` and `description` strings."
      }
    }
  }
}

Reference: See the Google learning manifest at [skills/ego-browser/learnings/google/manifest.json](https://github.com/citrolabs/ego-lite/blob/main/skills/ego-browser/learnings/google/manifest.json) for a production example.

Node-Tool Implementation

Create skills/ego-browser/learnings/my-site/tools/extract-info.js:

/** @type {import('..').NodeToolFn} */
module.exports = async function extractInfo (_, { cliLog }) {
  // Use the browser-side helper to get the page's title.
  await cliLog('Running js to fetch title...');
  const title = await cliLog(await js(String.raw`document.title`));

  // Grab the meta description (if any).
  const description = await cliLog(
    await js(String.raw`
      const meta = document.querySelector('meta[name="description"]');
      meta ? meta.content : ''
    `)
  );

  return { title, description };
};

When the agent calls runSiteTool('my-site', 'extract_info'), ego-lite loads this module and executes the exported extractInfo function.

Browser-Tool Implementation

Create skills/ego-browser/learnings/my-site/browser-tools/get-data.js:

// This script runs inside the page context.
export async function getData () {
  const items = [...document.querySelectorAll('.item')].map(el => ({
    text: el.innerText,
    href: el.querySelector('a')?.href || null,
  }));
  return items;
}

Expose it in the manifest under browserTools:

"browserTools": {
  "get_page_items": {
    "description": "Return a list of visible items on the page.",
    "path": "browser-tools/get-data.js",
    "args": {}
  }
}

Agents invoke this with await runBrowserTool('my-site', 'get_page_items').

Calling Tools from Agent Scripts

Use the learning in a heredoc executed with ego-browser nodejs:

const task = await useOrCreateTaskSpace('my-site data extraction');
await openOrReuseTab('https://mysite.com/some-page', { wait: true });

const data = await runSiteTool('my-site', 'extract_info');
cliLog('Extracted data:');
cliLog(JSON.stringify(data, null, 2));

Key Source Files Reference

File Purpose
skills/ego-browser/learnings/<site>/manifest.json Declarative description of a learning (domains, tools, notes). Example: google/manifest.json
package/ego-browser/src/learning/check-domain-learning.ts Determines the filesystem root of all learnings via learningsRoot().
package/ego-browser/src/learning/validate-learning-format.ts Validates each manifest.json against the required schema via validateLearnings().
package/ego-browser/src/learning/index.ts Loads all learnings at startup and builds lookup tables via loadLearnings().
package/ego-browser/src/helpers.ts Exposes the public helper surface (runSiteTool, runBrowserTool, etc.) to agent scripts.

Summary

  • Site-specific learnings are self-contained packages under skills/ego-browser/learnings/<site-id>/ that extend ego-lite without modifying core code.
  • The discovery system automatically finds learnings at startup, validates their manifests, and registers their tools.
  • Node-tools run in the Node.js context and can invoke browser-side code, while browser-tools execute directly inside the page.
  • Required components include a valid manifest.json (with id, name, domains, and tool definitions) and JavaScript files exporting async functions.
  • Validation via npm run validate:site-skills ensures manifests meet the schema before runtime.

Frequently Asked Questions

What is the difference between node-tools and browser-tools in ego-lite?

Node-tools execute in the Node.js runtime side of the agent and can access the full server-side environment, including the ability to call browserFetch or js() to interact with the page. Browser-tools are JavaScript files sent directly to the browser page context via await js() and execute within the page's sandbox, making them ideal for DOM queries that need access to the page's global state or elements.

Where does ego-lite store custom site-specific learnings?

According to the source code in src/learning/check-domain-learning.ts, ego-lite resolves learnings to skills/ego-browser/learnings/ relative to the installation root. Each learning must be a subdirectory named with a unique site ID, containing a manifest.json and optional tools/ and browser-tools/ directories.

How does ego-lite validate custom learning manifests?

The validateLearnings() function in src/learning/validate-learning-format.ts ensures every manifest.json contains required fields: id, name, domains, and tool definitions (nodeTools or browserTools). If validation fails, the system emits a clear error indicating the offending field, preventing the malformed learning from loading at runtime.

Can I use wildcards in domain patterns for site-specific learnings?

Yes. The domains array in the manifest supports wildcard patterns such as *.mysite.com to match subdomains. When the agent navigates to a URL, ego-lite matches the hostname against these patterns to determine which learning's tools are available for that session.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →