From e188b071e411aa5ba6cd6992858e8168de171023 Mon Sep 17 00:00:00 2001
From: "tembo[bot]" <208362400+tembo-io[bot]@users.noreply.github.com>
Date: Fri, 24 Oct 2025 02:00:35 +0000
Subject: [PATCH 1/7] feat(docs): Add Laminar x Kernel integration guide
Co-authored-by: null <>
---
 docs.json                 |   1 +
 integrations/laminar.mdx  | 299 ++++++++++++++++++++++++++++++++++++++
 integrations/overview.mdx |   1 +
 3 files changed, 301 insertions(+)
 create mode 100644 integrations/laminar.mdx
diff --git a/docs.json b/docs.json
index 75db29a..ec701cf 100644
--- a/docs.json
+++ b/docs.json
@@ -110,6 +110,7 @@
                   "integrations/computer-use/openai"
                 ]
               },
+              "integrations/laminar",
               "integrations/magnitude",
               "integrations/notte",
               "integrations/stagehand",
diff --git a/integrations/laminar.mdx b/integrations/laminar.mdx
new file mode 100644
index 0000000..d9b47ac
--- /dev/null
+++ b/integrations/laminar.mdx
@@ -0,0 +1,299 @@
+---
+title: "Laminar"
+---
+
+[Laminar](https://www.lmnr.ai/) is an observability and evaluation platform for AI applications. By integrating Laminar with Kernel, you can trace and monitor your browser automations with full visibility into LLM calls, browser actions, session recordings, and performance metrics.
+
+## Why use Laminar with Kernel?
+
+Combining Laminar's observability with Kernel's cloud browsers provides:
+
+- **Full tracing**: Track every step of your browser automation, from LLM decisions to browser actions
+- **Session recordings**: View synchronized browser session replays alongside execution traces
+- **Cost tracking**: Monitor LLM costs and token usage across your automations
+- **Performance monitoring**: Measure latency and identify bottlenecks in your workflows
+- **Unified visibility**: See the complete picture of your AI agent's behavior in one place
+
+## Prerequisites
+
+Before integrating Laminar with Kernel, you'll need:
+
+1. A [Kernel account](https://dashboard.onkernel.com/sign-up) with API access
+2. A [Laminar account](https://www.lmnr.ai/) and project
+3. Your Laminar project API key from the Project Settings page
+
+## Installation
+
+### JavaScript/TypeScript
+
+```bash
+npm install @lmnr-ai/lmnr @onkernel/sdk
+```
+
+### Python
+
+```bash
+pip install --upgrade 'lmnr[all]' kernel
+```
+
+For targeted instrumentation, you can specify only the extras you need:
+
+```bash
+pip install --upgrade 'lmnr[anthropic,openai]' kernel
+```
+
+## Getting your Laminar API key
+
+1. Log in to your [Laminar dashboard](https://www.lmnr.ai/)
+2. Navigate to **Project Settings**
+3. Copy your **Project API Key** (referred to as `LAMINAR_PROJECT_API_KEY`)
+4. Set it as an environment variable:
+
+```bash
+export LMNR_PROJECT_API_KEY=your_api_key_here
+```
+
+## Integration guides by framework
+
+Choose the framework you're using with Kernel:
+
+### Playwright
+
+Playwright is a popular browser automation framework. Here's how to use it with Laminar and Kernel:
+
+#### JavaScript/TypeScript
+
+```javascript
+import { Laminar } from '@lmnr-ai/lmnr';
+import Kernel from '@onkernel/sdk';
+import { chromium } from 'playwright';
+
+// Initialize Laminar with Playwright instrumentation
+Laminar.initialize({
+  projectApiKey: process.env.LMNR_PROJECT_API_KEY,
+  instrumentModules: {
+    playwright: {
+      chromium
+    }
+  }
+});
+
+// Initialize Kernel and create a cloud browser
+const kernel = new Kernel();
+
+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);
+const context = browser.contexts()[0];
+const page = context.pages()[0];
+
+// Your automation code
+await page.goto('https://onkernel.com');
+await page.click('text=Documentation');
+const title = await page.title();
+console.log('Page title:', title);
+
+// Clean up
+await browser.close();
+await kernel.browsers.deleteByID(kernelBrowser.session_id);
+
+// Flush traces to Laminar
+await Laminar.flush();
+```
+
+#### Python
+
+```python
+import os
+from lmnr import Laminar, observe
+from playwright.sync_api import sync_playwright
+from kernel import Kernel
+
+# Initialize Laminar
+Laminar.initialize(project_api_key=os.environ["LMNR_PROJECT_API_KEY"])
+
+# Use @observe decorator to create a trace
+@observe()
+def run_automation():
+    # Initialize Kernel
+    client = Kernel()
+    kernel_browser = client.browsers.create(stealth=True)
+
+    print(f"Live view url: {kernel_browser.browser_live_view_url}")
+
+    # Connect Playwright to Kernel's browser
+    with sync_playwright() as p:
+        browser = p.chromium.connect_over_cdp(kernel_browser.cdp_ws_url)
+        context = browser.contexts[0]
+        page = context.pages[0]
+
+        # Your automation code
+        page.goto('https://onkernel.com')
+        page.click('text=Documentation')
+        title = page.title()
+        print(f'Page title: {title}')
+
+        # Clean up
+        browser.close()
+        client.browsers.delete_by_id(kernel_browser.session_id)
+
+# Run the automation
+run_automation()
+```
+
+### Browser Use
+
+[Browser Use](https://github.com/browser-use/browser-use) is an AI browser agent framework. Here's how to integrate it with Laminar and Kernel:
+
+#### Python
+
+```python
+import os
+import asyncio
+from lmnr import Laminar
+from browser_use import Agent, Browser
+from langchain_anthropic import ChatAnthropic
+from kernel import Kernel
+
+# Initialize Laminar
+Laminar.initialize(project_api_key=os.environ["LMNR_PROJECT_API_KEY"])
+
+async def main():
+    # Initialize Kernel and create a browser
+    client = Kernel()
+    kernel_browser = client.browsers.create(stealth=True)
+
+    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': 1024, 'height': 768},
+        viewport={'width': 1024, 'height': 768},
+        device_scale_factor=1.0
+    )
+
+    # Create and run the agent
+    agent = Agent(
+        task="Go to onkernel.com and describe what the product does",
+        llm=ChatAnthropic(model="claude-3-7-sonnet-20250219"),
+        browser_session=browser
+    )
+
+    result = await agent.run()
+    print(f"Result: {result.final_result()}")
+
+    # Clean up
+    client.browsers.delete_by_id(kernel_browser.session_id)
+
+asyncio.run(main())
+```
+
+
+View your traces in the Laminar UI's traces tab to see synchronized browser session recordings and agent execution steps.
+
+
+### Stagehand
+
+[Stagehand](https://github.com/browserbase/stagehand) is an AI browser automation framework. Here's how to use it with Laminar and Kernel:
+
+#### JavaScript/TypeScript
+
+```javascript
+import { Laminar } from '@lmnr-ai/lmnr';
+import { Stagehand } from '@browserbasehq/stagehand';
+import Kernel from '@onkernel/sdk';
+import { z } from 'zod';
+
+// Initialize Laminar with Stagehand instrumentation
+Laminar.initialize({
+  projectApiKey: process.env.LMNR_PROJECT_API_KEY,
+  instrumentModules: {
+    stagehand: Stagehand,
+  },
+});
+
+// Initialize Kernel and create a browser
+const kernel = new Kernel();
+const kernelBrowser = await kernel.browsers.create({ stealth: true });
+
+console.log("Live view url:", kernelBrowser.browser_live_view_url);
+
+// Configure Stagehand to use Kernel's browser
+const stagehand = new Stagehand({
+  env: 'LOCAL',
+  verbose: 1,
+  domSettleTimeoutMs: 30_000,
+  modelName: 'openai/gpt-4.1',
+  modelClientOptions: {
+    apiKey: process.env.OPENAI_API_KEY
+  },
+  localBrowserLaunchOptions: {
+    cdpUrl: kernelBrowser.cdp_ws_url
+  }
+});
+
+await stagehand.init();
+
+// Your automation code
+const page = stagehand.page;
+await page.goto('https://onkernel.com');
+await page.act('Click on Blog in the navbar');
+await page.act('Click on the newest blog post');
+
+const output = await page.extract({
+  instruction: 'Extract a summary of the blog post',
+  schema: z.object({
+    summary: z.string()
+  })
+});
+
+console.log('Blog post summary:', output.summary);
+
+// Clean up
+await stagehand.close();
+await kernel.browsers.deleteByID(kernelBrowser.session_id);
+
+// Flush traces to Laminar
+await Laminar.flush();
+```
+
+
+Always call `Laminar.flush()` (JavaScript) or ensure your traced functions complete (Python) to submit traces to Laminar.
+
+
+## Viewing traces in Laminar
+
+After running your automation:
+
+1. Log in to your [Laminar dashboard](https://www.lmnr.ai/)
+2. Navigate to the **Traces** tab
+3. Find your recent trace to view:
+   - Full execution timeline
+   - LLM calls and responses
+   - Browser session recordings
+   - Token usage and costs
+   - Latency metrics
+
+Timeline highlights indicate which step your agent is currently executing, making it easy to debug and optimize your automations.
+
+## Benefits of Laminar × Kernel
+
+- **No local browser management**: Run automations in the cloud while maintaining full observability
+- **Scalability**: Launch multiple browser sessions with independent traces
+- **Debugging**: Use Kernel's [live view](/browsers/live-view) during development and Laminar's session recordings for post-execution analysis
+- **Cost optimization**: Track LLM costs across all your browser automations
+- **Performance tuning**: Identify slow operations and optimize your agent workflows
+
+## Next steps
+
+- Check out [Kernel's live view](/browsers/live-view) for real-time debugging
+- Learn about [stealth mode](/browsers/stealth) for avoiding detection
+- Explore [Laminar's evaluation features](https://docs.lmnr.ai/evaluations/overview) for testing agent quality
+- Learn how to [deploy your app](/apps/deploy) to Kernel's platform
diff --git a/integrations/overview.mdx b/integrations/overview.mdx
index 1bf9ac4..a5d062e 100644
--- a/integrations/overview.mdx
+++ b/integrations/overview.mdx
@@ -21,6 +21,7 @@ Kernel provides detailed guides for popular agent frameworks:
 - **[Stagehand](/integrations/stagehand)** - AI browser automation with natural language
 - **[Computer Use (Anthropic)](/integrations/computer-use/anthropic)** - Claude's computer use capability
 - **[Computer Use (OpenAI)](/integrations/computer-use/openai)** - OpenAI's computer use capability
+- **[Laminar](/integrations/laminar)** - Observability and tracing for AI browser automations
 - **[Magnitude](/integrations/magnitude)** - Vision-focused browser automation framework
 - **[Notte](/integrations/notte)** - AI agent framework for browser automation
 - **[Val Town](/integrations/valtown)** - Serverless function runtime
From c025e3be4d6b91b04402e115c2ad0df4b3e1311b Mon Sep 17 00:00:00 2001
From: "tembo[bot]" <208362400+tembo-io[bot]@users.noreply.github.com>
Date: Fri, 24 Oct 2025 02:39:44 +0000
Subject: [PATCH 2/7] fix(docs): update Laminar integration guide structure and
 examples
---
 integrations/laminar.mdx | 59 +++++++++++-----------------------------
 1 file changed, 16 insertions(+), 43 deletions(-)
diff --git a/integrations/laminar.mdx b/integrations/laminar.mdx
index d9b47ac..86217eb 100644
--- a/integrations/laminar.mdx
+++ b/integrations/laminar.mdx
@@ -6,13 +6,11 @@ title: "Laminar"
 
 ## Why use Laminar with Kernel?
 
-Combining Laminar's observability with Kernel's cloud browsers provides:
-
-- **Full tracing**: Track every step of your browser automation, from LLM decisions to browser actions
-- **Session recordings**: View synchronized browser session replays alongside execution traces
-- **Cost tracking**: Monitor LLM costs and token usage across your automations
-- **Performance monitoring**: Measure latency and identify bottlenecks in your workflows
-- **Unified visibility**: See the complete picture of your AI agent's behavior in one place
+- **No local browser management**: Run automations in the cloud while maintaining full observability
+- **Scalability**: Launch multiple browser sessions with independent traces
+- **Debugging**: Use Kernel's [live view](/browsers/live-view) during development and Laminar's session recordings for post-execution analysis
+- **Cost optimization**: Track LLM costs across all your browser automations
+- **Performance tuning**: Identify slow operations and optimize your agent workflows
 
 ## Prerequisites
 
@@ -24,30 +22,21 @@ Before integrating Laminar with Kernel, you'll need:
 
 ## Installation
 
-### JavaScript/TypeScript
-
-```bash
+```bash npm
 npm install @lmnr-ai/lmnr @onkernel/sdk
 ```
 
-### Python
-
-```bash
-pip install --upgrade 'lmnr[all]' kernel
-```
-
-For targeted instrumentation, you can specify only the extras you need:
-
-```bash
-pip install --upgrade 'lmnr[anthropic,openai]' kernel
+```bash python
+uv pip install --upgrade 'lmnr[all]' kernel
 ```
 
 ## Getting your Laminar API key
 
 1. Log in to your [Laminar dashboard](https://www.lmnr.ai/)
 2. Navigate to **Project Settings**
-3. Copy your **Project API Key** (referred to as `LAMINAR_PROJECT_API_KEY`)
-4. Set it as an environment variable:
+3. Generate a new API key in your project
+4. Copy your **Project API Key** (referred to as `LAMINAR_PROJECT_API_KEY`)
+5. Set it as an environment variable:
 
 ```bash
 export LMNR_PROJECT_API_KEY=your_api_key_here
@@ -61,9 +50,7 @@ Choose the framework you're using with Kernel:
 
 Playwright is a popular browser automation framework. Here's how to use it with Laminar and Kernel:
 
-#### JavaScript/TypeScript
-
-```javascript
+```javascript javascript
 import { Laminar } from '@lmnr-ai/lmnr';
 import Kernel from '@onkernel/sdk';
 import { chromium } from 'playwright';
@@ -106,9 +93,7 @@ await kernel.browsers.deleteByID(kernelBrowser.session_id);
 await Laminar.flush();
 ```
 
-#### Python
-
-```python
+```python python
 import os
 from lmnr import Laminar, observe
 from playwright.sync_api import sync_playwright
@@ -150,9 +135,7 @@ run_automation()
 
 [Browser Use](https://github.com/browser-use/browser-use) is an AI browser agent framework. Here's how to integrate it with Laminar and Kernel:
 
-#### Python
-
-```python
+```python python
 import os
 import asyncio
 from lmnr import Laminar
@@ -203,9 +186,7 @@ View your traces in the Laminar UI's traces tab to see synchronized browser sess
 
 [Stagehand](https://github.com/browserbase/stagehand) is an AI browser automation framework. Here's how to use it with Laminar and Kernel:
 
-#### JavaScript/TypeScript
-
-```javascript
+```javascript javascript
 import { Laminar } from '@lmnr-ai/lmnr';
 import { Stagehand } from '@browserbasehq/stagehand';
 import Kernel from '@onkernel/sdk';
@@ -283,17 +264,9 @@ After running your automation:
 
 Timeline highlights indicate which step your agent is currently executing, making it easy to debug and optimize your automations.
 
-## Benefits of Laminar × Kernel
-
-- **No local browser management**: Run automations in the cloud while maintaining full observability
-- **Scalability**: Launch multiple browser sessions with independent traces
-- **Debugging**: Use Kernel's [live view](/browsers/live-view) during development and Laminar's session recordings for post-execution analysis
-- **Cost optimization**: Track LLM costs across all your browser automations
-- **Performance tuning**: Identify slow operations and optimize your agent workflows
-
 ## Next steps
 
 - Check out [Kernel's live view](/browsers/live-view) for real-time debugging
 - Learn about [stealth mode](/browsers/stealth) for avoiding detection
-- Explore [Laminar's evaluation features](https://docs.lmnr.ai/evaluations/overview) for testing agent quality
+- Explore [Laminar's evaluation features](https://docs.lmnr.ai/evaluations/introduction) for testing agent quality
 - Learn how to [deploy your app](/apps/deploy) to Kernel's platform
From 60c6da4301fbfd5c624062fa60680152502edfa9 Mon Sep 17 00:00:00 2001
From: "tembo[bot]" <208362400+tembo-io[bot]@users.noreply.github.com>
Date: Fri, 24 Oct 2025 03:06:36 +0000
Subject: [PATCH 3/7] docs(codeblocks): use CodeGroup for tabbed code examples
---
 integrations/laminar.mdx | 63 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 60 insertions(+), 3 deletions(-)
diff --git a/integrations/laminar.mdx b/integrations/laminar.mdx
index 86217eb..49f4ce1 100644
--- a/integrations/laminar.mdx
+++ b/integrations/laminar.mdx
@@ -22,6 +22,7 @@ Before integrating Laminar with Kernel, you'll need:
 
 ## Installation
 
+
 ```bash npm
 npm install @lmnr-ai/lmnr @onkernel/sdk
 ```
@@ -29,6 +30,7 @@ npm install @lmnr-ai/lmnr @onkernel/sdk
 ```bash python
 uv pip install --upgrade 'lmnr[all]' kernel
 ```
+
 
 ## Getting your Laminar API key
 
@@ -50,7 +52,8 @@ Choose the framework you're using with Kernel:
 
 Playwright is a popular browser automation framework. Here's how to use it with Laminar and Kernel:
 
-```javascript javascript
+
+```javascript Typescript/Javascript
 import { Laminar } from '@lmnr-ai/lmnr';
 import Kernel from '@onkernel/sdk';
 import { chromium } from 'playwright';
@@ -93,7 +96,7 @@ await kernel.browsers.deleteByID(kernelBrowser.session_id);
 await Laminar.flush();
 ```
 
-```python python
+```python Python
 import os
 from lmnr import Laminar, observe
 from playwright.sync_api import sync_playwright
@@ -130,6 +133,7 @@ def run_automation():
 # Run the automation
 run_automation()
 ```
+
 
 ### Browser Use
 
@@ -186,7 +190,8 @@ View your traces in the Laminar UI's traces tab to see synchronized browser sess
 
 [Stagehand](https://github.com/browserbase/stagehand) is an AI browser automation framework. Here's how to use it with Laminar and Kernel:
 
-```javascript javascript
+
+```javascript Typescript/Javascript
 import { Laminar } from '@lmnr-ai/lmnr';
 import { Stagehand } from '@browserbasehq/stagehand';
 import Kernel from '@onkernel/sdk';
@@ -245,6 +250,58 @@ await kernel.browsers.deleteByID(kernelBrowser.session_id);
 await Laminar.flush();
 ```
 
+```python Python
+import os
+from lmnr import Laminar
+from stagehand import Stagehand
+from kernel import Kernel
+
+# Initialize Laminar
+Laminar.initialize(project_api_key=os.environ["LMNR_PROJECT_API_KEY"])
+
+# Initialize Kernel and create a browser
+client = Kernel()
+kernel_browser = client.browsers.create(stealth=True)
+
+print(f"Live view url: {kernel_browser.browser_live_view_url}")
+
+# Configure Stagehand to use Kernel's browser
+stagehand = Stagehand(
+    env="LOCAL",
+    verbose=1,
+    dom_settle_timeout_ms=30_000,
+    model_name="openai/gpt-4.1",
+    model_client_options={
+        "api_key": os.environ["OPENAI_API_KEY"]
+    },
+    local_browser_launch_options={
+        "cdp_url": kernel_browser.cdp_ws_url
+    }
+)
+
+stagehand.init()
+
+# Your automation code
+page = stagehand.page
+page.goto('https://onkernel.com')
+page.act('Click on Blog in the navbar')
+page.act('Click on the newest blog post')
+
+output = page.extract(
+    instruction='Extract a summary of the blog post',
+    schema={
+        "summary": {"type": "string"}
+    }
+)
+
+print(f"Blog post summary: {output['summary']}")
+
+# Clean up
+stagehand.close()
+client.browsers.delete_by_id(kernel_browser.session_id)
+```
+
+
 
 Always call `Laminar.flush()` (JavaScript) or ensure your traced functions complete (Python) to submit traces to Laminar.
 
From c20e08f63bdb6dcb517cb9e3af8bd938e2b58b15 Mon Sep 17 00:00:00 2001
From: "tembo[bot]" <208362400+tembo-io[bot]@users.noreply.github.com>
Date: Fri, 24 Oct 2025 03:11:11 +0000
Subject: [PATCH 4/7] docs(laminar): update section title and add framework
 links
---
 integrations/laminar.mdx | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/integrations/laminar.mdx b/integrations/laminar.mdx
index 49f4ce1..3774ba9 100644
--- a/integrations/laminar.mdx
+++ b/integrations/laminar.mdx
@@ -44,10 +44,14 @@ uv pip install --upgrade 'lmnr[all]' kernel
 export LMNR_PROJECT_API_KEY=your_api_key_here
 ```
 
-## Integration guides by framework
+## Browser Agent Framework Examples
 
 Choose the framework you're using with Kernel:
 
+- [Playwright](#playwright)
+- [Browser Use](#browser-use)
+- [Stagehand](#stagehand)
+
 ### Playwright
 
 Playwright is a popular browser automation framework. Here's how to use it with Laminar and Kernel:
From f2115c4bce8a95db628502ee5a0889342c3ab374 Mon Sep 17 00:00:00 2001
From: Daniel Prevoznik 
Date: Thu, 23 Oct 2025 20:15:47 -0700
Subject: [PATCH 5/7] Small copy edit change
---
 integrations/laminar.mdx | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/integrations/laminar.mdx b/integrations/laminar.mdx
index 3774ba9..1e631e5 100644
--- a/integrations/laminar.mdx
+++ b/integrations/laminar.mdx
@@ -46,7 +46,7 @@ export LMNR_PROJECT_API_KEY=your_api_key_here
 
 ## Browser Agent Framework Examples
 
-Choose the framework you're using with Kernel:
+Select your browser automation framework to enable Laminar tracing with Kernel:
 
 - [Playwright](#playwright)
 - [Browser Use](#browser-use)
@@ -54,7 +54,7 @@ Choose the framework you're using with Kernel:
 
 ### Playwright
 
-Playwright is a popular browser automation framework. Here's how to use it with Laminar and Kernel:
+Playwright is a popular low-level browser automation framework. Here's how to use it with Laminar and Kernel:
 
 
 ```javascript Typescript/Javascript
From 74ce330912336fb9fe1536a7120e53a0ce4afc6f Mon Sep 17 00:00:00 2001
From: Daniel Prevoznik 
Date: Mon, 27 Oct 2025 09:57:07 -0400
Subject: [PATCH 6/7] Add working code samples
Added working code samples to the Laminar integration guide, along with additional information about how to do the setup initially.
---
 integrations/laminar.mdx | 161 +++++++++++++++++++--------------------
 1 file changed, 79 insertions(+), 82 deletions(-)
diff --git a/integrations/laminar.mdx b/integrations/laminar.mdx
index 1e631e5..d251a5a 100644
--- a/integrations/laminar.mdx
+++ b/integrations/laminar.mdx
@@ -16,7 +16,7 @@ title: "Laminar"
 
 Before integrating Laminar with Kernel, you'll need:
 
-1. A [Kernel account](https://dashboard.onkernel.com/sign-up) with API access
+1. A [Kernel account](https://dashboard.onkernel.com/sign-up) with a Kernel API Key
 2. A [Laminar account](https://www.lmnr.ai/) and project
 3. Your Laminar project API key from the Project Settings page
 
@@ -44,6 +44,10 @@ uv pip install --upgrade 'lmnr[all]' kernel
 export LMNR_PROJECT_API_KEY=your_api_key_here
 ```
 
+
+You will also need to generate a `KERNEL_API_KEY` from your [Kernel dashboard](https://dashboard.onkernel.com/api-keys) to authenticate with Kernel's browser infrastructure.
+
+
 ## Browser Agent Framework Examples
 
 Select your browser automation framework to enable Laminar tracing with Kernel:
@@ -83,14 +87,30 @@ 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);
-const context = browser.contexts()[0];
-const page = context.pages()[0];
+const context = browser.contexts()[0] || (await browser.newContext());
+const page = context.pages()[0] || (await context.newPage());
 
 // Your automation code
-await page.goto('https://onkernel.com');
-await page.click('text=Documentation');
-const title = await page.title();
-console.log('Page title:', title);
+await page.goto('https://www.onkernel.com/docs');
+
+// Navigate to careers page
+await page.goto('https://www.onkernel.com/docs/careers/intro', { waitUntil: 'networkidle' });
+
+// Extract all job URLs from the ul next to #open-roles
+const jobLinks = await page.locator('#open-roles + ul a').evaluateAll((links) => {
+  const baseUrl = 'https://www.onkernel.com';
+  return links
+    .map(link => {
+      const href = link.getAttribute('href');
+      if (!href) return null;
+      // Convert relative URLs to absolute URLs
+      return href.startsWith('http') ? href : baseUrl + href;
+    })
+    .filter(href => href !== null);
+});
+
+console.log('Job URLs found:', jobLinks);
+console.log(`Total jobs: ${jobLinks.length}`);
 
 // Clean up
 await browser.close();
@@ -121,19 +141,40 @@ def run_automation():
     # Connect Playwright to Kernel's browser
     with sync_playwright() as p:
         browser = p.chromium.connect_over_cdp(kernel_browser.cdp_ws_url)
-        context = browser.contexts[0]
-        page = context.pages[0]
+        context = browser.contexts[0] if browser.contexts else browser.new_context()
+        page = context.pages[0] if context.pages else context.new_page()
 
         # Your automation code
-        page.goto('https://onkernel.com')
-        page.click('text=Documentation')
-        title = page.title()
-        print(f'Page title: {title}')
+        page.goto('https://www.onkernel.com/docs')
+
+        # Navigate to careers page
+        page.goto('https://www.onkernel.com/docs/careers/intro')
+        page.wait_for_timeout(2000)  # Wait 2 seconds
+
+        # Extract all job URLs from the ul next to #open-roles
+        job_links = page.locator('#open-roles + ul a').evaluate_all("""
+            (links) => {
+                const baseUrl = 'https://www.onkernel.com';
+                return links
+                    .map(link => {
+                        const href = link.getAttribute('href');
+                        if (!href) return null;
+                        // Convert relative URLs to absolute URLs
+                        return href.startsWith('http') ? href : baseUrl + href;
+                    })
+                    .filter(href => href !== null);
+            }
+        """)
+
+        print(f'Job URLs found: {job_links}')
+        print(f'Total jobs: {len(job_links)}')
 
         # Clean up
-        browser.close()
         client.browsers.delete_by_id(kernel_browser.session_id)
 
+# Flush traces to Laminar 
+Laminar.flush()
+
 # Run the automation
 run_automation()
 ```
@@ -147,8 +188,7 @@ run_automation()
 import os
 import asyncio
 from lmnr import Laminar
-from browser_use import Agent, Browser
-from langchain_anthropic import ChatAnthropic
+from browser_use import Agent, Browser, ChatOpenAI
 from kernel import Kernel
 
 # Initialize Laminar
@@ -157,7 +197,7 @@ Laminar.initialize(project_api_key=os.environ["LMNR_PROJECT_API_KEY"])
 async def main():
     # Initialize Kernel and create a browser
     client = Kernel()
-    kernel_browser = client.browsers.create(stealth=True)
+    kernel_browser = client.browsers.create(stealth=True, viewport={'width': 1920, 'height': 1080})
 
     print(f"Live view url: {kernel_browser.browser_live_view_url}")
 
@@ -165,20 +205,27 @@ async def main():
     browser = Browser(
         cdp_url=kernel_browser.cdp_ws_url,
         headless=False,
-        window_size={'width': 1024, 'height': 768},
-        viewport={'width': 1024, 'height': 768},
+        window_size={'width': 1920, 'height': 1080},
+        viewport={'width': 1920, 'height': 1080},
         device_scale_factor=1.0
     )
 
-    # Create and run the agent
+    # Initialize the model
+    llm = ChatOpenAI(
+        model="gpt-4.1",
+    )
+
+    # Create and run the agent with job extraction task
     agent = Agent(
-        task="Go to onkernel.com and describe what the product does",
-        llm=ChatAnthropic(model="claude-3-7-sonnet-20250219"),
+        task="""1. Go to https://www.onkernel.com/docs
+        2. Navigate to the main Jobs page
+        3. Extract all the job posting URLs. List each URL you find.""",
+        llm=llm,
         browser_session=browser
     )
 
     result = await agent.run()
-    print(f"Result: {result.final_result()}")
+    print(f"Job URLs found:\n{result.final_result()}")
 
     # Clean up
     client.browsers.delete_by_id(kernel_browser.session_id)
@@ -194,7 +241,6 @@ View your traces in the Laminar UI's traces tab to see synchronized browser sess
 
 [Stagehand](https://github.com/browserbase/stagehand) is an AI browser automation framework. Here's how to use it with Laminar and Kernel:
 
-
 ```javascript Typescript/Javascript
 import { Laminar } from '@lmnr-ai/lmnr';
 import { Stagehand } from '@browserbasehq/stagehand';
@@ -233,18 +279,21 @@ await stagehand.init();
 
 // Your automation code
 const page = stagehand.page;
-await page.goto('https://onkernel.com');
-await page.act('Click on Blog in the navbar');
-await page.act('Click on the newest blog post');
+await page.goto('https://www.onkernel.com/docs');
 
+// Navigate to careers page
+await page.goto('https://www.onkernel.com/docs/careers/intro');
+
+// Extract all job URLs
 const output = await page.extract({
-  instruction: 'Extract a summary of the blog post',
+  instruction: 'Extract all job posting URLs from the page. Look for the section with job listings and get all the links.',
   schema: z.object({
-    summary: z.string()
+    jobUrls: z.array(z.string()).describe('Array of job posting URLs')
   })
 });
 
-console.log('Blog post summary:', output.summary);
+console.log('Job URLs found:', output.jobUrls);
+console.log(`Total jobs: ${output.jobUrls.length}`);
 
 // Clean up
 await stagehand.close();
@@ -254,58 +303,6 @@ await kernel.browsers.deleteByID(kernelBrowser.session_id);
 await Laminar.flush();
 ```
 
-```python Python
-import os
-from lmnr import Laminar
-from stagehand import Stagehand
-from kernel import Kernel
-
-# Initialize Laminar
-Laminar.initialize(project_api_key=os.environ["LMNR_PROJECT_API_KEY"])
-
-# Initialize Kernel and create a browser
-client = Kernel()
-kernel_browser = client.browsers.create(stealth=True)
-
-print(f"Live view url: {kernel_browser.browser_live_view_url}")
-
-# Configure Stagehand to use Kernel's browser
-stagehand = Stagehand(
-    env="LOCAL",
-    verbose=1,
-    dom_settle_timeout_ms=30_000,
-    model_name="openai/gpt-4.1",
-    model_client_options={
-        "api_key": os.environ["OPENAI_API_KEY"]
-    },
-    local_browser_launch_options={
-        "cdp_url": kernel_browser.cdp_ws_url
-    }
-)
-
-stagehand.init()
-
-# Your automation code
-page = stagehand.page
-page.goto('https://onkernel.com')
-page.act('Click on Blog in the navbar')
-page.act('Click on the newest blog post')
-
-output = page.extract(
-    instruction='Extract a summary of the blog post',
-    schema={
-        "summary": {"type": "string"}
-    }
-)
-
-print(f"Blog post summary: {output['summary']}")
-
-# Clean up
-stagehand.close()
-client.browsers.delete_by_id(kernel_browser.session_id)
-```
-
-
 
 Always call `Laminar.flush()` (JavaScript) or ensure your traced functions complete (Python) to submit traces to Laminar.
 
From a62b0a9b3b1782d51e4f5aaa8d4225bcc44dcc09 Mon Sep 17 00:00:00 2001
From: Daniel Prevoznik 
Date: Mon, 27 Oct 2025 14:03:41 -0400
Subject: [PATCH 7/7] Edits based on feedback discussions
Made edits to copy and code snippets based on feedback received from Laminar team.
---
 integrations/laminar.mdx | 80 ++++++++++++++++++++++++++--------------
 1 file changed, 53 insertions(+), 27 deletions(-)
diff --git a/integrations/laminar.mdx b/integrations/laminar.mdx
index d251a5a..540a5c5 100644
--- a/integrations/laminar.mdx
+++ b/integrations/laminar.mdx
@@ -2,7 +2,7 @@
 title: "Laminar"
 ---
 
-[Laminar](https://www.lmnr.ai/) is an observability and evaluation platform for AI applications. By integrating Laminar with Kernel, you can trace and monitor your browser automations with full visibility into LLM calls, browser actions, session recordings, and performance metrics.
+[Laminar](https://www.lmnr.ai/) is an open-source observability and evaluation platform for autonomous AI agents. You can create a cloud account or self-host Laminar for your infrastructure. By integrating Laminar with Kernel, you can trace and monitor your browser automations with full visibility into LLM calls, browser actions, session recordings, and performance metrics.
 
 ## Why use Laminar with Kernel?
 
@@ -37,7 +37,7 @@ uv pip install --upgrade 'lmnr[all]' kernel
 1. Log in to your [Laminar dashboard](https://www.lmnr.ai/)
 2. Navigate to **Project Settings**
 3. Generate a new API key in your project
-4. Copy your **Project API Key** (referred to as `LAMINAR_PROJECT_API_KEY`)
+4. Copy your **Project API Key**
 5. Set it as an environment variable:
 
 ```bash
@@ -56,10 +56,18 @@ Select your browser automation framework to enable Laminar tracing with Kernel:
 - [Browser Use](#browser-use)
 - [Stagehand](#stagehand)
 
+
+Always call `Laminar.flush()` or ensure your traced functions complete to submit traces to Laminar.
+
+
 ### Playwright
 
 Playwright is a popular low-level browser automation framework. Here's how to use it with Laminar and Kernel:
 
+
+The Playwright examples include `waitForTimeout()` calls to help ensure Laminar traces populate properly for these short, fast code snippets.
+
+
 
 ```javascript Typescript/Javascript
 import { Laminar } from '@lmnr-ai/lmnr';
@@ -90,9 +98,15 @@ 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());
 
+// Wait for 3 second
+await page.waitForTimeout(3000);
+
 // Your automation code
 await page.goto('https://www.onkernel.com/docs');
 
+// Wait for 2 second
+await page.waitForTimeout(2000);
+
 // Navigate to careers page
 await page.goto('https://www.onkernel.com/docs/careers/intro', { waitUntil: 'networkidle' });
 
@@ -112,12 +126,15 @@ const jobLinks = await page.locator('#open-roles + ul a').evaluateAll((links) =>
 console.log('Job URLs found:', jobLinks);
 console.log(`Total jobs: ${jobLinks.length}`);
 
-// Clean up
-await browser.close();
-await kernel.browsers.deleteByID(kernelBrowser.session_id);
+// Wait for 3 seconds
+await page.waitForTimeout(3000);
 
-// Flush traces to Laminar
+// Clean up the browserand flush traces to Laminar
+await browser.close();
 await Laminar.flush();
+
+// Delete the browser for those who left open the live view url
+await kernel.browsers.deleteByID(kernelBrowser.session_id);
 ```
 
 ```python Python
@@ -144,12 +161,18 @@ def run_automation():
         context = browser.contexts[0] if browser.contexts else browser.new_context()
         page = context.pages[0] if context.pages else context.new_page()
 
+        # Wait for 3 seconds
+        page.wait_for_timeout(3000)
+
         # Your automation code
         page.goto('https://www.onkernel.com/docs')
 
+        # Wait for 2 seconds
+        page.wait_for_timeout(3000)
+
         # Navigate to careers page
         page.goto('https://www.onkernel.com/docs/careers/intro')
-        page.wait_for_timeout(2000)  # Wait 2 seconds
+        page.wait_for_timeout(3000)  # Wait 2 seconds
 
         # Extract all job URLs from the ul next to #open-roles
         job_links = page.locator('#open-roles + ul a').evaluate_all("""
@@ -169,11 +192,17 @@ def run_automation():
         print(f'Job URLs found: {job_links}')
         print(f'Total jobs: {len(job_links)}')
 
-        # Clean up
-        client.browsers.delete_by_id(kernel_browser.session_id)
+        # Wait for 3 seconds
+        page.wait_for_timeout(3000)
+
+        # Clean up the browser
+        browser.close()
 
-# Flush traces to Laminar 
-Laminar.flush()
+    # Flush traces to Laminar
+    Laminar.flush()
+
+    # Delete the browser for those who left open the Kernel live view url
+    client.browsers.delete_by_id(kernel_browser.session_id)
 
 # Run the automation
 run_automation()
@@ -227,16 +256,15 @@ async def main():
     result = await agent.run()
     print(f"Job URLs found:\n{result.final_result()}")
 
-    # Clean up
+    # Flush traces to Laminar
+    Laminar.flush()
+
+    # Delete the browser for those who left open the live view url
     client.browsers.delete_by_id(kernel_browser.session_id)
 
 asyncio.run(main())
 ```
 
-
-View your traces in the Laminar UI's traces tab to see synchronized browser session recordings and agent execution steps.
-
-
 ### Stagehand
 
 [Stagehand](https://github.com/browserbase/stagehand) is an AI browser automation framework. Here's how to use it with Laminar and Kernel:
@@ -286,7 +314,7 @@ await page.goto('https://www.onkernel.com/docs/careers/intro');
 
 // Extract all job URLs
 const output = await page.extract({
-  instruction: 'Extract all job posting URLs from the page. Look for the section with job listings and get all the links.',
+  instruction: 'Extract all job posting URLs from the Open Roles section.',
   schema: z.object({
     jobUrls: z.array(z.string()).describe('Array of job posting URLs')
   })
@@ -295,20 +323,18 @@ const output = await page.extract({
 console.log('Job URLs found:', output.jobUrls);
 console.log(`Total jobs: ${output.jobUrls.length}`);
 
-// Clean up
+// Clean up and flush traces to Laminar
 await stagehand.close();
-await kernel.browsers.deleteByID(kernelBrowser.session_id);
-
-// Flush traces to Laminar
 await Laminar.flush();
-```
 
-
-Always call `Laminar.flush()` (JavaScript) or ensure your traced functions complete (Python) to submit traces to Laminar.
-
+// Delete the browser for those who left open the live view url
+await kernel.browsers.deleteByID(kernelBrowser.session_id);
+```
 
 ## Viewing traces in Laminar
 
+View your traces in the Laminar UI's traces tab to see synchronized browser session recordings and agent execution steps.
+
 After running your automation:
 
 1. Log in to your [Laminar dashboard](https://www.lmnr.ai/)
@@ -324,7 +350,7 @@ Timeline highlights indicate which step your agent is currently executing, makin
 
 ## Next steps
 
-- Check out [Kernel's live view](/browsers/live-view) for real-time debugging
+- Explore [Laminar's tracing structure](https://docs.lmnr.ai/tracing/structure/overview) to understand how traces are organized
+- Learn about [Laminar's evaluations](https://docs.lmnr.ai/evaluations/introduction) for validating and testing your AI application outputs
 - Learn about [stealth mode](/browsers/stealth) for avoiding detection
-- Explore [Laminar's evaluation features](https://docs.lmnr.ai/evaluations/introduction) for testing agent quality
 - Learn how to [deploy your app](/apps/deploy) to Kernel's platform