DEV Community

Albert Mavashev
Albert Mavashev

Posted on • Originally published at runcycles.io

Adding runtime budget control to a Spring Boot AI agent

We recently wired budget checks into a Java/Spring Boot agent platform.

The problem was not that the platform had no limits. It had too many: subscription checks, credit checks, feature limits, and OpenAI calls all had their own logic.

The expensive path was simple: calling OpenAI. So we wrapped that path directly.

@Service
public class CyclesOpenAIService {

    private final SimpleOpenAI openAI;

    public CyclesOpenAIService(OpenAIClientProvider clientProvider) {
        this.openAI = clientProvider.getOpenAI();
    }

    @Cycles(estimate = "1", workspace = "#workspaceId", unit = "CREDITS")
    public Response runOpenAIRequestCycles(ResponseRequest request, String workspaceId) {
        return this.openAI.responses().create(request).join();
    }
}
Enter fullscreen mode Exit fullscreen mode

That one annotation does the request-time budget check.

Before the OpenAI call runs, Cycles reserves one credit against the user's workspace. If allowed, the call proceeds. If it succeeds, the reservation is committed. If it fails before billable work completes, the reservation is released.

The basic flow is:

reserve -> execute -> commit or release
Enter fullscreen mode Exit fullscreen mode

A few lessons from the integration:

  • The annotation path was the easy part.
  • The admin side was more work: creating wallets, funding budgets, looking up balances, and showing event history.
  • Stable idempotency keys matter. SDK-generated UUIDs are fine for one call, but app-level retries need the same logical request ID.
  • This first version protects OpenAI calls, not every tool call.
  • Tool-call gating is the next step for actions like email, refunds, CRM updates, deploys, and paid APIs.

The main takeaway: budget control belongs in the runtime path, not only in dashboards or billing reports.

The question is not just:

How much did this agent spend?

It is:

Should this agent, for this workspace, be allowed to take the next expensive action right now?

Full field report:

https://runcycles.io/blog/how-scalerx-wired-cycles-into-a-java-agent-runtime

Top comments (0)