Deploy

How deploying works

The contract between your source and agenthost — how a deploy runs, how the runtime is chosen, the one entrypoint each runtime looks for, and how to confirm a deploy actually serves. Read this before your first deploy.

You deploy an app by handing agenthost your project files in-band and letting it build and run them. This section is the contract: the one entrypoint each runtime looks for, the file it installs dependencies from, how the runtime is chosen, and how to confirm a deploy actually came up. Match these conventions and a deploy just works.

How a deploy works

Call create_app with your project source as inline files ([{ path, content, encoding }]). agenthost builds it and runs it on managed hosting with automatic HTTPS and routing — you never configure a server, a container, or a port. Passing files to create_app builds and deploys in the same call; deploy_app ships new source to an app that already exists.

Inline files are the right shape for source you just wrote. For a project that already exists on disk, begin_upload mints a one-time URL you can stream a tarball to — the bytes go straight over HTTPS instead of through your context. See Sending a large project.

For a project that lives in a GitHub repository, connect it once and skip handing over source altogether: agenthost clones the branch itself and every push deploys. See Deploying from GitHub.

Builds are asynchronous. Both tools return as soon as the build is queued, so the status you get back is not the final one — poll get_app until it settles, then confirm the app actually serves. See Checking a deploy.

There is no start_command, and no port setting.

The way an app is started is fixed per runtime — it's the convention described in these pages, not a parameter. If you pass a field the tool schema doesn't define, it is silently ignored. To control how your app starts, match the entrypoint your runtime expects. A project that genuinely cannot can commit its own build steps in an agenthost.build file, or a Dockerfile to take the build over entirely — both live in the source, not in a tool call.

Runtimes at a glance

The runtime decides how your source is built and started. Pass it explicitly as runtime (e.g. "node:22"), or omit it on create_app and agenthost infers it from your files. Each runtime looks for one entrypoint:

RuntimeInferred fromEntrypoint it looks forInstalls deps from
staticindex.htmlindex.html at the project root
nodepackage.jsonnpm start (the start script)package.json
pythonrequirements.txt, .pyapp imported from app.pyrequirements.txt
phpcomposer.json, .phpindex.php at the project rootcomposer.json (optional)

Inference is a convenience for the common case; when in doubt, set runtime explicitly. If you omit it and no runtime can be inferred, create_app fails and asks for one.

The shortest possible deploy

create_project   { name: "My things" }              → project_id
create_app       { project_id, name, files: [...] } → url, service_id
get_app          { service_id }                     → poll until status settles
GET <url>                                           → the real pass condition

One field is settled at creation and cannot be changed afterwards: fqdn. Get the hostname right on the first call, or the app has to be recreated to change it.

A new app starts with no environment variables, and there is no parameter for them — they are set by you, in a browser, at /secrets-manager. An app that needs a key to boot will crash on its first deploy and come up on its own once you save one.

What every runtime shares

  • Your source goes in, dependencies do not. node_modules, vendor, .venv, __pycache__, .git and .env files are excluded from the build. Ship the manifest, not the install.
  • Each deploy replaces the last wholesale. A file you stop sending disappears from the app.
  • HTTPS and routing are automatic. You never expose a port or configure a proxy.
  • Bring your own Dockerfile and it is used instead of the generated one — see the escape hatch.

Where to go next