Overview
gizzi-code gives every model three built-in tools for Artifacts v2: one account-level store of typed artifacts (docs, decks, sheets, designs, dashboards, motion, pages, cards, diagrams, images and code files) that Desktop, ai.allternit.com, the phone layout, the m.allternit.com PWA, cloud computers and gizzi all read and write. The tools behave the same for every model and provider. Any CLI agent that runs inside a gizzi session gets them too, through the session’sallternit MCP bridge.
The app renders every
artifact_* tool part in the transcript as an artifact card that opens the artifact beside the chat (full screen on phones).
When the model creates an artifact
The tool descriptions carry the rule from the contract:- Create an artifact when the content is substantial (about 15 lines or more), self-contained, and likely to be edited or reused, or when the user asked for one (“make this an artifact”, or an Output kind such as Docs or Slides was picked in the composer).
- Otherwise answer inline. Short snippets and interactive cards stay in the chat.
- Revise with
artifact_updateon the same id; don’t create a second artifact for a revision.
Kinds and body formats
body_format is optional on create. When it is left out, gizzi infers it from the kind and the body (for example, a doc whose body is JSON gets the doc JSON format, otherwise Markdown).
The JSON and OpenUI formats (docs, sheets, slides, designs, dashboards, motion, cards) are described to the model by the app’s system prompt; the tool descriptions point the model there. gizzi refuses a format that doesn’t belong to the kind and a
+json body that isn’t valid JSON, with an error the model can act on.
Where artifacts are saved
The tools write to the cloud store,/api/v2/artifacts on allternit-cloud-api (see the Artifacts v2 contract):
artifact_create→POST /api/v2/artifactswith an id gizzi mints itself (art_+ ULID),runtime_version: 2andorigin: {surface: "gizzi", client, session_id, message_id}.artifact_update→POST /api/v2/artifacts/:id/versionswithbase_version,meta.noteandauthor: "assistant".artifact_read→GET /api/v2/artifacts/:id, orGET /api/v2/artifacts/:id/versions/:vfor a specific version.
ALLTERNIT_API_KEY, ALLTERNIT_API_TOKEN, then the device token from gizzi login / gizzi pair. The token needs the compute scope.
Base URL: ALLTERNIT_CLOUD_API_URL, else GIZZI_PLATFORM_API_URL, else https://api.allternit.com.
When gizzi can’t reach the store
If there is no credential, the cloud rejects every credential, the route isn’t there, the network fails, or the cloud returns a server error, the tools still succeed:artifact_createreturns the artifact with the id gizzi minted andpersisted: false. The app saves it with an idempotent create under the same id, so a retry never makes a duplicate.artifact_updatereturns versionbase_version + 1withpersisted: falseandbase_version, built on the artifact this session already has in its transcript.artifact_readfalls back to the newest copy in this session’s transcript.
GIZZI_ARTIFACTS_OFFLINE=1 to skip the cloud and always let the app persist. Set GIZZI_DISABLE_ARTIFACT_TOOLS=1 to hide the three tools.
Tool results
Every result’s metadata carriesartifact, which is everything the app needs to render and persist it:
artifact_create and artifact_update leave the body out of the model-visible text; artifact_read shows it, cut at 60,000 characters, while the metadata keeps all of it.
Errors the model sees
Source
- Tools:
cmd/gizzi-code/src/runtime/tools/builtins/artifact.ts(descriptions inartifact-create.txt,artifact-update.txt,artifact-read.txt) - Store client:
cmd/gizzi-code/src/runtime/integrations/artifacts/index.ts - Tests:
cmd/gizzi-code/test/tool/artifact.test.ts