Appearance
Agent Versioning
Status: accepted + shipped (2026-07-13) · Full ADR archived at .indusk/planning/archive/agent-versioning/adr.md
Decision
A hosted agent is one stable identity per owner (hosted_agents.id, get-or-create, a unique owner_user_id index) that carries immutable snapshots in a new agent_versions table holding two spaces:
- Versions — a single linear retained pathway (
v1 → v2 → v3 …, append-only, every version archived-not-deleted). Revert re-deploys any prior version by moving a pointer; it does not rewrite history (a later commit still appends forward). - Drafts — a separate creator-named, forkable experiment space. Committing a draft appends it as the next version.
A version freezes decision-shaping fields only — strategy / model / fallback_model / skill / agent_skills. Identity fields (name / avatar / subtitle) stay mutable and unversioned.
Load-bearing rules
- Only the published version is seatable at real games. It's bound into
AgentDeploymentat the single/seatsnapshot point; drafts are rejected at the real-table gate. Concurrent seats all run the same published version (no mid-game drift). - Off-every-table lock is pointer-scoped. An agent seated at any table cannot publish or revert until off every table (those move the pointer new seats bind). Drafts + identity stay editable while seated — they never affect live play. Enforced at the route and inside the publish/revert transaction under a per-agent advisory lock the seat-claim path also takes (closes the publish-vs-seat TOCTOU).
- Every decision record is version-attributable.
agent_version_idis stamped onagent_inference_charges,agent_call_records,decision_observations, andhosted_agent_seats. - One agent per owner retires the roster. Every "pick which agent" affordance (seat/tournament/copilot) collapses to auto-pick the single agent.
- Fingerprint, dormant anchor. Publishing mints a
version_hash(keccak of the canonical frozen bytes) + dormantanchored_at/anchor_txcolumns. The real encrypt/anchor is deferred toagent-version-onchain-anchor.
Key tradeoffs accepted
- Publish snapshots the draft in place (draft row →
published) rather than minting a new agent row — keeps everyagent_idFK / history stable (a publish-mints-new-agent design fragments them). - Storage migration is a reader-migration. Phase 6 dropped the legacy decision columns from
hosted_agents;getHostedAgent/listHostedAgentsByUsernow LEFT JOIN the published version and alias the fields back onto the same names, so the play-path readers were untouched. - Destructive pre-launch dev reset — multi-agent test data was wiped to one-per-owner (backfilled a v1 per agent); no graceful multi-agent conversion.
Blocks agent-decision-inspection (needs version tags + the draft/commit fix-loop) and agent-training-sandbox (drafts are its test substrate).