The state domain agents read: Paimon for the work queue, stock and approvals

A planner seen from behind at a standing desk in a quiet dispatch office, one wide monitor showing an abstract blue-and-grey board of queued rows that updates as she watches, a thin blue status strip along the top edge of the desk

A procurement agent is asked to prepare a replenishment order for a component that is running short. To do that well it needs the stock position in three warehouses, the open customer orders that reserve some of it, the inbound deliveries already on the road, and the supplier’s current risk status. Each of those changed in the last hour. The nightly copy in the warehouse is wrong about all four. The production tables of the modules are right, but an agent reading them at scale is the fastest way to slow the people who work in those modules.

This is the gap between the two memories of a company operating system: the record, which keeps every event for good, and the live state, which is what things look like now. The pillar text describes both. This one is about the second, and about the table format the Data layer uses for it. The Data layer is in build; what follows is how it is being designed.

What a domain agent actually reads

Hurukan’s agents are domain agents: one for procurement, one for customer service, one for the work queue in operations, and so on. Each of them works from a small number of state tables that answer present-tense questions.

The work queue. Which jobs are released, which are blocked and why, which machine or team is free. Fed by the operations module as jobs change status.

Stock and reservations. Quantity on hand per item and location, minus what open orders have already claimed, plus what is inbound. Fed by Inventory and logistics, commerce and procurement events.

The approval inbox. Every proposal an agent has made, with its sources and its risk, and whether a person has decided yet. Fed by the agents themselves and by the people in Decisions and tasks.

None of these tables is a copy of a module’s database. Each is built from the events the modules emit, which the record also keeps. The state table is a derived, always-current view of the record; the record is the proof behind it.

Why this is a Paimon table

A state table changes thousands of times an hour by key: the same item, the same job, the same proposal, updated again and again. Table formats built around appending new files handle that badly, because every update becomes a new file and the table drowns in small files. Apache Paimon was designed for exactly this case. Its primary-key tables store rows in an LSM tree, sorted by key within a bucket, so a stream of updates to the same keys stays compact and a reader always sees the latest version of each row (table types, checked 21 October 2026).

Two Paimon features do work that would otherwise be code. A merge engine decides what happens when a new row arrives for an existing key: replace it, keep the first one, aggregate, or fill in only the fields that arrived. The stock table uses the last of these: inventory writes the on-hand quantity, commerce writes the reserved quantity, procurement writes the inbound quantity, and the table holds all three in one row without any module knowing about the others. A changelog producer emits every change to the table as a stream of its own, so a downstream agent can react to “stock fell below the reorder point” instead of polling.

The current release is Paimon 2.0.0 of 7 August 2026 (release catalog, checked 21 October 2026). Flink writes and reads it, and the lookup join lets a streaming job enrich an event with the current state of another table — a new order with the stock it reserves — without a round trip to anything else. Spark, Trino, Hive, StarRocks and Doris read the same tables (engines).

The agent reads the state and writes only a proposal

The boundary matters more than the format. A domain agent reads the state tables freely. It does not write to a module, and it does not write to the state table either. What it produces is a proposal: a drafted replenishment order with the rows it read, the rule it applied and the risk it sees. The proposal lands in the approval inbox. A person decides. The module carries the decision out, emits the event, and the state table changes because the event was recorded — not because the agent changed it.

This is what keeps the two memories honest. If agents wrote state directly, the state would contain things that never happened in any module and were never recorded. By reading state and writing proposals, every change to what the company considers true still passes through a person and through the record.

It also answers the audit question. Paimon keeps snapshots, and a tag pins one so that it is not expired. When a proposal is questioned months later, the snapshot taken at the moment the agent read the table shows exactly the stock, the queue and the open orders it saw. The decision log holds the reasoning; the snapshot holds the evidence.

Seconds, minutes, or tonight

Not every state needs to be a Paimon table fed by a stream. The approval inbox has to be current to the second, because a person is waiting in it. The work queue has to be current to the minute, because a machine is waiting. Stock for replenishment is a decision made a few times a day; a state that is a few minutes behind is fine. Supplier risk status changes weekly.

Pushing everything to seconds costs continuous compaction, a streaming engine that never sleeps, and an operations team to keep both healthy. So the Data layer asks, for each state table, which decision depends on it and how fast that decision really changes — and only the tables that need seconds get them. “Real time” is not a property of the platform; it is a budget spent per table.

A test you can run today

Pick one decision somebody in your company makes several times a day: approving a purchase, releasing a job, promising a delivery date. Write down every number they look at before deciding and, next to each, where it comes from and when it was last refreshed.

If several of those numbers come from different systems and were refreshed at different times, the person is already doing the join in their head, from state that was never consistent at a single instant. That is the table a domain agent would need first — and the one to design before any agent is asked to decide anything.