Semantic Kernel + Anchor: Browser Agents in Python

Hands On
Jun 28
by Idan Raman

Semantic Kernel is Microsoft's open-source AI orchestration SDK for building production-grade agents in Python, .NET, and TypeScript. Its plugin system lets you extend any agent with custom tools—including a live browser. Pair it with Anchor's cloud browser infrastructure and you get an agent that can navigate real websites, handle bot-detection challenges, and extract structured data without managing a single headless browser yourself.

What we're building

A ChatCompletionAgent backed by three browser tools: one to start an Anchor session, one to navigate and extract page text, and one to close the session when done. The agent reasons over which tool to call and when—you only write the tools and the task.

Setup

pip install semantic-kernel openai playwright requests
playwright install chromium

export OPENAI_API_KEY="your-openai-api-key"
export ANCHOR_API_KEY="your-anchor-api-key"

Define the browser plugin

Semantic Kernel discovers tools through the @kernel_function decorator. Each decorated method becomes a callable the model can invoke during its reasoning loop.

import asyncio, os, requests
from playwright.async_api import async_playwright
import semantic_kernel as sk
from semantic_kernel.functions import kernel_function
from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion

ANCHOR_API_KEY = os.environ["ANCHOR_API_KEY"]

class BrowserPlugin:
    def __init__(self):
        self._session = None

    @kernel_function(description="Start a cloud browser session")
    async def start_browser(self) -> str:
        resp = requests.post(
            "https://api.anchorbrowser.io/v1/sessions",
            headers={"anchor-api-key": ANCHOR_API_KEY},
            json={"headless": True},
        )
        self._session = resp.json()["data"]
        return f"Session ready: {self._session['id']}"

    @kernel_function(description="Navigate to a URL and return visible page text")
    async def browse(self, url: str) -> str:
        if not self._session:
            return "Call start_browser first."
        async with async_playwright() as p:
            browser = await p.chromium.connect_over_cdp(self._session["cdp_url"])
            page = browser.contexts[0].pages[0]
            await page.goto(url, wait_until="domcontentloaded")
            text = await page.evaluate("() => document.body.innerText")
            await browser.close()
        return text[:5000]

    @kernel_function(description="Close the active browser session")
    async def close_browser(self) -> str:
        if self._session:
            requests.delete(
                f"https://api.anchorbrowser.io/v1/sessions/{self._session['id']}",
                headers={"anchor-api-key": ANCHOR_API_KEY},
            )
            self._session = None
        return "Session closed."

Build the kernel and agent

async def run(task: str):
    kernel = sk.Kernel()
    kernel.add_service(
        OpenAIChatCompletion(
            service_id="gpt4o",
            ai_model_id="gpt-4o",
            api_key=os.environ["OPENAI_API_KEY"],
        )
    )
    plugin = BrowserPlugin()
    kernel.add_plugin(plugin, plugin_name="browser")

    from semantic_kernel.agents import ChatCompletionAgent
    from semantic_kernel.connectors.ai.function_choice_behavior import FunctionChoiceBehavior
    from semantic_kernel.connectors.ai.open_ai import OpenAIChatPromptExecutionSettings
    from semantic_kernel.contents import ChatHistory

    agent = ChatCompletionAgent(
        kernel=kernel,
        name="WebResearcher",
        instructions=(
            "You are a web research agent. Use your browser tools to navigate "
            "websites and answer questions. Always start a session first, "
            "then browse, then close when done."
        ),
    )
    settings = OpenAIChatPromptExecutionSettings(
        function_choice_behavior=FunctionChoiceBehavior.Auto()
    )
    history = ChatHistory()
    history.add_user_message(task)

    async for response in agent.invoke(history=history, settings=settings):
        print(response.content)

asyncio.run(run(
    "Go to https://anchorbrowser.io/pricing and summarize the available plans."
))

Why Semantic Kernel + Anchor works well together

Semantic Kernel's plugin architecture maps cleanly onto Anchor's session model. Each @kernel_function becomes a discrete tool the model can call—FunctionChoiceBehavior.Auto() handles invocation timing. Anchor brings the infrastructure: fingerprinted sessions, built-in stealth, Cloudflare-verified agent identity, and Playwright-compatible CDP endpoints that require zero extra configuration.

The combination shines for multi-step research tasks where the agent needs to open several pages, cross-reference information, and synthesize an answer. SK's ChatCompletionAgent keeps conversation state while Anchor keeps the browser alive between calls—no re-authentication, no session cold starts.

Production tips

Persist sessions across turns: Store self._session outside the plugin instance (e.g., in Redis) so agents can resume a browser across separate requests without spinning up a new one.

Use profiles for login state: Pass "profile": {"id": "user-123"} in the session body to reuse saved cookies and local storage on every run—no re-login required.

Enable stealth: Add "stealth": true to the session payload to activate Anchor's fingerprint hardening and bypass common bot filters with zero extra code.

Fan out with AgentGroupChat: SK's AgentGroupChat lets you run a planner agent alongside multiple browser agents in parallel—each with its own Anchor session—for high-throughput research workflows.

What's next

Extend BrowserPlugin with click and form-fill actions using Playwright's full API. Add SK's built-in TextMemoryPlugin to store extracted findings across sessions. Or swap gpt-4o for claude-sonnet-4-6 using SK's Anthropic connector—the plugin code stays identical.

Get started

Sign up at anchorbrowser.io, grab your API key, and run your first Semantic Kernel browser agent in minutes.

Stay ahead in browser automation

We respect your inbox. Privacy policy

Welcome aboard! Thanks for signing up
Oops! Something went wrong while submitting the form.