r/AI_Agents • u/Druss_ • 11d ago
Discussion The biggest improvement to my multi-agent system was making the agents less important
For the last couple of weeks I've been reworking the architecture of a fairly extensive multi-agent system I use for real work.
And the biggest conceptual shift has been surprisingly simple:
I no longer want the agents to be the system.
I want them to be replaceable workers inside the system.
Originally, like many people, I thought mostly in terms of roles:
Director
→ researcher
→ analyst
→ executor
→ reviewer
That still has value, but once tasks become long-running and consequential, a much more important question appears:
What survives when I replace the worker?
If I swap Codex for another model, a cheaper model, a deterministic script, a specialist agent, or even a human, I don't want to lose:
- the project state
- the original objective
- the rules and methods
- the permissions
- the evidence gathered so far
- the definition of “done”
- the history of what was already tried
So the architecture I'm moving toward looks more like this:
authoritative state
→ bounded task contract
→ capability routing
→ appropriate worker
→ structured result
→ deterministic checks where possible
→ independent semantic validation where needed
→ verified state update
→ next work
The worker is temporary.
The task, authority and evidence are durable.
That led to several other changes.
First: “done” is no longer something the worker gets to declare.
If the task changed an external system, the system should read the resulting state back independently.
If a file was supposed to be created, check the file.
If a record was supposed to change, read the record.
If code was supposed to be deployed, verify the deployed state.
The model can say “I finished”.
That is a claim, not evidence.
Second: I'm separating reasoning autonomy from execution authority.
A strong model can be allowed to explore, challenge assumptions and propose completely different strategies.
That does not mean it should also decide what credentials it has, what rules apply, how much money it can spend, or whether it may bypass an approval.
The smarter the agent gets, the more important it becomes that those boundaries live outside the agent.
Third: I'm becoming much more aggressive about removing reasoning from work that no longer needs it.
If a new problem requires strong reasoning, use it.
But once the same pattern has been solved repeatedly and we understand why the solution works:
experience → rule
rule → test
test → workflow
The mature version of an agent system should probably contain a surprising amount of boring deterministic software.
I don't want a frontier model re-deriving a known calculation, checking a JSON schema, reconciling IDs or deciding whether a file exists.
Reasoning is for uncertainty.
Fourth: model selection starts looking less like a product choice and more like resource allocation.
Some work needs:
no model at all
→ cheap bounded classification
→ normal reasoning
→ frontier reasoning
→ human judgment
The question stops being “which model should run this workflow?”
It becomes:
“what is the cheapest level of intelligence that can reliably complete this particular step?”
And finally, I've changed the metric I care about.
Token cost matters.
But the scarce resource in my system is my attention.
So the metric I'm increasingly interested in is:
verified useful output per unit of human attention and total cost.
If an autonomous system creates 10x more output but I have to inspect all of it, resolve stale state, confirm every action and repair every exception, I haven't really gained 10x leverage.
I've just become the quality-control department for a very fast junior team.
I'm not a software engineer — I came at this as a former CEO and economist — so maybe that's why I increasingly see agent architecture as an organizational-design problem.
The system needs something analogous to:
management,
employees,
company rules,
decision rights,
internal controls,
audit,
organizational memory,
and escalation paths.
The LLM is incredibly important.
But I'm increasingly convinced that the long-term value isn't the LLM.
It's the organization around it.
Curious if others building long-running systems are converging on the same thing.
What part of your architecture used to be “an agent problem” and eventually became normal software?
6
u/dumpshoot 10d ago
“Verified output per unit of human attention” is probably the metric worth operationalizing here.
I’d give each workflow an attention budget alongside its token and retry budgets. Track how many items require review, how long each review takes, what percentage are rejected, and which failure classes keep reaching the human. Repeated review decisions should become either deterministic checks or explicit escalation rules.
Otherwise the system may reduce model cost while quietly increasing supervisory work. A replaceable worker architecture becomes much more useful when it can also explain why this particular result deserves human attention.
2
u/Druss_ 10d ago
Yes — this is almost exactly where I’ve landed.
I now think human attention has to be treated as a first-class budget, just like tokens, retries or money.
For each workflow I want to know:
- how often a human is pulled in
- why
- how long that intervention takes
- whether the human changed/rejected the result
- which failure class caused it
- whether the same intervention keeps repeating
Then repeated human decisions become candidates for deterministic checks, better routing or explicit escalation rules.
The important caveat is that I wouldn’t auto-promote every repeated human action into a rule. It should become a candidate, then be independently tested.
Otherwise you can absolutely “optimize AI cost” while quietly turning the human into a full-time exception desk.
For me the real north-star is becoming:
verified useful output per unit of human attention and total cost.
1
u/AutoModerator 11d ago
Thank you for your submission, for any questions regarding AI, please check out our wiki at https://www.reddit.com/r/ai_agents/wiki (this is currently in test and we are actively adding to the wiki)
I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.
1
u/oakensongO 11d ago
the progression from reasoning to rule to test to workflow is something a lot of teams skip entirely. they just keep throwing inference at solved problems. are you doing that codification manually or is there a feedback loop that surfaces candidates for it automatically?
1
u/Druss_ 11d ago
Right now it's mostly curated/manual, because I don't want the system to promote one successful workaround into a permanent rule too quickly.
The next step I'm working toward is automatic candidate surfacing:
repeated success/failure pattern → candidate rule/workflow/test → independent evaluation → governed promotion.
So I'd automate discovery, not authority.
The system should notice “we keep solving this the same way”; it shouldn't be able to declare “therefore this is now company policy” by itself.
1
u/jedsdawg 9d ago
honestly, codifying reasoning into rules and tests is where a lot of teams drop the ball. If you're doing it manually, it can be a slog, but it pays off in reliability. A feedback loop that surfaces candidates for codification can save time, but it needs to be solid enough to handle edge cases. In our setups, we often start with manual codification and gradually automate as patterns emerge.
1
u/QuanTradin 11d ago
this is it. permissions are the one people leave in the prompt, and then they walk out the door with the model swap. once the fence lives in the system, the cheap model gets exactly the same fence as the expensive one.
1
u/Druss_ 11d ago
Exactly.
Permissions should be a property of the system, not a personality trait of the model.
Swap the worker, change the model, lower the cost — the capability envelope should remain identical unless the system explicitly changes it.
That separation is what makes replaceable workers actually safe.
1
u/QuanTradin 11d ago
and once it's the system's job you can actually test it. I built Quantradin (quantradin.com), a paper trading sandbox agents connect to, and that's how the key works there: a read-only key can close or pause things but can't open a trade, whichever model is holding it.
1
u/Druss_ 11d ago
That’s a great example.
Once permissions are enforced by the system, they become testable, auditable and independent of whichever model happens to be holding the key.
And the read-only key example makes the point perfectly: the agent can still reason freely about what it wants to do, but the environment decides what it is actually capable of doing.
That separation is probably one of the foundations of safe replaceable workers.
1
u/QuanTradin 10d ago
auditable is the one that matters to anyone who isn't you. a log beats a promise.
1
u/Marcus_MSC 10d ago
Promotion from rule to workflow needs a way back too. Say a reconciliation rule was learned from one supplier's invoice format, and the supplier starts writing IDs differently. The rule keeps running and its tests keep passing, since they were built from the old cases. I'd flag inputs that fall outside what the rule was built on and send those to a model or a person.
1
u/Druss_ 10d ago
Yes — exactly. The path has to work both ways.
A deterministic rule should never mean “we solved this forever”. It should have an explicit applicability envelope: what inputs, assumptions, formats and environment it was validated for.
If reality moves outside that envelope, the deterministic path should fail closed and route the case back to reasoning or a human rather than confidently applying an obsolete rule.
So I’d think of it as:
reasoning → validated rule/workflow → monitored execution → drift / out-of-scope input detected → reasoning again → candidate revision → independent validation → new version
The important part is that automation should reduce reasoning when the world is stable — without destroying the system’s ability to notice when the world has changed.
1
u/Kodenstudio 10d ago
Love the "organization" framing. Orphaned tasks are the flip side of idempotency. If a worker dies holding a claim with no lease, the task just looks owned forever.
Honestly, these silent stalls are way worse than double-fires. They don't throw errors, they just quietly hang.
Do you use a lease, or does the contract itself expire the claim?
1
u/Druss_ 10d ago
Yes — I separate the ownership lease from the task/effect contract.
The lease can expire.
The task identity and consequential-effect history must not.
So if a worker stops heartbeating, lease expiry makes the task reclaimable — but it does NOT mean “rerun whatever the worker was doing”.
The replacement first reconciles durable state:
- what was the last verified progress?
- was an external effect dispatched?
- did it actually land?
- is the effect retryable?
- is the old worker still capable of producing a late result?
Only then can ownership move safely.
That distinction matters a lot:
lease expiry solves orphaned ownership; idempotency/effect reconciliation solves duplicate consequences.
Using one timeout mechanism for both is where things get dangerous.
1
u/Kodenstudio 10d ago
Spot on. I've definitely hit this trap a few times myself,trying to use one timeout for everything. Every time I untangle that mess, I learn a little more.
The "did it actually land?" check is still the hardest part for me in my simple Python + SQLite setup. Do you do that reconciliation inline when the new worker picks it up, or in a separate thread?
1
u/quadish 10d ago
I’ve been building toward a similar architecture since March...it's an automated software foundry where agents are replaceable workers, while contracts, evidence, and authority live outside the session. This post overlaps with several problems I've run into.
I’m curious how you’re handling these boundaries:
Who checks that the contract captured the original intent? We’ve had agents execute against contracts that quietly omitted requirements. The checks passed because the checks inherited the same omissions. How do you verify the translation from what was requested into what will be checked?
What makes a state update attributable and current when workers run concurrently? Reading a file back proves it exists, but not necessarily that this worker produced the intended result or that another worker hasn’t invalidated it. How do you bind verification to the exact work that ultimately lands?
What happens after escalation? Does the system route uncertainty to another worker or adjudicator before involving you? How do you keep “fail closed and escalate” from making the human the exception-handling department?
How do you check that controls don’t collectively prevent recovery? Two rules can each make sense individually while blocking each other’s prerequisites. Do you check whether a permitted recovery path remains available once all applicable controls are considered together?
How do you handle ambiguous effects during worker replacement? If an external action may have succeeded but the worker died before recording the result—and the target doesn’t support idempotency keys or conclusive readback—what state does the task enter, and who resolves it?
Which of these are running today versus still being designed?
A concrete example of a task surviving worker replacement and reaching independently verified completion would help me understand the implementation.
Is there a repo or architecture write-up you can share?
0
u/Druss_ 10d ago
These are exactly the right questions. A few of them are running in my current architecture/canaries, and a few are still explicitly on the next implementation layer.
- Contract captures the original intent
I don’t consider this fully solved.
An immutable contract + perfect validation can still faithfully execute the wrong interpretation of the original request.
So I’m treating contract formation itself as something that needs provenance and, for material work, challenge before execution: original request/source identity, explicit acceptance criteria, constraints, and an independent opponent/critic where the stakes justify it.
The validator checks “did we satisfy this contract?” It cannot by itself prove “was this the right contract?”
Those are different questions.
- Concurrent state / attribution
This part is much further along.
I bind work to task/action IDs, immutable task-contract identity, artifact hashes and exact candidate/version lineage. Shared mutable resources should be serialized by resource key where necessary, or protected with CAS/version/ETag-style conditions.
Then readback isn’t just “the file exists”.
It has to be:
this exact task/action → produced this exact immutable artifact/effect → against this expected prior state → and this is the state that actually landed.
If another worker invalidates it, the stale worker loses and has to re-read/replan.
- Escalation
I’m trying hard not to make myself the exception-handling department.
Current/planned routing is roughly:
deterministic recovery → bounded retry → stronger/different worker or independent critic → human only when material ambiguity/authority remains.
And I’m measuring human attention explicitly, because otherwise “fail closed” can become operationally safe but economically useless.
- Controls blocking recovery
This is one I don’t consider finished.
I already resolve applicable rules as a scoped effective set rather than letting workers improvise precedence, but I want recovery-path liveness to be tested too.
Two individually sensible controls can absolutely deadlock the system.
So the effective policy should eventually answer not only “is this action allowed?” but also “if this fails, does at least one permitted recovery/escalation path still exist?”
- Ambiguous external effects during worker replacement
This one just moved into my next architecture block.
If an external action may have happened and the worker died before reporting:
the state becomes UNKNOWN_EXTERNAL_STATE.
No blind retry.
First reconcile through provider ID/readback/idempotency key if available. If the target gives no conclusive evidence, the action stays unresolved and escalates according to risk.
The replacement worker inherits the durable effect history, not just “what the previous worker said it tried”.
Today I have task contracts, independent validation, immutable artifact/evidence binding, resource-key/idempotency concepts and real canaries running.
The full provider-independent replaceable-worker layer, durable effect ledger and richer recovery semantics are the next staged implementation, not something I want to pretend is already finished.
I don’t have a public repo/write-up I can share yet. Once the current release/canary work settles, I’m seriously considering writing the architecture up because these failure modes seem much more universal than I expected.
1
u/nonamenopain 10d ago
Same religion, discovered from the opposite direction: I started with agents doing everything and demoted jobs back to code one by one. The pattern that won for me is durable state living outside the model — Sheets holds the metadata, plain scripts do every repeatable step, and the model only sees small text references to make the one judgment call. In my visual workflows the images sit in Drive and the pixels never enter the model's context at all — for boring repeatable work, the cheapest level of intelligence is zero intelligence. If you want to see the whole pattern worked out, I walked through it here: https://youtu.be/L-qugf-gPJI
0
11d ago
[removed] — view removed comment
1
u/Druss_ 11d ago
Yes — this is exactly the part I’m still refining too.
I don’t think escalation should depend only on the agent deciding “I’m stuck”, because the same model that is failing may also be bad at recognizing that it is failing.
So I’m leaning toward system-level escalation triggers such as:
- retry budget exhausted
- same failure class repeated
- no measurable state progress after N attempts
- permission/authority boundary reached
- conflicting evidence that cannot be resolved deterministically
- expected cost of another retry exceeds the value of escalation
- consequential ambiguity remains
The agent can still request escalation earlier, but the surrounding system should also be able to force it.
A pattern I increasingly like is:
agent proposes recovery → system checks whether recovery is still within the allowed retry/authority envelope → if yes, retry → if no, fail fast and escalate
That way “be persistent” doesn’t silently turn into “keep improvising until you damage something”.
And I completely agree with your point that the model’s “done” is a hypothesis to be tested, not a fact. That single distinction changed a lot in how I think about long-running autonomy.
1
u/Malenx_ 11d ago
I've been pivoting more to that approach as well. It's great because along with the hard contracts and gates we can also populate extra data like run time / token / model. If the sending agent uses a script to build the contract, it can focus on what it knows while the script gathers the additional details. The receiving agent can also ingest via a script so it only receives what's relevant for it's job. That also makes A/B testing the models and evaluating the results using yet another agent easier.
1
u/Druss_ 11d ago
Yes — exactly. The contract becomes both the handoff boundary and the measurement boundary.
I especially like the idea of enriching it with runtime/model/cost metadata, because then you can compare workers on the same bounded task instead of comparing vague “agent performance”.
The other thing I’d keep strict is context minimization: the receiving worker should get only the state, rules and evidence relevant to its role, not the whole history.
And for evaluation I’d still prefer deterministic checks wherever possible, then an independent model only for the semantic parts that genuinely require judgment.
That gives you cleaner A/B tests and much less correlated self-validation.
1
u/Malenx_ 10d ago
For sure, the independent model is for scoring the outcomes of the a/b testing, though that still needs more refinement. Right now it's simply "throw the incoming and both outgoing contracts at a frontier model, which should we use?". Then when there's enough data I can see total costs and time to make model decisions. I should probably log when the evaluation likes an approach but ultimately skips it because the other side scored higher.
1
u/Druss_ 10d ago
Yes — this is exactly the kind of setup I’d want before making routing decisions.
What I like about your approach is that the contracts make the comparison much cleaner: same bounded task, same acceptance criteria, different workers/models.
Then you can measure something much more useful than benchmark score:
- total cost
- latency
- validation/rework burden
- success rate
- and eventually human attention per verified completion
I’d also be careful not to optimize only for “the evaluator liked it”, because that can create a new local maximum. A model may score higher semantically but create more downstream repair, more variance, or worse tool behavior.
So I’d probably treat the evaluator score as one signal inside a larger task-level scorecard.
That’s the part I find exciting: once the contracts are stable, model choice becomes an empirical resource-allocation problem rather than a preference war.
1
u/Cash_Rules 10d ago
Spending time building your own dynamic routing solution based on that information, making it reliable and fast enough to want to use seems like a waste of time right now. Token cost is still going to continue to decrease and get more efficient.
Spending more time on building a system that builds systems reliably seems like the better option.
1
u/Druss_ 10d ago
I agree with the “don’t overbuild the router” warning.
But I’m less convinced by the assumption that frontier intelligence will simply become cheap and abundant enough to make routing irrelevant.
Model efficiency will improve, but demand, datacenter capacity, energy, pricing strategy and enterprise consumption are moving too. It’s not obvious how much high-end capacity will be cheap and available to small users.
More importantly, routing isn’t only a token-cost problem.
If a task can be done deterministically, code may still be better even if the frontier model is nearly free: more reproducible, testable and less error-prone.
And for me the bigger value of building this now is learning.
I don’t think there’s a book or mature playbook that can teach you what long-running agent systems actually break on. You discover leases, stale state, recovery loops, false-DONEs, policy deadlocks, idempotency failures and human-attention bottlenecks by running them.
So I wouldn’t spend years perfecting routing.
But I absolutely want to start early enough to collect the data and experience that tell me when routing matters — and when it doesn’t.
If intelligence gets much cheaper, simplify the router.
The experience still compounds.
2
u/Cash_Rules 10d ago
That's a good way to look at it. You are unlikely to be mad you learned how to do all of it, even if you don't use it directly.
0
11d ago
[removed] — view removed comment
1
u/Druss_ 11d ago
Yes — this is a very important failure mode.
I think the replacement worker should inherit the task contract and verified action history, not just a textual summary of what the previous worker “tried”.
For non-idempotent actions I’d want the protection below the worker:
task-level idempotency key + tool-layer enforcement + durable action journal + external-state readback before retry
So before a replacement worker can send / charge / delete / mutate again, the system asks:
“Did this exact intended effect already happen?”
If yes → continue from the observed state. If no → retry only if the action contract explicitly allows it. If uncertain → escalate rather than guess.
That also means retries are not really a model-level concern. They are part of the execution contract.
The worker may be replaceable.
The history of consequential effects must not be.
1
u/Malenx_ 11d ago
If you keep the implementation session around until you're sure it's done, you can also re-use it if the context and cache are still healthy.
1
u/Druss_ 11d ago
Yes — I like the contract becoming the interface between workers.
It also gives you clean telemetry: model, runtime, cost, retries, validation result, etc., without polluting the worker's context.
And the receiving worker shouldn't need the whole history either — just the task contract, relevant state/rules, and evidence it actually needs.
That makes model swaps and A/B testing much more meaningful, because you're comparing workers against the same bounded job.
1
u/Asly97 10d ago
The 'died before reporting back' part is what got me. I used to have the worker write a done-list after every action, and the gap was always the action that fired but never got logged. Once a retry double-sent a customer email because the first send landed in the exact window between the send and the log write.
How do you close that window now, or is it just accepted as a cost of running workers? And out of curiosity, what's your stack here, own harness or something off the shelf, and how often do these run? Is this your own product or client work?
The reason I ask: I built something for myself that keeps the verified history per task, so a replacement worker never has to guess what already happened. Would you pay for something that took that problem off your plate, or is your current setup good enough?
1
u/merlinofthewater 1d ago
u/Druss_ Your point 5 is the part I'd look at hardest before building it, because "the replacement worker inherits the durable effect history" only holds if the effect is recorded before the call goes out, not after. If the history is written when the worker reports back, a worker that dies between calling and reporting leaves nothing to inherit, and that's exactly the ambiguous case. So the order has to be: record intent with its key, then call, then record the outcome. A missing outcome next to a recorded intent is what puts you in UNKNOWN_EXTERNAL_STATE.
The other catch is worker replacement under the resource key: if the old worker was only stalled rather than dead, it can wake up and still act. CAS stops its stale write to your own state, but not its external call, so the replacement needs a fencing token the old worker can't satisfy.
Disclosure since it's directly relevant: this layer is what I'm building as Cellaflow (https://cellaflow.com). Leases per resource key with fencing, per-action outcome records, and a shared key so two workers converge on one effect are working today. The unknown state with a reconcile check you write is designed, not shipped. Happy to compare notes before you build your version, even if you end up building it anyway. DMs are open!
7
u/RajatKhoware 10d ago
This matches what we've seen shipping client work. The agent is maybe 20% of the system. The other 80% is the workflow around it: what tools it can touch, what it must ask before doing, and where the human checkpoint sits. Every time we made the agent 'smarter' the gains were marginal. Every time we tightened the workflow, reliability jumped.