Productionizing Agentic Systems
Take agents to production: per-run budgets and step caps, guardrails, durable execution, scaling on the JVM, cost control and the operational patterns that keep agents from causing incidents.
On this page
The gap between an agent that demos well and one you can leave running is entirely operational: budgets, guardrails, durability and cost control. This tutorial covers the production concerns that, skipped, turn an impressive prototype into a 2am incident.
Key Takeaways
- Enforce a hard per-run budget on steps and tokens — agents fail by looping.
- Guardrails are deterministic code around the agent: timeouts, authorization, validation, approval.
- Durable execution lets long tasks survive restarts and crashes.
- Scale on concurrency (virtual threads), externalise state, bound per-run resources.
Budgets: the first guardrail
Agents fail by looping — retrying a failing tool with variations, each attempt re-sending the whole conversation, cost growing quadratically. A budget is the hard stop.
public class RunBudget {
private final int maxSteps;
private final long maxTokens;
private int steps;
private long tokens;
// Called before every model call. Throws when a limit is hit, converting an
// unbounded runaway into a bounded, logged failure.
public synchronized void checkAndRecord(long tokensThisStep) {
if (++steps > maxSteps) {
throw new BudgetExceededException("step limit " + maxSteps + " reached");
}
tokens += tokensThisStep;
if (tokens > maxTokens) {
throw new BudgetExceededException("token budget " + maxTokens + " reached");
}
}
}The full guardrail stack
Each is ordinary, deterministic code:
- Budgets — step and token caps (above).
- Timeouts — on every model and tool call; a hung dependency must not hang the agent.
- Authorization — every action checked in code against the authenticated principal, never trusted from model output. See securing AI applications.
- Validation — inputs bounded, outputs checked before they trigger anything.
- Human approval — for irreversible actions. See human-in-the-loop systems.
- Trajectory logging — every step, for debugging and audit.
Durable execution
An agent task that takes minutes should survive a restart. Persist state so it can resume:
record AgentState(String runId, String goal, List<Step> completedSteps, String status) {}
public AgentState resume(String runId) {
AgentState state = stateStore.load(runId);
if (state.status().equals("COMPLETED")) {
return state;
}
// Continue from where it stopped, not from the beginning. A crash or deploy
// mid-task loses no work.
return continueFrom(state);
}For serious durability, a workflow engine (Temporal and similar) gives you persistence, retries and resumption as infrastructure rather than something you hand-roll. For simpler cases, a database-backed state machine suffices.
Scaling on the JVM
Agents are I/O-bound — mostly waiting on model and tool calls — so they scale beautifully on Java 21 virtual threads:
// Each run blocks on I/O most of the time; a blocked virtual thread costs
// almost nothing, so thousands of concurrent runs fit on a small instance.
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
runs.forEach(run -> executor.submit(() -> agentService.execute(run)));
}Scale horizontally on concurrency, not CPU (agents barely use CPU), and externalise agent state so any instance can handle any run. See Docker & Kubernetes for Java developers.
Cost control in production
- Per-feature cost metrics with alerts on the hourly rate — catch runaways in minutes, not on the invoice. See Spring AI observability.
- Model routing — cheap models for easy steps, expensive ones only where needed.
- Semantic caching — avoid re-answering near-identical requests. See AI caching strategies.
- Budget alerts — a daily spend cap with a page when approached.
The pre-production checklist
Before an agent runs unattended in production:
- Hard step and token budget, enforced before every call
- Timeout on every model and tool call
- Every action authorized in code
- Irreversible actions behind human approval
- Input bounded, output validated
- Full trajectory logging
- Per-feature cost metrics with alerting
- State externalised; runs resumable
- Evaluated on a fixed task set for outcome and safety
- A kill switch to disable the agent instantly
Next
Frequently Asked Questions
How do you stop an AI agent from running up huge costs?
What guardrails does a production agent need?
What is durable execution for agents?
How do you scale agents on the JVM?
Related tutorials
- Human-in-the-Loop (HITL) SystemsDesign human-in-the-loop AI systems in Java: approval flows for agent actions, escalation patterns, confidence thresholds and feedback loops — how to deploy autonomy without accepting unbounded risk.
- Ethical AI & Responsible Agent DesignBuild responsible AI agents: managing bias, ensuring transparency and accountability, designing for contestability, and the engineering practices that make agents safe and fair.
- Agentic RAG — Advanced PatternsAdvanced RAG where the model controls retrieval: self-RAG, corrective RAG, adaptive retrieval and query planning — when to let an agent decide whether and what to retrieve, in Java.
- Agent Evaluation & TestingHow to evaluate and test AI agents: trajectory analysis, benchmarking, hallucination detection, outcome verification and human-in-the-loop evaluation — with Java patterns.