What an agent is made of
An agent is a model plus the modules installed into it. Restarting a two-year project from that one line is what decided everything after it.
Most agent frameworks define an agent as a prompt plus a set of tools: you write the instructions, attach the functions it may call, and the framework runs the loop. It breaks the moment the agent has to remember anything. Memory is not a tool and not a prompt, so it ends up outside the agent, in a database you provision and wire yourself.
Motivation
The restart ran on a different definition, and it fits on one line:
I want to make Agent = AgentFlow (program) + module-configs. And then black-box the module interface as we will reverse engineer what has to occur. I think this is the clearest articulation of it yet.
An agent is a program plus a set of installed modules it draws on. Restating a two-year-old project in one line has a cost: everything already built carries opinions about what those words mean, and none of those opinions were examined when they were formed.
The restart rule
The rule governing the restart, in capitals:
THE PAST IS IRRELEVANT MEMORYLESSNESS MARKOV PROPERTY
A Markov process is one where the next step depends only on the current state, not on the path that produced it. Applying that to the prior work is a decision rather than an observation. The alternative is carrying every earlier commitment into the new design as a constraint nobody re-examined.
The module
Abstract descriptions of a module all failed the same way: nothing in them says what installing one actually does. The definition that stuck is mechanical:
they are prepacked units of functionality that bring their own model (database, all managed on idyllic), state, prompts, flows / functions and export methods, functions, tools, context that can be used within the agent builder
- A module brings a data model, state, prompts and flows.
- A module exports tools, functions, methods and context.
Installing the Telegram module is the concrete version:
install the telegram module and it creates a messages table, a contacts table, stores conversation state, includes prompts for handling telegram conversations, and exports tools like "send_message" and "get_conversation_history" that show up in your agent builder. you drag those tools into your flow, configure them, done.
The load-bearing detail is the tables. Installing the module creates them, on the platform, and you never provision a database, because the module brought its own. That is the difference from a tool protocol, where you get callable functions and whatever they need to remember is somebody else's problem.
The mechanism has a closer analogy outside the agent field:
I think it basically is creating digital assets / resources, similar to creating a database or imagine a mini AWS. These resources would be stateful and they would have operations on them (this is the semantic objects thing again). So we give the agent a virtual environment
A mini cloud provider for one agent: stateful resources with operations defined on them. That supplies the verb the tool framing is missing. You install a module the way you provision a resource, and the storage arrives as part of the provisioning rather than as a step you go and do yourself.
Modules against agents
The field's default unit is an agent. Mine is a module:
modules take advantage of the fact that multi-agent systems are already the most compatible composability layer but people are focused on the wrong thing, making them "multi-agent teams" when in fact they are separate functional units of a single agent
The common framing puts several agents in a room with roles, a researcher and a writer and a critic, and has them talk to each other. That misreads what the decomposition is for. Splitting the work is useful because each part gets its own context, its own data and its own instructions, not because the parts are colleagues. So the unit to package and share is a functional unit, not a persona.
The module interface
The founding line's second clause is methodological: black-box the module interface and reverse engineer what has to occur. The shape of the boundary stays undefined and gets discovered by building against it.
That is the opposite of specifying an interface first, and it is right when you do not yet know what will cross the boundary. A specification written before any use is a guess with a commitment attached. Three modules built against a black box report what all three needed; a specification written first reports what one person guessed.
The form factor
A module is distributed as a folder inside somebody else's project:
it's not a component library or a typescript framework it's a thing that uses typescript as a DSL substrate that leverages all of typescript flexibility while being embedded in a folder within another project
The comparison is to a backend platform rather than to a library:
i want to be convex for agents. drop it in your app you get a folder that defines code for your agent. cloud runtime on by default
A domain-specific language is a small notation built for one job. Using an existing language as the substrate for one, rather than inventing new syntax, means the parts you need are an existing notation, used in a constrained way, and a runtime that gives the constraint meaning.
The same priority governs the infrastructure:
I don't want to focus on infra I want to focus on dx, they upload code to us I want to wrap it and manage it
The choice there is which problem to own. Wrapping and managing code somebody else uploaded is a smaller surface than running infrastructure, and it is the surface a developer actually touches.
What shipped
The definition has two halves and they landed differently. The module system is a specification: what a module brings and exports, what installing one does, and the black-box method for discovering the interface. The program half shipped as a TypeScript class:
export default class SimpleSystem extends AgenticSystem {
@field query = '';
@field count = 0;
@action()
async increment(amount?: number) {
this.count += amount ?? 1;
}
}Two decorators carry the whole runtime:
@fieldis state that synchronises to every connected client without anybody writing the synchronisation. A streaming field appends while a model generates, so the interface updates as it fills.@actionis a method the browser can call with its types intact.
It reads as a plain class because of the argument the README makes: a game developer does not implement networking or rendering before writing what happens when a character eats an apple. Infrastructure is not what distinguishes one game from another, so an engine absorbs it. History, context, prediction, streaming and persistence are common to nearly all AI applications, and what differs is the intelligence design on top.
The substrate
The runtime underneath became the constraint:
i was stuck on the durable objects platform, cuz that's just the streaming runtime for the web but it actually needs complex agent code or cool agent ideas and i was stuck trying to come up with something cuz "10 agents streaming!" doesn't resonate anymore
The platform is Cloudflare Workers for Platforms with Durable Objects underneath. Server-sent events, plain WebSockets and Upstash were the other candidates for the realtime channel, and weighing them settled that the transport is not the deciding axis:
Tbh ws transport should be transparent doesn't seem like there is something that actually necessitates it except multiple tabs open on the same thread for the same user. And even in that case upstash realtime looks ok?
What decided it was the resource layer rather than the channel. A Durable Object is a single addressable instance that stays alive near its own storage, which is the module design expressed in infrastructure:
benefit of Idyllic is I want to promote the river-actors / durable-objects pattern of modules with mini dbs inside of them (live JS objects) as the resource layer so it is all self contained
So the substrate gets chosen for the same property the module was: state lives inside the unit rather than beside it. Delivery arrives with it, and delivery is the part that does not distinguish an agent from a chat room. Ten agents streaming is a fact about the infrastructure.
The pull that replaced it was toward local agents, where the use cases expand and iteration is faster, against the objection that an open source framework for local agents is hard to sell. Where the agent runs and how the thing gets distributed pull against each other.
The definition
An agent as a program plus installed modules, where a module brings its own tables and its own state and exports the handful of things the program can call, is a sharper answer than a prompt plus tools for one reason: memory arrives with the unit you install rather than as infrastructure you assemble.