guide

Agent guideUS

The contract AI agents read at /llms.txt

read / paint

Compact contract for AI agents painting watercolor in a browser the owner can watch. Static and browser-local: no remote paint API, model, account or cloud sync.

The owner gives a subject; this file is the rest of the job: paint one watercolor where the owner can watch, accept a trial only after looking at its actual image, then deliver as in Finish.

Start

  1. Any browser works: the owner's open Emaki tab, a new window, or your own built-in browser. Prefer one the owner can see (not headless), so they can watch the painting form; if you can only run headless, send the owner an image after each stage. Open / or /en/ and wait for document.body.dataset.workspaceReady==="true".
  2. const S=window.emakiStudio; let o=S.observe({includeImage:false}); Require o.writable && !o.busy. One Emaki tab per browser profile can write. If writable is false, another Emaki tab in this browser holds the paper: work in that tab instead, or stop and ask the owner to close it, then reload.
  3. Saved art lives in that browser. If o.marks>0, first await S.execute({op:"snapshot"}). Mutations require the current expectedRevision; after any error re-observe and fix the named cause. Never blindly retry.

First painting

o = S.observe({includeImage:false});
if (o.marks > 0) await S.execute({op:"snapshot"});
o = await S.newDocument({aspectRatio:"3:4", expectedRevision:o.revision});
const scene = S.scene();                         // keep this fixed header
scene.title = "Evening sea";
scene.layers.push({id:"sky", intent:"Pale sky wash, then let it settle", marks:[
  {type:"brush", points:[[.1,.2],[.5,.18],[.9,.2]], width:.08,
   color:"#6f9fd8", opacity:.35, water:.4, duration:1.2,
   pressure:[.6,1,.5]},
  {type:"wait", seconds:5}
]});
const trial = await S.preview(scene,{expectedRevision:o.revision});
// Inspect the actual trial image. Accept only if it serves the aim.
o = await S.accept(trial.candidateId,{expectedRevision:trial.baseRevision});
const files = await S.exportBundle();             // PNG + scene JSON
const movie = await S.exportVideo();              // required process video

preview renders a candidate on the paper without changing accepted art. On archiveWarning, keep the tab open; see recovery. accept adopts the active candidate; undo returns one accepted step. newDocument makes a new sheet, not a resized painting.

Scene essentials

Iterate without resending the full scene

Use stable layer IDs. All operations below create an unaccepted preview:

await S.execute({op:"append_layer", layer:newLayer, expectedRevision:o.revision});
await S.execute({op:"replace_layer", layer:completeReplacement, expectedRevision:o.revision});
await S.execute({op:"remove_layer", layerId:"old-detail", expectedRevision:o.revision});
await S.execute({op:"preview_patch", expectedRevision:o.revision, patch:{
  title:"Refined evening sea",
  replaceLayers:[completeReplacement], appendLayers:[newLayer],
  removeLayerIds:["old-detail"]
}});

Add trialId to patch a saved trial instead of the accepted scene. A patch may change only title, appendLayers, replaceLayers, and removeLayerIds; full validation still applies. Use full S.preview(scene,...) for canvas/material changes or broad rewrites.

For long computation use {op:"submit"} jobs (see workspace.md).

Inspect and decide

Finish and deliver

  1. Export accepted files: await S.exportBundle() returns PNG/JSON artifact metadata and downloads both. S.artifacts() or S.execute({op:"artifacts"}) lists stable re-download URLs for files made during this page session; the same links appear under the paper.
  2. Export the required process video: await S.exportVideo(). It begins with the finished painting for 0.5 s, replays the brush process with layer-intent captions, and ends on the finished painting. It repaints the painting first (minutes on v5), then records in real time; keep the tab visible. For short tool timeouts use S.execute({op:"video",wait:false}), then poll S.observe({includeImage:false}).video.
  3. Give the owner the real PNG, JSON and video plus a short note: aim, main stages, rejected trial/reason, and remaining limitation. Use the owner's language.
  4. Ask whether the owner wants matching Gemini BGM added. Do not make music before explicit approval; if approved, follow video.md.

Load more only when needed