Most of what an agent does is worker work — classify, extract, route, summarise, pick the next step. Bees runs that on a hive of small models and escalates automatically when a task turns out not to be worker work.
We do not agonise over it. We run the hive and let the answer decide.
Every task arrives as the same question: is this worker work, or does it need the frontier? The usual approach is to guess from the request before running anything. We think that is the wrong move, and the rest of this page is why.
Difficulty is not something you can read off a request. Anything that predicts which tasks deserve the expensive model will be wrong sometimes, and wrong silently.
So Bees does not predict. It runs the hive and reads what happens. Workers agreeing is evidence the task was routine. Workers splitting is what triggers the escalation.
Not on raw answer quality — a frontier model will often answer better than any of our workers. Where a hive wins is structural.
| Errors are not correlated | One model fails the same way across every request, invisibly. Workers that fail differently surface it as disagreement. |
| Nothing is load-bearing | A worker down, rate-limited or retired does not stop the hive. |
| Composed per task | Membership changes with the work. A single model is the same model for everything. |
| A number, not prose | Divergence is measurable, so it can drive behaviour. Stated confidence cannot. |
And it holds as models improve: fluency is rising faster than correctness, so wrong answers get better camouflaged. A signal from outside any one model matters more, not less.
For a chat product a wrong answer is embarrassing. For an agent it is executed. A hive convening takes longer than one call — disqualifying for a chat box, irrelevant at three in the morning.
What you get back is which of your tasks were routine, which needed the frontier, and which needed a person. In our own shorthand:
| Worker bees | the workers agreed, and it was answered there |
| Frontier | the workers split, so a stronger model was called in |
| Needs a person | nothing converged, so nothing was served |
Anthropic or OpenAI, keep the client you already use. Only the base URL and key change.
client = OpenAI(base_url="https://api.bees.riif.com/v1", api_key=BEES_KEY)
r = client.chat.completions.create(..., extra_body={"policy": "verified"})
if r.choices[0].finish_reason == "low_consensus":
queue_for_human(task, r.bees) # the hive did not converge
else:
proceed(r.choices[0].message.content)
Models, failover, retirements and spend ceilings are ours to manage. Your code does not move when a provider changes.
With a measurement on your real traffic, changing nothing about your product. After two weeks you will know what the hive would have caught. If that is not compelling, we will say so.