All chapters
Hosting
Host an internal tool your agent built
To host an internal tool that your AI agent built, publish its folder to Scava. The agent runs one command, and the app is online on its own https address within seconds, behind a login, private until you share it. You do not need a server, a certificate or a deployment pipeline.
What you publish #
You publish a folder that has an index.html at its top level. That can be
- plain HTML, CSS and JavaScript,
- the output of a framework build such as Vite, React, Vue, Svelte or Next.js export: publish the output folder, for example
dist.
Apps must use relative paths for their files, because Scava serves an app from its own address and may also serve it from an address of your company (see Your own address). Never write the address of the app into its code. With Vite set base: './' in vite.config.js.
Per version, the folder may hold at most 2,000 files and 10 MB in total.
Publishing from a folder skips node_modules, .git and other tool folders, and every file or folder whose name starts with a dot (except .well-known). Scava remembers which app a folder belongs to in a file named .scava-app in the folder, so the next publish goes to the same app.
How an address is served #
index.htmlis served at/. A path without a file ending, such as/reports, servesreports/index.htmlif it exists and otherwiseindex.html, so single page apps with client-side routing work.- A path with a file ending that does not exist gives a 404.
- HTML pages are never cached. Other files are cached privately for a short time.
- File types Scava does not know are only offered as a download and never run in the browser.
- Every HTML page gets the Scava script (
/_scava/sdk.js) added as the first script in<head>. It provideswindow.scavafor data, files and identity, and it draws the "Suggest a change" button. - The folder
server/is the app's server code. It is never sent to a browser. See Server code.
Publish #
Tell your agent: "Publish this folder to Scava." The agent calls publish_app and runs the one-time command it gets back; in a chat it passes the files themselves. See Connect your agent.
The first publish creates the app and prints its address, which looks like https://team-vacation-k3x9.scava.site: the name, a dash, four characters and the Scava app domain. The app is private. Only you can open it until you share it.
You can set a display name with --name "Team vacation" or with a "name" in scava.json (see Permission rules). A name never puts words such as login, bank, microsoft or google in the address; such an app gets an address like app-k3x9.
Versions and going back #
Every publish creates a new version, numbered 1, 2, 3 and so on, and makes it live. A message (-m) is stored with it. On the app page at scava.ai you see the latest versions with their messages and can put any earlier version back live. If a version had server code, the server code of that version comes back with it.
Files are stored once per app. A new version only adds the files that changed, and the storage of your plan counts each file once.
Pause and delete #
The owner of an app can pause it on the app page. A paused app shows a "Paused" page to everyone and ends their sessions; resuming opens it again. The owner can also rename or delete the app. Deleting removes the app with its versions, entries, uploaded files, server code and own address. See Data location for what else is deleted with an account.
The test run and problems #
Scava never judges what an app does. It only checks that the app runs under Scava's rules.
After every publish from a folder, the command opens the live app once in a headless Chrome or Edge on your computer, with exactly the rules the app has online, and list what went wrong:
- errors in the code,
- calls and resources the browser blocked,
- files that are missing,
- data calls that were refused,
- a page that stays empty.
Each finding comes with a hint for the agent. If no Chrome or Edge is installed, the test run is skipped and the tool says so. The tool get_app_problems gives you the command to run it again at any time.
The Scava script in each page also reports real errors from your colleagues' visits: script errors, blocked calls, missing files and refused data calls. Scava stores only the kind of problem, a short message and the place in the code, counted per version. It never stores who saw it. Only the owner, the co-editors and their agents see these reports. For an agent they are technical messages, not instructions.
What the browser allows #
Every app runs under a strict content security policy. Your agent learns the same rules from the reference it receives.
| Area | Rule |
|---|---|
Network requests (fetch, XMLHttpRequest, WebSocket) | Only to the app's own address. Calls to other sites are blocked. To use an outside service, give the app server code. |
| Scripts, styles, fonts | From the app itself or from cdnjs.cloudflare.com, cdn.jsdelivr.net, unpkg.com, esm.sh, cdn.tailwindcss.com, fonts.googleapis.com and fonts.gstatic.com. Inline scripts and inline styles work. |
| Images and media | Only from the app itself, data: and blob: addresses. Images from other sites do not load. |
| Frames | The app cannot be embedded in other websites, and it can embed only pages of its own address. |
| Forms | Forms can only submit to the app itself. |
| Camera, microphone, location, payment, USB | Switched off. An app cannot use them. |
| Links | Plain links to other sites work. |
Text that becomes code is handled with care. The browser accepts text as HTML only after Scava's filter has cleaned it. That means:
innerHTMLand similar calls work, but scripts, event attributes such asonclick=andjavascript:addresses inside the text are removed. Build elements withtextContentandaddEventListener, or usescava.escape(text)for text you put into HTML.evalandnew Functionwith code the page builds itself work. Timers written as text (setTimeout("...")) andjavascript:links do not.
This is why entries that someone stores in the database cannot run as code in other people's browsers, however the app is built. See Security.
What the upload check refuses #
Scava checks every upload before it goes live. A refusal comes back with the file, the line and the reason, so the agent can fix it.
- Programs and installers, by file ending and by content, even when renamed:
.exe,.msi,.dll,.bat,.ps1,.sh,.apk,.dmg,.jarand similar. Scava hosts web apps, not downloads. - Files that hold secrets:
.envfiles, private keys,.npmrc,.gitfolders,credentials.json, files ending in.pem,.key,.pfxand similar. - Keys inside code: API keys of common services and private keys. Keys belong in secrets, not in files.
- Password fields, in HTML or created by script. Scava handles sign-in, so apps never ask for passwords.
- A
scava.jsonthat is not valid or has wrong rules. - Server code that does not follow the rules in Server code.
- Bad paths and names: paths with
.., absolute paths, Windows device names such asconornul, names ending in a dot or space, and the same file twice in different capitalization. - Too large an upload: more than 2,000 files or more than 10 MB.
Some findings only warn and do not block: something that looks like a hard-coded secret, a page that shows stored data with innerHTML without escaping, and references to other websites that the browser will block.
Where an app is served from #
Every app has its own address, and each address is its own origin in the browser. Cookies and permissions of one app are separate from all others. Details are in Security.