ai newsDo., 15. Okt.
EilmeldungMeta and Apple team up to make Muse AI models run better on Macs

Why One Happy Path Beats a Menu of Options When Your User Is an AI Agent

Give a human engineer five ways to deploy an app and they'll pick one. Give an AI agent the same five ways and it will try three of them, invent a sixth, and leave you debugging at midnight. So why do we keep building infrastructure as if the primary user is still a person clicking through a dashbo

dev.toDonnerstag 16:17 · 15.10.5 Min. Lesezeit
Bild: dev.to

Give a human engineer five ways to deploy an app and they'll pick one. Give an AI agent the same five ways and it will try three of them, invent a sixth, and leave you debugging at midnight. So why do we keep building infrastructure as if the primary user is still a person clicking through a dashboard?

This post is about a design rule that sounds too simple: one happy path per job. I'll show how agentic-hosting, an open-source self-hosted platform for AI agents, builds around that rule, and how an agent actually uses it. By the end you'll know why the constraint exists, and how to deploy from git, add a database, and hit a live URL through the API.

⭐ agentic-hosting is open source — star it on GitHub: https://github.com/dennisonbertram/agentic-hosting

🤖 Give this to your agent: point it at https://raw.githubusercontent.com/dennisonbertram/agentic-hosting/main/llms.txt (or the skill at https://raw.githubusercontent.com/dennisonbertram/agentic-hosting/main/skills/agentic-hosting/SKILL.md ) and it can sign up and set things up from one link.

I used to treat "one way to do it" as a product smell. Real platforms ship flexibility. Heroku, Kubernetes, Coolify, Dokku: each one gives you knobs because operators disagree about builds, routers, and databases.

Agents don't disagree. They sample. When a tool returns three valid options, the next token can go any direction. Retries compound that. So a menu of build systems isn't convenience. It's a lottery over failure modes you didn't write tests for.

The fix isn't smarter prompting. It's a smaller grammar. If there's only one way to build, route, and provision a database, the agent can't invent a clever path that your security model never considered.

agentic-hosting's README puts it as design principle #2: one happy path per primitive. One build system (Nixpacks), one router (Traefik), one engine per database type (Postgres or Redis). The rest of this post is what that looks like in real API calls.

Nixpacks turns a git repo into a container image without a Dockerfile. That's the only build path. There's no "also support Buildpacks" fork, and no "also accept a custom Dockerfile upload" branch for the agent to wander into.

An agent deploys from git in two steps. First it creates a service. The image field is required by the API, so for a git deploy it passes the placeholder "pending" (this is what the ahc CLI sends):

POST /v1/services Authorization: Bearer <api_key> Content-Type: application/json { "name": "my-app", "image": "pending", "port": 3000 } Enter fullscreen mode Exit fullscreen mode Then it starts a build:

POST /v1/services/ { serviceID } /builds { "source_type": "git", "source_url": "https://github.com/org/repo", "source_ref": "main" } Enter fullscreen mode Exit fullscreen mode Those three fields are the whole request. source_type must be "git". source_ref defaults to "main" if you omit it. HTTPS only. Allowed hosts are fixed: github.com, gitlab.com, bitbucket.org, sr.ht, codeberg.org. Anything else is rejected before a build starts.

The agent can stream build logs while Nixpacks runs:

GET /v1/services/ { serviceID } /builds/ { buildID } /logs?follow = true Enter fullscreen mode Exit fullscreen mode One build path means one log shape to parse and one place to look when something fails. That matters more than the build tool itself.

Routing is also a single path. Traefik sits in front on ports 80/443. The control plane writes Traefik's file-provider config itself, and every tenant container sets traefik.enable=false so an image's own labels can't hijack traffic.

The URL the agent gets back is deterministic:

dns_label is derived from the service name. There's no "pick your own reverse proxy" setting, and no custom-domain API yet (that's tracked as issue #82, still open). The agent asks for a service and gets one URL pattern. Period.

GET /v1/services/ { serviceID } # → includes "url": "http://svc_….localhost" # or "https://my-app.example.com" Enter fullscreen mode Exit fullscreen mode One engine per database type Need a database? The type field accepts exactly two values: "postgres" or "redis". Not MySQL. Not Mongo. Not "bring your own container."

POST /v1/databases { "name": "my-db", "type": "postgres" } Enter fullscreen mode Exit fullscreen mode Creation takes roughly 10–30 seconds (it's a long-running route so it isn't killed by the short request timeout). Then:

GET /v1/databases/ { dbID } /connection-string Enter fullscreen mode Exit fullscreen mode Wire it into the service with encrypted env vars, then restart:

POST /v1/services/ { serviceID } /env { "DATABASE_URL": "<connection-string>" } POST /v1/services/ { serviceID } /restart Enter fullscreen mode Exit fullscreen mode Env values are encrypted at rest with AES-256-GCM and masked on read unless you pass?reveal=true. Again: one shape for "attach a database," not a family of adapters.

The happy-path rule shows up in smaller places too. Service create accepts name, image, port, and optional env. No memory_mb. No cpu_count. Image pulls are Docker Hub or the loopback registry at 127.0.0.1:5000 only. Mutating requests can send an Idempotency-Key header so a retry doesn't deploy twice (10-minute TTL, scoped to tenant + method + path + body).

You're not removing power. You're removing branches. Humans still get a supervisory dashboard. The agent gets a short list of verbs that always mean the same thing.

If the control plane is already running (see the README quickstart, or --dev --open-registration locally), the agent path is:

Or skip curl and install the Claude Code skill plus /ah-deploy, /ah-db, /ah-logs, /ah-status commands from the repo. Same happy paths, fewer characters.

Custom domains (#82) and richer per-agent dev environments (PR #44) are still in progress. Don't wait on them to try the core loop.

When the primary user is an agent, a menu of options is a menu of mistakes. One build system, one router, and one engine per database type turn infrastructure into a small, predictable language. agentic-hosting is an open-source version of that idea you can run on a box you own.

I'd love to hear what breaks when you hand an agent the keys.

Quelle: dev.to (dev.to). Original öffnen