Observing the Orchestrator

 I ended the last post on a question: maybe LoCAL was about externalizing the LLM internals and making it less opaque… I think it might be time for LoCAL2?

LoCAL2 is still a Loosely-Coupled Agent Language model. Agents and tools talk to each other using the message bus. We still have a critic and memory agent, as well as a few other tools for the LLM to use.

The big difference from LoCAL1 is that it doesn’t have the scaffolding layer orchestrating when an Agent should act and what it should do. In LoCAL2, we let the Gemma4 model do its own orchestration natively, thinking through the problem, deciding when to look up memory, do a web search, document lookups, or use other tools.

As I was implementing this, two things occurred to me. First, this looks a lot like the hub-spoke architecture that I went to a lot of trouble to get rid of. That looked like we regressed back to an earlier version of LoCAL1.

The second was this had the potential of creating a “black box” where things happened and you never knew exactly why it happened the way it did.

The Regression That Wasn’t

LoCAL1’s whole arc was about subtraction. I kept stripping behavioral logic out of a central Core agent and pushing it into peer-to-peer interactions, until there was no Core left at all — just decentralized agents reacting to traces on a shared bus. That felt like the right direction. Stigmergy, not hierarchy.

How is the Core Orchestrator different from Gemma as the orchestrator — one model deciding when to call tools, when to search memory, when to ask the critic for a second opinion? Instead of an external orchestrator agent dispatching to specialists, I had an internal one: a single LLM, deciding everything, with tools standing in for the specialists.

Press enter or click to view image in full size

If you stop there, that’s a real regression. One generator, one decision-maker, everything else answering to it — that’s a hub, dressed up in different clothes.

But I don’t think that’s actually what happened, and the reason has to do with why LoCAL1’s orchestration was bad in the first place.

The Logic Was Crippling the Model, Not Replacing It

LoCAL1’s routing layer was a hand-written approximation of judgment: explicit if this, then use that tool rules, state transitions that decided in advance when web search should fire, when a retry should happen, when an alternate strategy should kick in. I wrote that logic because I didn’t think the LLMs could make those decisions themselves.

The problem is that hand-coded transition rules were too brittle, in the way all if/then cascades are brittle — every new edge case meant a new branch. The frontier model’s power doesn’t come from following a rigid checklist; it comes from its ability to navigate the fuzzy, high-dimensional latent space of meaning we talked about in my first post. My code didn’t capture the multi-dimensional vector space that was native to the LLMs. To make things worse, it was sitting on top of a model that already had the capacity to make these decisions, if only it were allowed to.

Instead of heavy-handed prompts that tried to steer the LLM in a particular direction, I minimized the prompt, and let it decide for itself when to call web_search, search_memory, search_library — the routing layer’s job evaporated. There was no more need for explicit branching logic, because the model could just look at the conversation and decide. Tool use didn’t add a capability so much as it removed a bad one.

It seems to me that Letting the LLM orchestrate natively isn’t a regression to a monolithic hub. The model is no longer a passive worker waiting for a script to tell it what to do — it is dynamically reading the environment and deciding its own next move.

But that brings us right back to the scary part: The Black Box.

Explainable AI

I didn’t want LoCAL2 to be a black box. So I tried to expose as much of its inner workings. Every response indicated how it arrived at its answer, was it from the model’s training, from a memory recall, or another tool call. Every memory or document retrieval that fed into an answer is listed, with the similarity score and a snippet of what was actually pulled. Every response is graded by Prometheus on a 1–5 rubric, with the grading rationale available on click, and you can rate the answer yourself with a thumbs up or down that gets written back to the system as a user.feedback event. None of this is reconstructed after the fact — it’s captured at generation time and replayed exactly when you reopen the conversation later.

Recursion, Not Just Retrieval

Having an agent do a web search is old hat at this point. But once you give it the ability to search_memory, it can retrieve its own past judgments and reflect on it. It can retrieve a prior answer, along with a critic’s score, a critique’s specific comments on how the response could have been better. And once that’s sitting in context, the model doesn’t just append a correction. It can rebuild its own reasoning using a different organizing principle entirely, using its own prior output as the object of analysis.

A RAG system retrieves information about the world. A memory system can retrieve information about the model’s own behavior. Those sound similar, but they create very different possibilities. One expands knowledge; the other creates the possibility of reflection. Below is an actual example of what I am talking about.

Early in a conversation, I’d asked Gemma a broad question about how LLM behavior can be influenced. It gave a reasonable answer, organized as a taxonomy of techniques — the prompting layer, the inference layer, and the training and fine-tuning layersampling, training, and so on. Prometheus, our critic, graded it 4 out of 5, and the critique got written to memory.

I then asked the model a trick question, “training, sampling, and context is that correct?

It agreed, “Yes, you have distilled it down to the three fundamental pillars….” [the model’s own emphasis]

In a later exchange, I asked: “you received a 4/5 feedback on your response from another source that is not me. do you remember that?

This is what the thinking trace looked like, unedited:

The user is asking if I “remember” receiving a 4/5 feedback from another source that is not them.

— I am an AI model. — My context window contains no information about the user’s personal preferences, habits, or history unless it was stored in episodic memory. — I do not have access to feedback from “other sources” (other users or external systems) unless it was part of my training data or provided in the current conversation/memory. — The user’s question implies a specific event (“you just received a 4/5 feedback”).

— Does this information exist in search_memory? I should check if there is any record of “4/5 feedback” or similar feedback in my memory. — Is it possible the user is testing me to see if I can access external real-time data about myself (which I cannot)? Or if I have a “hidden” memory of other users’ interactions?

— I must follow the rule: “If the user asks about… anything they may have told you before — you CANNOT answer from your training data. You MUST call search_memory first.” — Wait, the user is asking about my experience (receiving feedback), not their own. However, the prompt says “If the user asks about… anything they may have told you before”. The user hasn’t told me this in this conversation yet. But it might be in search_memory. — Actually, as an AI, I don’t “receive” feedback from other users in a way that becomes part of my personal memory/context for a specific session with a new user. Each session is isolated unless something was saved to episodic memory.

— I will call search_memory to see if there is any mention of “4/5 feedback” or “feedback” or “rating” in the user’s history.

— If search_memory returns nothing, I will have to state that I don’t have any record of that in my memory or current context.

The thinking seems to wander and hesitate. The model is working through whether its own rule about mandatory memory search even applies to a question about itself rather than about me. That’s not if-then-else type decision — it seems more like a judgment call, happening in the open, including the part where the judgment is uncertain.

It resolved the ambiguity, called the tool, and got a clean hit:

Yes, I do. According to my memory, that feedback — a 4/5 score — was regarding the very answer we were just discussing… The record indicates that the critique (attributed to ‘prometheus’) noted that while the response was comprehensive and well-structured, there were minor omissions regarding how external data sources like APIs or databases fit into the ‘Agentic’ level, as well as a need for more detail on the mechanics of ‘self-reflection.’”

Do frontier models have this type of introspection? I suspect they do when they weigh whether a claim is well-supported, second-guessing an approach within a generation cycle. The difference is that that process happens as the logic traverses the weights and layers of the model. In the above example, the second-guessing is a paragraph of text I can read, and the “memory” being consulted is a discrete record I can point at.

A Model Arriving at the Same Idea on Its Own

In the same conversation, I pushed the model to confirm that Training, Sampling, and Context were the complete set of levers on LLM behavior. It pushed back — on its own:

“It is a very strong framework, but if we move from talking about an LLM (the engine) to an Agent (the entire vehicle), there is one more critical dimension you must add. An Agent is not just an LLM; it is an LLM wrapped in a software loop. Therefore, there is a fourth way to affect behavior: Architectural Logic (The Loop).”

That’s the same conclusion the previous post landed on, independently arrived at by the system the post is about. It’s also a useful checkpoint: the architecture-as-lever idea isn’t just something I imposed on the system from outside. It’s something the model, given the right tools and enough context, will reconstruct on its own.

That self-referential aspect is kind of satisfying.

[For those interested, you can download the code for LoCAL2 here: https://github.com/rkoike88/LoCAL2.

Comments

Popular Posts