Fathym
Menu

Before and After

Five contrasts. Same scenario each time - the old way, then the holon way.

A function vs. a Capability

A function carries behavior. It knows how to do something; it doesn't know what it accepts, what it guarantees, or what it means. Everything outside it - callers, validators, AI agents, docs generators - has to read the source to understand it.

A Capability declares its input contract, its output shape, its execution logic, and its intent. Pass style: 'diagonal' and TypeScript catches it before execution. The schemas are data that exist at runtime: a validator checks against them, a docs generator reads them, an AI agent understands each field through its .describe(). The function's contract lived only in your head; the Capability's contract is part of what it IS.

A complex system vs. a typed handle

Not every Capability maps input to a value. Some open something - a connection, a session, a stream - and return a handle the caller uses to interact with what's inside. The Capability holds the internal state; the caller gets typed methods. A Transaction Capability keeps BEGIN, the connection acquire, and the release inside itself, and hands back Query, Commit, Rollback. Forget to commit, forget to release? Those paths live inside the Capability - the caller can't misuse them by accident. The handle IS the contract.

An assertion test vs. an Intent

A Deno.test records a verification after the fact: "this ran, this matched." The test is separate from what it tests - when the function moves, the import breaks. An Intent inverts this: it's part of the Capability's definition.

CapabilityIntent('FormatText — title case', FormatText)
  .WithInput({ text: 'hello world', style: 'title' })
  .Expect(ExpectCapabilityResultEquals({ formatted: 'Hello World' }))
  .Run();

The intent is a machine-readable declaration that travels with the entity. When an AI agent reasons about FormatText, it reads the intents to learn what the entity is supposed to do - not just what it happened to produce last run. You're not writing tests to catch bugs; you're declaring the contract the holon makes to every caller, in the same language as the code.

A service class vs. a Steward

As systems grow, behavior gets organized into service classes - objects that own related operations and hold dependencies through constructor injection. The class IS the coupling point: add an operation, touch the class; swap a dependency, touch the class; test an operation, test the whole dependency tree.

A Steward is the container; Operations are the mutable layer; the Capabilities stay stable. Adding an Operation means adding an entry to .Operations({}) - the existing Operations don't know about it. Each Operation declares exactly what it needs (.Capabilities({}) for typed access, .Services(async (ctx, ioc) => ...) for IoC-resolved dependencies). Nothing about the parts changes when the composition changes.

A raw LLM call vs. an Agent

An LLM interaction is usually a raw fetch - no declared contract on the input, no schema on the output, no governance on who can call it. To an AI reading your codebase, it looks like any other fetch. An Agent gives the LLM interaction the same structure as everything else: typed input validated before the call, a handle contract (SendMessage, Close), an intent declaration, and governance hooks via .Governance(). Compose it into an Operation with .Agents({}) and it stays exactly the same entity.

What a holon carries

A function carries its logic. A service class carries its dependencies. A fetch call carries its implementation. Every entity in @fathym/steward carries something more:

  • A Capability carries its input contract, output contract, execution logic, and intent - the same in every context.
  • An Agent carries its input schema, its handle contract, and its intent. The LLM call, the credentials, the session live inside; outside is a typed input and a message-based handle.
  • An Operation carries its Capabilities, Agents, and Services, and declares exactly what it needs. Change the Operation and the Capabilities don't change.
  • A Steward holds its Operations, coordinates execution, and shares governance. The entities inside stay whole.

None of these collapse when composed. Each was whole before composition, and stays whole inside it. That's what "whole and part" means in code.


On this page