pub const OBJECT_SCHEMA_VERSION: i64 = 44;Expand description
user_version value stamped into objects.db after run_object_schema.
The flat schema reset the counter to 1 (the pre-flatten chain never set
user_version, so legacy files read 0). Bumped per additive migration:
v1 — flat schema baseline
v2 — db_agent_definitions.updated_at
v3 — db_agent_definitions.user_hidden (Phase 2 hide templates,
SPEC_AGENT_PICKER_TWO_TIER_2026_05_24.md Q2 Decision Y)
v4 — db_agents consolidation table (Phase 3a: every definition/
instance write dual-writes here). Reads moved over
piecemeal afterwards — the instance side in Phase 3b (#3080),
every agent_def_* method in Phase 3d (#3092, v31) — and both
legacy tables were dropped in v32.
v5 — db_agents.last_block_id (Phase 3c; latest launch’s block, so the
consolidated read can find the session snapshot without joining
db_agent_instances)
v6 — container_image / container_volumes / container_name on both
db_agent_definitions and db_agents (Phase 0 of
SPEC_CONTAINER_PANE_SUPPORT_2026_06_11.md; host agents default
to ‘’ / ‘[]’ / ‘’)
v7 — db_muxbus_credentials: global singleton for MuxBus cloud
Cognito PKCE tokens (access, refresh, id) + expiry + user email
v8 — db_memory_bundles.is_global: global-tier flag for Armory
bundles injected into every agent’s CLAUDE.md at launch
v9 — db_memory_bundles.sort_order: explicit ordering for the Armory
global bundles (controls CLAUDE.md injection order). Existing
rows default to 0; the Armory Global section assigns positions via reorder.
v10 — db_skills, db_mcp_servers, db_agent_skills_ref, db_agent_mcp_ref:
standalone MCP Server and Skill primitives with per-agent ref tables
(v1 composable model, SPEC_V1_MCP_SKILLS_PRIMITIVES_2026_06_30.md).
v11 — Phase 4a of SPEC_PRESET_TO_BUNDLE_REFACTOR_2026_07_02.md: rename
db_identity_accounts -> db_accounts, db_memory_bundles -> db_bundles
(SPEC_ARMORY_PHASE4_STORAGE_RENAME_COMPLETION_2026_07_12.md).
v12 — use_ambient_login on both db_agent_definitions and db_agents:
explicit per-agent opt-in to the CLI’s global (ambient) login when
no oauth-class account resolves at spawn (layer 3 of
SPEC_ACCOUNT_DELETE_DEAUTH_LAYERS_2_4_2026_07_14.md §2.3). Defaults
to 0 (fail-by-default); the m0017 data migration grandfathers
pre-existing linkless agents to 1.
v13 — db_agent_credentials: per-agent M2M muxbus credential, mirroring
db_muxbus_credentials’ presence in both schemas — id_store falls
back to this (per-channel) schema on installs that haven’t yet
applied 0011_shared_store_backfill, so cloud_subscriber’s calls
must not assume the shared-schema copy (v4 there) is the one in use.
v14 — db_agent_native_memory: durable mirror of each agent’s native
memory files, keyed by (agent_id, filename). Same both-schemas
duplication as db_agent_credentials, for the same id_store
fallback reason. See
docs/specs/SPEC_NATIVE_MEMORY_DURABLE_SYNC_2026_08_07.md.
v15 — model_vendor_base_url on both db_agent_definitions and db_agents:
redirects a harness (CLI) at a non-default model vendor backend
(e.g. ANTHROPIC_BASE_URL for a claude-provider agent) — the data-
model side of formalizing harness vs. model-vendor as distinct
concepts. Defaults to ‘’ (use the harness’s default vendor).
Only settable via agent.define, validated against the resolved
provider’s ProviderConfig::base_url_env_var.
v16 — db_bundles.instructions_by_provider: JSON object of
{provider_id: content} instruction variants, additive to the
existing flat instructions column (which keeps meaning
“default”). ABF v0.2 storage half of provider-scoped
instructions — see
docs/specs/SPEC_ABF_V0_2_PROVIDER_AWARE_COMPONENTS_AND_NATIVE_MEMORY_2026_08_10.md
§2.2. Defaults to ‘{}’ for existing rows; delivering a selected
variant into a running agent is explicitly out of scope for this
version (per that spec’s non-goals) — this column only makes the
data storable/exportable/importable.
v17 — auto_continue_enabled on both db_agent_definitions and db_agents:
per-agent opt-in letting a Warden Supervisor watcher agent
auto-continue this agent’s session on turn-end (subject to a
server-side consecutive-nudge ceiling). Defaults to 0 (opt-in
required — fail-by-default, same posture as use_ambient_login).
See docs/analysis/ANALYSIS_WARDEN_AUTO_CONTROLLER_CONTINUATION_WATCHER_2026_08_12.md.
v18 — db_agent_jekt_keys: per-agent HMAC-SHA256 signing key for
host-tier jekt sender verification. One row per agent_id, minted
on first use and injected into that agent’s own MCP server
process env (AGENTMUX_JEKT_KEY) at spawn — never into any other
agent’s env, so a signature can only be produced by the agent it
claims to be from. See
docs/specs/SPEC_JEKT_TRUST_LAYER_COMPLETION_2026_08_13.md §2.2.
v19 — db_agent_definitions.memory_id: the agent’s own dedicated ABF
bundle, set once at creation and never updated thereafter
(agent_def_update’s SET clause deliberately omits it, same
immutable-after-creation treatment as is_seeded/slug/parent_id).
Distinct from db_agent_instances.memory_id (a specific launch’s
bundle, can still diverge on purpose). Mirrored into db_agents as
a SEPARATE default_memory_id column, not db_agents.memory_id —
that column is instance-only by existing convention (see
db_agents’ CREATE TABLE comment). Defaults to ‘’ for existing
rows; the m0021 migration
backfills every unbound definition to a freshly-provisioned
bundle. See ARCHITECTURE_MANDATORY_ABF_RETHINK_2026_08_14.md §3.1.
v20 — db_agent_lan_keys: per-agent Ed25519 keypair for LAN-tier jekt
sender verification — mirrors v18, asymmetric instead of HMAC
(LAN is multi-party: a receiving peer must verify without being
able to forge, which a shared secret can’t provide). public_key
is distributed to LAN peers on demand (not secret); private_key
is injected into that one agent’s own MCP process env
(AGENTMUX_LAN_KEY) at spawn, same never-over-RPC guarantee as
v18. See docs/specs/SPEC_JEKT_LAN_TIER_SIGNING_2026_08_15.md §2.1.
v21 — db_lan_peer_pubkey_pins: trust-on-first-use pin of a REMOTE
agent_id’s LAN public key, as first observed from mDNS-discovered
peers. reagentx P0 on the LAN signing PR: peer discovery itself
is unauthenticated (any device can broadcast an mDNS instance and
register an agent under an existing agent’s name), so trusting
“whichever peer answers first” for a pubkey lookup lets an
attacker’s self-minted key be accepted as authoritative for a
victim’s agent_id. Pinning the first-seen key and rejecting any
later mismatch (rather than silently accepting the newest
answer) is the standard SSH-host-key mitigation for exactly this
“no PKI available” situation — closes the always-spoofable case,
narrows it to a race on the very first lookup ever performed for
that agent_id. See
docs/specs/SPEC_JEKT_LAN_TIER_SIGNING_2026_08_15.md §2.2.
v22 — db_background_tasks: durable record of a declared long-running
(run_in_background: true) task attached to a block, so its
liveness survives past DockSnapshotCache‘s 1-hour eviction and
a session reconnect/reload — the ephemeral client-transcript-
derived signal chain had no durable source of truth at all. Per-
channel (block ids are only meaningful within their own
channel), not the shared store. Renumbered from an earlier v20
to v22 when merged alongside the LAN-tier jekt signing PR, which
independently claimed v20/v21 for an unrelated table pair — see
docs/status/STATUS_ATTACHED_TASK_AXIS_AND_DEV_LOOP_2026_08_15.md,
issue #2492.
v23 — db_bundle_skills_ref, db_bundle_mcp_ref: bundle-level references
to the standalone skill/MCP-server primitives, mirroring the v10
agent-level ref tables but keyed by bundle_id — composable model
v2, step 1 of docs/specs/SPEC_BUNDLE_AS_CONTAINER_V2_2026_08_17.md
(GH issue #2024 item 3). A bundle’s existing mcp_servers/skills
JSON columns are untouched by this — still the .abf export/import
format — these ref tables are the new live-resolution path.
Deliberately NO FK to db_bundles (unlike the agent-level ref
tables’ FK to db_agent_definitions) — see this table’s own doc
comment at its CREATE TABLE for why.
v24 — db_agent_native_memory_versions: append-only version history for
native memory content, mirroring the v14 table’s own dual-
schema duplication (id_store per-channel fallback). See
docs/specs/SPEC_MEMORY_VERSION_CONTROL_AND_ARMORY_AUDIT_2026_08_19.md.
v25 — db_agent_groups: saved, named target sets for the fleet-control
feature (broadcast/bulk-stop across many agent panes at once —
docs/specs/SPEC_MULTI_AGENT_FLEET_CONTROL_2026_08_20.md). A
group is just a durable list of block ids under a name — the
Ansible-inventory-group lesson from that spec’s research: a
saved group, not raw ephemeral selection, is the abstraction
that scales as a fleet grows. Per-channel (block ids are only
meaningful within their own channel), not the shared store.
Renumbered from an earlier v24 — merged alongside the native-
memory-version-history PR, which independently claimed v24 for
an unrelated table (see that entry above for the same class of
collision this codebase has hit before, e.g. v20→v22).
v26 — db_agent_definitions.conversation_visibility (TEXT, default
‘private’) + db_conversation_trust_grants: muxspect Phase B/C’s
per-agent disclosure policy for an incoming cross-tier
transcript_request jekt (LAN/WAN conversation visibility —
docs/specs/SPEC_MUXSPECT_CROSS_TIER_CONVERSATION_VISIBILITY_2026_08_21.md,
jekt tier rules confirmed in
docs/specs/SPEC_JEKT_TRANSCRIPT_REQUEST_TIER_RULES_2026_08_22.md).
One of “private” (default, auto-deny)/“trusted_peers” (auto-
approve an allow-listed requester)/“ask” (force human
escalation). Also dual-written to db_agents (mirrors
auto_continue_enabled’s treatment exactly — a simple per-agent
opt-in-style setting, unlike memory_id/model_vendor_base_url,
which use a differently-named column there). Deliberately NOT
added to DefinitionRecordV1’s cross-channel wire format —
channel-local only, same precedent as those two fields; a
cross-channel-reopened agent starts back at the safe “private”
default. db_conversation_trust_grants mirrors
db_lan_peer_pubkey_pins’s exact shape (own module,
get/set-style methods, case-insensitive agent_id lookups).
v27 — db_bundles.is_system: an AgentMux-controlled, highest-priority
Global Bundle tier (INTEGER, default 0). A system row is always
also is_global=1 (enforced in code, not a CHECK constraint —
see bundle_upsert_system). Writable only through the
dedicated upsertsystemmemory/deletesystemmemory RPCs and
Store::bundle_upsert_system/_delete_system — the
generic bundle_upsert/_delete/_reorder all refuse
to touch an is_system=1 row. Injected first in
format_global_bundle_block’s output, wrapped in explicit
override wording, ahead of every ordinary Global Bundle
section. See docs/specs/SPEC_GLOBAL_MEMORY_SYSTEM_TIER_2026_08_24.md.
v28 — db_agent_activity_summaries: one-shot, on-demand Haiku-generated
activity summary per definition_id, used as the AgentPicker’s
“My Agents” conversation-preview fallback when a row has no
structured output.state.json snapshot to preview (legacy rows
predating snapshot persistence — see has_snapshot in
listrecentsessions, agent_handlers/session.rs). Generated
from the instance’s raw "output" filestore file (present even
when the newer structured snapshot isn’t) via the same shared
Ambient Model Call gateway dispatch_name/term:ambient_summary
already use (invoke_haiku,
docs/specs/SPEC_AMBIENT_MODEL_CALLS_FRAMEWORK_2026_07_03.md).
Generated lazily (first picker load that needs it, not on every
turn) and cached forever once non-empty — mirrors
SubAgent.display_name’s cache-once posture, not
term:ambient_summary’s per-turn refresh. Renumbered from an
earlier v27 — merged alongside the Global Bundle system-tier PR
(#2782), which independently claimed v27 for an unrelated
column (same collision class as this file’s own v20→v22 and
v24→v25 history, see those entries above). See
docs/reports/REPORT_AGENT_PICKER_FIELD_ORDER_SORT_AND_DATA_GAPS_AUDIT_2026_08_24.md §5a.
v29 — db_agents.session_id / status / started_at / ended_at: the
agent’s LATEST launch state, the four db_agent_instances
columns the consolidated row never got (Phase 3a deliberately
left them “on the block”, but the recent-sessions picker, the
pane close/reopen continuity write-back and the status-filtered
instance list all kept reading them from the legacy table — the
reason it could not be dropped). One row per agent ⇒ one launch
state per agent; a continuation moves it to the new block/session.
Backfilled from the legacy rows by
m0025_agents_launch_state_backfill (latest instance per
projection key), kept current by the instance dual-write, and
the read flip in SPEC_AGENT_ARCHITECTURE_2026_05_27.md Phase
3b retires the legacy reads on top of it. No unique index on
db_agents(slug) is added: template-launch projections copy
their template’s slug, so uniqueness stays a definition-level
rule enforced by the slug collision scan in agent_def_insert.
v30 — db_agent_content / db_agent_skills / db_agent_history /
db_agent_identity_links / db_agent_skills_ref /
db_agent_mcp_ref: agent_id‘s foreign key now targets
db_agents(id) instead of db_agent_definitions(id). Every
existing row already satisfies the new target (its agent_id is
a definition id, and every definition has a db_agents mirror
at the same id) — what changes is that a db_agents row with NO
definition counterpart (a template launch) can now hold these
directly too, closing the gap listrecentsessions’ template
fallback (Phase 3b, #3080) exists for. SQLite has no in-place FK
redefinition, so an existing store needs its six tables rebuilt;
m0028_agent_child_tables_repoint_fk does that (rename,
recreate, copy, drop, PRAGMA foreign_key_check before commit).
A fresh install gets the new FK directly from the CREATE TABLE
statements below — nothing to rebuild there. Phase 3c
(SPEC_AGENT_ARCHITECTURE_2026_05_27.md).
v31 — No DDL change. Every agent_def_* write now lands on
db_agents only — db_agent_definitions is no longer kept in
sync (Phase 3d, #3092). Bumped anyway (codex P1 on #3092):
check_schema_compat is a downgrade guard as much as a schema
guard, and this release changes what a NEWER binary’s writes
mean to an OLDER one just as much as a column would. Without the
bump, rolling back to the immediately preceding binary after
this version has run would silently accept a store where new
agents exist only in db_agents — that binary’s agent_def_get/
update/delete still target db_agent_definitions and would
404 on them, or replay stale legacy values back into db_agents
on edit. Stamping 31 makes that downgrade refuse to open instead.
v32 — db_agent_definitions and db_agent_instances are dropped.
Nothing has read or written either table since v31 (agent-concept
consolidation’s definition and instance flips, #3080/#3092); this
is the final phase (Phase 3e,
SPEC_AGENT_ARCHITECTURE_2026_05_27.md) closing out the tracking
spec. db_agent_instances’ CREATE TABLE/indexes and
db_agent_definitions’ CREATE TABLE are gone from this function
— leaving either would silently recreate the tables (empty) on
the very next Store::open() after the drop migration runs,
since migrations execute before this function does on every
boot. db_agent_definitions’ own ALTER TABLE ADD COLUMN
entries, by contrast, are KEPT — gated on the table still
existing (see that block’s own comment below) — because several
pending migrations (m0007, m0025, m0026, m0028) call
Store::open() internally, running this function, before m0029
(numbered last) ever drops the table in the SAME upgrade pass; a
store old enough to be missing one of those columns would fail
those migrations’ own reads with “no such column” otherwise
(Codex P1 on #3096). An existing store’s tables are actually
removed by m0029_drop_legacy_agent_tables; a fresh install
never has them to begin with, so the gate is a no-op for it.
adopt_legacy_table_names’s
db_forge_agents → db_agent_definitions rename entry is left
in place deliberately: an install old enough to still carry
db_forge_agents reaches it during an EARLIER migration’s own
Store::open() call (every migration in this chain lays down
schema that way), so the rename still fires before
m0029 runs later in the same upgrade pass and correctly drops
what the rename just produced — no special-casing needed, and no
data is stranded under the old name.
v33 — db_agent_project_instructions: what each agent was last observed
to read as project instructions from its working directory, keyed
(agent_id, path). Phase 3 of
SPEC_INSTRUCTION_AND_MEMORY_PORTABILITY_2026_09_09.md.
Records a content hash and an observation time, never the content:
this is a tracking table, not a mirror. The distinction from
`db_agent_native_memory` above is deliberate — that one stores
content because it is a durable copy of files AgentMux may have to
serve when the originals are unreachable, whereas these files
belong to the repository, are always readable from it, and are
never written by AgentMux. Storing their content would create a
second copy of somebody else's file with no one to keep it honest.
Purely additive: nothing reads it at launch, and an agent with no
row simply has no prior observation to compare against.v34 — db_agent_skills_ref / db_agent_mcp_ref / db_bundle_skills_ref
/ db_bundle_mcp_ref drop their skill_id/mcp_id FK to this
store’s LOCAL db_skills/db_mcp_servers. Phase 2 of
SPEC_DURABLE_BINDINGS_2026_09_10.md §5.4 (Codex P1, PR #3182):
once catalog writes redirect to identity_store, this channel’s
local catalog copies stop gaining new rows, so binding a
post-redirect skill/server would otherwise hit a hard FOREIGN KEY constraint failed (PRAGMA foreign_keys=ON in production, see
Store::configure_and_migrate). The agent_id → db_agents FK on
the agent-level pair is kept verbatim — only the catalog-pointing
FK is dropped. Same shape db_bundle_skills_ref/db_bundle_mcp_ref
already used for db_bundles (see those tables’ own doc comment
below): existence moves to the application layer
(managed_bind_agent/managed_bind_bundle’s new catalog: &Store
check). SQLite has no ALTER TABLE ... DROP CONSTRAINT, so an
existing store’s four tables are rebuilt by
m0032_drop_catalog_fk_from_ref_tables; a fresh install gets the
trimmed FK directly from the CREATE TABLE statements below.
v35 — db_bundle_versions: append-only version history for Global
Memory entry content (name + instructions), one row per
write through the new agent-facing Global Memory API
(docs/specs/SPEC_AGENT_FACING_GLOBAL_MEMORY_API_2026_09_15.md
Phase 0) — mirrors db_agent_native_memory_versions’s shape
exactly, keyed by a single bundle_id instead of that table’s
composite (agent_id, filename), since a Bundle’s identity is
already a single id. Global Memory (db_bundles) previously had
no audit trail at all — only updated_at, no way to see what
changed, when, or by which agent, unlike native memory which has
had this since v24. Opened specifically because Global Memory is
about to gain a write path an agent (not just a human at the
Armory UI) can reach. written_by is a TRUSTED identity column
(an agent’s real AGENTMUX_AGENT_ID, or "armory-ui"),
deliberately separate from the caller-describable source/
source_detail pair — an agent could otherwise claim
source: "human" with nothing to contradict it (codex P2, PR
#3237, caught before this table ever shipped).
v36 — db_agent_wan_keys: per-agent Ed25519 keypair for general
agent-to-agent WAN-tier jekt signing (issue #2586’s second half).
Mirrors v20’s shape; a SEPARATE keypair from db_agent_lan_keys by
design, not a reuse — LAN public keys are permanently TOFU-pinned
by peers (v21), which is why they cannot rotate
(SPEC_JEKT_HOST_KEY_TTL_ROTATION_2026_09_14.md §4), whereas WAN
keys are served from muxbus’s authoritative ownership registry and
are meant to. One key cannot have both lifecycles. key_version
is reserved for the publish-sync and rotation phases (that spec’s
§3.2/§3.6) and is not yet read by anything.
v37 — db_agent_tokens: per-agent local identity token, keyed by the
agent’s UID (db_agents.id) — identity M1 of
SPEC_AGENT_IDENTITY_CARRIED_NOT_DERIVED_2026_09_23.md (§6, §9.1).
Minted on first spawn (agent_token_ensure), injected into that
one agent’s process env as AGENTMUX_AGENT_TOKEN, revoked on
delete via purge_agent_dependents. Unlike v18’s jekt key and the
registry entry files, which are keyed by display name and so are
shared by two same-named agents (spec §6.3), this is keyed by a
PRIMARY KEY that is a UUID for every non-template row. Not read
by anything until M4 — mint-and-carry only, revertible by ignoring
the field. See storage/agent_tokens.rs.
v38 — db_agent_key_tombstones: the lowercased names (slug, display
name, instance name) of every deleted agent — identity M4a of
SPEC_AGENT_IDENTITY_CARRIED_NOT_DERIVED_2026_09_23.md §6.5.4.
Signing keys are keyed by name, so a later agent that takes a
deleted agent’s name would inherit its keys; M4d copies name-keyed
keys to UIDs and must never copy a tombstoned name’s. Written from
M4a on, before any copy exists, so the record is complete when M4d
reads it. Written only — nothing reads it until M4d.
v39 — db_bundle_versions.written_by_uid: the writer’s UID beside the
written_by name, taken from the request’s Caller (its
X-Agent-Token), never from a body field; empty for an
Unattributed write, the Armory UI and the seeders. Dual-written,
not yet read. Not only parity with the shared store: when that
store is unavailable id_store falls back to this one and writes
here. Identity M4c-1 of
SPEC_AGENT_IDENTITY_CARRIED_NOT_DERIVED_2026_09_23.md §6.5.9.
v40 — db_jekt_held: a jekt to a known agent of this channel that no
delivery tier could take (the agent was not running anywhere), held
for up to 24 h and replayed when it registers, with the trust
verdicts it was accepted with as explicit columns.
SPEC_DURABLE_JEKT_DELIVERY_2026_09_24.md Phase 1.
v41 — db_background_tasks.owner_tool_use_id: the tool_use_id of the
Agent call whose subagent launched this background task (the
parent_tool_use_id on the stream line that issued the Bash call);
NULL for the agent’s own tasks. Joins a task to its subagent, whose
meta.json records the same id. Phase 2 of
SPEC_BACKGROUND_TASK_STRUCTURED_FEED_AND_SWARM_OWNERSHIP_2026_09_27.md.
v42 — db_agents.last_runtime: the Runtime menu choices (permission mode,
model, effort) the user last made for this agent, as a JSON object,
‘’ when none. Lets Continue / Reattach / a fresh open start where
the user left off instead of on the definition’s defaults. Written
only when the user picked something. Item 2 of
SPEC_RUNTIME_MENU_REMAINING_GAPS_2026_10_01.md.
v43 — db_viewer_devices: the devices paired with this channel’s viewer
listener, each with the SHA-256 of its viewer token (never the
token), its name, its optional public key and when it was paired
and last seen; plus db_agents.hide_from_devices, an agent’s opt-out
from the viewer routes. agentmux-mobile’s
SPEC_AGENT_STATUS_AND_LIVE_PANE_FEED_2026_10_07 §13.2, §4.3. See
storage/viewer_devices.rs.
v44 — db_mcp_server_reach: per catalog MCP server, whether it reaches
every agent (all_agents) and whether container agents get it
too (in_containers). A table of its own beside db_mcp_servers,
so nothing that copies catalog rows changes. Both default 0: a
catalog server reaches only the agents it is bound to.
SPEC_CONNECTORS_MCP_WHAT_AGENTS_RUN_2026_10_10.md §2.1.