DEV Community

Scalix World
Scalix World

Posted on • Originally published at scalix.world on

How to Deploy an AI Agent to the Cloud

You built an agent. It is a loop: call a model, read the tool calls it comes back with, run them, feed the results in, go again until the work is done. It runs on your laptop, it works, and it stops the moment you close the lid.

Getting it running around the clock is a different problem from getting it working. Not a harder one, but a different one, and most of the guides on deploying an AI agent skip straight to the deploy command without saying what an agent actually needs from the infrastructure underneath it. That part is worth ten minutes.

What an agent needs that an app does not

Start with the shape of the thing. A web app receives a request, does some work, returns a response, and forgets everything. An agent is the opposite: it is a process that stays alive, accumulates context, and decides for itself what to do next. Four consequences fall out of that.

State has to outlive the process. Conversation history, task progress, what the agent has already tried. If that lives in a Python dict, the next restart is an amnesiac. Put it in a database from the start, keyed by session or task, and write to it at the end of every loop iteration rather than at the end of the run.

Secrets have to come from the environment. Your model provider key, your database URL, whatever credentials the tools need. These belong in environment variables set at deploy time, not baked into the image and definitely not in the repository. Rotating a key should be a redeploy, not a rebuild.

Restarts are normal, so make them boring. Processes get killed. A node reboots, a deploy rolls, the agent hits an unhandled exception on a malformed tool response at 3am. If your loop resumes from durable state, a restart costs you seconds. If it does not, it costs you the run.

Egress and logs are the whole observability story. An agent talks to an LLM API and to whatever tools you gave it, so it needs outbound network. And because you cannot attach a debugger to something that only misbehaves once a day, structured logs on every iteration (which tool, which arguments, what came back) are how you find out what your agent actually did.

Why functions are the wrong default here

The instinct is to reach for serverless functions, because agents feel event-driven. It fights the model more than it helps.

Functions are built for request-and-forget work inside a bounded execution window. An agent loop holds context across many model calls, keeps connections open, and can legitimately run for minutes. You end up either fighting the timeout or shredding the loop into a state machine across a dozen invocations, which is a lot of engineering to make the wrong shape fit.

Functions are still useful here. They are a good home for the individual tools your agent calls, where request-and-forget is exactly right. The loop itself wants a long-running service.

The isolation question, honestly

Here is the part that matters more for agents than for ordinary services.

Your agent executes what a model told it to execute. Maybe it shells out. Maybe it runs generated code. Maybe it just fetches a web page, and that page contains text engineered to steer the next tool call. The blast radius of agent code is decided at runtime, not at review time, which is not true of the CRUD service running next to it.

Most container platforms run your workload as a process in a shared kernel, isolated by namespaces and cgroups. That is genuinely good isolation and it holds up for the overwhelming majority of workloads. It is also, by construction, one kernel vulnerability away from your neighbours. That is a well-understood trade-off and plenty of people accept it knowingly.

We think agent code is the workload where you should think twice before accepting it by default. So on Scalix Run, every deployment gets its own microVM: its own kernel, its own memory boundary, hardware-level isolation. The obvious objection is startup cost, and it used to be a real one. MicroVMs boot in roughly 76ms on our hardware, which is why this is the default tier rather than a premium one. You are not choosing between fast and isolated.

Packaging the loop

Nothing exotic. Your agent needs to be a process that starts, runs, and does not exit.

If it exposes an HTTP endpoint, so you can trigger it or check on it, listen on a port and read that port from the environment. If it is a pure worker driven by a queue or a timer, it just needs a main loop that blocks. Either way: no local state that matters, no secrets in the image, and logs to stdout.

You do not have to write a Dockerfile if you do not want one. Scalix Run deploys from source and detects the runtime from your package.json, requirements.txt, go.mod, Cargo.toml, or a Dockerfile if you have written one, and builds the image for you.

Deploying it

With a prebuilt image, the deploy is one command:

scalix-cloud run deploy --name agent \
  --image api.scalix.world/<project-id>/agent:v1 \
  --port 8080 \
  --min-instances 1 --max-instances 5

Enter fullscreen mode Exit fullscreen mode

Secrets go in as environment variables on the service. Through the API that is the env block:

curl -X POST https://api.scalix.world/v1/services \
  -H "Authorization: Bearer $SCALIX_API_KEY" \
  -d '{
    "name": "agent",
    "container": {
      "image": "api.scalix.world/<project-id>/agent:v1",
      "port": 8080,
      "env": {
        "MODEL_API_KEY": "...",
        "DATABASE_URL": "postgres://..."
      }
    },
    "scaling": { "min_instances": 1, "max_instances": 5 }
  }'

Enter fullscreen mode Exit fullscreen mode

The service comes up at a URL that does not change between deploys:

https://agent.run.scalix.world

Enter fullscreen mode Exit fullscreen mode

Every deploy is a revision, so when a prompt change makes your agent worse in a way the tests did not catch, scalix-cloud run rollback <service-id> puts the old one back. Logs come back with scalix-cloud logs <deployment-id>.

Scale to zero, if your agent is bursty

Most agents are not busy. They wake up on a webhook, a schedule, or someone typing, do a few minutes of work, and go quiet. Paying for an instance that sits idle 22 hours a day is the default cost of agent hosting on most stacks.

Deploy with --min-instances 0 and the service scales down when nothing is calling it, then scales back up on the next request. Compute meters only while an instance is actually running. Two honest caveats: anything you keep, like stored data, bills whether the agent is awake or not, and an agent that has to react within seconds of an event should keep a floor of one instance rather than paying a cold start on every trigger.

The part that gets interesting

Your agent is now running on infrastructure. It can also operate that infrastructure.

We run a hosted MCP server at api.scalix.world/v1/mcp that exposes the platform as 55 tools: run queries and migrations, branch a database, deploy a service, check status and spend. One API key authorizes all of it, and that same key covers database, storage, functions, AI inference, and the registry. Point your deployed agent at it and the tools become things it can do.

Which means an agent can provision the database it needs for a new task, spin up a second service to handle a workload, check whether its deploys landed, and check what all of that cost. It is the same capability we wrote about when a coding agent deploys your app, except the agent doing the operating is the one you deployed. Give that scoped keys and approval gates on the destructive actions, the way you would with any other operator.

Where we are

Being straight about the stage: one EU region today, India next. When something breaks you get the two engineers who built it rather than a support tier. We publish uptime at status.scalix.world so you can check the claim rather than take it.

If you have an agent on your laptop that should be running somewhere else, Scalix Run is where to put it. Deploy it, point it at the MCP server, and let it run its own infrastructure. Come tell us what breaks on Discord.

Top comments (0)