How Site Skills (Learnings) Work in ego-lite: Discovery, Loading, and Validation

Site skills in ego-lite are reusable, per-site knowledge packs stored under skills/ego-browser/learnings/ that provide agents with contextual notes, selectors, and executable tools—all validated through a strict schema enforcement system before runtime use.

In ego-lite, site-specific intelligence isn't hardcoded. Instead, the framework uses a modular learning subsystem that lets you package knowledge for any website into version-controlled directories. This article explains how these learnings are structured, discovered, loaded into the agent runtime, and rigorously validated to ensure reliability.


What Site Skills (Learnings) Actually Are

A site learning is a directory named after its site ID (e.g., google, x-com) containing four core components:

Component Location Purpose
manifest.json learnings/<site>/manifest.json Declares site ID, human-readable name, domain patterns, note files, and tool definitions
Knowledge notes learnings/<site>/notes/*.md Markdown documentation with site descriptions and selector hints
Node tools learnings/<site>/tools/*.js Server-side JS modules with callable functions
Browser tools learnings/<site>/browser-tools/*.js Client-side JS snippets executed via site.runBrowserTool

The runtime discovers and loads these learnings dynamically through the learning subsystem in package/ego-browser/src/learning/.


How Site Skills Are Discovered and Loaded

The loading pipeline involves three distinct phases: domain matching, context assembly, and tool execution.

Domain Matching

When an agent requests knowledge for a URL, siteSkillsForUrl() in check-domain-learning.ts extracts the hostname and iterates over every learning directory via iterLearningDirs. It keeps only those learnings whose manifest.domains field matches the host—supporting both exact matches and wildcards like *.example.com.

// Discover learnings for a URL
const { siteSkillsForUrl } = await import('ego-browser');
const matches = await siteSkillsForUrl('https://news.x.com/articles/123');
console.log(matches.map(m => m.id)); // → ["x-com"]

The domainMatches function handles pattern evaluation, comparing the extracted urlHostname against each declared domain pattern.

Context Assembly

loadLearnedContext (exported from index.ts) orchestrates the full loading process. It calls siteSkillsForUrl() to gather matching learnings, then reads each note file and builds tool signatures for both node and browser tools. The result is a LearnedContext object consumed through helpers like site.runTool() and site.runBrowserTool().

// Load the full learned context (notes + tool signatures)
import { loadLearnedContext } from 'ego-browser';
const ctx = await loadLearnedContext('https://google.com');
if (ctx.exists) {
  console.log('Site name:', ctx.siteName);
  console.log('Available tools:', ctx.tools.map(t => t.toolName));
  console.log('Notes files:', ctx.knowledge.map(n => n.fileName));
}

Tool Execution

  • Node tools: Dynamically imported via import() through runNodeSiteTool in index.ts, then invoked with the exported callable function
  • Browser tools: Read as plain text via loadBrowserToolSource(), wrapped in an async IIFE via wrapBrowserTool(), and executed via site.runBrowserTool()
// Running a node-tool from a learning
await site.runTool('google', 'search', { query: 'open source AI' });
// Loads skills/ego-browser/learnings/google/tools/search.js and invokes the exported callable

All learning helpers are exposed to agents through helperContext() in src/helpers.ts.


The Site Skills Validation Process

Before any learning can be used, it must pass comprehensive schema validation implemented in validate-learning-format.ts. The validateLearning() and validateLearnings() functions enforce a strict contract across six validation layers.

Manifest Validation

The validator confirms:

  • manifest.json exists and parses as valid JSON
  • id matches the directory name exactly
  • name is non-empty
  • domains is a non-empty array of well-formed patterns

Domain Pattern Checks

Each domain must be either:

  • A plain hostname (example.com)
  • A single leading wildcard (*.example.com)

The isValidDomain() function rejects malformed patterns.

Note File Verification

Every entry in manifest.notes must:

  • Use relative paths matching notes/*.md
  • Point to existing files (verified via requireFile)
  • Exclude temporary snapshot references (blocked by rejectTemporaryRefs)

This prevents agents from relying on fragile, auto-generated selectors that break on page changes.

Tool Schema Enforcement

Tool Type Requirements
Node tools Relative tools/*.js path, non-empty callable name, valid args/returns schema; JS file is imported to verify callable exists
Browser tools Relative browser-tools/*.js path, valid argument/return schemas; source checked for temporary refs

Value Type Constraints

Argument and return schemas are restricted to JSON-Schema primitives defined in TOOL_VALUE_TYPES. This ensures type-safe serialization between the agent runtime and tool implementations.

Safety Sanitization

Tool names and paths undergo isSafeToolName() and isSafeRelativePath() checks to prevent:

  • Directory traversal attacks
  • Malformed identifiers
  • Path injection vulnerabilities

Running Validation

The top-level entry point validateLearnings() (exported as validateSiteSkills) walks all learning directories via iterLearningDirs() and aggregates errors. The repository includes a CLI convenience script:


# Validate all site skills in the repository

node package/ego-browser/scripts/validate-site-skills.ts

# Exits code 0 when all learnings pass; prints detailed errors otherwise

Why Site Skill Validation Matters

  • Selector stability — Rejecting temporary refs (@123 or ref=123) forces durable, maintainable locators
  • Runtime reliability — Catches missing files and malformed manifests before deployment
  • Deterministic contracts — Tool argument/return schemas enable automatic documentation generation via site.runTool().help()

Summary

  • Site skills in ego-lite are modular knowledge packs under skills/ego-browser/learnings/<site-id>/
  • Discovery uses hostname matching against manifest.domains patterns in check-domain-learning.ts
  • Full context loading combines notes and tool signatures via loadLearnedContext() in index.ts
  • Node tools execute server-side via dynamic import(); browser tools inject into page context
  • Six-layer validation in validate-learning-format.ts enforces manifest integrity, domain correctness, file existence, schema compliance, type safety, and path sanitization
  • Use validateLearnings() or scripts/validate-site-skills.ts to verify learnings before runtime use

Frequently Asked Questions

How do I create a new site skill for ego-lite?

Create a directory under skills/ego-browser/learnings/ named with your site ID (e.g., my-site). Add a manifest.json declaring id, name, and domains. Place Markdown notes in notes/ and JavaScript tools in tools/ (server-side) or browser-tools/ (client-side). Run the validation script to verify your learning passes all checks before committing.

What happens if a learning fails validation?

validateLearnings() collects all errors and returns them in detail—manifest syntax failures, missing files, invalid domain patterns, schema mismatches, or temporary snapshot references. The CLI script exits with a non-zero status code, blocking CI/CD pipelines from deploying broken learnings.

Can site skills use wildcards in domain patterns?

Yes. The domainMatches function supports *.example.com patterns for subdomain matching. However, wildcards are restricted to a single leading asterisk—patterns like example.*.com are rejected by isValidDomain() to prevent ambiguous matching.

Where does ego-lite load site skills from at runtime?

The iterLearningDirs() function scans skills/ego-browser/learnings/ relative to the working directory. This discovery happens dynamically in siteSkillsForUrl() and loadLearnedContext(), allowing hot-reloading of learnings without restarting the agent runtime.

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 →