Skip to content
BetterWrightPublic

About

Open, batch-native website actions for browser agents

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

WebAgents

WebAgents is a small, open protocol proposal for giving browser agents a safe directory of first-party website actions and one dependency-aware batch endpoint.

An agent normally spends a model round trip discovering each control, performing one action, observing the new page, and planning again. A participating site publishes the exact actions it supports, so the agent can plan a complete workflow and submit it once. The site still owns authentication, authorization, validation, rate limits, pacing, state, and business logic.

GET /webagents.md                     discover a compact action directory
POST /api/agent/workflow              submit one bounded operation graph
read → write → write → final read     return verified results in one response

WebAgents is not remote code execution, a page-authored prompt, or permission to bypass the visible product. Descriptions and results are untrusted data. Action names resolve only through a server-owned allowlist.

Why it is fast

  • One discovery fetch replaces repeated accessibility-tree inspection.
  • $ref passes one operation's result into a later input without another model turn.
  • Independent reads can run concurrently.
  • Writes stay in deterministic list order.
  • A final read verifies the state in the same batch.
  • Server-declared pacing keeps fast batches realistic and rate-limit friendly.

The result is especially useful for multi-step tasks such as “find this exact item, create an account, perform an authorized action, then verify it.” It does not make the network instantaneous and it does not remove application checks.

Five-minute setup

  1. Define a manifest:
{
  "version": "0.1",
  "workflow": {
    "endpoint": "/api/agent/workflow",
    "maxOperations": 8,
    "parallel": true,
    "references": true,
    "pacing": { "minIntervalMs": 120, "maxConcurrency": 2 }
  },
  "actions": {
    "catalog.find": {
      "pathPrefixes": ["/products"],
      "description": "Find an exact product; reference productId.",
      "effect": "read",
      "inputSchema": {
        "type": "object",
        "properties": { "query": { "type": "string" } },
        "required": ["query"]
      }
    },
    "cart.add": {
      "pathPrefixes": ["/products"],
      "description": "Add one productId to the active cart.",
      "effect": "write"
    },
    "cart.state": {
      "pathPrefixes": ["/products"],
      "description": "Return the active cart for verification.",
      "effect": "read"
    }
  }
}
  1. Serve that JSON in one fenced block at /webagents.md and as raw JSON at /.well-known/webagents.json.

  2. Route the manifest's endpoint to handlers backed by the same service layer as the visible UI:

import { createNodeAdapter, WebAgentsError } from "webagents-protocol";

const webagents = createNodeAdapter({
  origin: "https://shop.example",
  manifest,
  getContext: (req, res) => loadSessionAndRequestContext(req, res),
  handlers: {
    "catalog.find": ({ input, context }) => context.catalog.find(input.query),
    "cart.add": async ({ input, context }) => {
      if (!context.user) {
        throw new WebAgentsError("Sign in first.", { status: 401, code: "unauthorized" });
      }
      return context.cart.add(input.productId);
    },
    "cart.state": ({ context }) => context.cart.read(),
  },
});

const server = http.createServer(async (req, res) => {
  if (await webagents.handle(req, res)) return;
  return handleYourExistingSite(req, res);
});

The package is currently installable from this repository:

npm install github:BetterWright/WebAgents

The adapter has no runtime dependencies. The complete session-aware implementation is in examples/node-server.

One batch

{
  "version": "0.1",
  "operations": [
    {
      "id": "find",
      "action": "catalog.find",
      "input": { "query": "wireless keyboard" }
    },
    {
      "id": "add",
      "action": "cart.add",
      "input": { "productId": { "$ref": "find.productId" } }
    },
    {
      "id": "verify",
      "action": "cart.state",
      "input": {}
    }
  ]
}

$ref implies a dependency on find. Because add is a write, a conforming server also makes the later verify read depend on it. The response is keyed by operation id:

{
  "ok": true,
  "protocol": "webagents/0.1",
  "pacing": { "minIntervalMs": 120, "maxConcurrency": 2 },
  "results": {
    "find": { "productId": "kbd-75" },
    "add": { "added": true },
    "verify": { "items": [{ "productId": "kbd-75", "quantity": 1 }] }
  }
}

Discovery rules

  • Clients try https://origin.example/webagents.md, then https://origin.example/.well-known/webagents.json.
  • Markdown contains exactly one webagents or webagents-json fenced JSON block. Surrounding prose is never executable.
  • The endpoint must resolve to the active page's origin.
  • pathPrefixes keeps unrelated actions out of the model context. It is a relevance hint, not authorization.
  • If discovery is absent, invalid, or unsafe, the client falls back to normal browser interaction.

Validate before deploying

Validate a local manifest:

node bin/webagents.js validate examples/node-server/webagents.json --origin https://example.com

Smoke-test a deployed site without running any actions:

node bin/webagents.js check https://example.com/products/keyboard

The live checker verifies both GET and HEAD discovery paths, MIME types, normalized mirror equality, same-origin endpoint resolution, and active-path action scoping. It deliberately never POSTs.

A deployed example is available at bhbench.ssh.codes/webagents.md.

Production checklist

  • Use one fixed PUBLIC_ORIGIN; do not trust arbitrary forwarded host headers.
  • Keep the endpoint same-origin and HTTPS.
  • Reuse the website's normal cookie or token session.
  • Authenticate and authorize every action inside its handler.
  • Validate action inputs in the application even when a schema is published.
  • Rate-limit authentication and expensive actions.
  • Hash passwords, redact secrets, and never place credentials in results or logs.
  • Let the server enforce its configured pacing; ignore faster client hints.
  • Serialize writes, bound bodies/results, reject cycles, and use database transactions where atomicity matters.
  • End mutating workflows with a read and test the public origin after every deploy.

Read the normative SPECIFICATION.md, the deployment-focused SECURITY.md, and TROUBLESHOOTING.md before production use.

Status

Version 0.1 is an implementable protocol proposal. Compatibility changes require a new manifest version. Contributions and real-world deployment reports are welcome.

MIT licensed.

About

Open, batch-native website actions for browser agents

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages