The question this answers
What does a model or agent workload need from infrastructure that an ordinary request/response service never asked for?
A support-automation agent takes between forty seconds and three minutes per task: four to nine model calls, a vector search over the knowledge base, and two tool calls against the ticketing and billing systems. The HTTP request that started it cannot stay open that long, the browser tab may close, and a retry must not issue the refund twice.
A durable place for work that outlives the request that created it, a worker pool sized independently of the API, an isolation boundary around tool execution, a credential path that never puts the model provider key inside the sandbox, and a trace that explains a run after it has finished.
The request finished; the work did not
The first version of every agent product is a synchronous endpoint: the browser posts a message, the handler loops over model calls and tool calls, and eventually returns an answer. It works in a demo and fails in production for infrastructure reasons that have nothing to do with the model. The load balancer idle timeout cuts the connection at sixty seconds. The deploy that rolls the API pod kills nine in-flight runs mid-refund. The client retries a timed-out request and the agent runs the whole plan a second time.
The fix is the oldest pattern in the book, and it is the reason this lesson exists in an infrastructure domain rather than an AI one: accept the request, persist a run record, enqueue it, return 202 with a run id, and let a worker pool do the work. The agent runtime becomes a *worker* — a long-lived process that leases a job, executes the loop, checkpoints progress and reports terminal state. See Serverless and Database Connections for why the same workload is awkward under a function runtime with a hard execution ceiling, and the Architecture domain for the queue semantics themselves.
What is genuinely new compared with a normal background job is the fan-out from a single worker. One run touches a model provider over the public internet, a vector store, a blob store for attachments, and two internal APIs — each with its own identity, its own timeout, its own retry rule and its own bill. A worker that dies halfway leaves a partially executed plan, which is why every side-effecting tool call needs an idempotency key stored with the run, not generated per attempt.
Two boundaries people collapse into one
The model credential and the tool execution environment are separate trust boundaries, and the most common production incident in this space comes from putting them in the same process. The worker needs the provider key to call the model. The sandbox needs to run whatever the model decided to run — a shell command, a generated SQL query, a fetch against a URL that came out of a retrieved document. If the sandbox inherits the worker's environment, then prompt-injected text in a support ticket has a path to the model key, the database credential and the instance metadata endpoint.
So the sandbox gets its own execution context with no ambient identity: a separate container or micro-VM, a network policy that denies egress except to an allow-listed proxy, a filesystem that is empty and non-persistent, and CPU/memory/wall-clock limits so a runaway loop costs a bounded amount. Credentials it genuinely needs arrive as short-lived, task-scoped tokens minted per run — not as an environment variable baked into the image. This is the infrastructure half of what the Security and Agentic domains teach as tool sandboxing; see Least Privilege in Infrastructure and Roles vs Static Keys for the identity mechanics.
Model credentials also behave unlike a database password in one important way: they are a *spending* credential. A leaked read-only API key costs you data. A leaked model key costs you data and an unbounded bill, charged to you, until you notice. Treat it as a first-class secret with rotation, per-environment scoping and a spend alert — the alert is the control that actually catches the leak.
- read the three ticket fields the tool schema declares
- call the ticketing API through the egress proxy, allow-listed host only
- write to its own empty scratch filesystem, discarded at run end
- read three ticket fields
- POST one comment to the ticketing API
- read the model provider credential
- reach the instance metadata endpoint
- open outbound connections to any host not on the allow-list
- read or write another tenant's objects
Blast radius: A successful indirect prompt injection gets one tenant's three fields and the ability to post a comment, for the length of one run. It does not get the model key, the cloud role, or any other tenant.
The meter runs somewhere new
Agent infrastructure moves the dominant cost line off compute. A conventional API bills you for instance-hours and a bit of egress. An agent platform bills you for tokens — a variable that scales with *conversation length and plan depth*, not with request count — plus retries, plus the runs that a bug turned into a loop. A single unbounded agent loop can spend more in an afternoon than the entire worker fleet spends in a month, and it will look like healthy traffic on every infrastructure dashboard.
That is why termination budgets belong in the infrastructure discussion rather than only in the prompt: a hard cap on steps, on tokens and on wall-clock per run, enforced by the runtime and not by the model's good intentions. Pair it with per-tenant quotas so one customer's pathological input cannot consume the shared model rate limit and starve everyone else — the model provider's rate limit is a shared, finite resource exactly like a connection pool.
Traces are the other non-negotiable. When a run produces a wrong refund, the question is *which step decided that*, and no metric answers it. Persist the full step sequence — prompts, tool calls, arguments, results, timings, token counts — to object storage keyed by run id, with a lifecycle rule that ages it into cheap storage. It is simultaneously your debugging tool, your cost attribution data and, when a regulator asks, your audit record. See Storage Lifecycle: Hot, Warm, Archive, Delete and Audit Trails.
Bars are relative weights, not currency. Real rates depend on provider, region, commitment and volume.
Key points
- An agent run outlives the HTTP request that started it, so the unit of infrastructure is a durable job with a run id, not a synchronous handler.
- Workers hold the model credential; sandboxes execute tools and must hold no ambient identity at all — collapsing the two is the signature security failure.
- Model API keys are spending credentials: rotation and scoping matter, and a spend alert is the control that actually detects a leak.
- Step, token and wall-clock budgets belong in the runtime, because an unbounded loop is invisible on infrastructure dashboards.
- Per-run traces to object storage are the only thing that explains a bad outcome after the fact, and they double as cost attribution.
The loop, answered
Every field is required, which is why no lesson here can recommend something without saying what it costs and what simpler thing to consider first.
- • The API validates the request, writes a run record with a client-supplied idempotency key, enqueues the run id and returns
202with a polling or streaming URL. - • A worker leases the job with a visibility timeout longer than the p99 run duration, so a slow run is not handed to a second worker while the first is still on step four.
- • The worker fetches the model credential from the secret store using its workload identity — never a static key in the image — and begins the agent loop.
- • Each tool call is dispatched into a sandbox with a task-scoped token and a deny-by-default egress policy; the result comes back as data, and is treated as untrusted input.
- • After every step the worker checkpoints state and appends to the trace, so a worker replacement resumes rather than restarting.
- • Terminal state — completed, failed, budget-exceeded — is written to the run record; the queue message is acknowledged only then.
- • Size the visibility timeout and the client polling contract against real p99 run duration, and re-tune both whenever the plan gets longer.
- • Own the idempotency of every side-effecting tool: the key is stored with the run, so attempt two of step seven reuses it instead of minting a new one.
- • Rotate model credentials on a schedule and per environment; staging must not be able to spend production budget.
- • Keep sandbox images minimal and rebuilt, because a tool sandbox is a place you deliberately run untrusted instructions.
- • Run drain-aware shutdown: on deploy, stop leasing new runs, let in-flight ones finish or checkpoint, then exit. See Graceful Shutdown: The 502 Spike Nobody Investigates.
- • Watch the model provider's rate limit like a shared connection pool, and give each tenant a slice of it.
- • Load balancer or gateway idle timeout cuts a synchronous run at sixty seconds; the user sees a 504 while the work continues and completes invisibly.
- • Visibility timeout shorter than the run duration: a second worker leases the same run, and the customer gets two refunds.
- • Model provider rate limit or outage: every worker blocks, queue depth climbs, and CPU-based autoscaling adds workers that immediately block too.
- • Prompt injection in retrieved content drives a tool call that the sandbox boundary is the only thing stopping.
- • A loop with no step budget spends the monthly model allowance in an afternoon, with every infrastructure metric green throughout.
- • Deploy restarts workers mid-run; without checkpointing, every in-flight run restarts from step one and pays for its earlier steps again.
- • Workers are almost never CPU-bound — they are blocked on the model API — so concurrency per worker, not instance count, is the first dial. See Autoscaling Signals.
- • Queue depth and oldest-message-age are the honest scaling signals; CPU utilization will sit low while the backlog grows.
- • The ceiling you hit first is usually the model provider's rate limit, and adding workers past it converts queueing into 429s.
- • The vector store scales on index size in memory before it scales on query rate; retrieval quality degrades before latency does.
- • Sandbox capacity is its own pool — a burst of tool-heavy runs can exhaust it while the worker fleet looks idle.
- • The worker is the credential holder; the sandbox is the untrusted execution zone. Never let the second inherit the first's environment or instance role.
- • Deny egress from the sandbox by default and route allowed calls through a proxy with a host allow-list — this is the control that turns exfiltration from easy into logged.
- • Block the instance metadata endpoint from the sandbox explicitly; it is the standard escalation path from code execution to cloud credentials.
- • Treat every tool result and every retrieved document as attacker-controlled input, because on a support platform it literally is.
- • Traces contain prompts, and prompts contain customer data — classify and encrypt them like the database, not like application logs.
- • A public load balancer on 443 in front of the API is correct; a worker or vector store reachable from the internet is the finding.
- • Tokens dominate, and they scale with plan depth and conversation length rather than with request count.
- • Retries are a real cost line: a run that fails at step eight and restarts at step one pays for the first eight steps twice.
- • Worker compute is usually the smallest item, because workers spend their lives blocked on a network call.
- • The vector index bills as fixed capacity — it is resident whether queried or not.
- • Trace retention grows faster than anyone forecasts; a storage lifecycle rule is the difference between a footnote and a line item.
- • Queue depth and oldest-message-age — the workload signal that actually tracks pressure.
- • Runs by terminal state, split by failure reason: model error, tool error, budget exceeded, worker lost.
- • Tokens and cost per run and per tenant, alerted on a step change, not on an absolute threshold.
- • Sandbox denials — an egress denial is both a security signal and a sign a tool schema is wrong.
- • The signal that lies: worker CPU and the API's own latency, both of which stay perfectly healthy while every run in the system is stuck behind a model provider outage.
- • A plain background job queue with a deterministic script. If the task has a fixed sequence of five steps, an agent loop is a more expensive and less predictable way to run a workflow you already know.
- • A single model call with a structured output schema, executed inline. Enormous numbers of "agent" features are one classification call and a switch statement, and need none of this infrastructure.
- • A managed agent or inference platform that runs the loop, the sandbox and the traces for you — the right first answer for a small team, at the cost of control and portability. See Hosted APIs, Managed Inference or Your Own Cluster.
- • Synchronous execution is genuinely fine when p99 run time is under a few seconds and the tools are read-only. Add the queue when duration or side effects force it, not before.
- • Buys durability and independent scaling; costs you an asynchronous API contract, a run-status endpoint and a client that must handle "not finished yet".
- • The sandbox boundary buys containment and costs latency per tool call plus a second image to build, patch and monitor.
- • Checkpointing every step buys cheap resumption and costs write amplification against the run store.
- • Full traces buy explainability and cost storage, a data-classification obligation and a retention decision.
What people believe, and what is true
Agent infrastructure is just a bigger web service.
The defining property is that a unit of work outlives its request and has side effects partway through. That forces a durable run record, idempotent tools and checkpointing — none of which a web service needs.
The sandbox is about protecting against bad code the model writes.
It is about protecting against instructions an attacker planted in data the model reads. The model is the confused deputy; the sandbox is what limits what the deputy can do.
Autoscale the workers on CPU like everything else.
Workers are blocked on network calls almost continuously. CPU stays low while the backlog grows for an hour — scale on queue depth and message age.