Artifacts are structured outputs produced during a workflow run — documents, reports, charts, spreadsheets, email drafts, and more. They attach to the run and are visible to human reviewers when they evaluate Decisions.
A well-designed plugin doesn’t just route approvals — it produces the materials the reviewer needs to make a good decision. An ai_assess step that generates a formatted compliance report as an artifact means the reviewer sees the full analysis right there in the Decision Queue, not just a notification.
How artifacts are produced
The LLM produces artifacts using a special XML tag in its response:
<artifact name="Compliance Assessment" type="report">
## Subcontractor Compliance Report
**Company:** Acme Contractors
**Trade:** Electrical
**Assessment Date:** March 10, 2026
### Findings
The application is missing the following required documents:
- Certificate of Insurance (expired)
- State electrical license (not provided)
### Recommendation
Do not approve until insurance and license documentation are provided.
</artifact>
CableKnit parses this tag from the LLM’s response and creates an Artifact record automatically. No additional configuration is needed — the LLM just needs to produce the tag in the right format.
Artifact tag format
<artifact name="DISPLAY_NAME" type="TYPE">CONTENT</artifact>
| Attribute | Description |
|---|---|
name |
Display name shown in the UI |
type |
The artifact type (see below) |
blueprint |
Optional slug of an artifact blueprint to validate against |
Content can be Markdown, plain text, JSON, or any structured format depending on the type.
Artifact types
| Type | Use case | Content format |
|---|---|---|
document |
General documents, memos, letters | Markdown or plain text |
report |
Structured analysis reports | Markdown |
email_draft |
Draft emails for human review before sending | Plain text or Markdown |
spreadsheet |
Tabular data | JSON (array of objects) |
csv |
CSV-formatted data | CSV text |
chart |
Chart data for visualization | JSON (see below) |
json_data |
Structured JSON for downstream use | JSON |
schedule |
Scheduling data | JSON |
image |
Image content | File (via ActiveStorage) |
options_selection |
Structured option sets | JSON |
other |
Anything else | Any |
Artifact blueprints
Blueprints are templates that define structured output schemas for specific artifact types. They tell the AI exactly how to format a particular kind of artifact — field structure, validation rules, and default content.
Blueprint files live in the blueprints/ folder of your bundle. Each file is a JSON document at blueprints/{slug}.json. You can ship up to 20 blueprints per plugin.
Blueprint file format
{
"name": "Weekly Report",
"slug": "weekly-report",
"artifact_type": "report",
"description": "Standard weekly operations summary",
"instructions": "Generate a weekly report covering KPIs, incidents, and action items. Use Markdown headers for each section.",
"content_schema": {
"type": "object",
"properties": {
"kpis": { "type": "array" },
"incidents": { "type": "array" },
"action_items": { "type": "array" }
}
},
"default_content": {
"kpis": [],
"incidents": [],
"action_items": []
}
}
Field reference
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Display name |
slug |
string | Yes | Lowercase letters and hyphens only |
artifact_type |
string | Yes | Must match a valid artifact type (see types table above) |
description |
string | No | Internal description |
instructions |
string | No | AI guidance for generating this artifact |
content_schema |
object | No | JSON Schema for validation (max 4KB) |
default_content |
object | No | Default content if none generated |
How blueprints appear to the AI
CableKnit injects blueprint definitions into the AI prompt as XML:
<artifact_blueprints>
<blueprint slug="weekly-report" type="report" name="Weekly Report">
Instructions text here
Schema: { ... }
</blueprint>
</artifact_blueprints>
Referencing a blueprint
When producing an artifact, set the blueprint attribute to the blueprint’s slug:
<artifact name="Ops Summary — Week 11" type="report" blueprint="weekly-report">
...content...
</artifact>
CableKnit validates the content against the blueprint’s content_schema if one is defined.
Chart schema
Artifacts of type chart expect JSON content describing the chart data and layout:
{
"chart_type": "bar",
"title": "Monthly Revenue",
"subtitle": "Q1 2026",
"x_axis": { "key": "month", "label": "Month", "type": "categorical" },
"y_axis": { "key": "revenue", "label": "Revenue ($)", "type": "numeric", "format": "currency" },
"series": [
{
"name": "Revenue",
"color": "#0066FF",
"data": [
{ "x": "January", "y": 45000 },
{ "x": "February", "y": 52000 },
{ "x": "March", "y": 61000 }
]
}
]
}
Chart field reference
| Field | Description |
|---|---|
chart_type |
bar, line, pie, or area |
title |
Chart title |
subtitle |
Optional subtitle |
x_axis.key |
Data key for x values |
x_axis.type |
categorical or temporal |
y_axis.key |
Data key for y values |
y_axis.type |
numeric |
y_axis.format |
number, currency, or percent |
series[].name |
Series label |
series[].color |
Hex color |
series[].data |
Array of { x, y } data points |
Schedule schema
Artifacts of type schedule expect JSON content describing a staffing or shift schedule:
{
"period_start": "2026-03-10",
"period_end": "2026-03-16",
"days": [
{
"date": "2026-03-10",
"day_name": "Monday",
"is_closed": false,
"shifts": {
"morning": {
"time": "6:00-14:00",
"assignments": [
{ "employee_id": "E01", "name": "Jane Smith", "role": "manager", "hours": 8 }
]
},
"afternoon": {
"time": "14:00-22:00",
"assignments": []
},
"evening": {
"time": "22:00-6:00",
"assignments": []
}
}
}
],
"warnings": [
{ "type": "coverage_gap", "severity": "high", "message": "Tuesday evening has no coverage" }
]
}
Schedule field reference
| Field | Description |
|---|---|
period_start / period_end |
Date range (YYYY-MM-DD) |
days[].date |
Date for this day |
days[].day_name |
Day of week |
days[].is_closed |
Whether the location is closed |
days[].shifts |
Object with morning, afternoon, evening keys |
shifts.*.time |
Time range string |
shifts.*.assignments |
Array of employee assignments |
assignments[].employee_id |
Employee identifier |
assignments[].name |
Employee display name |
assignments[].role |
Role for this shift |
assignments[].hours |
Hours assigned |
warnings[].type |
Warning category (e.g. coverage_gap, overtime) |
warnings[].severity |
low, medium, or high |
warnings[].message |
Human-readable warning |
Spreadsheet format
Artifacts of type spreadsheet use JSON content where each object in the array represents one row. Object keys become column headers.
[
{ "Name": "Jane Smith", "Department": "Operations", "Status": "Active" },
{ "Name": "Bob Jones", "Department": "Sales", "Status": "On Leave" }
]
Producing a report
Reports are the most common artifact type. Write Markdown in the artifact content:
<artifact name="Invoice Review Summary" type="report">
## Invoice Review —
**Invoice Number:**
**Amount:** $
**Submitted:**
### AI Assessment
### Recommended Action
</artifact>
Prompt the LLM to produce the artifact in your ai_assess system prompt:
{
"type": "ai_assess",
"system_prompt": "You are reviewing an invoice submission. Extract the key details and produce a structured report.\n\nRespond with JSON containing your assessment fields, followed by an artifact tag containing a formatted Markdown report:\n\n<artifact name=\"Invoice Review\" type=\"report\">\nYour Markdown report here\n</artifact>",
"output_key": "assessment"
}
Producing a JSON artifact
For structured data that will be consumed programmatically or displayed as a chart:
<artifact name="Monthly Compliance Metrics" type="json_data">
{
"total_applications": 47,
"approved": 31,
"rejected": 8,
"pending": 8,
"approval_rate": 0.66,
"common_rejection_reasons": ["missing_insurance", "expired_license", "incomplete_application"]
}
</artifact>
Artifacts and Decisions
Artifacts attach to runs and are visible in the Decision Queue. When a reviewer opens a Decision, they see all artifacts produced during that run — giving them the full context to make an informed decision.
To ensure your artifacts reach the reviewer, produce them in an ai_assess step before the request_decision step:
// Step 1: assess — produces artifact
{
"name": "assess",
"entry_action": {
"type": "ai_assess",
"system_prompt": "Assess this application and produce a compliance report artifact."
}
}
// Step 2: review — reviewer sees the artifact
{
"name": "review",
"entry_action": {
"type": "request_decision",
"title": "Application Review",
"decision_options": [...]
}
}
Artifact versioning
Artifacts support versioning via a parent_artifact_id reference. When the LLM produces a new version of an existing artifact (for example, a revised report after additional information is received), CableKnit tracks the version history. Reviewers can see the latest version and browse previous versions.
Email drafts
The email_draft type is designed for workflows where a human should review and send an email rather than having the system send it automatically:
<artifact name="Vendor Response Draft" type="email_draft">
Subject: Re: Invoice #1234 — Additional Information Required
Dear ,
Thank you for submitting invoice #1234. We have reviewed your submission and require the following additional information before we can process payment:
1. Updated certificate of insurance (current certificate expired on January 15, 2026)
2. Signed W-9 form
Please provide these documents at your earliest convenience.
Best regards,
The Accounts Payable Team
</artifact>
The reviewer sees the draft in their Decision Queue, can edit it, and sends it from within CableKnit.