Authoring for people and agents

How do the graph editor, the Frame designer, the in-app prompt panel and later CLI/MCP adapters change a Toy without bypassing one another? Every author, human or model, goes throu

How do the graph editor, the Frame designer, the in-app prompt panel and later CLI/MCP adapters change a Toy without bypassing one another? Every author, human or model, goes through packages/authoring: the same node catalog, the same structured operations, the same revision checks. No model-specific JSON becomes the stored Toy representation.

Status: implemented locally — typed operations and history, manual candidate JSON, optional server-side Claude text generation, compilation, audition, acceptance and Undo. Richer domain-level explanations, durable server history, serialized inverse operations and an MCP adapter remain planned. Evidence: recorded live Claude proposal journey and implementation status.

Proposal lifecycle#

A user asks for a complete Toy, a node group, or a Frame that controls existing parameters. The agent inspects a bounded selection, the current revision, public interfaces, available nodes, target limits and relevant examples. It returns an ordinary candidate operation batch, a concise explanation, requested capabilities and validation diagnostics. Acceptance and publication stay separate actions.

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#FAFAF7', 'primaryTextColor': '#1C1C1B', 'primaryBorderColor': '#1C1C1B', 'lineColor': '#64645F', 'actorBkg': '#DCEBDD', 'actorBorder': '#1C1C1B', 'signalColor': '#1C1C1B', 'noteBkgColor': '#DED8F0', 'noteBorderColor': '#1C1C1B', 'fontFamily': 'DM Sans, Inter, system-ui, sans-serif'}}}%%
sequenceDiagram
  participant User
  participant App as Editor / prompt panel
  participant Agent as Agent adapter (API)
  participant Authoring as packages/authoring
  participant Host as Runtime host

  User->>App: prompt or manual candidate JSON
  App->>Agent: bounded selection, revision, catalog, limits
  Agent-->>App: candidate operation batch + explanation + diagnostics
  App->>Authoring: validate against base revision
  Note over App: before/after source diff, separate from the model's explanation
  App->>Host: optional bounded audition in a separate generation
  User->>App: accept
  App->>Authoring: atomic revision with inverse operations
  Authoring-->>App: new revision, Undo entry
  App->>Host: prepare new runtime generation
  Note over Host: failure leaves the current sound running
  User->>App: publish (separate authorized action, release checks)
RuleConsequence
A stale expected revision is a conflictThe candidate is rejected and must be regenerated against the latest
Acceptance writes one atomic revision with inverse operationsOne Undo removes the whole proposal
Activation prepares a new runtime generation separately from acceptanceAccepted source and the running sound are distinct states
Failed compilation or cancelled inference never overwrites accepted sourceThe current sound is never interrupted by a bad proposal
A proposal can be schema-valid and musically badTechnical checks and listening judgment stay separate
Imported notes, asset text and documentation are untrusted contextThey cannot override application or user authorization

Data design for models#

The portable model is designed so an agent can edit it without ingesting the whole project.

PrincipleIn the Toy format
Descriptive stable IDs and keyed maps, not index referencesnodes, connections, parameters, frames are keyed objects
Explicit endpointsConnections carry from and to objects with node and port
Self-describing controlsPublic parameters carry units, ranges, defaults, smoothing and named targets
Presentation binds to identityFrames bind parameter IDs, never pixel positions or runtime-generated names
Small files, inspectable partsA definition or selection can be discovered and inspected on its own
Catalog as documentationDescriptions, typed ports, parameter domains, examples, capability needs, versions, target support
Diagnostics with addressesError codes and authored paths
Extension data preserved, not executedNamespaced extension data survives round trips but confers no execution authority

Authoring API responsibilities#

Method groupPurpose
discover, inspectCatalog and selection context for people and models
create candidate, validate, diffBuild and check a proposal without touching accepted source
prepare / render audition, compareHear or see a candidate in an isolated generation
accept, undoCommit one atomic revision; reverse it
save, request publicationPersist a draft; start the separate release path

Operations carry actor and provenance, base revision, idempotency key, affected object IDs and the declared target profile. Store concise intent and observable artifacts; private model reasoning is not required. Revisions are server-ordered and sequential, with isolated candidate branches. Offline/local editing keeps a local history and reconciles explicitly; concurrent multi-user CRDT editing is deferred (the current collaboration subset is in community). The full envelope is in the operation contract.

Service boundaries#

The AI integration lives in the API/worker layer behind authoring permissions and per-job budgets. Provider credentials stay server-side. Users choose whether private source and assets may leave their device and which service receives them. Cancellation propagates through model and render jobs; budgets bound tokens, duration, asset uploads and retry count. Provider choice never affects local playback or recall. The app works without the agent service.

New Toy recipes#

The New Toy chooser's AI-first flow (v0.0.4 plan) uses the same proposal path. A recipe from @tunetoys/recipes fixes the form, the starter base, the effort level and a guidance paragraph; the form compiles to a small brief, and the browser applies the returned batch to its own copy of the shared base from @tunetoys/discovery before the person presses Create. The request is one cached system block (rules plus the compact catalog), one base-Toy block cached for official bases, and the brief, so a generation costs the brief plus output; one corrective turn reuses the prefix. Usage is metered per run and generation is bounded by per-address brakes, a rolling account allowance and a deployment ceiling (HTTP contract). The recipe forms and result step in the browser are planned.

Current review experience#

Before acceptance the browser shows actual source-property before/after values, separately from the model's explanation. The diff is bounded to 500 changes with explicit truncation and expandable full values. It is a structural source diff, not a semantic explanation.

High-level agent text, control and nested-Frame actions preserve unstated appearance, layer metadata and responsive constraints when updating an existing widget of the same kind. New widgets and kind changes use replacement semantics. The emitted canonical widget.put is still a complete replacement, so every write passes the same source validator and revision boundary.

Implementation#

Edit this page on GitHub

esc

↑ ↓ move↩ open⌘↩ new tabesc close