# Primitives

Six things. Everything else is metaphor. Each entity lives in its own typed table — "record" is the mental category, not a polymorphic Postgres table.

```
Records      the only entity. Identity is emergent from usage (parent_id), not from type.
Streams      append-only logs on a separate storage plane (HTTP-addressed byte logs, CDN-cacheable).
Agents       records whose type grants participation. Human or bot, irrelevant at this layer.
Permissions  who can act in a scope. Today: house membership; formal layer: scoped capabilities.
Mutations    structural changes — the *category*, not a separate log. Today it lives as Postgres
             row writes plus narrating signal.* entries on streams.
Signals      the system witnessing its own operation. Latencies, retries, decisions, failures.
```

A record becomes a scope when other records address it as their parent. Identity is emergent from usage, not declared by type — closer to speech act theory than database design. Streams are a primitive because they're a fundamentally different storage plane from rows: different write semantics, different read patterns, different durability guarantees. There was once a separate mutations audit log; that was removed — structural narration now rides on `signal.*` entries on the relevant scope's stream, alongside content. Mutations and streams share the concept "append-only history" and share nothing else.

The identity and authorisation model is symmetric — humans and bots are both agents with the same scope membership model. Embodiment is **not** symmetric: a human's runtime is a browser, a bot's is an LLM plus optional sandbox work. Arbe equalises authorship, not embodiment.

The formal layer wants scoped capabilities: managing a house is not the same risk as invoking a tool, even if both are permissions. The v1 implementation is deliberately smaller: `members.role` gates house-level member vs owner behaviour, and that membership inherits to threads, environments, and configs.

Signals are easy to miss as a primitive because they're parasitic on other transport mechanisms — they often look like stream messages or mutations. Their **purpose** is different. A stream message records what an agent intended; a signal records what the system experienced while carrying that intent. Every signal has an `agent_id` because every action has an author.

Tools are records with `type: 'tool'`, scoped to a house or room — a record type with a behavioural convention, not a seventh primitive. A sandbox is a *capability* an agent holds, not a primitive. A session is a room with a short lifecycle. A thread is a child room. A workspace is a house. The names change. The primitives don't.

**See:** [thinking/thesis](./thesis.md), [thinking/layers](./layers.md), [thinking/record-types](./record-types.md), [vocabulary](../vocabulary.md).
