Summary
With the Kernel provider, setting KERNEL_PROFILE_NAME makes every browser open fail with HTTP 400. connect_kernel() serializes the create-browser profile field as a bare string, but Kernel's API expects an object ({ name, save_changes }). The request is rejected at JSON-decode time, so no browser is ever created.
Version
agent-browser 0.29.1 (current main). This has been broken since the Kernel provider was added (#200) — connect_kernel has always sent profile as a string.
Reproduction
export AGENT_BROWSER_PROVIDER=kernel
export KERNEL_API_KEY=...
export KERNEL_PROFILE_NAME=anything # any non-empty value
agent-browser --session t open https://example.com
Actual:
✗ Kernel API error (400): can't decode JSON body: json: cannot unmarshal
string into Go struct field BrowserRequest.profile of type map[string]json.RawMessage
Expected: the browser opens using the named profile (and, per the docs below, persists cookies/logins back to it on close).
Root cause
cli/src/native/providers.rs → connect_kernel():
body.as_object_mut()
.unwrap()
.insert("profile".to_string(), json!(profile)); // profile: String
Kernel's POST /browsers expects profile as an object, matching the @onkernel/sdk BrowserProfile type:
interface BrowserProfile { id?: string; name?: string; save_changes?: boolean }
Evidence (string vs object, same pre-existing profile)
Posting directly to POST /browsers with an existing profile, varying only the profile field:
profile value |
Status |
Body |
"my-profile" (string) |
400 |
cannot unmarshal string into ... profile of type map[string]json.RawMessage |
{ "name": "my-profile", "save_changes": true } (object) |
200 |
browser created |
The string is rejected at decode time regardless of whether the profile exists, so this is purely a serialization mismatch.
Note on persistence (save_changes)
The README and Kernel provider docs state that profile data is "automatically saved back to the profile when the browser session ends." That requires save_changes: true in the object — the SDK's own default is false, which would load the profile but silently never persist. So the object should be sent with save_changes: true to make the documented behavior actually work.
I have a fix ready (send { name, save_changes: true }, plus unit tests) and will open a PR referencing this issue.
Summary
With the Kernel provider, setting
KERNEL_PROFILE_NAMEmakes every browser open fail with HTTP 400.connect_kernel()serializes the create-browserprofilefield as a bare string, but Kernel's API expects an object ({ name, save_changes }). The request is rejected at JSON-decode time, so no browser is ever created.Version
agent-browser 0.29.1(currentmain). This has been broken since the Kernel provider was added (#200) —connect_kernelhas always sentprofileas a string.Reproduction
Actual:
Expected: the browser opens using the named profile (and, per the docs below, persists cookies/logins back to it on close).
Root cause
cli/src/native/providers.rs→connect_kernel():Kernel's
POST /browsersexpectsprofileas an object, matching the@onkernel/sdkBrowserProfiletype:Evidence (string vs object, same pre-existing profile)
Posting directly to
POST /browserswith an existing profile, varying only theprofilefield:profilevalue"my-profile"(string)cannot unmarshal string into ... profile of type map[string]json.RawMessage{ "name": "my-profile", "save_changes": true }(object)The string is rejected at decode time regardless of whether the profile exists, so this is purely a serialization mismatch.
Note on persistence (
save_changes)The README and Kernel provider docs state that profile data is "automatically saved back to the profile when the browser session ends." That requires
save_changes: truein the object — the SDK's own default isfalse, which would load the profile but silently never persist. So the object should be sent withsave_changes: trueto make the documented behavior actually work.I have a fix ready (send
{ name, save_changes: true }, plus unit tests) and will open a PR referencing this issue.