DEV Community

Mykola Bielousov
Mykola Bielousov

Posted on

Otto is live: what it took to ship an AI browser agent to the Chrome Web Store

On July 15, Google rejected my Chrome extension. I found out on July 23. Years ago I had set up a Gmail filter that auto-deleted every email from Google, so the rejection notice spent that week sitting in my Trash while I refreshed the developer dashboard, wondering why review was taking so long.

The extension is Otto, and it's live on the Chrome Web Store now: https://chromewebstore.google.com/detail/otto/pbkhgagiaojcgbpcecmpmldgaifkcpoo It's a side-panel agent that drives your real, logged-in browser: you type what you want done, and it navigates, reads pages, clicks, types, takes screenshots, and reports back in chat. You can stop it at any moment, and Chrome shows a banner the whole time it's in control.

The rejection reason was "Keyword Spam". My description listed which AI providers Otto supports, and naming other companies' brands in a listing counts as keyword stuffing, true or not. I deleted the names (the list lives in the README now), resubmitted, and got approved in about a day. The whole detour cost two weeks. The actual fix took twenty minutes.

What makes Otto different from the hundred other AI sidebars: there is no Otto server and no Otto account. You bring your own API key, it lives in Chrome's local extension storage, and it goes to exactly one place, the AI provider you picked. I never see your data. I couldn't if I wanted to; there is nothing to see it with.

Under the hood it's plain ES modules, with no build step and zero runtime dependencies. The agent loop and the provider adapters take fetch and the chrome APIs as arguments instead of importing them, so the whole logic layer runs under Node's built-in test runner, offline, with Chrome nowhere in sight. When a provider changes its streaming format, I can reproduce the failure in a unit test in seconds instead of clicking through the extension by hand.

The one scary dependency is the chrome.debugger permission. Gmail, Google Docs, and most login and checkout flows ignore synthetic DOM events, so an extension that "clicks" with JavaScript does nothing there. Input dispatched through the DevTools Protocol is trusted, the same as a real mouse and keyboard. It also lets Otto screenshot background tabs, so it never has to steal your focus. That permission is the reason my review took the slow, in-depth track.

A few smaller things that might save someone a day. The manifest description caps at 132 characters, and the store rejects the whole upload over it. Screenshots at 1280x800 worked for me, but PNGs with an alpha channel get refused, so export JPEGs. Each permission justification caps at 1,000 characters, which for chrome.debugger is a genuinely hard writing exercise. And don't promise more than the product does: Otto needs an API key, not a chatbot subscription, so the listing has to say so up front.

Otto is free and open source. Install it from the Chrome Web Store: https://chromewebstore.google.com/detail/otto/pbkhgagiaojcgbpcecmpmldgaifkcpoo. The code, the test suite, and the manual test plan are on GitHub: https://github.com/legisus/otto-ai-sidebar. If you try it and something breaks, open an issue. The debugger attach flow and provider quirks are where the dragons live, and real-world reports are the only way I find them.

Top comments (0)