Skip to content

๐Ÿ—๏ธ Architecture โ€‹

WCI separates what the agent sees, what the site allows, and how actions execute into three cooperating layers.

WCI architecture: data-wci-* markup, distiller, LLM context, WciBridge actions, and site context files

Layer 1 โ€” Semantic HTML (@webcontextinterface/spec) โ€‹

Standard DOM nodes carry machine-readable metadata:

  • Identity โ€” data-wci-id
  • Role โ€” action, form, display, nav, status, landmark
  • Intent โ€” data-wci-desc, data-wci-action
  • State โ€” data-wci-state (JSON snapshot)
  • Guards โ€” data-wci-precondition, data-wci-required

readWciNodeSpec(element) maps attributes to the WciNodeSpec TypeScript interface.

Layer 2 โ€” Distiller (@webcontextinterface/distiller) โ€‹

The distiller walks the DOM, collects annotated nodes, sorts by priority, and emits a compact WciView (JSON) or Markdown string suitable for LLM context windows.

Design goals:

  • Drop decorative/layout nodes (data-wci-hidden)
  • Scope to a landmark (scope option)
  • Cap node count (maxNodes) for token budgets
  • Optionally attach site summary metadata

Layer 3 โ€” Bridge (@webcontextinterface/bridge) โ€‹

The bridge translates agent decisions into real DOM interactions:

ActionDOM effect
click.click(), updates state
fillNative value setter + input/change events
select<select>.value + change
checkcheckbox checked + change
focus.focus()
clearClears input value
submitform.requestSubmit()
navigatewindow.location.href

Every dispatch returns a typed ActionResult: success flag, before/after state, optional side effects on sibling nodes, and structured errors (NODE_NOT_FOUND, PRECONDITION_UNMET, etc.).

State changes also emit wci:state-change on document for observers.

Site context (@webcontextinterface/context) โ€‹

Before touching a page, agents can load site policy. WciContextLoader resolves URLs in priority order: <meta name="wci:*"> tags, then X-WCI-Directives / X-WCI-Manifest / X-WCI-Context headers, then root /wci.txt, /wci.json, /wci.md. Well-known /.well-known/wci/* paths are fetched only as a fallback when no explicit URL was set.

PolicyEngine enforces allow/deny scopes, auth requirements, and human-confirmation scopes. Attach it to WciBridge via setPolicy so every dispatch is validated before DOM mutation.

Typical agent loop โ€‹

  1. WciContextLoader.load() โ†’ system prompt + policy
  2. WciDistiller.distilJSON() โ†’ page tool context
  3. LLM chooses { nodeId, action, value }
  4. WciBridge.dispatch() โ†’ ActionResult
  5. Re-distil or read sideEffects โ†’ next turn

Size and deployment โ€‹

Packages are tree-shakeable ESM/CJS builds. Use only the layers you need:

  • Read-only crawlers: @webcontextinterface/distiller + @webcontextinterface/spec
  • In-page agents: add @webcontextinterface/bridge
  • Multi-page flows: add @webcontextinterface/context