AI & Systems Architecture Kiến trúc Hệ thống & AI · · 12 min read

Tencent BrowserSkill: High-Performance Rust CDP Engine & Browser-Agent IPC Architecture Tencent BrowserSkill: Kiến Trúc Rust CDP Hiệu Năng Cao & Cơ Chế Giao Tiếp Agent-Trình Duyệt

A deep dive into Tencent BrowserSkill: dissecting its daemon-extension architecture, cross-platform IPC synchronization, and deterministic DOM reference mapping for AI coding agents. Phân tích chuyên sâu Tencent BrowserSkill: bóc tách kiến trúc daemon-extension bằng Rust, cơ chế đồng bộ IPC đa nền tảng và ánh xạ DOM reference cho AI coding agent.

Written by Nguyen Cong Ben Nguyễn Công Ben
Tencent BrowserSkill Architecture Banner

Introduction: The Fragility of Modern Browser Agents

The current generation of browser-use agent harnesses faces a crippling operational bottleneck: context bloat and session fragmentation. Traditional approaches spawn ephemeral, headless Chromium instances via Playwright or Puppeteer. While functional for simple scraping tasks, this architecture collapses when applied to complex developer workflows:

  1. Session Severing: Headless instances lose user cookies, multi-factor authentication (MFA) tokens, passkeys, and existing tab state.
  2. Context Budget Exhaustion: Dumping raw HTML or accessibility trees into an LLM context window consumes 30k–80k tokens per observation step, causing reasoning degradation and latency spikes exceeding 6–10 seconds per turn.
  3. Execution Instability: High memory footprints (300MB–800MB per Playwright process) limit local agent orchestrators running on edge devices or modest development servers.

Tencent BrowserSkill (Tencent/BrowserSkill) introduces a paradigm shift. Instead of spawning isolated browser runtimes, it connects autonomous AI agents directly into the developer’s existing, active Chromium browser using an ultra-low-overhead Rust daemon (bsk-cli) paired with a native Chromium Extension.

In this deep dive, we inspect the Rust codebase, protocol specifications, and concurrency models that power this breakthrough architecture.


1. High-Level System Architecture

Tencent BrowserSkill divides the automation stack into three modular layers:

graph TD
    Agent[AI Agent / LLM Harness] -->|CLI Stdout/JSON-RPC| Daemon[bsk-cli Rust Daemon]
    Daemon -->|Localhost IPC / WebSocket| Ext[BrowserSkill Chromium Extension]
    Ext -->|Chrome DevTools Protocol - CDP| Tab[Active User Tab DOM / Storage]
    
    subgraph "Rust Core (crates/)"
        Daemon --> RefStore[Ref Store & Element Mapper]
        Daemon --> SessionMgr[Session & Tab Lifecycle]
    end
    
    subgraph "Chromium Browser"
        Ext --> Background[Extension Service Worker]
        Background --> ContentScript[Injected DOM Observer]
    end

The Three Pillars:

  1. The CLI & Native Daemon (crates/bsk-cli): Written in pure Rust with tokio. It manages the lifetime of client sessions, serializes requests, and provides sub-10ms response times for command dispatch.
  2. The Extension Bridge (apps/extension): Injected with debugger permissions, allowing zero-friction CDP attachment without requiring users to launch Chrome with dangerous --remote-debugging-port flags.
  3. The Protocol Engine (crates/bsk-protocol): Enforces strict serialization contracts and converts heavy DOM trees into deterministic compact numeric references (@e1, @e2, @e3).

2. IPC Protocol & Concurrency Guarantees

One of the standout engineering decisions in BrowserSkill is its strict session-scoped serialization.

When multiple agents or parallel processes invoke the CLI simultaneously, naive implementations suffer from race conditions—where Agent A’s click alters the DOM while Agent B is computing coordinates.

BrowserSkill solves this in crates/bsk-cli/src/daemon.rs:

pub struct SessionRouter {
    active_sessions: Arc<RwLock<HashMap<SessionId, mpsc::Sender<SessionCommand>>>>,
    ref_store: Arc<RwLock<ElementRefStore>>,
}

impl SessionRouter {
    pub async fn dispatch(&self, cmd: Command) -> Result<Response, ProtocolError> {
        let (tx, rx) = oneshot::channel();
        let session_channel = self.get_or_create_channel(&cmd.session_id).await?;
        
        // Strictly serializes execution per session while allowing concurrent multi-session execution
        session_channel.send(SessionMessage { cmd, reply_to: tx }).await
            .map_err(|_| ProtocolError::SessionTerminated)?;
            
        rx.await.map_err(|_| ProtocolError::InternalChannelDropped)
    }
}
  • Per-Session Serialization: All commands targeting the same browser session are queued into an asynchronous mpsc queue. This guarantees that element references generated during a page_info call remain strictly valid for subsequent clicks or typing actions.
  • Global Multi-Tenancy: Distinct sessions run across decoupled tokio tasks, allowing parallel evaluations across different tabs without cross-talk.

3. Deterministic Element Ref Store (bsk-protocol)

Rather than streaming thousands of lines of raw HTML to the LLM, BrowserSkill uses a Reference Tokenization Engine.

When a page snapshot is taken, the DOM tree is traversed inside the extension, pruning non-interactive elements and assigning monotonic identifiers:

{
  "title": "GitHub Pull Requests",
  "url": "https://github.com/nguywnben/synapse-engine/pulls",
  "elements": [
    { "ref": "@e1", "role": "button", "name": "New pull request", "visible": true },
    { "ref": "@e2", "role": "link", "name": "feat(core): initial release", "href": "/pull/1" },
    { "ref": "@e3", "role": "textbox", "placeholder": "Search all issues" }
  ]
}

When the LLM issues an action:

bsk click --target "@e1"

The Rust daemon resolves @e1 against its cached node coordinates in memory and executes the click via Input.dispatchMouseEvent over CDP in less than 4 milliseconds.


4. Key Takeaways for AI Systems Builders

  1. Preserve User Session Over Headless Sandboxes: AI agents become exponentially more useful when they operate within the user’s authentic environment (logged-in dashboards, private repos, SSO sessions) rather than hitting bot-detection walls.
  2. Move DOM Preprocessing to Rust/Extension: Filtering out styling slop, invisible DOM nodes, and tracking coordinates on the client saves up to 92% of LLM token costs.
  3. Deterministic Concurrency: Without an explicit command queue per browser tab, autonomous agents will encounter non-deterministic DOM drift.

Mở đầu: Điểm yếu chí mạng của Browser Agent hiện nay

Hầu hết các framework điều khiển trình duyệt cho AI hiện nay (như Puppeteer, Playwright hay selenium) đều gặp phải một bài toán nan giải: tiêu tốn quá nhiều tài nguyên và làm đứt gãy phiên làm việc (Session). Các công cụ này thường mở một trình duyệt Chromium hoàn toàn trắng (Headless mode). Điều này mang lại 3 hạn chế lớn:

  1. Mất phiên đăng nhập: Người dùng phải đăng nhập lại từ đầu, vướng mã OTP 2FA, Captcha hoặc bị các nền tảng lớn (Google, Cloudflare) chặn ngay lập tức.
  2. Nghẽn Token LLM: Việc copy toàn bộ mã HTML hoặc cây Accessibility vào ngữ cảnh của mô hình ngôn ngữ ngốn tới 30.000 – 80.000 tokens cho mỗi hành động, làm tăng chi phí và độ trễ phản hồi lên tới hàng chục giây.
  3. Ngốn RAM máy chủ: Mỗi tiến trình Chromium headless ngốn từ 400MB đến gần 1GB RAM, khiến việc chạy nhiều tác tử đồng thời trên máy chủ cá nhân hay VPS trở nên bất khả thi.

Tencent BrowserSkill (Tencent/BrowserSkill) mang đến một tư duy thiết kế đột phá: Thay vì tự bật trình duyệt riêng, nó kết nối thẳng AI Agent vào chính trình duyệt Chromium đang mở của lập trình viên thông qua một Daemon viết bằng ngôn ngữ Rust (bsk-cli) kết hợp cùng Extension siêu nhẹ.

Bài viết này sẽ mổ xẻ chi tiết kiến trúc Rust, giao thức IPC và cơ chế mapping DOM của dự án này.


1. Kiến trúc Tổng thể Hệ thống

Tencent BrowserSkill phân tách hệ thống thành 3 tầng độc lập:

graph TD
    Agent[AI Agent / LLM Harness] -->|CLI Stdout/JSON-RPC| Daemon[Daemon bsk-cli bằng Rust]
    Daemon -->|Localhost IPC / WebSocket| Ext[Extension BrowserSkill]
    Ext -->|Chrome DevTools Protocol - CDP| Tab[Tab làm việc của Người dùng]
    
    subgraph "Lõi Rust (crates/)"
        Daemon --> RefStore[Lưu trữ & Ánh xạ Element Ref]
        Daemon --> SessionMgr[Quản lý vòng đời Tab & Session]
    end
    
    subgraph "Trình duyệt Chromium"
        Ext --> Background[Service Worker Extension]
        Background --> ContentScript[Bộ quan sát DOM Injected]
    end

3 Thành phần chính:

  1. Lõi Daemon Rust (crates/bsk-cli): Xây dựng trên nền tảng tokio bất đồng bộ, quản lý kết nối và chuyển tiếp lệnh với độ trễ siêu thấp (<10ms).
  2. Cầu nối Extension (apps/extension): Sử dụng quyền debugger của Chrome Extension, cho phép điều khiển CDP trực tiếp mà người dùng không cần phải khởi động trình duyệt bằng cờ --remote-debugging-port nguy hiểm.
  3. Bộ chuẩn hóa giao thức (crates/bsk-protocol): Rút gọn cây DOM phức tạp thành các mã định danh ngắn gọn (@e1, @e2, @e3).

2. Giao thức IPC & Cơ chế Đảm bảo Tuần tự

Một thách thức lớn của AI Agent là hiện tượng trôi dữ liệu (DOM drift): Khi Agent A đang bấm chuột thì Agent B lại gửi lệnh gõ chữ, làm trang web bị giật và click sai vị trí.

BrowserSkill xử lý triệt để vấn đề này trong crates/bsk-cli/src/daemon.rs:

pub struct SessionRouter {
    active_sessions: Arc<RwLock<HashMap<SessionId, mpsc::Sender<SessionCommand>>>>,
    ref_store: Arc<RwLock<ElementRefStore>>,
}

impl SessionRouter {
    pub async fn dispatch(&self, cmd: Command) -> Result<Response, ProtocolError> {
        let (tx, rx) = oneshot::channel();
        let session_channel = self.get_or_create_channel(&cmd.session_id).await?;
        
        // Tuần tự hóa tuyệt đối mọi tác vụ trên cùng 1 tab, loại bỏ xung đột race-condition
        session_channel.send(SessionMessage { cmd, reply_to: tx }).await
            .map_err(|_| ProtocolError::SessionTerminated)?;
            
        rx.await.map_err(|_| ProtocolError::InternalChannelDropped)
    }
}
  • Xử lý tuần tự theo Session: Mọi hành động trên cùng 1 tab được đẩy vào hàng đợi mpsc, đảm bảo tọa độ nút bấm vừa lấy từ page_info sẽ được click chính xác 100%.
  • Độc lập đa luồng: Các tab khác nhau chạy trên các task tokio riêng biệt, không làm chậm lẫn nhau.

3. Hệ thống Element Reference Store Rút gọn

Thay vì gửi hàng nghìn dòng HTML thô cho AI, BrowserSkill chuyển đổi giao diện thành danh sách ngắn gọn:

{
  "title": "Danh sách Pull Request",
  "elements": [
    { "ref": "@e1", "role": "button", "name": "Tạo Pull Request mới" },
    { "ref": "@e2", "role": "link", "name": "feat(core): initial release" },
    { "ref": "@e3", "role": "textbox", "placeholder": "Tìm kiếm issue..." }
  ]
}

Khi AI muốn bấm nút:

bsk click --target "@e1"

Daemon Rust lập tức tra cứu tọa độ của @e1 trong RAM và phát lệnh click qua CDP trong chưa đầy 4 mili-giây. Cơ chế này giúp tiết kiệm tới 90% chi phí token và tăng tốc độ suy luận của AI lên gấp 5 lần.


4. Bài học Rút ra khi Thiết kế Hệ thống AI Agent

  1. Tận dụng môi trường thật của người dùng: Tác tử AI sẽ mạnh mẽ hơn gấp nhiều lần khi làm việc trên chính trình duyệt thật có sẵn cookie, passkey và lịch sử của người dùng thay vì chạy trong sandbox cô lập.
  2. Tiền xử lý DOM trước khi đưa vào LLM: Tối ưu hóa việc lọc bỏ CSS thừa và ánh xạ id ngắn (@e1) ngay tại client giúp tiết kiệm chi phí vận hành cực lớn.
  3. Cơ chế hàng đợi bất đồng bộ: Luôn luôn tuần tự hóa các hành động trên giao diện web để tránh các lỗi click trượt do giao diện render bất ngờ.