Chapter 31

Agents API: Managed Agent Lifecycle Control and Concurrent Agent Orchestration

Chapter 31: Artifacts System: Real-Time Generation and Deployment of Code, Charts, and Web Pages

31.1 What Artifacts Changed

Before Artifacts, when Claude generated code or HTML, it appeared as plain text in the conversation. Users had to manually copy it, paste it into a local editor, and run it themselves. This "output as text" model severely limited Claude's practical utility as a tool.

Artifacts transforms Claude from a "text generator" into a "runnable artifact producer." When Claude generates a React component in Claude.ai, users see it compile and run live in the preview pane โ€” no local environment required. This is a fundamentally different experience.

For developers building products with the Claude API, Artifacts carries an additional implication: the same generation patterns that power Claude.ai's Artifact rendering can be replicated in your own application. You can build products where Claude generates interactive, deployable outputs โ€” dashboards, tools, diagrams โ€” directly within your UI.

31.2 The Six Artifact Types

Type 1: Code Artifacts

Code Artifacts are the foundational type: standalone, runnable code in any programming language.

When to generate:

Appropriate for Code Artifacts:
โœ“ "Write a Python script to read a CSV and generate a statistics report"
โœ“ "Implement an in-order binary tree traversal function"
โœ“ "Write a bash script to automatically back up a MySQL database"

Not appropriate:
โœ— Explaining a concept (no artifact needed)
โœ— Single one-liner code snippets
โœ— Code embedded in explanatory prose

Example โ€” CSV Analysis Script:

import csv
import statistics
from collections import defaultdict

def analyze_csv(filepath: str) -> dict:
    """
    Analyze a CSV file and return column statistics.
    
    Args:
        filepath: Path to the CSV file
    
    Returns:
        Dictionary mapping column names to their statistics
    """
    data = defaultdict(list)
    
    with open(filepath, newline='', encoding='utf-8') as f:
        reader = csv.DictReader(f)
        for row in reader:
            for key, value in row.items():
                try:
                    data[key].append(float(value))
                except ValueError:
                    data[key].append(value)
    
    results = {}
    for col, values in data.items():
        numeric = [v for v in values if isinstance(v, (int, float))]
        if numeric:
            results[col] = {
                "type": "numeric",
                "count": len(numeric),
                "mean": statistics.mean(numeric),
                "median": statistics.median(numeric),
                "stdev": statistics.stdev(numeric) if len(numeric) > 1 else 0,
                "min": min(numeric),
                "max": max(numeric)
            }
        else:
            unique = set(str(v) for v in values)
            results[col] = {
                "type": "categorical",
                "count": len(values),
                "unique": len(unique),
                "most_common": max(unique, key=lambda x: str(values).count(x))
            }
    return results


if __name__ == "__main__":
    import sys
    if len(sys.argv) != 2:
        print("Usage: python analyze.py <csv_file>")
        sys.exit(1)
    for col, stats in analyze_csv(sys.argv[1]).items():
        print(f"\n{col}:")
        for k, v in stats.items():
            print(f"  {k}: {v:.2f}" if isinstance(v, float) else f"  {k}: {v}")

Type 2: SVG Artifacts

SVG Artifacts generate resolution-independent vector graphics that render live in the Claude.ai preview pane.

System architecture diagram example:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 500"
     font-family="Arial, sans-serif" font-size="14">
  <rect width="800" height="500" fill="#f8f9fa" rx="10"/>
  <!-- API Gateway -->
  <rect x="300" y="30" width="200" height="60" rx="8"
        fill="#4285f4" stroke="#2b5dcc" stroke-width="2"/>
  <text x="400" y="55" text-anchor="middle" fill="white" font-weight="bold">
    API Gateway</text>
  <!-- Services, databases, arrows... -->
  <defs>
    <marker id="arrow" markerWidth="10" markerHeight="7"
            refX="9" refY="3.5" orient="auto">
      <polygon points="0 0, 10 3.5, 0 7" fill="#666"/>
    </marker>
  </defs>
</svg>

Type 3: HTML Artifacts

HTML Artifacts generate complete, runnable web pages with full JavaScript interactivity, rendered in an inline browser:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Sales Dashboard</title>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/chart.umd.min.js"></script>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body { font-family: -apple-system, sans-serif; background: #f0f2f5; padding: 24px; }
        .cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-bottom: 24px; }
        .card { background: white; border-radius: 12px; padding: 20px;
                box-shadow: 0 2px 8px rgba(0,0,0,0.08); }
        .card-value { font-size: 32px; font-weight: 700; }
        .card-label { color: #666; font-size: 14px; margin-top: 4px; }
        .up { color: #52c41a; font-size: 13px; } .down { color: #ff4d4f; font-size: 13px; }
        .chart-box { background: white; border-radius: 12px; padding: 24px;
                     box-shadow: 0 2px 8px rgba(0,0,0,0.08); }
    </style>
</head>
<body>
    <h1 style="margin-bottom:24px;color:#1a1a2e">Monthly Sales Dashboard</h1>
    <div class="cards">
        <div class="card">
            <div class="card-value">$231,800</div>
            <div class="card-label">Monthly GMV</div>
            <div class="up">โ†‘ 12.3% vs last month</div>
        </div>
        <div class="card">
            <div class="card-value">4,821</div>
            <div class="card-label">Orders</div>
            <div class="up">โ†‘ 8.7% vs last month</div>
        </div>
        <div class="card">
            <div class="card-value">$48.0</div>
            <div class="card-label">Avg. Order Value</div>
            <div class="down">โ†“ 3.2% vs last month</div>
        </div>
    </div>
    <div class="chart-box">
        <canvas id="chart"></canvas>
    </div>
    <script>
        new Chart(document.getElementById('chart'), {
            type: 'bar',
            data: {
                labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
                datasets: [{
                    label: 'GMV ($K)',
                    data: [185, 172, 198, 215, 206, 231.8],
                    backgroundColor: 'rgba(66, 133, 244, 0.8)',
                    borderRadius: 6
                }]
            },
            options: { responsive: true, scales: { y: { min: 150 } } }
        });
    </script>
</body>
</html>

Type 4: React Artifacts

React Artifacts are the most powerful type โ€” compiled and executed live in the browser:

import { useState } from "react";

const PRIORITIES = ["High", "Medium", "Low"];
const COLORS = {
  High: "bg-red-100 text-red-700",
  Medium: "bg-yellow-100 text-yellow-700",
  Low: "bg-green-100 text-green-700"
};

export default function TaskManager() {
  const [tasks, setTasks] = useState([
    { id: 1, title: "Complete API documentation", priority: "High", done: false },
    { id: 2, title: "Review PR #234", priority: "Medium", done: false },
    { id: 3, title: "Update dependencies", priority: "Low", done: true },
  ]);
  const [newTitle, setNewTitle] = useState("");
  const [priority, setPriority] = useState("Medium");

  const add = () => {
    if (!newTitle.trim()) return;
    setTasks(p => [...p, { id: Date.now(), title: newTitle.trim(), priority, done: false }]);
    setNewTitle("");
  };

  const toggle = id => setTasks(p => p.map(t => t.id === id ? {...t, done: !t.done} : t));
  const remove = id => setTasks(p => p.filter(t => t.id !== id));

  const pending = tasks.filter(t => !t.done);
  const done = tasks.filter(t => t.done);

  return (
    <div className="max-w-lg mx-auto p-6">
      <h1 className="text-2xl font-bold text-gray-800 mb-6">Task Manager</h1>
      <div className="flex gap-2 mb-6">
        <input className="flex-1 border border-gray-300 rounded-lg px-3 py-2 text-sm"
               placeholder="New task..." value={newTitle}
               onChange={e => setNewTitle(e.target.value)}
               onKeyDown={e => e.key === "Enter" && add()} />
        <select className="border border-gray-300 rounded-lg px-3 py-2 text-sm"
                value={priority} onChange={e => setPriority(e.target.value)}>
          {PRIORITIES.map(p => <option key={p}>{p}</option>)}
        </select>
        <button onClick={add}
                className="bg-blue-500 text-white px-4 py-2 rounded-lg text-sm hover:bg-blue-600">
          Add
        </button>
      </div>
      <h2 className="text-sm font-semibold text-gray-500 mb-2">Pending ({pending.length})</h2>
      {pending.map(t => (
        <div key={t.id} className="flex items-center gap-3 p-3 bg-white border border-gray-200 rounded-lg mb-2">
          <input type="checkbox" onChange={() => toggle(t.id)} className="w-4 h-4 cursor-pointer" />
          <span className="flex-1 text-sm">{t.title}</span>
          <span className={`text-xs px-2 py-1 rounded-full ${COLORS[t.priority]}`}>{t.priority}</span>
          <button onClick={() => remove(t.id)} className="text-gray-400 hover:text-red-500">ร—</button>
        </div>
      ))}
      {done.length > 0 && (
        <>
          <h2 className="text-sm font-semibold text-gray-400 mt-4 mb-2">Done ({done.length})</h2>
          {done.map(t => (
            <div key={t.id} className="flex items-center gap-3 p-3 bg-gray-50 rounded-lg mb-2 opacity-60">
              <input type="checkbox" checked readOnly className="w-4 h-4" />
              <span className="flex-1 text-sm text-gray-500 line-through">{t.title}</span>
              <button onClick={() => remove(t.id)} className="text-gray-300 hover:text-red-500">ร—</button>
            </div>
          ))}
        </>
      )}
    </div>
  );
}

Type 5: Mermaid Artifacts

Mermaid Artifacts render technical diagrams without any design tools:

sequenceDiagram
    autonumber
    actor User
    participant FE as Frontend
    participant GW as API Gateway
    participant Auth as Auth Service
    participant Order as Order Service
    participant DB as Database

    User->>FE: Submit order
    FE->>GW: POST /api/orders (Bearer token)
    GW->>Auth: Validate JWT
    Auth-->>GW: Valid, user_id=123
    GW->>Order: Create order (user_id=123)
    Order->>DB: INSERT INTO orders...
    DB-->>Order: order_id=456
    Order-->>GW: 201 Created {order_id: 456}
    GW-->>FE: 201 Created {order_id: 456}
    FE-->>User: Order #456 created successfully

Type 6: Markdown Artifacts

Markdown Artifacts produce standalone documents that can be exported and used in other systems โ€” distinct from conversational text in that they have their own identity, version history, and can be downloaded directly.

31.3 Generating Artifacts via API

The same patterns that power Claude.ai's Artifact rendering work through the standard Messages API:

import anthropic
import re

def generate_artifact(prompt: str, artifact_type: str = "react") -> dict:
    """Generate an artifact via the Claude API"""
    client = anthropic.Anthropic()

    type_instructions = {
        "react": """Generate a complete React component.
Requirements:
- Functional component with Hooks
- Tailwind CSS for styling
- May import from 'recharts' for charts
- Default export
- Self-contained (no external file dependencies)
Wrap output in ```react code block""",

        "html": """Generate a complete HTML page.
Requirements:
- Full HTML5 document structure
- CSS in <style> tags, JS in <script> tags
- May use CDN-hosted libraries
Wrap output in ```html code block""",

        "svg": """Generate an SVG graphic.
Requirements:
- Complete <svg> element with viewBox
- Professional, clear, appropriately dense
Wrap output in ```svg code block""",

        "mermaid": "Generate a Mermaid diagram. Wrap in ```mermaid code block",
        "python": "Generate complete runnable Python code. Wrap in ```python code block",
    }

    instruction = type_instructions.get(artifact_type, f"Generate {artifact_type} code")

    response = client.messages.create(
        model="claude-opus-4-5",
        max_tokens=4096,
        system=f"You are a professional code generation assistant.\n{instruction}\nOutput only the artifact, no explanations.",
        messages=[{"role": "user", "content": prompt}]
    )

    raw = response.content[0].text
    pattern = rf"```{re.escape(artifact_type)}\n(.*?)```"
    match = re.search(pattern, raw, re.DOTALL)

    if not match:
        match = re.search(r"```\w*\n(.*?)```", raw, re.DOTALL)

    return {
        "type": artifact_type,
        "content": match.group(1).strip() if match else raw,
        "raw": raw
    }


# Example usage
result = generate_artifact(
    "Create a bar chart component showing monthly sales trends using recharts",
    artifact_type="react"
)
print(result["content"][:400])

31.4 Multi-Turn Artifact Iteration

Users typically need multiple rounds of refinement. Build an iterator that preserves context:

class ArtifactIterator:
    """Context-preserving multi-turn artifact editor"""

    def __init__(self, artifact_type: str = "react"):
        self.client = anthropic.Anthropic()
        self.artifact_type = artifact_type
        self.messages = []
        self.current = None
        self.history = []

    def create(self, prompt: str) -> str:
        self.messages.append({"role": "user", "content": prompt})
        resp = self._call()
        self._save(resp)
        return self.current

    def modify(self, request: str) -> str:
        self.messages.append({
            "role": "user",
            "content": f"Modify the current {self.artifact_type}: {request}"
        })
        resp = self._call()
        self._save(resp)
        return self.current

    def revert(self, steps_back: int = 1) -> str:
        idx = -(steps_back + 1)
        if abs(idx) <= len(self.history):
            self.current = self.history[idx]
        return self.current

    def _call(self) -> str:
        instructions = {
            "react": "Generate React component with Tailwind CSS, wrap in ```react",
            "html": "Generate complete HTML page, wrap in ```html",
            "mermaid": "Generate Mermaid diagram, wrap in ```mermaid",
        }
        system = instructions.get(self.artifact_type, f"Generate {self.artifact_type} code")
        response = self.client.messages.create(
            model="claude-opus-4-5", max_tokens=4096,
            system=system, messages=self.messages
        )
        text = response.content[0].text
        self.messages.append({"role": "assistant", "content": text})
        return text

    def _save(self, text: str):
        pattern = rf"```{re.escape(self.artifact_type)}\n(.*?)```"
        match = re.search(pattern, text, re.DOTALL)
        if match:
            self.current = match.group(1).strip()
            self.history.append(self.current)


# Usage
iterator = ArtifactIterator("react")
v1 = iterator.create("Create a simple counter with increment and decrement buttons")
v2 = iterator.modify("Add a reset button that sets counter back to zero")
v3 = iterator.modify("Change the background to light blue, make buttons circular")
v2_restored = iterator.revert(steps_back=1)  # Go back to v2

31.5 Embedding Artifact Rendering in Your Product

# Backend: parse artifact type and content from Claude response
def parse_artifact(text: str) -> dict:
    type_patterns = {
        "react": r"```react\n(.*?)```",
        "html": r"```html\n(.*?)```",
        "svg": r"```svg\n(.*?)```",
        "mermaid": r"```mermaid\n(.*?)```",
        "python": r"```python\n(.*?)```",
    }
    for atype, pattern in type_patterns.items():
        m = re.search(pattern, text, re.DOTALL)
        if m:
            return {"has_artifact": True, "type": atype,
                    "content": m.group(1).strip(),
                    "prose": text[:m.start()].strip()}
    return {"has_artifact": False, "content": text}
// Frontend: render the appropriate component for each artifact type
function ArtifactRenderer({ artifact }) {
  if (!artifact.has_artifact) return <ChatMessage text={artifact.content} />;

  switch (artifact.type) {
    case 'html':
      return (
        <iframe srcDoc={artifact.content}
                sandbox="allow-scripts allow-same-origin"
                className="w-full h-96 border rounded-lg" />
      );
    case 'mermaid':
      return <MermaidDiagram code={artifact.content} />;
    case 'react':
      return <ReactSandbox code={artifact.content} />;
    case 'svg':
      return <div dangerouslySetInnerHTML={{ __html: artifact.content }} />;
    default:
      return <CodeBlock language={artifact.type} code={artifact.content} />;
  }
}

Summary

The Artifacts system is the feature that most clearly demonstrates Claude's evolution from language model to interactive tool builder. Each type has a distinct role:

All of these patterns work through the standard Messages API, enabling any developer to embed Artifact generation capabilities in their own products. The iteration pattern โ€” multi-turn conversation with context preservation and version history โ€” is the key engineering pattern for building production Artifact-generation features.

The next and final chapter of this part examines Claude.ai API integration: how to extend Managed Agent capabilities through official interfaces and enterprise-grade API access patterns.

Rate this chapter
4.6  / 5  (3 ratings)

๐Ÿ’ฌ Comments