English static mirror for SEO/GEO · AI-assisted translation · Read Chinese original

OpenBot Architecture Deep Dive: Giving AI Agents a Real Computer Without Burning Down Your Company

Forum topic · QianXun · 2026-11-01

Summary

OpenBot is an open-source, self-hosted enterprise agent platform that wraps LLM-powered agents in a ChatGPT-like interface while confining every agent to a sandboxed, controlled computer container. This in-depth technical guide explains its four-block architecture (Surfaces, Server/Gateway control plane, pluggable AG-UI brains, and supervised computers), then walks through setup in minutes via Docker or source, declarative YAML-based coworker configuration, and integration of custom agents in Python (Pydantic AI) or TypeScript (LangGraph) without any private SDK. The core innovation is a single security gateway through which every tool call must pass: server-side snapshot resolution of browser targets, CEL policy evaluation with asymmetric fail-closed semantics (deny-before-allow), append-only PostgreSQL audit rows written before execution, DNS-rebinding protection with DNS pinning, blind credential entry that never exposes secrets to the model, and instant 409 rejection when a human takes over control. The article also covers anti-hallucination prompt engineering lessons, skill-based tool pruning with fail-open behavior, routine scheduling guardrails, and tamper-resistant audit trails that even block TRUNCATE attempts.

OpenBot Architecture Deep Dive: Giving AI Agents a Real Computer Without Burning Down Your Company

*Structured English summary of a long-form Chinese technical article on zhichai.net. The original includes hands-on attack tests, full architecture diagrams, and code samples.*

Key points

  • What OpenBot is: An open-source, self-hosted enterprise agent platform (a template, not a hosted product — all workspaces are "private": true, no npm packages). It gives agents a ChatGPT/Claude-style UI while locking each agent into an isolated, controlled computer container.
  • The problem it solves: Real office automation needs real browsers (legacy systems, 2FA login walls), framework-agnostic governance (agent frameworks churn every few months), tool-list noise reduction (200+ tool definitions wreck model accuracy), and safe unattended execution (prompt injection at 3 a.m.).
  • Architecture overview

    Four building blocks plus one iron rule — every tool call passes through a single gateway:

    | Module | Port | Role | | :--- | :--- | :--- | | app/ | 3010 (dev) / 3001 (single container) | React 19 main console: channels, live screen, admin | | server/ | 3001 | Bun + Hono control plane: auth, context assembly, the single gateway | | agent-computer/ | 4100 (loopback only) | Sandboxed container: headed Chromium, /workspace, sanitized Bash | | supervisor/ | 4500 | Sole holder of read-only Docker socket; provisions per-person computer containers | | worker/ | none | 30-second routine poller with DB row locks | | agent-* (15 samples) | 4200–4214 | AG-UI sample brains: LangGraph, CrewAI, Pydantic AI, Claude SDK, Mastra, etc. |

    Governance rides on the protocol, not the framework: OpenBot only requires agents to speak AG-UI (standard JSON input, SSE event stream). A brain can run anywhere in any language; the gateway still decides what it may do.

    Security gateway: five key mechanisms

    The gateway enforces a fixed order: resolve target → evaluate CEL policy → write audit row → execute.

    1. Zero-DOM-pollution snapshots & anti-DNS-rebinding: Uses Playwright's ariaSnapshot() to extract the accessibility tree (17 interactive control types, elements referenced as e5, etc.). The gateway never trusts the agent's claimed element names — it re-resolves e5 from its own server-side computer_snapshot table, checking session/snapshot generation (409 StaleSnapshotError on mismatch). Egress goes through a local filter proxy doing exactly one DNS resolution, then connecting to the validated literal IP — DNS rebinding is physically impossible. Cloud metadata hosts (169.254.169.254, etc.) are hard-blocked, including IPv6-mapped disguises. 2. Asymmetric fail-closed CEL policies: Deny rules evaluate before allow rules; nothing is allowed by default. A broken deny rule evaluates as *deny* (error → true); a broken allow rule evaluates as *no-allow* (error → false). Intent normalization groups clicks, submit-typed inputs, and Enter/Space keypresses into one activate intent so models can't bypass rules. An initiator.kind field distinguishes person from routine, enabling rules like "block all writes/commands when no human is watching." 3. Write-before-act auditing: Audit rows are await-written to PostgreSQL *before* execution — if the DB is down, actions never fire. The audit_events table is append-only with row-level and BEFORE TRUNCATE triggers; CSV export defends against formula injection and logs exports themselves. 4. Credential blindness: Agents can never receive passwords. Users type credentials into out-of-band secure forms; the container verifies page origin before filling (anti-phishing), and secret inputs are masked in all snapshots/screenshots ("[hidden: sensitive field]") via DOM tagging plus CSS text security. 5. No queuing on human takeover: When a human takes control, in-flight actions drain and all new agent actions (including shell and file writes) get an instant 409 Conflict — never queued or replayed, since the page state has changed. Stale snapshots are invalidated so the agent must re-observe before acting.

    Hands-on validation (the author's three "knife tests")

  • Extracting DATABASE_URL via env in the agent's shell: nothing leaked — even proxy credentials are stripped.
  • Creating a dangling symlink to /etc/cron.d/backdoor: blocked with 403 via a manual lstat/readlink walk up to 32 hops before any write.
  • TRUNCATE audit_events; on the database: rejected — Audit events are append-only (enforced by a migration literally named 0012_truncate_is_not_a_way_around_append_only.sql).
  • Setup and operations

  • Path A (single container): one docker run with EMBEDDED_POSTGRES=on on port 3001. Pitfall: mount the volume at /var/lib/postgresql, not /var/lib/postgresql/data — a lost+found folder makes initdb fail silently.
  • Path B (source dev stack): requires Docker, Bun 1.4.3+, Node/npx; scripts/start.sh auto-generates two distinct tokens (MANAGED_AGENT_TOKEN server→agent, AGENT_TOOL_TOKEN agent→gateway) with automatic restart on rotation.
  • Declarative coworkers: tenants are pure YAML (brand.yaml, agents.yaml, skills.yaml, channels.yaml); hiring a new bot is copying a catalog YAML file. Theme CSS is validated to block @import/url() exfiltration.
  • Prompt engineering and tool pruning

  • Anti-self-deception lesson: An unconditional "tell users you have no access when not connected" instruction caused the agent to claim no access *even after tools returned real files*. Fix: condition on observable facts (tool returned results = connected) instead of moral slogans.
  • Skills as a noise funnel: When granted tools exceed SELECTION_FLOOR = 12, a lightweight model matches relevant skills and the offered tool set becomes T_granted ∩ (union of skill-declared tools ∪ unclaimed tools). Skills never grant permissions (outer intersection is the security floor), and this narrowing layer deliberately fails open — it is a usability layer, not a security boundary. The gateway remains fail-closed.
  • Integrating your own agents

  • 15 sample brains, zero private SDK: none install any OpenBot SDK. Two integration paths:
  • Path A (13 of 15 samples): tools arrive as JSON Schema in the AG-UI request; server-side tools are intercepted in-gateway by HeadlessToolsMiddleware (policy, audit, human approval as interrupt) and the agent is re-invoked with results — no gateway calls in agent code.
  • Path B (graph-internal callbacks): for multi-step LangGraph graphs, agents call POST /api/agent-tools/call with AGENT_TOOL_TOKEN plus an HMAC-SHA256-signed 10-minute openbotRun assertion, cross-verified against the static token identity to prevent impersonation.
  • Python example (~30 lines): FastAPI + pydantic-ai + AGUIAdapter.dispatch_request, with constant-time token comparison middleware; endpoints must be explicitly allow-listed via AGENT_ENDPOINT_ALLOWED_HOSTS (no wildcards, SSRF protection).
  • Routine guardrails: minimum 15-minute interval verified by simulating 200 future firings from a leap-year-safe anchor; max 20 concurrent routines per person; automatic fatigue circuit-breaker after 10 consecutive failures.

Takeaway

OpenBot's central thesis: "can call your tools" and "you dare let it near production tools" are separated by an entire customs bureau. By pinning governance to an open protocol (AG-UI) and enforcing one audited, fail-closed gateway, it lets teams use any agent framework while keeping secrets out of model context, blocking DNS rebinding and symlink attacks, and producing an append-only audit trail that survives even deliberate TRUNCATE attempts.

*Original article by the zhichai.net community; all technical details, file names, and code excerpts are drawn from the OpenBot repository as cited in the source post.*

Tags

#openbot#ai-agents#agent-security#ag-ui-protocol#cel-policies#audit-logging#sandboxing#self-hosted

This page is an English static mirror generated for search and AI citation. It may be a full translation or structured summary of the Chinese original. Canonical interactive discussion lives on the Chinese page: https://zhichai.net/topic/178636664