Compare commits

...

2 Commits

Author SHA1 Message Date
ebb7fb8af3 openclaw-tools: fix browser_invoke tool description (act, not click/type)
The bridge advertised non-existent gateway actions ("click"/"type"), so Kimi
sent action="type" -> "Unknown action". Corrected to the real vocabulary:
interactions go through action="act" with args={kind, ref, text} (e.g.
{kind:"type", ref:"e59", text:"..."}, {kind:"click", ref}), plus the real
top-level actions (open/navigate/snapshot/screenshot/act/...). Verified Adolf
can now type/click in the browser.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014t8Qg9gi7H7HtT8MncoXAB
2026-07-16 15:01:18 +00:00
442bc377bf Adolf: enable OpenClaw browser + local wiki network access
- openclaw.json: browser.enabled + noSandbox (containers can't sandbox) +
  ssrfPolicy.dangerouslyAllowPrivateNetwork (local *.alogins.net resolve to
  the private host gateway); "browser" added to gateway.tools.allow.
- docker-compose.yml: extra_hosts family.alogins.net / wiki.alogins.net ->
  host-gateway on both adolf and adolf-llm, so the gateway browser AND the
  Kimi CLI's fetch reach the local wikis (hairpin-NAT dodge, like matrix).

Enables Adolf to open + log into the family wiki (kb#64). Root 401 on the
openclaw-tools bridge was a separate fix (empty ADOLF_GATEWAY_TOKEN -> just
recreate the bridge container; no file change).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014t8Qg9gi7H7HtT8MncoXAB
2026-07-16 14:40:12 +00:00
3 changed files with 54 additions and 9 deletions

View File

@@ -22,7 +22,32 @@
// /tools/invoke surface by default. The openclaw-tools MCP bridge
// (P5) calls that surface for cron_create/cron_list/nodes_invoke, so
// without this allow-list those tools 404 even with a valid token.
allow: ["cron", "nodes"],
// "browser" added (kb#64 follow-up) so Adolf can drive the OpenClaw
// browser via the openclaw-tools bridge for authenticated web access
// (e.g. the family wiki login form).
allow: ["cron", "nodes", "browser"],
},
},
// Browser tool — bundled plugin, off by default. Enables a dedicated,
// agent-only headless Chromium profile ("openclaw") driven through the
// gateway's loopback control service. Chromium is already in the image
// (playwright chromium-1228). Needs both this browser.enabled=true and the
// "browser" entry in gateway.tools.allow above.
browser: {
enabled: true,
// Chromium's setuid sandbox can't initialize inside this container (no
// unprivileged user namespaces), so run with --no-sandbox. Safe here: the
// browser profile is agent-only and isolated, and the container already
// drops NET_RAW/NET_ADMIN. Without this, `browser start` fails with
// "No usable sandbox".
noSandbox: true,
// The local *.alogins.net services resolve to the host gateway (private
// 172.17.0.1 via extra_hosts), so the browser's SSRF guard blocks them by
// default ("navigation blocked by policy"). Opt in for this trusted,
// self-owned network — same decision as channels.matrix.network above.
ssrfPolicy: {
dangerouslyAllowPrivateNetwork: true,
},
},

View File

@@ -197,6 +197,14 @@ services:
# same fix). Caddy on the host terminates TLS on :443 and proxies to
# synapse:8008.
- "mtx.alogins.net:host-gateway"
# Local *.alogins.net web services (family wiki / OtterWiki, РодоВики) —
# same hairpin-NAT dodge: the public A record can't loop back through the
# router from inside a container, so route the hostname to the host
# gateway where Caddy terminates TLS on :443 and proxies to the service.
# Lets Adolf's OpenClaw browser reach them with the real URL + the
# Vaultwarden creds. Add more *.alogins.net hosts here as needed.
- "family.alogins.net:host-gateway"
- "wiki.alogins.net:host-gateway"
cap_drop:
- NET_RAW
- NET_ADMIN
@@ -242,6 +250,12 @@ services:
# this compose project's network) via shared-mcp.json's "kanboard"
# entry — same host-gateway trick used by adolf/cognee/pipecat above.
- "host.docker.internal:host-gateway"
# Local *.alogins.net web services: the Kimi CLI's own web-fetch tool
# runs IN THIS container, so it needs the same hairpin-NAT dodge as the
# adolf gateway (the public A record can't loop back through the router).
# Route to the host gateway where Caddy terminates TLS on :443.
- "family.alogins.net:host-gateway"
- "wiki.alogins.net:host-gateway"
restart: unless-stopped
# hindsight — Adolf memory backend, replacing cognee/cognee-mcp/cognee-llm

View File

@@ -185,15 +185,21 @@ function buildServer() {
// --- browser --------------------------------------------------------------
server.registerTool('browser_invoke', {
description:
'Generic pass-through to the OpenClaw gateway "browser" agent tool (agent-controlled Chrome/Brave/Edge ' +
'automation: tabs, snapshot, click, type, screenshot). Unlike cron/nodes, "browser" is NOT in the ' +
'gateway HTTP default hard-deny list, so this can work as soon as the gateway is up and its normal ' +
'tools.* policy allows "browser" for the caller — no special P6 HTTP-deny override needed. Args are ' +
'forwarded verbatim as the tool call payload; the exact action/argument vocabulary is defined by the ' +
'running gateway and needs live introspection once it exists (deferred to P6/P7).',
'Drive the OpenClaw gateway "browser" tool (a headless Chromium the agent controls). ' +
'TOP-LEVEL actions (the "action" arg): status, start, stop, profiles, tabs, open, navigate, ' +
'snapshot, screenshot, act, console, dialog, pdf, upload. ' +
'IMPORTANT: there is NO top-level "click"/"type"/"fill"/"evaluate" action — ALL page ' +
'interactions go through action="act" with args={kind, ref, ...}. ' +
'Typical flow: action="open" {url} -> action="snapshot" to get element refs (e.g. "e59") -> ' +
'action="act" to interact. Interaction args examples: ' +
'type text -> {kind:"type", ref:"e59", text:"hello"}; ' +
'click -> {kind:"click", ref:"e33"}; ' +
'fill -> {kind:"fill", ref:"e65", text:"secret"}; ' +
'also kind can be hover|select|press|scrollIntoView|drag|evaluate. ' +
'Refs go stale after navigation/DOM change — if an action reports "ref not found", re-snapshot.',
inputSchema: {
action: z.string().describe('Browser tool action, e.g. "status", "open", "snapshot", "click", "type".'),
args: z.record(z.string(), z.unknown()).optional().describe('Action-specific parameters object.'),
action: z.string().describe('Top-level browser action: open | navigate | snapshot | screenshot | act | tabs | status | start | stop | profiles | console | dialog | pdf | upload. Use "act" for ALL page interactions (click/type/fill), never "click"/"type" directly.'),
args: z.record(z.string(), z.unknown()).optional().describe('Action params. action="open": {url, label?}. action="act": {kind:"type"|"click"|"fill"|"hover"|"select"|..., ref:"eN" from snapshot, text:"..." for type/fill}. action="snapshot": {refs:"aria"} for stable refs.'),
},
}, async ({ action, args }) => invokeGatewayTool('browser', action, args || {}));