Buffaly is a different kind of agent. When we talk about memory and learning in agent systems, we usually mean Markdown: a file of remembered facts, a saved prompt, or a skill that tells the model how to run a Python script. Since its release six months ago, Buffaly has used a different architecture. Its brain is a cross between an ontology and a programming language: an executable graph.

The things Buffaly knows about and the functions it can run belong to that same graph. Its executable skills are ProtoScript code, with identities, properties and relationships that Buffaly can inspect and change. From the beginning, it has been able to add new objects to its ontology, write new functions, incorporate them into its running system and use them without restarting.

In June, we analyzed how Buffaly was building its own tools. Most of those new tools were used in the same session in which they were created, to solve the problem that prompted Buffaly to write them. It was already creating the capabilities it needed as it worked.

The next step was to make learning autonomous. I wanted Buffaly to recognize the things worth remembering and the procedures worth keeping, and to keep acquiring useful capabilities every day without waiting for me to say, “Remember this.”

Each Buffaly instance develops its own knowledge and code through its environment and interactions. For this article, I examined my primary instance, which has been running since late February: over 10,000 agent sessions spanning more than 5 million messages. Its ontology now contains over 6,000 entities and 3,000 actions. The great majority were written by Buffaly itself, rather than entered by hand. Its autonomous learning now accounts for nearly 5,000 entities and about 1,200 actions.

That distinction is the subject of this article. Buffaly has long been able to write what I ask it to learn. Today I want to explain how we moved from that semi-supervised process to a system that makes the learning decisions for itself—and how we got it to work at scale.

My primary Buffaly instance — September 8 research snapshot

Measure Exact count
Agent sessions 10,653
Messages and event records 5,253,407
Entities in the ontology 6,157
Actions in the ontology 3,371
Entities learned autonomously in sessions 4,679
Actions learned autonomously in sessions 1,204
Background: Buffaly was already building tools for the job at hand.

Our June study, Buffaly Builds Its Own Tools, examined more than a million messages and hundreds of thousands of tool calls. About seven in ten newly created tools were used in the same session. Most were written because the agent needed them to solve a particular problem.

Contents
  1. Background: an ontology that can run code
  2. 1. Supervised learning: “Please remember this”
  3. 2. The offline critic: learning from the whole conversation
  4. 3. The multi-pass critic: better review, still supervised
  5. 4. Unsupervised learning: the online memory and action critics
    1. Insight 1: Separate entity learning from action learning
    2. Insight 2: Create a local ontology that extends the permanent ontology
    3. Insight 3: Use a smaller model to extend the local ontology
    4. Insight 4: Allow non-local discovery, borrowing and promotion
    5. Insight 5: Let the ontology hierarchy mirror the session hierarchy
  6. What autonomous learning changes in practice
  7. What we learned while building it

Background: an ontology that can run code

In a traditional text-based agent, most of the work passes through the model as text. It reads instructions, chooses a tool, reads the result, and decides what to do next. Memories, tool descriptions and the current state of the job are repeatedly brought back into that loop. A Markdown skill gives the agent written instructions to follow; a knowledge graph gives it facts and relationships to look up.

Buffaly works in an executable graph: a connected structure containing both knowledge and functions the system can run. A code repository, a database, a backup, a workflow and the function that verifies the backup all have identities in that graph. Buffaly can find them by meaning, follow their relationships and call their functions directly. We described this architecture in Executable Graph Agents vs. Text-Based Agents.

Entities and actions belong to the same system

An ontology is an organized description of the things a system knows about and how they relate. An entity is one of those things: a particular code repository, a database, a record of a startup run, or a function. Entity and object mean the same thing here. An entity can have properties—a startup record's log-file path, for example—and relationships to other entities, such as the repository protected by a backup.

What makes actions interesting is that functions are entities too. A function is not merely the name of an external tool written into a prompt. Buffaly represents its inputs, behavior, type and relationships in the same system as the things it acts on. This is what we mean by a first-class function: the system can inspect and work with the function itself. We call an operation it can run an action; when an agent is given access to it, it serves as a tool. An action may run code, ask a model to perform a task, or combine the two.

That is why Buffaly is an executable graph, not just an ontology. The structure describes the world and runs the program. An action can take an entity as an input, call another action, or pass a .NET object already held in memory straight into compiled code. Buffaly can also inspect a function, correct it, compare it with another function and turn the differences into inputs. A procedure learned for one job can become useful in others.

Ontology versus executable graph / the same facts plus callable behavior
An ontology view shows a backup, its stored size and hash, and its BackedUpRepository relationship to a repository. Buffaly's executable graph retains those same entities and adds a callable backup verifier that directly calls a PowerShell execution action. Blue arrows mean stored relationships; purple arrows mean method calls.
The same facts, plus callable behavior. The blue relationship identifies the repository the backup protects. The purple connection is a real call from one action to another in the verifier's code. The caller supplies paths and expected values; the graph does not infer or run that call automatically. Names are shortened here.

ProtoScript is the language Buffaly uses to define the entities and functions in this graph. Each named definition is a prototype. Here is a real example from Buffaly's browser integration: a browser-installation object with properties and methods that use them. Service setup and its description are omitted; the properties and method bodies are unchanged. Complete definition

PROTOSCRIPT
prototype ExtensionBrowserInstallationService : Service
{
    String InstallationRegistrationId = new String();
    String EntityName = new String();

    function ToGetStatus() : string
    {
        return ExtensionBrowserServiceFacade.GetStatus(
            this.InstallationRegistrationId);
    }

    function ToListBrowserContexts() : string
    {
        return ExtensionBrowserServiceFacade.ListBrowserContexts(
            this.InstallationRegistrationId);
    }
}

This object represents a particular Chrome installation. It stores the installation's identity and has methods for checking its status and finding its browser contexts. Both methods use that stored identity. When Buffaly selects the browser object, it has the information about that browser and the operations for inspecting it together in the same definition. Another registered browser has its own identity and inherits the same behavior.

Why this is more than a Markdown skill

Claude Code and Codex skills ordinarily start with SKILL.md: instructions and descriptive information, with scripts, references and other resources alongside them. Those scripts can run ordinary code without asking a model to interpret every step. The distinction is the role the function itself plays in the agent's environment.

Question A standard skill package A Buffaly executable action
What is retained? Instructions and supporting resources A named graph entity with executable behavior
How is it used? The agent follows instructions and can run included scripts The system calls a function; other actions can call it directly
What connects it to the environment? Descriptive information and the agent's conventions Types, properties, inherited definitions, search phrases and relationships
How can it develop? The package can be reused and revised Buffaly can also inspect the action, combine it with others and compare its structure

Buffaly can search for “analyze a startup log,” inspect the matching action's inputs, load it and call it. Once another function knows which action it needs, it can call that action directly. The model does not have to sit between every operation, translating one result into instructions for the next. The graph can also be much larger than the set of tools presented to any one agent: agents find the relevant parts as they work.

For learning, this is fundamental. The output of one investigation can become part of the environment in which the next investigation runs.

New code joins the running system

A missing function does not have to end the job. Buffaly can write a new ProtoScript action and make it available while the agent is working. It can also write C#, compile a .NET assembly—a loadable package of code—and add it to the running system. The agent can use the new function without a restart.

This is native execution. Existing .NET objects can go straight into the new code. They do not have to be converted into a long message for the model to process. Consider a DataTable, a table of rows and columns already held in memory. This installed method reads its dimensions and column names and returns a compact description:

CSHARP
public static string Describe(DataTable table)
{
    ArgumentNullException.ThrowIfNull(table);
    return JsonSerializer.Serialize(new
    {
        Rows = table.Rows.Count,
        Columns = table.Columns.Count,
        ColumnNames = table.Columns.Cast<DataColumn>()
            .Select(column => column.ColumnName).ToList()
    }, JsonOptions);
}

The full table stays in memory. The model receives only the description it needs. Here is the corresponding ProtoScript action, with its descriptive property omitted:

PROTOSCRIPT
[SemanticProgram.InfinitivePhrase("to describe a native datatable")]
prototype ToDescribeDataTable : TabularDataSkillAction
{
    function Execute(DataTable table) : string
    {
        return TabularDataFunctions.Describe(table);
    }
}

This short wrapper names the function, gives Buffaly a phrase it can search for, and specifies the kind of input it accepts. It calls the C# method directly. This example is already installed; the same mechanism lets Buffaly add new compiled functions during a job. We demonstrated the build, load and use sequence in the existing C# tool-building walkthrough.

Native code loading / recorded walkthrough
Illustration from Buffaly’s earlier tool-building article showing the hot-swap lifecycle.
Watch Buffaly build and use a C# tool without restarting. A missing capability becomes a new graph action, and the same job continues.
Watch Buffaly build, load and use native code ↗

Being able to create a function and call it while the system was still running opened up a world of possibilities. The longer journey was getting Buffaly to decide for itself which functions and objects to learn. We tried learning on request, a critic that reviewed whole conversations afterward, and a multi-pass process that brought proposals back to me for approval. Each taught us something. The fourth approach—the online memory critic and online action critic—finally made autonomous learning practical at scale.

1. Supervised learning: “Please remember this”

In the beginning, I was the learning critic. We would work through a problem, find the right service or finally get a procedure working, and I would see something worth keeping. Then I would say:

“Please remember how to do this.”

Buffaly would turn the work we had just done into functions and entities. A successful sequence of steps could become an action, with inputs for the parts that would change next time. Discovering which repository produced an installation could become a stored relationship. We already had a system that could learn either one. What it needed from me was the decision that this particular result mattered.

Phase 1 / human-selected action learning
Phase 1: successful work leads a human to identify a useful action. Buffaly checks the permanent ontology, synthesizes a parameterized function and writes the action into the permanent ontology for later use.
The human identifies what is worth learning. Buffaly creates the definition and adds it to the permanent ontology. The numbered path follows one action from evidence to use; the green box is where it is saved. If an existing action already does the job, Buffaly reuses it.
One learned procedure / different inputs
Two separate calls pass different log-file paths into the same retained AnalyzeLog function. Its saved body reads the log, recognizes Starting and Stopping records, counts calls and totals their duration. Each invocation returns its own report with Name, Starts, Stops and TotalMs fields.
The file changes; the parsing procedure does not. The real log analyzer shown here makes the mechanism concrete: each call supplies one path, and both run the same retained procedure. This later critic-learned example illustrates what it means to retain a function; it is not a claim that this particular action was created manually. Its name is shortened, and the file names illustrate two different inputs.

The value was immediate. We had already paid for the exploration: trying an approach, seeing why it failed and finding the version that worked. Why pay for that again? Retaining the procedure let the next call start there. Buffaly could supply new inputs instead of generating another implementation and potentially making the same mistake.

After the exploration What we wanted to preserve
“This is the repository that owns the service.” An identified repository and its link to the service
“These checks tell us why the lookup is failing.” A diagnostic procedure with inputs for the next job
“This part depends on interpreting the evidence.” A procedure that explicitly asks a model to make that judgment

We learned thousands of things this way, and it worked. I could point to a useful result, ask Buffaly to remember it, and use the resulting entity or action on the next job. But the decision about what mattered was still mine. That was effective learning, not unsupervised learning.

The problem was that I had to be there to notice it. I was trying to get work done, not supervise every learning opportunity. The working agent had the same competing demands. We could solve something difficult, move on, and leave behind none of the structure that would make the next attempt easier.

I wanted Buffaly to supply that judgment itself. Our next attempt was the obvious one: give a critic the completed conversation and ask it to recover what we should have learned.

2. The offline critic: learning from the whole conversation

The first offline approach was brute force. After the work was done, a large model had to read an entire conversation, work out what had actually happened, and decide which parts were important enough to keep. The destination was the permanent ontology.

The permanent ontology was Buffaly's shared knowledge and code: the entities, relationships and actions maintained in its projects and skills. Learning meant adding to that shared collection. A new definition would remain available to future work, not just the conversation that produced it.

That made every learning decision a decision for the whole system. The critic had to understand the conversation, distinguish successful conclusions from failed attempts, check what was already known, and predict what would be useful in future work. Learning a fact and deciding that everybody should know it were effectively the same assignment.

Phase 2 / whole-conversation critic
Phase 2: a large model reviews an entire conversation, identifies a reusable operation, reconciles it with the permanent ontology, synthesizes the action and materializes the selected definition into that same permanent ontology.
The critic now chooses the action, but must also decide whether it belongs in permanent knowledge. It reviews the whole conversation and checks the shared ontology before adding anything. Rejected suggestions and operations already covered by an existing action produce no new definition.

It worked, but it did not scale. Consider a conversation containing a sensible plan, three failed attempts and a correction much later. Which version should the critic keep? What had actually been established? Was the same thing already represented under another name? Would anybody need it again? The model needed enough context and reasoning capacity to answer all of those questions together. That made this an expensive way to learn a small thing.

What a review of past work must decide Why it is difficult
Recover what happened Important meaning is spread across requests, failed attempts and later corrections.
Predict future usefulness The reviewer must explain why a discovery will matter beyond the original problem.
Fit the discovery into shared knowledge Each proposal must agree with existing definitions and their assumptions.
Carry the consequences A poorly generalized definition remains available to future work until someone corrects it.

The permanent destination made mistakes expensive too. Once promoted, a definition stayed in the shared ontology until somebody corrected or removed it. There was no automatic expiry just because it turned out to be unnecessary. If a session used “production” to mean one particular installation, retaining that shorthand as a shared answer could send the next agent to the wrong system.

And an ontology can be cluttered with facts that are perfectly true. An obscure, one-off detail can turn up in searches for years, making agents inspect and reject it again and again. The namespace is the set of named definitions an agent works with. Filling the shared namespace with everything that happened makes it harder to find what matters. Every permanent addition carries an ongoing cost, even when it is correct.

Historical statement Why it may not deserve permanent memory
“A connectivity request failed during this turn.” An event alone may say little about the enduring service.
“This service’s health endpoint is here, and this repository owns it.” An address and repository link can prevent another investigation.

The batch process also lacked the feedback loop we wanted. A critic swept through past work and proposed what the future might need. The working agent was no longer right there using the new definition and showing whether it helped. Every new conversation meant another expensive review and more proposed additions to fit into shared knowledge.

We had automated the review, but asked it to do too much at once. The next design broke that review into passes.

3. The multi-pass critic: better review, still supervised

The multi-pass critic separated noticing something worth learning from adding it to the ontology. The first critic kept a proposal ledger: a saved list of suggestions, the evidence behind them and the work already reviewed. A second critic worked out how to turn selected suggestions into actual definitions. We called it the materializer because its job was to turn a proposed idea into knowledge or code the system could use.

That separation mattered. A reviewer could inspect part of the conversation, record a useful suggestion and continue later. A checkpoint saved its place. It no longer had to rediscover every suggestion or produce the final ontology changes in one giant pass. The implementation kept separate files for the review, proposals, preview and proposed definitions rather than making each pass rewrite one growing document.

The proposal carried an argument for learning something. The reviewer had to tie it to what the user asked for, establish what that language referred to, and show how retaining it would reduce future confusion or wasted work. “This appeared in a conversation” was not enough. The prompt asked for a small set of changes the user could accept or deny.

The second critic could then concentrate on the proposed changes. It read the suggestions, searched the existing ontology, inspected the real definitions and prepared exact edits. Its instructions told it not to repeat the first review or reread the original conversation unless a proposal was ambiguous. The ledger was the handoff between two different jobs.

Pass What it produced What it did not decide by itself
Review Suggestions with evidence and a saved place to resume Whether every suggestion should become permanent knowledge
Prepare definitions Exact definitions, owners and proposed edits Permission to apply every proposed change
Human approval and writing Approved changes in the permanent ontology A reason to keep everything else on the proposal list

In our workflow, we put those proposals in front of a human. I could approve, reject or defer an item before it entered the permanent ontology. The second critic prepared the concrete change; a proposal was not permission to apply it. Its output ended with the explicit statement, “No ontology changes have been applied.”

Phase 3 / proposals and approved writes
Phase 3: the first critic incrementally identifies actions and records proposals in a checkpointed ledger. A second critic prepares exact definitions and changes. A human approves, rejects or defers them; only approved authoring changes the permanent ontology.
There are two writes here, and they do different things. Writing a proposal into the ledger preserves a suggestion and its evidence. Applying an approved definition changes the permanent ontology. A stored proposal is not an executable definition; only the approved action changes what Buffaly can do.

This was a real improvement. The ledger let us review a little at a time, preserve the evidence and reject a bad idea before it entered shared knowledge. But the final judgment had not changed. We still needed a large model to decide what deserved a place in the permanent ontology, and in practice a human to approve it. We had made the batch process more manageable without removing its most expensive question.

In the first phase I had to say “remember this” while we were working. Now I could inspect a list afterward. That was more systematic, but I was still supervising what became shared knowledge. Until approved and turned into definitions, the suggestions remained just that—a list of proposals.

We had improved how we reviewed the work, but learning still required a decision about the permanent ontology. The next design needed to change that requirement.

4. Unsupervised learning: the online memory and action critics

The working agent already produces the evidence for learning: what was asked, what it tried, what worked and what it corrected. Our online critics review that work alongside the agent and decide which discoveries should become usable knowledge or code. They can make additions while the job continues, and later use supplies the next round of evidence.

We made that possible by separating five problems we had been asking one critic to solve at once: what kind of thing to learn, where to put it, how much judgment the decision requires, how other agents can find it, and how that knowledge should follow the organization of the work.

These are five complementary insights, not five more historical phases. Together, they let us learn continuously without asking every new definition to justify its place in the permanent ontology.

Insight 1: Separate entity learning from action learning

Learning which database a project uses is different from learning a reusable procedure for querying it. The first problem is about identity, properties and relationships. The second is about behavior: which steps belong together, what should become an input, what the function returns, and whether the procedure already exists.

So we separated the online memory critic, which learns about things and their relationships, from the online action critic, which learns procedures and improves existing actions. Functions are still entities in the same executable graph. We gave the critics different jobs; we did not split knowledge and code into unrelated systems.

Phase 4 · Insight 1 / separate the learning judgments
The same completed interaction is examined independently for entities and relationships by the memory critic, and for a reusable function by the action critic. The figure separates the two learning judgments without introducing storage scope or cross-session reuse.
One interaction, two different questions. The memory critic asks what things and relationships the work revealed. The action critic asks what operation is worth retaining. Neither waits for the other, and either can conclude that nothing needs to change.

The System 2 companion checks whether an agent has done what the user asked. These companions look at what the work should teach Buffaly. Giving each one its own instructions, searches and model lets us improve its learning job without distracting the working agent from the original request.

The online memory critic searches what is already known about the things involved. It checks their structure—the properties they inherit, the values already filled in and the fields still empty—before deciding whether to create something new or update an existing entity. A useful discovery may require a new property or relationship. The critic can add it; it is not limited to filling out a fixed memory form.

Memory critic decision Example effect
Resolve an identity A nickname points to the existing repository instead of creating another repository object.
Add a useful reference A trace gains the path needed to read it.
Add a relationship A backup gains a link to the repository it protects.
Keep different states distinct A planned deployment is not recorded as an installation that has passed its checks.

The online action critic looks for a reusable procedure or a demonstrated improvement to an action learned in its session. Before writing, it searches using more than one phrasing and checks likely matches. We learned to make this distinction explicit: using a long script does not prove a new action is needed, and failing to find a tool does not mean it is missing. When a procedure is worth keeping, the critic can write code, retain instructions that call a model, or combine the two. A substantial PowerShell workflow can become a reusable action too, with inputs for the parts that change.

What the action critic observes Appropriate response
Repeated substantial script with clear inputs Consider saving it as a reusable action.
Existing action already does the job Reuse it; do not manufacture a second capability.
Demonstrated defect in an action learned in this session Improve the definition and save the evidence for the change.
Temporary failure or suspected product defect Identify or report it; do not hide it behind a local workaround.

Splitting the assignments made each critic more focused. It did not yet solve the problem of where its output should live.

Insight 2: Create a local ontology that extends the permanent ontology

Until this final phase, learning had meant adding to the permanent ontology. To change that, we invented session-local ontologies: knowledge and actions learned within a particular working session. A critic could now keep something useful without first adding it to everybody else's shared knowledge.

A session-local ontology extends the permanent ontology. The agent can use all the shared permanent knowledge plus the entities, relationships and actions learned in its session. The local additions do not replace the original collection. A new entity can build on an existing type, and a new function can call an existing action, because both are in the same working graph.

Phase 4 · Insight 2 / extend the permanent ontology locally
The permanent graph remains intact as a session adds an AnalyzeLog function and its relationships. Existing entities and functions stay usable; the green addition extends the graph rather than replacing it.
The repeated blue nodes are the permanent base. The new green function belongs to the session's extension. Learning changes what the session can do without writing that function into the permanent ontology.

We store only the session's own additions, which we call its fragment. What the agent can use is larger: the permanent knowledge plus that fragment. Two independent sessions share the same starting knowledge, then each adds what it learns. The notation below makes that distinction precise; the fifth insight adds parent and child sessions.

Ontology scope What it contains
Permanent base P
Session A's own additions ΔA
Session A's full working ontology P ∪ ΔA
Independent session B's full working ontology P ∪ ΔB

These are real entities and actions the agent can use, not proposals waiting for a human to approve their existence. They can be saved, called and corrected as the work develops. Actions are stored in the session's SessionActions.pts file; entities are stored in SessionMemory.pts. The definitions become available to the working agent without changing the shared permanent ontology.

This changes the question from “Should every future agent know this?” to “Will retaining this help the work here?” That smaller question leads to the next insight.

Insight 3: Use a smaller model to extend the local ontology

Learning happens alongside the main job. It cannot cost another large-model conversation every time the working agent discovers something useful. We made the assignment narrow enough for smaller, less expensive models: learn one kind of thing, review a limited amount of completed work, and keep the result in that session.

Phase 4 · Insight 3 / smaller models for a smaller decision
A bounded view of a completed interaction feeds a smaller learning model. It proposes a useful local addition, checks it against the existing graph and writes an accepted definition into that session's extension. The permanent base remains unchanged, and NoChange leaves no addition.
The architectural saving comes from reducing the decision, not asking a cheap model to make the same enormous global judgment. The routine critic decides whether something is useful here; it need not predict permanent value for every future agent.

The two online critics independently review completed interactions: the request, the result and a limited view of the tools used to get there. The working agent can continue while they review. Neither critic has to reconstruct an entire conversation, invent a procedure for every possible future use and install it permanently, all in one step.

A smaller model still uses Buffaly's tools for writing and checking definitions. After saving an action, the critic reads it back, checks that search can find it, and runs it when safe. A saved review record keeps the original interaction, the reason for the decision and the checks performed. It also records when no change is needed—NoChange—so reviewing the same interaction again need not create another version.

Choosing the model for each learning job

Learning runs alongside the main work, so the critic needs to earn its cost. We gave each model the same set of completed interactions and examined the actions it learned. The comparison below asks one question: what share of those actions was worth keeping or improving?

GLM 5.2 came close to GPT-5.6 Sol: about seven in ten learned actions were useful, compared with about eight in ten. Some other configurations did much worse. Luna's medium setting produced useful actions about half the time; Terra's medium setting produced none worth keeping. The expensive model was no longer a prerequisite for useful learning.

How much of the learned code was useful?
Share of learned actions worth keeping or improving: GLM 5.2 medium about 70%, GPT-5.6 Sol medium about 80%, GLM 5.2 max about 70%, GPT-5.6 Terra max about 60%, GPT-5.6 Luna medium 50%, GPT-5.5 medium 100% from just one action, GPT-5.6 Luna max about 40%, and GPT-5.6 Terra medium 0%.
How much of the code was worth keeping? All configurations reviewed the same interactions. “Worth keeping” includes useful actions that needed refinement. Medium and max are reasoning settings. GPT-5.5 produced only one action.

The percentages describe the quality of what each model wrote. GPT-5.5's perfect score came from a single action across the entire test; the other models found useful procedures it missed. We needed a critic that noticed worthwhile opportunities as well as making good choices about what to keep.

GLM 5.2 was the practical choice for routine action learning. In a larger follow-up spanning nearly 600 interactions, more than four in five of its learned actions were worth keeping or improving. That fits the way Buffaly learns: useful local code can be exercised, corrected and generalized before it becomes shared infrastructure.

We tested memory learning separately. Recognizing useful objects and relationships calls for a different judgment from identifying reusable code. A model that extracted rich memory could still miss the procedures worth learning. Separating the critics let us choose a model for each job instead of paying for the same large model to do both.

Local learning could now be practical and frequent. But if it stayed invisible outside the source session, other agents would keep discovering the same things.

Insight 4: Allow non-local discovery, borrowing and promotion

The next insight was finding useful knowledge without importing everybody else's ontology. An agent needs to discover what other sessions have learned without loading all of it into its own working environment.

Search can find a relevant action or entity and identify the session that learned it. Finding it does not add it to the searching agent's ontology. The agent can inspect the match, then borrow the particular definition it needs. That makes another session's learning useful without bringing along everything else that session knows.

Phase 4 · Insight 4 / non-local discovery and selective reuse
A search reaches another session's learned AnalyzeLog action without importing that session's graph. Borrowing adopts the selected definition into the requesting runtime. A separate promotion route gives a selected definition maintained shared ownership; it is not an automatic consequence of borrowing.
Search finds a definition. Borrow makes it usable here. Keep saves this session's own copy. Promotion makes it part of a shared collection that someone maintains. These are separate decisions, not an automatic chain.

An agent can borrow the definition it needs, use it and retain a local copy. Missing dependencies are reported explicitly, and invoking an action remains a separate operation. What that new use teaches us is the basis for deciding whether the definition should travel further.

Each session keeps its own fragment of the executable graph: the entities, relationships and actions it learned. Their origin remains clear. “The backup” can mean the backup we just created and verified, without becoming every future agent's default backup. Session-local does not mean temporary or disposable; the definitions can be saved and found from other sessions.

This also gives us a way to handle contradictions. A fact can be true for one product, installation or stage of a job and false for another. Keeping those identities separate prevents us from forcing different situations into one shared answer too early.

Phrase encountered in work Identity that may actually be required
“Production” Which product, environment and installation—and its current state
“The backup” Protected repository + archive + verification evidence
“Copy the package” Source + destination + overwrite permission + required checks

Find it elsewhere before adding it here

Search reaches beyond the definitions already available in the current session. It distinguishes shared and local matches from things learned by other sessions. Each outside match identifies the exact definition and where it came from; search does not load it. Seeing that another session has a useful action is different from adding that action to your own ontology.

That distinction keeps search from cluttering the agent's working knowledge. An agent can find another session's log analyzer without loading that session's traces, repositories, experimental actions or unrelated assumptions. In a search result, “unavailable” means the definition is not loaded here yet. It does not mean the capability does not exist.

The agent can inspect the match and borrow one selected action or entity. It gets the benefit of the other session’s work without importing the whole fragment or declaring its contents permanent.

Cross-session reuse and promotion
Discovery identifies an owner; Borrow loads one definition; Keep persists a destination-owned copy; promotion establishes shared ownership and a contract.
Discovery finds the definition. Borrow makes it available here. Keep retains a local copy. Promotion gives it a shared owner. Borrowing an action does not execute it.

Borrow loads the selected definition unchanged into the requesting session. It makes an action available without running it. If the action depends on another definition that is missing, Buffaly reports that missing dependency rather than silently importing more knowledge. Keep saves the requesting session's own copy; later changes to the original do not automatically change that copy.

Knowledge improves as it travels

A session is a good place to learn something before we know how widely it matters. The exact path to one investigation's log can stay there. So can a useful description of a temporary deployment or a procedure tailored to the problem in front of us. Most of that detail never needs to become permanent knowledge. It remains in the leaves of the session tree, where it has meaning.

The useful parts can move further. Another session discovers a definition, borrows it and puts it to work in a different situation. That gives Buffaly an opportunity to improve the knowledge. A thin record can gain a useful property or a missing relationship. A function can acquire a parameter that replaces a hard-coded assumption. Two specific procedures can reveal a shared operation worth expressing once.

This also gives us a way to discover bugs. A first implementation may just about solve the original problem and then fail on a new input. The next use reveals the assumption that was wrong. Buffaly can fix it, retain the evidence and use the improved version. Repeated use turns a narrowly successful procedure into one that handles a wider range of work.

We found a small, concrete example in a learned database-backup action. It created the backup but wrote the timestamp variable literally into the filename. The critic corrected the code, and later runs produced the intended timestamped names. The code improved through use. The same feedback is valuable when deciding whether an action deserves a wider role.

Promotion lets us make that decision incrementally. A definition can become useful to related work at the parent level, then to work elsewhere, before we decide it belongs in the permanent ontology. At each step we can refine its meaning, generalize its inputs and test the behavior that other agents will rely on. The one-off details stay local; the definitions that earn broader use become better candidates for shared knowledge.

We can set the standard for that final step: useful across the intended range of work, clear about its inputs and effects, checked against existing capabilities, and tested in the situations it claims to support. The standard can be stricter for an action that changes a database than for one that reads a log. Promotion is where we decide that a definition is mature enough for the wider role.

We have already moved locally learned operations into permanent action families. Workbench's run-status lookup is one example: an operation learned during a session became a shared action with a run identifier as its input. What matters is the progression from a particular need to a capability other work can rely on.

This is how fragmented learning accumulates. Every discovery has somewhere to live, and useful knowledge has a route to improve. We can learn at the scale of individual jobs while allowing the permanent ontology to grow around definitions whose value and behavior are increasingly well understood.

Comparing and generalizing action definitions

This is where treating functions as entities becomes especially powerful. Buffaly can examine two actions, find the structure they share and identify the parts that differ. It can keep the shared procedure and turn the differences into inputs. The formal name for finding the closest common structure is least general generalization; making the changing parts into inputs is parameterization. In this simple example, the backup relationship stays the same while the repository changes:

Example A:  Verify(BackupOf(RepositoryA))
Example B:  Verify(BackupOf(RepositoryB))
Shared:     Verify(BackupOf(repository))
Variable:   repository

Buffaly has implemented these comparison and parameterization mechanisms for its definitions. The backup example shows why that matters: a procedure tied to one repository can become an operation that accepts a repository as its input. Further uses tell us which assumptions belong in the shared procedure and which should vary. Because the functions themselves are represented in the ontology, Buffaly can work on their structure as it improves them. The example above illustrates the mechanism; it is not a recorded automatic promotion.

The sequence matters: learn something concrete, use it, borrow it where it helps, and generalize when the examples justify it. We stopped requiring the routine learner to solve every one of those problems at once. It also gives promotion a stronger basis than the first impression of a retrospective reviewer.

Search connects knowledge from otherwise separate sessions. The final insight organizes sessions that already work together.

Insight 5: Let the ontology hierarchy mirror the session hierarchy

Working sessions already form a hierarchy. An agent can assign part of a job to a child session, which can assign a smaller part to another child. Their ontologies can follow that same structure.

It becomes a hierarchy of ontologies. A child session can use its parent's entire ontology, including the knowledge and actions the parent has learned. The child adds its own discoveries to that starting knowledge. Its children can do the same.

A child starts with everything its parent can use, then adds what it learns. A grandchild gets both sets of discoveries and adds its own. Sibling sessions share their parent's starting knowledge, but one sibling's private discoveries do not automatically become part of the other's ontology. The diagram shows these layers as P, A, B, C and D.

Phase 4 · Insight 5 / mirror the session hierarchy
The ontology hierarchy mirrors the session tree: permanent P, parent A, children B and C, and grandchild D. Each descendant graph retains the entities and functions from its ancestors and adds its own layer. This figure shows inheritance only; cross-branch borrowing and promotion are explained separately in Insight 4.
Knowledge follows the family tree. Grandchild D can use the permanent base and what A and B learned. Sibling C gets the base and A's knowledge—not everything B learns. Each row shows what that session inherits and what it adds.

The child does not need to relearn what its parent already knows, and its specialist discoveries need not immediately become everybody's knowledge. When a definition deserves a wider home, borrowing and promotion can give it one: another session, a parent session, or the permanent ontology.

How the five insights work together

Consider what happens during a startup investigation. The working agent identifies the installation, finds its logs and works out how to measure the time spent in database procedures. The memory critic can preserve the installation and the references needed to investigate it again. The action critic can retain the procedure as a function that accepts a log path. Each critic has a concrete result to learn from and a different decision to make.

Both additions enter that investigation's ontology. The agent can use them while the work continues. At this stage, the critics need to recognize that the knowledge is useful to this job; they have no need to predict every installation, log format or future investigation it might eventually serve. That smaller decision is what makes inexpensive, focused learning practical.

A child working on the same investigation starts with its parent's knowledge. A separate session investigating another problem can search for the parser and borrow it without importing the original investigation's logs, status updates and experimental dead ends. The hierarchy gives related work a common starting point; search lets useful discoveries travel beyond it.

The new use gives us another test of the procedure. It may work immediately. It may reveal that a path should be an input, that an assumption only held for the first installation, or that a parsing case was missed. Buffaly can retain the correction, make the action more general and test it again. Useful knowledge gains a wider role as the evidence for it improves. The run-specific details remain attached to the run.

That is how the five decisions fit together. Separate critics make focused learning choices; local ontologies let the results become useful immediately; smaller models keep routine learning economical; inheritance and discovery carry the useful definitions to new work. Promotion can then draw on actual use, corrections and broader applicability when choosing what becomes permanent.

We moved the hardest judgment to the point where we have evidence for it. The first critic no longer has to decide whether a discovery deserves to become permanent before anyone can benefit from learning it.

What earns a place in a session ontology?

Keeping knowledge within a session is not a reason to keep everything. We still need a practical definition of usefulness. Ours is simple: give the model less text to process, avoid repeated searches and tool calls, and reduce errors. Learning should make later work easier. It might settle which repository a name refers to, save a procedure that took several attempts to get right, or keep a correction attached to the function that needed it.

That objective went into the prompts. The offline critic was told to make “objects easier to locate, actions easier to replicate, and previous mistakes easier to avoid.” A proposal had to reflect what the user meant, have evidence behind it and save future work. We kept that objective, then narrowed the decisions the online critics would have to make.

Candidate The usefulness question A reason to decline
Memory Can later work use this to find, open or identify something? It is a generic summary or a passing event with nothing the agent can use.
Action Will keeping this procedure make later work more reliable, repeatable or efficient? It adds no useful behavior, serves only a one-off need or duplicates an existing action.
Revision Does the evidence show that an existing definition needs correcting? The same thing is merely described using different words.

For memory, the test is whether the agent can do something with the knowledge. “There is a backup” tells it very little. A backup record with a name, size, file hash—a fingerprint of its contents—and a link to its repository gives the agent something it can locate and verify. This graph shows a real learned example, with client names replaced:

Learned backup entity and verification action
A learned backup entity points to its website repository. A learned verification action calls an existing execution action; dashed edges show caller-supplied inputs.
Source-backed definitions and September 1–2 verification results. Solid arrows show the stored relationship and direct code call; dashed arrows show caller-supplied values.

The retained backup definition includes these assignments:

PROTOSCRIPT
// Excerpt from WebsiteProject_CloneBackup (client-neutral name)
SemanticEntityBase BackedUpRepository = new SemanticEntityBase();

ArchiveSizeBytes = "5916789";
BackupGitTag = "clone-backup-9d38bac";
BackedUpRepository = WebsiteProject_WebRepository;

Now the next request can find the backup, and code can follow BackedUpRepository to the repository it protects. That saves an investigation. The memory critic's instructions make this concrete: a learned object must contain something the agent can use—a path, an identifier, or a link to another entity that has one. These assignments come from the saved definition. We also checked whether the accumulated information survived being loaded again, an engineering lesson we return to below.

When should the action critic learn a procedure? It should solve a recognizable problem likely to come up again, make the work meaningfully easier or more reliable, and be something Buffaly can implement with its available services. An existing action should be reused unless the evidence shows it needs an improvement.

For an action, the investigation needs to establish what the procedure does and what inputs it needs. The log analyzer shows the payoff: the saved procedure runs without calling a model. A model may choose the action, supply the log path and interpret the result, while ordinary code does the parsing. If a procedure still needs judgment, its action can include a step that asks a model. We wanted models to work on decisions still open, rather than reproduce mechanics we had already worked out.

Exploration cost:  discover the procedure + try it + inspect the outcome
Later use:        select the operation + supply new inputs + execute

For a deterministic caller, even selection can be a direct function call.

We judge usefulness when selecting a candidate, when using it later, and when reviewing what to keep or improve. No single score replaces those checks. Writing a definition costs something. Maintaining it costs something. Searching through unnecessary definitions costs something. Sometimes the best learning decision is that the system already has what it needs. The critics can record “no change needed” and move on. In roughly four out of five reviews, the action critic did exactly that. We wanted a useful addition or correction, not a new definition after every interaction.

This is the assignment the online critics repeat: look at the work that just happened, identify something useful, check whether it already exists, and retain the justified addition or correction. The results let us test whether those decisions actually helped.

What autonomous learning changes in practice

The result is a growing collection of knowledge and code that reflects the work this instance actually does. Its autonomously learned session additions now contain more than three times as many entities as the shared foundation. They have also added about 1,200 actions, giving agents new operations they can use without expanding the permanent ontology on every learning pass.

Supervised foundation / autonomous additions
Supervised learning supplies the shared foundation: 1,478 entities and 2,167 actions. Unsupervised learning has added 4,679 entities and 1,204 actions in sessions.
Supervised learning built the shared foundation. Unsupervised learning adds knowledge and code as agents work. These are the sessions' own additions; every session can also use the shared foundation.

The two critics leave a substantial, directly attributable record of that growth: the memory critic created or enriched about 4,000 entities, while the action critic contributed about 1,100 actions. Their work is a large part of this instance's knowledge, not a handful of demonstrations sitting beside a developer-written catalog.

New capabilities put to work in about 90 sessions

About 90 sessions put autonomously learned tools to work. Across those sessions, around 180 actions received nearly 2,000 later calls after the critic created them. Buffaly was using new capabilities in the work that produced them.

Same-session use after the action critic created a tool Exact count
Main working sessions with later use 89
Critic-created action/source-session pairs used later 180
Later tool-result records 1,920

These records establish that learning reached the working agents and was used. They do not count completed jobs or prove how many sessions would otherwise have remained blocked. Some calls can be tests or return errors. We followed individual actions into later work to see what the aggregate count could not tell us.

The study includes older conversations run through the critics as well as ongoing work. The totals show what accumulated. The path from saving a definition to making it available, together with the creation and use records, shows how learning joins the running system.

Roughly 90% less text in the tool calls

Around 1,300 tokens became about 130. In the log-analysis example, Buffaly passed a file path to a function it had already learned instead of generating the parser again. The stored parser ran without a model call.

During a startup investigation, Buffaly worked out how to read debug logs, count database-procedure calls and total their durations. The action critic retained that procedure as ToAnalyzeBuffalyDebugLogProcedures. Here is its callable definition, with the long statement that constructs the parsing script omitted. The complete source is included in the evidence file.

PROTOSCRIPT
[SemanticTag("Action",
    "to quantify stored procedure volume and timing from a buffaly debug log")]
prototype ToAnalyzeBuffalyDebugLogProcedures : OpsAction
{
    function Execute(string logFilePath) : string
    {
        // Omitted: the statement that builds `script` to read the log,
        // count procedure starts and stops, and total their durations.

        string result =
            ToExecuteFastPowerShellOperationInWorkingDirectoryWithTimeout
                .Execute(script, "C:\\logs\\Buffaly", 120);
        return result;
    }
}

The function's input is a log-file path. Its body runs the retained parser and returns the report. This part of the parser recognizes a procedure's stopping record, counts it and adds its duration:

POWERSHELL
if ($line -match '\tStopping\s+([^\t]+)\t([0-9.]+) total seconds') {
    $n = $matches[1].Trim()
    $stops[$n] = 1 + ($stops[$n] ?? 0)
    $dur[$n] = ($dur[$n] ?? 0) + [double]$matches[2]
}

Later investigations can supply another path, or take that path from a trace object in the ontology:

PROTOSCRIPT
// Illustrative path supplied directly to the learned action.
ToAnalyzeBuffalyDebugLogProcedures.Execute(@"C:\traces\startup.log");

// Or use the stored path from a trace identified in the ontology.
ToAnalyzeBuffalyDebugLogProcedures.Execute(
    StagingLatencyTrace20260802_1500.WorkerLogPath);
Trace entity and analyzer
A startup trace stores its log path; the learned analyzer accepts that path and runs the retained procedure. Later use can reveal a correction or another learning opportunity.
The trace provides the input; the learned action provides the procedure. Keeping both in the graph gives the next investigation something it can identify and something it can run. Paths in the displayed calls are illustrative; the token comparison below uses four recorded calls.

Across a few later calls, passing inputs to the saved function required about 130 tokens, compared with about 1,300 to supply the equivalent code again. That is about 90% less text to generate in the tool calls. The saved procedure itself made no model call.

Tool-call text comparison Exact measurement
Recorded calls 4
Arguments passed to the learned action 125 tokens
Equivalent inline code and arguments 1,309 tokens
Argument tokens avoided 1,184
Reduction 90.5%
Model calls inside the saved implementation 0
Recorded outcomes 3 clean results; 1 output-collection timeout after process exit
Argument tokens across four analyzer calls
Four learned calls require 125 argument tokens compared with 1,309 for equivalent inline implementations; 1,184 argument tokens are avoided.
This measures the text sent as tool arguments. For comparison, we reconstructed the equivalent inline calls from the saved code. It does not include the cost of learning the function, finding it, reasoning about the job or returning results.

Most of those calls returned clean results; one timed out while collecting output after the process had exited. The comparison measures the text we avoided generating by calling stored code, not the cost of the entire job. Learning, finding, checking and maintaining the function still take work. The saving makes the original “remember how to do this” objective concrete: later calls supplied inputs instead of reproducing the parser.

Thousands of actions within reach of a working session

A working session can search thousands of actions instead of being limited to the tools it started with. It can find a relevant function, inspect it, load or borrow it, and call it. A useful capability learned during one job becomes available for another without loading every session's knowledge into the prompt.

That changes the range of jobs an agent can take on. A session asked to package a deliverable can acquire a verified-copy procedure learned during website work. An investigation can find a log parser that another session already debugged. The agent gains the operation it needs, not a larger prompt full of unrelated procedures. Existing permissions and missing dependencies still matter; search makes a capability discoverable, not automatically loaded or authorized.

Available to search in this snapshot Exact count
Action entries across shared and session-owned definitions 3,371

Reusing a copy action and correcting a backup action

A learned copy-and-verification action gives us a concrete reuse example. It refuses to overwrite an occupied destination, copies a folder tree and checks the copied files against their originals. Later work used it to deliver more than 300 screenshots—about 70 MB—with no reported mismatches. We independently compared every source file, copied file and recorded file hash; all matched. A procedure learned for a website had become useful in a screenshot-delivery job.

Recorded sequence Result
Explore Copy and verify a 1,659-file website tree
Learn Create the copy-and-hash action
Reuse Copy and verify a 310-image screenshot set
Data delivered 71,016,168 bytes; 0 reported hash mismatches
Inspect retained evidence All 310 source/destination/manifest hash triples agree

We also found the correction loop we had wanted. A learned database-backup action put a timestamp variable inside single quotes when constructing its filename. The backup succeeded, but the variable name appeared literally in the filename. The critic revised the implementation, and later results show timestamped names. The change is small enough to read directly:

POWERSHELL
# Before: ${stamp} remains literal text.
$bak = Join-Path $backupDirectory 'application_staging_backup_${stamp}.bak'

# After: evaluate the timestamp and concatenate the filename.
$bak = Join-Path $backupDirectory ('application_staging_backup_' + $stamp + '.bak')

Here the records follow the full sequence: create the action, see the problem, update its code and see the correction in later runs. The operation also reports the backup's size and file hash and uses SQL Server's VERIFYONLY check. We verified the filename correction; restoring the database would be a separate test. This is a concrete example of later experience improving a learned procedure.

What we learned while building it

The biggest mental leap for me was embracing imperfection. I had to get comfortable with Buffaly learning something useful before it knew how useful that thing would become. A first version could be incomplete or too specific. Good things should get incrementally better as the system uses them.

That is what the session ontologies let us do. Buffaly identifies entities and actions in the course of one job. The ones that prove reusable percolate up: another session borrows them, puts them to work and finds ways to improve them. A function gains a parameter. An entity gains a relationship. An assumption that worked in the original situation fails somewhere else, and the code gets corrected. The one-off details stay behind in the sessions where they mattered.

Across thousands and thousands of sessions, this becomes a kind of evolutionary process. Use gives the useful definitions more opportunities to improve. They become more general, more robust and better candidates for the permanent ontology. The brain gets better through the accumulated experience of doing the work.

Our initial approaches tried to make too much of that judgment in advance. We asked a large model to read a whole session and pick out what would be useful later. That was expensive, and it didn't scale. More fundamentally, usefulness changes. Something useful today might not be useful tomorrow. Something that looks like a minor detail in one job can become important when another job needs it. A larger retrospective review doesn't give us that future experience.

Using a small model to pull out potentially useful things, then letting the pressure of actual use refine them, works much better. The initial learning decision can be imperfect because it is the beginning of a process. Reuse, correction and generalization help determine what earns a wider place in the ontology.

I don't tell Buffaly to remember things very much anymore. For the most part, I let the autonomous loop do its work. Every once in a while, I'll see it borrow or use an action I've never seen before—something it learned along the way and now knows how to use. Watching that happen has been one of the most interesting parts of building this.

I used to spend a lot of attention deciding what Buffaly should remember. Now I sometimes find out what it learned by watching it work.