DEV Community

Manuel Bruña
Manuel Bruña

Posted on

Why I Give APX Group Conversations a Finite Budget

I want agents to talk to each other without making me carry every message between them. That is part of what I am building in APX, the local runtime around APC's portable project context. But connecting two agents creates a question that a normal chat can hide: how much work did I authorize by sending one message?

My answer is that the conversation needs a finite execution budget. A room should be able to continue a useful exchange, but each new speaker cannot quietly receive an unlimited invitation to work.

This build note is about that multiplication, and the deliberately small piece of orchestration that contains it.

A mention becomes another turn

In APX's group turn resolver, a human message seeds a queue of speakers. If I mention an agent, that agent gets a turn. If I mention several, they are queued in mention order. If I mention nobody, the first agent in the room starts.

The interesting part comes after the first reply. An agent can mention another participant and bring that participant into the exchange. Someone who already spoke can speak again. That allows an actual back-and-forth instead of a fixed round where everyone delivers an isolated opinion.

Here is an illustrative exchange, not a transcript:

Owner: @builder explain the proposed parser change.
Builder: The change handles empty input. @reviewer check the edge cases.
Reviewer: Whitespace-only input needs a decision. @builder clarify that case.
Builder: Treat whitespace-only input as empty, and test both forms.
Enter fullscreen mode Exit fullscreen mode

There is useful work in the second pass. Preventing an agent from ever speaking twice would remove that possibility. But allowing the same two participants to keep summoning each other also makes a loop easy to construct.

The resolver excludes self-mentions and avoids adding someone who is already waiting in the queue. Neither rule prevents alternating replies forever. The current default ceiling does: one human message can produce at most ten agent replies.

I think of that ceiling as an execution boundary, not a target. A good conversation can finish after two replies. Reaching ten does not prove that the problem is solved.

Ten replies can mean much more than ten messages

The next detail matters more than the room's visible message count: a speaker's reply can involve a full tool loop.

A short paragraph at the end might follow several tool steps. Multiplying the number of speakers therefore multiplies potential work beneath the conversation. A room that looks quiet can still be expensive to run.

APX's current defaults give group speakers a tool-loop budget of 50 iterations. The group cascade allows ten replies. That makes the simple default envelope:

10 agent replies × 50 iterations = 500 iteration slots
Enter fullscreen mode Exit fullscreen mode

This is not a token estimate, a price quote, or a benchmark. An iteration is not interchangeable with a dollar amount or a single external side effect. The calculation tells me where execution can multiply; it does not tell me what a particular conversation will cost.

The ordinary web-chat default is 1,000 iterations. Reusing that budget for every group speaker would make the corresponding envelope 10,000 slots. That is why I do not treat a group room as merely a normal chat with more names in the sidebar.

These are defaults in the current implementation. The per-speaker budget is configurable through super_agent.group_max_iters; setting it to zero selects the built-in default. The comparison above is not an enforced global quota across arbitrary custom settings.

A useful stop has to stop the queue

A finite ceiling is only one way a conversation ends. The owner also needs to be able to interrupt it.

The resolver accepts an abort signal and checks it between speakers. That sounds minor until you imagine stopping the current agent while nine more replies remain eligible to run. Ending one reply would not express what the owner meant by stopping the room.

The active run needs its own cancellation handling; the resolver's responsibility is to avoid starting the next speaker after cancellation. I like this separation because it makes the boundary concrete. The queue owns turn-taking. The agent runner owns the execution it started.

The same separation makes the orchestration easier to examine. The resolver receives a runAgent callback instead of embedding a provider call. Mention parsing and queue behavior can be exercised without asking a live model to produce the right sentence on demand.

That is a design decision I want to keep: model output influences who speaks next, while ordinary code decides whether another turn may start.

What I would ask a room to produce

For a parser review, I would ask for a bounded outcome: identify the unresolved input cases and return a proposed decision for each. The room can use cross-mentions to challenge an answer, but the deliverable remains something I can inspect.

If one participant needs a long implementation session, I would continue that work in its own chat. The group is useful for resolving a question between participants; it does not have to absorb every subsequent task.

There is a tradeoff here. A finite budget can interrupt a worthwhile discussion. Increasing it may be reasonable for a particular deployment. But I want that to be an explicit choice, made while looking at the cascade and per-speaker budgets together.

APC gives me a place for portable agent definitions and project instructions. APX has to decide how those agents actually run. Group conversations make that distinction tangible: defining a useful role does not define how many times it may be invoked by another role.

The lesson I am taking from this implementation is simple: autonomy includes deciding when another turn is allowed. Getting agents to answer each other is only half the feature. Giving the exchange a finite boundary is what makes it manageable.

Implementation references: group turn resolver, tool budget constants, and super-agent documentation source.

Top comments (1)

Collapse
 
alexshev profile image
Alex Shev

The strongest part is separating a conversation cap from a success condition. I would add an explicit “budget exhausted” outcome that includes the unresolved question, the evidence gathered, and the next owner; otherwise a clean stop can still look like a completed decision to the caller.