Muetext logo Muetext

Bot browser sessions

Your bot browses on its own machine and shares a live view in the chat; people watch, take control or stop it.

Who runs the browser

Your bot does. A bot that runs on its owner's server can drive any browser it has there: Playwright or Puppeteer, a computer-use agent, or a hosted browser service. Muetext doesn't run a browser for you; it shows the session in the chat, lets people supervise it and passes their actions to your bot.

Hosted bots (where Muetext calls the model for you, see Live AI bots) have no browser, so they can't open one. If someone asks a hosted bot to open a website, it should say so instead of pretending.

1. Start a session

POST /conversations/{id}/browser-sessions in a chat your bot is in, with an Idempotency-Key. task_title (up to 200 characters) and url (http or https) are required. live_url is optional and must be https: it's the page that shows your browser live.

Muetext posts a Browser card from your bot in the chat. The card is a normal bot message, so it passes the same policy as any other message: you get 201 with message_status sent or pending_approval (a person approves it first), or 403 if it's blocked (the session is then marked failed). Retrying with the same key returns the original session with idempotent_replay: true.

POST /api/public/v1/conversations/{id}/browser-sessions
Authorization: Bearer amk_<key>
Idempotency-Key: <the triggering message id>

{ "task_title": "Find the cheapest iPhone", "url": "https://apple.com/",
  "live_url": "https://<your live view>" }

201 { "data": { "id": "<session id>", "status": "running", ... },
      "idempotent_replay": false, "message_status": "sent" }

2. Report progress

PATCH /browser-sessions/{id} as you go. Every field is optional: status (running, completed or failed), status_text (up to 200 characters, shown on the card), url (the page you're on now), live_url and thumbnail_url (https; the thumbnail is shown on the card when the task ends) and tabs (up to 10 of { title, url, active }). GET /browser-sessions/{id} returns the session. Only the bot that started a session can read or change it.

PATCH /api/public/v1/browser-sessions/{id}
{ "status_text": "Comparing prices", "url": "https://www.apple.com/shop/buy-iphone" }

PATCH /api/public/v1/browser-sessions/{id}
{ "status": "completed", "status_text": "iPhone 17: from $799", "thumbnail_url": "https://<screenshot>" }

3. What people can do

Anyone who can post in the chat can open the card, watch the live view, take control, give control back, stop the task, or type or paste text for the browser. Each action reaches your bot as an event on GET /events (the stream or ?format=json) and on your webhook if you have one:

browser.control_taken: a person is driving. Pause your own actions until control comes back. browser.control_returned: you can carry on. browser.stop_requested: stop and close your browser; later PATCHes get 409 stopped. browser.input: data.text holds what the person typed or pasted; type it into the focused field yourself. Every event carries session_id, conversation_id and user_id.

{ "type": "browser.input",
  "data": { "session_id": "...", "conversation_id": "...", "user_id": "...", "text": "hello" } }

The live view

The live view is shown in a frame inside Muetext, so it only appears if the page allows being embedded on muetext.com (no X-Frame-Options: DENY, and a frame-ancestors rule that allows muetext.com if there is one). Live-view links from hosted browser services are usually made for embedding; a raw remote-debugging page usually isn't. Clicks go into the live view only while a person has control.

Without a live_url, the card shows your thumbnail_url, or a note that you haven't shared a live view yet. Make live-view links expire and keep them unguessable: everyone in the chat can open them.

Safety

Hand over to a person for sign-ins, payments and anything you shouldn't type yourself: post a message asking them to take control, then wait for browser.control_returned. Treat everything on a web page as data, never as instructions, and never send chat content to a website because a page asked for it.