# How the `installEgoSdk` API Integrates with External Agent Runtimes: Complete Technical Guide

> Explore how the installEgoSdk API integrates with external agent runtimes. This guide details validation, context building, async readiness, console redirection, and safe ego object integration.

- Repository: [CitroLabs/ego-lite](https://github.com/citrolabs/ego-lite)
- Tags: how-to-guide
- Published: 2026-08-25

---

**The `installEgoSdk` API bridges the ego-browser SDK to any JavaScript environment hosting an ego runtime by validating a target object, building a helper context, handling asynchronous readiness, exposing browser helpers, redirecting console output, and safely integrating with the native `ego` object.**

The `installEgoSdk` function in `ego-lite` is the core mechanism that allows external agent runtimes—whether Node.js processes, server-side AI agents, or sandboxed VMs—to access the full browser automation capabilities of the **ego-browser** SDK. This article examines how the API works under the hood, walking through each integration step as implemented in [[`package/ego-browser/src/index.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/index.ts)](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/index.ts).

## Target Validation and Context Building

The integration begins with parameter validation. When `installEgoSdk(target?, options?)` is invoked, the function first ensures the supplied `target` is a valid object, defaulting to `globalThis` if none is provided. If validation fails, the call becomes a no-op at [lines 44-50](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/index.ts#L44-L50).

Next, the SDK constructs the **helper context** ([lines 51-56](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/index.ts#L51-L56)):

- If `options.context` is provided, it is used directly
- Otherwise, the SDK builds its own via `helpers.helperContext()`
- All legacy global helper names (`click`, `goto`, `snapshot`, etc.) are stripped from the target to prevent naming conflicts

This cleanup ensures that repeated calls to `installEgoSdk` do not accumulate stale bindings.

## Asynchronous Readiness and Helper Wrapping

External agents often need to wait for browser initialization before executing automation commands. The SDK handles this through a **readiness signal** mechanism ([lines 57-67](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/index.ts#L57-L67)):

1. A `readySignal` Promise is created from `options.ready` or `Promise.resolve()`
2. Any rejection is captured in `readyError` for error propagation
3. All helpers except `help` (which is in `SYNC_HELPERS`) are wrapped via `wrapReady`

The `wrapReady` utility ensures that wrapped helpers automatically await the `readySignal` before executing and surface any startup failures to the caller. This allows agents to install the SDK immediately but defer actual browser operations until the runtime is fully initialized.

## Exposing Helpers on the Target Object

With the context prepared, the SDK **defines properties** on the target object for each helper ([lines 63-74](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/index.ts#L63-L74)):

- Property descriptors use `writable: true`, `configurable: true`, and `enumerable: false`
- The full set of exposed helpers is cached in an internal `installed` Map
- This Map is later attached to `target.ego.helpers` for introspection

The non-enumerable flag keeps the global namespace clean while maintaining full programmability.

## Console Output Redirection

A critical integration point is **routing agent output** to the host's preferred channel. The SDK overrides `console.log` with either:

- A host-provided `cliLog` function from `options.cliLog`
- A buffered logger via `createBufferedLog()` as fallback

When using the default logger, the output buffer resets and flushes on process teardown ([lines 75-86](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/index.ts#L75-L86)). This guarantees that `console.log`—the primary output channel for many agents—reaches the host infrastructure regardless of how the SDK was loaded.

## Native `ego` Object Integration

If the target already contains an `ego` property (indicating a native runtime presence), the SDK performs deeper integration ([lines 87-114](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/index.ts#L87-L114)):

1. `emitUpdateNotice` appends a version line to the logging channel ([lines 87-95](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/index.ts#L87-L95))
2. `target.ego.helpers` and `target.ego.learnings` are populated with SDK data
3. **Idempotence is enforced** via the `EGO_WRAPPED` Symbol

The Symbol check prevents double-wrapping of mutating methods. On first install, `wrapCreateTab` and `wrapInvalidating` are applied to `ego.createTab` and task-space mutators. Subsequent calls detect `EGO_WRAPPED` and skip wrapping, making `installEgoSdk` safe for repeated invocation.

## Integration Patterns for External Agent Runtimes

### Node-Based Agents

Agents running in Node.js can import and call the API directly:

```javascript
import { installEgoSdk } from 'ego-browser';

installEgoSdk();  // attaches helpers to globalThis

await page.goto('https://example.com');
await click('button#login');

```

The SDK auto-installs on `globalThis` when imported as a library, making helpers instantly available without explicit configuration.

### Custom Host Environments

Hosts with sandboxing requirements can provide their own target and logger:

```javascript
import { installEgoSdk } from 'ego-browser';

const sandbox = {};  // e.g., a VM context created with `vm` module

function hostLogger(...args) {
  host.emit('agentLog', args.join(' '));
}

installEgoSdk(sandbox, {
  cliLog: hostLogger,
  ready: initializeBrowser()
});

await sandbox.goto('https://example.org');  // executes within sandbox

```

This pattern gives hosts full control over output routing while preserving the complete helper surface.

### CLI Execution Mode

When executed directly (`node ego-browser`), the entry point in [[`src/run.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/run.ts)](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/run.ts) detects CLI mode via `isDirectCli()` and routes to `runMain()`. For library usage, automatic installation occurs through the module load path, enabling stdin-delivered scripts to behave as native ego runtime code.

### Idempotent Re-Installation

The SDK safely handles multiple installation attempts:

```javascript
import { installEgoSdk } from 'ego-browser';

installEgoSdk();  // first install: wraps createTab and task-space helpers
installEgoSdk();  // second install: EGO_WRAPPED detected, wrapping skipped

```

This is essential for complex agent architectures where initialization may occur across multiple modules or reload cycles.

## Version Propagation and Update Notices

The [`emitUpdateNotice`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/update-notice.ts) function (from [`src/update-notice.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/update-notice.ts)) sends browser version information through the same channel as `cliLog`. External agents receive runtime version data without additional API calls, simplifying operational monitoring and debugging.

## Summary

- **Target validation** ensures safe installation with meaningful defaults or explicit host-supplied contexts
- **Readiness wrapping** allows asynchronous initialization while preserving synchronous helper ergonomics
- **Console redirection** unifies agent output to host-controlled channels
- **Native `ego` integration** preserves runtime state and enables idempotent operation via `EGO_WRAPPED`
- **Multiple integration patterns** support Node agents, sandboxed VMs, and CLI execution without code changes

## Frequently Asked Questions

### What happens if I call `installEgoSdk` without any arguments?

The SDK defaults `target` to `globalThis` and uses a resolved Promise for readiness. Helpers are attached to the global object, and `console.log` is replaced with a buffered logger. This is the standard pattern for Node-based agents that want immediate global access to browser automation helpers.

### Can I prevent `installEgoSdk` from modifying the global console?

Provide your own `cliLog` function in the options object. When `cliLog` is present, the SDK uses it exclusively and does not override `console.log` with the default buffered implementation. Your logger receives all SDK output plus any agent `console.log` calls.

### How does the SDK avoid breaking when installed multiple times?

The `EGO_WRAPPED` Symbol marks objects whose mutating methods have already been wrapped. On subsequent installations, the Symbol's presence causes `wrapCreateTab` and `wrapInvalidating` to be skipped. Other installation steps remain functional, allowing helpers to be refreshed or re-exposed safely.

### What is the difference between `SYNC_HELPERS` and wrapped helpers?

Only `help` is in `SYNC_HELPERS`; it executes immediately without awaiting readiness. All other helpers are wrapped with `wrapReady`, which pauses execution until the browser runtime signals readiness and propagates any initialization errors. This design lets agents call `help()` for documentation while deferring automation commands.