How do I create an artifact extension?
An artifact extension is a named, persistent output. When an agent produces something worth keeping — a code file, a document, an analysis report — it can save it as an artifact so you can retrieve, view, and iterate on it outside the conversation that created it.
When would I use an artifact?
Use an artifact when you want an agent’s output to be a first-class, retrievable object rather than ephemeral chat text. Good candidates:
- Generated code — a script, component, or module the agent wrote
- Documents — a spec, a report, a README draft
- Data exports — a CSV or JSON file extracted from a thread or external source
- Transformed content — a translated document, a reformatted dataset
- Checkpoints — a saved state you can branch from or roll back to
Artifacts are not the right tool for configuration — use a control extension for that. They are not for running code — use a job extension for autonomous execution.
How do I create one by chatting?
Ask Daemion to save something as an artifact during a conversation:
You: Save this code as an artifact
Daemion: I’ll save that as an artifact.
Saved as
typescript-utils— you can retrieve it any time with “show me the typescript-utils artifact” or via the dashboard. Want me to set a MIME type so it renders with syntax highlighting?
You: Yes, TypeScript
Daemion: Updated —
typescript-utilsis now tagged astext/x-typescript. It’ll render with syntax highlighting whenever you open it.
The artifact is stored as an extension record in SQLite immediately.
How do I create one via the API?
The API is the programmatic path — for scripts or agents creating artifacts programmatically. Chat is the primary path during a conversation.
curl -X POST http://localhost:3001/extensions
-H “Authorization: Bearer $DAEMION_TOKEN”
-H “Content-Type: application/json”
-d ’{
“type”: “artifact”,
“name”: “typescript-utils”,
“description”: “Utility functions generated during the refactor session on 2026-03-31.”,
“definition”: {
“mime_type”: “text/x-typescript”,
“content”: “export function clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}”,
“created_in_thread”: “thr_01abc123”
},
“source”: “agent”,
“enabled”: true
}’
The gateway validates the envelope against ExtensionSchema and stores the record. The definition field is open (GenericDefinitionSchema) — include the content and any metadata that helps you retrieve and render it later.
What does the artifact schema look like?
Artifact extensions use the generic definition schema. The top-level envelope (shared across all 12 extension types):
interface Extension { id: string; // e.g. “ext_09def789” — assigned by gateway on creation type: “artifact”; name: string; // unique per type, kebab-case, 1-100 chars description: string; // human-readable, max 500 chars definition: Record<string, unknown>; // artifact content and metadata source: “built-in” | “user” | “agent” | “community”; enabled: boolean; created_at: string; // ISO 8601 updated_at: string; // ISO 8601 }
A typical definition for a code artifact:
// Example definition shape — adapt to your content type interface ArtifactDefinition { mime_type?: string; // e.g. “text/x-typescript”, “text/markdown”, “application/json” content?: string; // the artifact body (for text content) url?: string; // external URL (for binary or large content) created_in_thread?: string; // thread ID where this artifact originated version?: number; // for tracking iterations [key: string]: unknown; }
Frequently asked questions
/extensions with type: "artifact" and source: "agent". The artifact is immediately retrievable by name.GET /extensions?type=artifact to list all artifacts. Fetch a specific one with GET /extensions/:id.version field in the definition and update it with PATCH /extensions/:id, or create a new artifact with a versioned name like typescript-utils-v2.description field is capped at 500 characters, but the definition field (where content lives) has no hard limit beyond SQLite's practical row size. For large binary files, store the content externally and put the URL in definition.url.PATCH /extensions/:id to update fields or DELETE /extensions/:id to remove it. See the Extensions API for the full reference.What can go wrong
400 {"error": "validation failed"} — The envelope failed ExtensionSchema validation. Check that type is exactly "artifact", name is 1-100 characters, and description is under 500 characters.
401 {"error": "unauthorized"} — The Authorization header is missing or the bearer token doesn’t match. The token is in ~/.daemion/.gateway-token. Use $DAEMION_TOKEN in your shell.
403 {"error": "cannot disable essential extensions"} — Essential built-in extensions cannot be disabled.
403 {"error": "cannot delete essential extensions"} — Essential extensions cannot be deleted. Create a new artifact with source: "user" or source: "agent" to customize behavior.
What’s next?
- How do I create an app extension? — full Vite applications, not just content blobs
- How do I create a job extension? — autonomous work units that produce artifacts
- Extensions API — full CRUD reference