The main feeling of the week: almost everything revolved not around one feature, but around Ordo’s boundaries. Not “what else to add”, but “where the right surface is”. The same motif kept coming back: do not hide meaning inside convenience, do not treat architectural holes with one more wrapper, do not mistake documentation for truth.
Ordo is my project about giving an agent workflows and tools in a way that does not hide important decisions inside a shell hack, prose documentation, or a local convention. It is based on the idea that the environment that runs an agent’s helpers should validate run scenarios, explain why a run is impossible, and when something fails, suggest what to do next. Since it is not published yet, this note is specifically about the architectural forks where the system, under pressure from reality, started to show a more honest shape.
Decision 1. Connectors should be fact-first
A connector is a pluggable set of files for a domain: git, GitHub, shell, and so on. It consists of probes (“what is the state of the world right now?”) and actions (“what exactly do we change in the world?”).
At first, by oversight, I mixed them together, and as a result something specific to a particular process started to appear as a neutral fact. The raw engine kept slapping my hand, forcing me to clarify the “small things”. If I sum up the conclusions I reached while building a couple of connectors for the engine, they are these:
- a probe should answer one domain question;
- a probe should not smuggle in implicit constraints, otherwise you can no longer reuse it properly in another workflow;
- sets of facts are fine, but smuggling habits in under the name of facts is not;
- a convenience surface turns into trash very easily.
If the engine starts replacing facts with the local morality of a workflow, it becomes non-portable very quickly. Convenient and frequent things are better kept in a process library than canonized in the core engine.
Decision 2. It is better not to delegate the engine’s responsibilities
state is storage between runs. Value expressions are local data transformations. If you hide things like that inside connectors and extra functions, the system starts looking simpler than it really is, but also gets worse at holding its own boundaries.
Again and again there was a temptation to solve everything in some crooked but quick way:
- with a connector;
- with a shell/helper layer;
- with an oversized memory/facts model;
- with a little “come on, let’s just add a bit of language”, which would then spread.
The results of the classic fight between orthogonality and convenience:
-
stateis a built-in runtime capability, not an external trick; - value expressions are also part of the runtime surface, but for pure local computation;
- implicit normalizations should not be hidden inside
git.*orgh.*; -
${...}should not become a second language for controlling the world.
The constraint here was always the same: do not let local expressiveness quietly turn into a hidden control layer. The slide toward an ordinary command launcher does not start when the system gets a bit more expressive. It starts when expressions begin replacing control.
If some need really belongs to the process orchestrator, it is more reliable to admit that immediately instead of disguising it as an integration.
Decision 3. Project help should be built directly from code, not from texts about code
This was very much the central decision of the week. If help lives only in texts about code instead of in the code itself, it is guaranteed to fall behind the real runtime and confidently advise the wrong thing.
From this decision, almost everything else started to pull out after it: how the system discovers its own capabilities, how it publishes its contract, how it builds help in the first place.
This is also a limit on expressiveness at the same time: useful constructs can be added only up to the point where they can still be honestly published as part of the contract, rather than hidden as internal magic.
If the agent cannot work from the help and has to go digging in the code, that is bad code.
An accidental but important idea
One insight of the week: it is not enough to simply tell the agent why it cannot continue right now. If the system only puts up a stop signal at that point, it leaves behind not clarity, but emptiness.
A good failure path should not only forbid the wrong next step, but support the right one: what to check now, what to rely on, how to rearrange the line of reasoning. Otherwise failure stops being useful and turns into a dead end, after which the agent is once again left alone with raw context.
This is also a way not to slide into runner-thinking: Ordo should stay useful even in the cases where executing right now is a bad idea.
Top comments (0)