Skip to main content

Overview

Kernel is a platform that provides infrastructure for running browser and computer using agents. You can run your browser agents on Kernel to get top tier performance and developer experience. Kernel’s SDKs are tightly integrated with Laminar, allowing you to trace your agents down to the LLM calls and browser/computer actions.
A version of this guide is available in Kernel’s documentation.

Advantages of using Kernel

  • Reliable infrastructure and quick computer startup times.
  • Reusable sessions, cookies, browser history and more.
  • Stealth mode for browser automation avoids blockers and CAPTCHAs.
  • Framework agnostic automations – you can use any browser framework you want.

Prerequisites

  1. A Kernel account.
  2. A Laminar account or a self-hosted instance.
  3. API keys for both Kernel and Laminar set as KERNEL_API_KEY and LMNR_PROJECT_API_KEY environment variables.

Getting Started

Installation

  • JavaScript/TypeScript
  • Python
npm install @lmnr-ai/lmnr @onkernel/sdk

Setting up API keys

  1. Signup on the Kernel dashboard.
  2. Create an API key during the onboarding process or in the API keys page.
  3. Store the API key in the KERNEL_API_KEY environment variable.
  4. Create a Laminar project.
  5. Navigate to the project settings and create a new project API key.
export KERNEL_API_KEY=<your-kernel-api-key>
export LMNR_PROJECT_API_KEY=<your-laminar-project-api-key>

Running agents on Kernel

Browser Use

Laminar provides observability for Browser Use and Kernel, so if you host your Browser Use agents on Kernel, you will get full observability of both the browser agent and the computer interactions. Full guide on browser-use integration
import os
import asyncio
from lmnr import Laminar, observe
from browser_use import Agent, Browser, ChatGoogle
from kernel import Kernel

# Initialize Laminar
Laminar.initialize(project_api_key=os.environ["LMNR_PROJECT_API_KEY"])

@observe()
async def main():
    # Initialize Kernel and create a browser
    client = Kernel()
    kernel_browser = client.browsers.create(
        stealth=True,
        viewport={'width': 1920, 'height': 1080},
    )

    print(f"Live view url: {kernel_browser.browser_live_view_url}")

    # Configure Browser Use with Kernel's CDP URL
    browser = Browser(
        cdp_url=kernel_browser.cdp_ws_url,
        headless=False,
        window_size={'width': 1920, 'height': 1080},
        viewport={'width': 1920, 'height': 1080},
        device_scale_factor=1.0
    )

    # Initialize the model. Don't forget to set GOOGLE_API_KEY env variable.
    llm = ChatGoogle(
        model="gemini-2.5-flash",
    )

    # Create and run the agent with job extraction task
    agent = Agent(
        task="""
        Go to duckduckgo.com and search for "browser agent observability".
        """,
        llm=llm,
        browser_session=browser
    )

    result = await agent.run()
    print(f"Job URLs found:\n{result.final_result()}")


    # Delete the browser for those who left open the live view url
    client.browsers.delete_by_id(kernel_browser.session_id)

asyncio.run(main())
# Flush traces to Laminar
Laminar.flush()

Playwright

You can use Laminar to trace your Playwright browser sessions hosted on Kernel.
  • JavaScript/TypeScript
  • Python
import { Laminar } from '@lmnr-ai/lmnr';
import Kernel from '@onkernel/sdk';
import { chromium } from 'playwright';

// Initialize Laminar with Playwright and Kernel instrumentations
Laminar.initialize({
  instrumentModules: {
    playwright: {
      chromium
    },
    kernel: Kernel
  }
});

// Initialize Kernel and create a cloud browser
const kernel = new Kernel();

const main = async () => {
  const kernelBrowser = await kernel.browsers.create({
    stealth: true,
  });

  console.log("Live view url:", kernelBrowser.browser_live_view_url);

  // Connect Playwright to Kernel's browser via CDP
  const browser = await chromium.connectOverCDP(kernelBrowser.cdp_ws_url);
  // Use existing context and page or create a new one
  const context = browser.contexts()[0] || (await browser.newContext());
  const page = context.pages()[0] || (await context.newPage());

  // Your automation code
  await page.goto('https://www.duckduckgo.com/')
  await page.waitForTimeout(2000)
  await page.goto('https://www.github.com/trending');

  // Wait for 2 seconds
  await page.waitForTimeout(2000);

  // Extract all trending repos
  const trendingRepos = await page.locator("h2 a.Link").evaluateAll((repos) => 
    repos.map((repo) => repo.textContent.trim().replace(/[\n\s]/g, ''))
  );

  console.log('Trending repos:', trendingRepos);
  await page.waitForTimeout(2000);

  // Clean up the browser and flush traces to Laminar
  await browser.close();
  await Laminar.flush();

  // Delete the browser
  await kernel.browsers.deleteByID(kernelBrowser.session_id);
}

main().catch(console.error);

Deploying Kernel apps and using Kernel’s Computer and Process APIs

When you use Kernel’s App platform or use their Computer controls, Laminar will trace the computer and process interactions. In addition, you don’t have to observe your kernel app.actions and worry about manual trace flushing inside your Kernel apps.
Laminar will take care of trace lifecycle automatically.
As a result of the example below, you will see the following in the Laminar UI: Kernel app trace

Example Kernel app with Laminar tracing

To deploy this example on Kernel, follow the steps in Kernel’s documentation.
  • JavaScript/TypeScript
  • Python
import { Laminar } from '@lmnr-ai/lmnr';
import { chromium } from 'playwright';
import { config } from 'dotenv';
import Kernel, { type KernelContext } from "@onkernel/sdk";

config();


Laminar.initialize({
  instrumentModules: {
    playwright: {
      chromium,
    },
    kernel: Kernel,
  }
});
const kernel = new Kernel();
const app = kernel.app('my-app-name');

app.action('my-action', async (ctx: KernelContext, payload) => {
  const kernelBrowser = await kernel.browsers.create({
    invocation_id: ctx.invocation_id,
  });
  const browser = await chromium.connectOverCDP(kernelBrowser.cdp_ws_url);
  const context = browser.contexts[0] || (await browser.newContext());
  const page = context.pages[0] || (await context.newPage());

  // Your automation code
  await page.goto('https://www.duckduckgo.com/')
  await page.waitForTimeout(2000)
  await page.goto('https://www.github.com/trending');

  // Wait for 2 seconds
  await page.waitForTimeout(2000);

  // Extract all trending repos
  const trendingRepos = await page.locator("h2 a.Link").evaluateAll((repos) =>
    repos.map((repo) => repo.textContent.trim().replace(/[\n\s]/g, ''))
  );

  console.log('Trending repos:', trendingRepos);
  await page.waitForTimeout(2000);

  // Computer tool call
  await kernel.browsers.computer.captureScreenshot(
    kernelBrowser.session_id,
  );
  // Process tool call
  await kernel.browsers.process.exec(
    kernelBrowser.session_id,
    {
      command: 'ls',
      args: ['-la'],
    }
  )

  await browser.close();
  await kernel.browsers.deleteByID(kernelBrowser.session_id);
});

Next steps