Run a Claude Code browser agent on a managed Kernel browser pool with a single SDK call. Environment Pools handle provisioning, agent execution, and teardown — you provide a task prompt and a browser profile.
Source script: cookbooks/computer-use-kernel.mdx (runnable snippet below)
Architecture
What happens under the hood:
You call create_rollout() with an AgentSpec and browser config
Environment Pools claims a browser from your Kernel pool
Claude Code + agent-browser launches inside the browser session
The agent executes your task, interacting with the live website
Results (reward, screenshots, traces) are returned
Prerequisites
Python 3.11+
uv or pip
API keys:
SYNTH_API_KEY — your Synth platform key
KERNEL_API_KEY — your Kernel API key
ANTHROPIC_API_KEY — for Claude Code agent
Kernel CLI: npm install -g @onkernel/cli
1. Install the SDK
pip install synth-ai
# or
uv add synth-ai
2. Create a Kernel browser profile
Create a persistent browser profile with saved authentication state:
# Create a named profile
kernel profiles create --name my-site
# Launch a browser to log in manually
kernel browsers create --stealth --profile-name my-site --save-changes
Open the live-view URL that Kernel prints, log in to your target site, then close the browser:
kernel browsers delete < session-i d >
Your login cookies are now saved in the my-site profile.
3. Create a browser pool
kernel browser-pools create \
--name agent-pool \
--profile-name my-site \
--stealth \
--size 5
This pre-warms 5 browser instances with your saved auth state. Rollouts claim one browser each.
4. Run a single agent rollout
import os
from synth_ai import SynthClient
import time
# --- Config ---
SYNTH_API_KEY = os.environ[ "SYNTH_API_KEY" ]
BACKEND_URL = "https://api.usesynth.ai"
client = SynthClient( api_key = SYNTH_API_KEY , base_url = BACKEND_URL )
# --- Create the rollout ---
result = client.pools.agent_rollouts.create(
{
"task_ref" : {
"dataset" : "my-computer-use-task" ,
"task_id" : "check-dashboard" ,
},
"agent" : {
"harness" : "claude-code" ,
"model_id" : "claude-sonnet-4.5" ,
"permission_mode" : "bypassPermissions" ,
},
"environment" : { "backend" : "browser" },
"browser" : {
"task_prompt" : "Navigate to the analytics dashboard and export last week's revenue report as CSV." ,
"profile" : "my-site" ,
"timeout_sec" : 120 ,
"headless" : True ,
"capture_screenshot" : True ,
},
"pool_tags" : [ "browser" , "kernel" ],
"timeouts" : { "agent_sec" : 120 },
},
)
rollout_id = result.get( "rollout_id" )
print ( f "Rollout started: { rollout_id } " )
# --- Poll until complete ---
while True :
status = client.pools.agent_rollouts.get(rollout_id)
state = status.get( "status" )
print ( f " Status: { state } " )
if state in ( "succeeded" , "failed" , "cancelled" , "error" , "completed" ):
break
time.sleep( 5 )
# --- Results ---
reward = status.get( "reward_primary" , 0.0 )
print ( f "Reward: { reward } " )
print ( f "Final status: { status.get( 'status' ) } " )
5. Run multiple seeds in parallel
Environment Pools handles concurrency for you — just submit multiple rollouts:
import concurrent.futures
seeds = [ 0 , 1 , 2 , 3 , 4 ]
def run_seed ( seed : int ) -> dict :
result = client.pools.agent_rollouts.create(
{
"task_ref" : { "dataset" : "my-task" , "task_id" : f "task- { seed } " },
"agent" : {
"harness" : "claude-code" ,
"model_id" : "claude-sonnet-4.5" ,
"permission_mode" : "bypassPermissions" ,
},
"environment" : { "backend" : "browser" },
"browser" : {
"task_prompt" : f "Complete task variant { seed } " ,
"profile" : "my-site" ,
"timeout_sec" : 120 ,
},
"pool_tags" : [ "browser" , "kernel" ],
},
)
rollout_id = result.get( "rollout_id" )
# poll until done...
return { "seed" : seed, "rollout_id" : rollout_id}
with concurrent.futures.ThreadPoolExecutor( max_workers = 5 ) as pool:
futures = [pool.submit(run_seed, s) for s in seeds]
for f in concurrent.futures.as_completed(futures):
print (f.result())
Keep max_workers at or below your Kernel pool size. If you submit more rollouts than available browsers, they will queue until a browser is released.
6. Add LLM verification
Include a verifier model and expected output to get automated reward scoring:
"browser" : {
"task_prompt" : "Find the total revenue for Q4 2025 on the dashboard." ,
"profile" : "my-site" ,
"timeout_sec" : 120 ,
"verifier_model" : "claude-sonnet-4-20250514" ,
"expected" : "The agent should navigate to the revenue dashboard and report a numeric total." ,
},
The verifier compares the agent’s output against the expected description and assigns a reward between 0.0 and 1.0.
Key Concepts
Concept Description Environment Pool Pre-provisioned set of browser instances with saved auth state AgentSpec Which agent harness to use (claude-code, codex, opencode) Browser config Task prompt, profile name, timeouts, screenshot capture Pool tags Route rollouts to specific pool types (browser, kernel) Rollout A single agent execution against one browser instance
Troubleshooting
“Pool not found” — Ensure your Kernel pool has matching tags (browser, kernel) or pass pool_id directly in the request.
“Auth expired” — Re-login to the Kernel profile and recreate the browser pool.
Timeouts — Increase timeout_sec in the browser config and agent_sec in timeouts.
Rate limits — Reduce concurrency or increase pool size.
Next Steps
Optimize with GEPA : Use this same setup as a container backend for GEPA optimization to evolve agent skills automatically.
Add custom rewards : Implement verifiers that check specific page state or downloaded files.
Ready to get started?
Get Started Sign up and start running browser agents today.
Schedule Demo See Synth in action with a personalized walkthrough.