Agents API:托管 Agent 生命周期控制与并发 Agent 编排
第三十一章:Artifacts 系统:代码、图表与网页的实时生成与部署
31.1 Artifacts 改变了什么
在 Artifacts 出现之前,Claude 生成代码或 HTML 的方式是把它们作为纯文本输出在对话框里。用户必须手动复制代码,粘贴到本地编辑器,自己运行。这种"输出即文本"的模式限制了 Claude 作为工具的实用价值。
Artifacts 将 Claude 从"文本生成器"升级为"可运行工件生产者"。 当 Claude 生成一个 React 组件时,用户不需要任何本地环境——它直接在对话界面旁边的预览窗口中编译运行。这是一个根本性的体验飞跃。
对于开发者而言,Artifacts 系统还有更深远的意义:Claude API 支持生成 Artifacts,这意味着可以在自己的产品中嵌入"Claude 生成可运行内容"的能力。
31.2 六种 Artifact 类型详解
类型一:代码(Code)
代码 Artifact 是最基础的类型,适合生成任意编程语言的独立可运行代码。
触发时机:
适合生成代码 Artifact 的请求:
✓ "写一个 Python 脚本,读取 CSV 并生成统计报告"
✓ "实现一个二叉树的中序遍历函数"
✓ "写一个 bash 脚本自动备份 MySQL 数据库"
不适合的请求:
✗ "解释一下什么是递归"(概念解释,不需要 Artifact)
✗ 只需要一两行代码片段的情况
代码 Artifact 的组成:
# 代码 Artifact 示例:CSV 数据分析脚本
import csv
import statistics
from collections import defaultdict
from typing import Dict, List, Tuple
def analyze_csv(filepath: str) -> Dict:
"""
分析 CSV 文件并返回统计信息
Args:
filepath: CSV 文件路径
Returns:
包含列统计信息的字典
"""
data = defaultdict(list)
with open(filepath, newline='', encoding='utf-8') as f:
reader = csv.DictReader(f)
headers = reader.fieldnames or []
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_values = set(str(v) for v in values)
results[col] = {
"type": "categorical",
"count": len(values),
"unique": len(unique_values),
"most_common": max(unique_values, key=lambda x: 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)
results = analyze_csv(sys.argv[1])
for col, stats in results.items():
print(f"\n{col}:")
for key, val in stats.items():
if isinstance(val, float):
print(f" {key}: {val:.2f}")
else:
print(f" {key}: {val}")
类型二:SVG 图形
SVG Artifact 生成矢量图形,在 Claude.ai 界面中实时渲染,支持无损缩放。
典型用途:系统架构图
<!-- SVG Artifact 示例:微服务架构图 -->
<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>
<text x="400" y="75" text-anchor="middle" fill="#cce5ff"
font-size="12">nginx / Kong</text>
<!-- 用户服务 -->
<rect x="100" y="160" width="160" height="60" rx="8"
fill="#34a853" stroke="#1e7e34"/>
<text x="180" y="185" text-anchor="middle" fill="white"
font-weight="bold">User Service</text>
<text x="180" y="205" text-anchor="middle" fill="#c3e6cb"
font-size="12">:8001</text>
<!-- 订单服务 -->
<rect x="320" y="160" width="160" height="60" rx="8"
fill="#34a853" stroke="#1e7e34"/>
<text x="400" y="185" text-anchor="middle" fill="white"
font-weight="bold">Order Service</text>
<text x="400" y="205" text-anchor="middle" fill="#c3e6cb"
font-size="12">:8002</text>
<!-- 支付服务 -->
<rect x="540" y="160" width="160" height="60" rx="8"
fill="#34a853" stroke="#1e7e34"/>
<text x="620" y="185" text-anchor="middle" fill="white"
font-weight="bold">Payment Service</text>
<text x="620" y="205" text-anchor="middle" fill="#c3e6cb"
font-size="12">:8003</text>
<!-- 数据库 -->
<ellipse cx="180" cy="370" rx="70" ry="30"
fill="#ea4335" stroke="#b31412"/>
<rect x="110" y="340" width="140" height="60" fill="#ea4335"/>
<ellipse cx="180" cy="400" rx="70" ry="30"
fill="#ea4335" stroke="#b31412"/>
<text x="180" y="375" text-anchor="middle" fill="white"
font-weight="bold">User DB</text>
<!-- 连接线 -->
<line x1="400" y1="90" x2="180" y2="160"
stroke="#666" stroke-width="2" marker-end="url(#arrow)"/>
<line x1="400" y1="90" x2="400" y2="160"
stroke="#666" stroke-width="2" marker-end="url(#arrow)"/>
<line x1="400" y1="90" x2="620" y2="160"
stroke="#666" stroke-width="2" marker-end="url(#arrow)"/>
<!-- 箭头定义 -->
<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>
类型三:HTML 网页
HTML Artifact 生成完整可运行的网页,在内嵌浏览器中预览,支持 JavaScript 交互。
示例:交互式数据看板
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>销售数据看板</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, BlinkMacSystemFont, 'Segoe UI', sans-serif;
background: #f0f2f5; padding: 24px; }
.dashboard { max-width: 1200px; margin: 0 auto; }
h1 { color: #1a1a2e; margin-bottom: 24px; font-size: 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; color: #1a1a2e; }
.card-label { color: #666; font-size: 14px; margin-top: 4px; }
.card-change { font-size: 13px; margin-top: 8px; }
.up { color: #52c41a; }
.down { color: #ff4d4f; }
.chart-container { background: white; border-radius: 12px;
padding: 24px; box-shadow: 0 2px 8px rgba(0,0,0,0.08); }
</style>
</head>
<body>
<div class="dashboard">
<h1>月度销售数据看板</h1>
<div class="cards">
<div class="card">
<div class="card-value">¥2,318,000</div>
<div class="card-label">本月 GMV</div>
<div class="card-change up">↑ 12.3% vs 上月</div>
</div>
<div class="card">
<div class="card-value">4,821</div>
<div class="card-label">订单数</div>
<div class="card-change up">↑ 8.7% vs 上月</div>
</div>
<div class="card">
<div class="card-value">¥480</div>
<div class="card-label">客单价</div>
<div class="card-change down">↓ 3.2% vs 上月</div>
</div>
</div>
<div class="chart-container">
<canvas id="salesChart"></canvas>
</div>
</div>
<script>
const ctx = document.getElementById('salesChart');
new Chart(ctx, {
type: 'bar',
data: {
labels: ['1月', '2月', '3月', '4月', '5月', '6月'],
datasets: [{
label: 'GMV(万元)',
data: [185, 172, 198, 215, 206, 231.8],
backgroundColor: 'rgba(66, 133, 244, 0.8)',
borderRadius: 6,
}]
},
options: {
responsive: true,
plugins: { legend: { position: 'top' } },
scales: { y: { beginAtZero: false, min: 150 } }
}
});
</script>
</body>
</html>
类型四:React 组件
React Artifact 是 Claude.ai 最强大的 Artifact 类型,在浏览器中实时编译并运行:
// React Artifact 示例:交互式任务管理组件
import { useState } from "react";
const PRIORITIES = ["高", "中", "低"];
const PRIORITY_COLORS = { 高: "bg-red-100 text-red-700", 中: "bg-yellow-100 text-yellow-700", 低: "bg-green-100 text-green-700" };
export default function TaskManager() {
const [tasks, setTasks] = useState([
{ id: 1, title: "完成 API 文档", priority: "高", done: false },
{ id: 2, title: "代码审查:PR #234", priority: "中", done: false },
{ id: 3, title: "更新依赖版本", priority: "低", done: true },
]);
const [newTitle, setNewTitle] = useState("");
const [newPriority, setNewPriority] = useState("中");
const addTask = () => {
if (!newTitle.trim()) return;
setTasks(prev => [...prev, {
id: Date.now(), title: newTitle.trim(),
priority: newPriority, done: false
}]);
setNewTitle("");
};
const toggleDone = (id) => {
setTasks(prev => prev.map(t => t.id === id ? {...t, done: !t.done} : t));
};
const deleteTask = (id) => {
setTasks(prev => prev.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 font-sans">
<h1 className="text-2xl font-bold text-gray-800 mb-6">任务管理</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="新任务标题..."
value={newTitle}
onChange={e => setNewTitle(e.target.value)}
onKeyDown={e => e.key === "Enter" && addTask()}
/>
<select
className="border border-gray-300 rounded-lg px-3 py-2 text-sm"
value={newPriority}
onChange={e => setNewPriority(e.target.value)}
>
{PRIORITIES.map(p => <option key={p}>{p}</option>)}
</select>
<button
onClick={addTask}
className="bg-blue-500 text-white px-4 py-2 rounded-lg text-sm hover:bg-blue-600"
>
添加
</button>
</div>
{/* 待办任务 */}
<div className="mb-4">
<h2 className="text-sm font-semibold text-gray-500 mb-2">
待办 ({pending.length})
</h2>
{pending.map(task => (
<div key={task.id}
className="flex items-center gap-3 p-3 bg-white border border-gray-200 rounded-lg mb-2">
<input type="checkbox" onChange={() => toggleDone(task.id)}
className="w-4 h-4 cursor-pointer" />
<span className="flex-1 text-sm text-gray-800">{task.title}</span>
<span className={`text-xs px-2 py-1 rounded-full ${PRIORITY_COLORS[task.priority]}`}>
{task.priority}
</span>
<button onClick={() => deleteTask(task.id)}
className="text-gray-400 hover:text-red-500 text-lg">×</button>
</div>
))}
</div>
{/* 已完成 */}
{done.length > 0 && (
<div>
<h2 className="text-sm font-semibold text-gray-400 mb-2">
已完成 ({done.length})
</h2>
{done.map(task => (
<div key={task.id}
className="flex items-center gap-3 p-3 bg-gray-50 border border-gray-100 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">{task.title}</span>
<button onClick={() => deleteTask(task.id)}
className="text-gray-300 hover:text-red-500 text-lg">×</button>
</div>
))}
</div>
)}
</div>
);
}
类型五:Mermaid 图表
Mermaid Artifact 生成各类技术图表,无需任何图形设计工具:
sequenceDiagram
autonumber
actor User as 用户
participant FE as 前端
participant GW as API Gateway
participant Auth as Auth Service
participant Order as Order Service
participant DB as Database
User->>FE: 提交订单请求
FE->>GW: POST /api/orders (Bearer token)
GW->>Auth: 验证 JWT Token
Auth-->>GW: Token 有效,user_id=123
GW->>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: 订单创建成功 #456
erDiagram
USER {
int id PK
string email UK
string name
datetime created_at
}
ORDER {
int id PK
int user_id FK
decimal total_amount
string status
datetime created_at
}
ORDER_ITEM {
int id PK
int order_id FK
int product_id FK
int quantity
decimal unit_price
}
PRODUCT {
int id PK
string name
decimal price
int stock
}
USER ||--o{ ORDER : "creates"
ORDER ||--|{ ORDER_ITEM : "contains"
PRODUCT ||--o{ ORDER_ITEM : "included in"
类型六:Markdown 文档
Markdown Artifact 适合生成独立文档,可以下载和在其他系统中使用。
31.3 在 API 中控制 Artifact 生成
通过 Claude API,可以在自己的产品中实现类似 Claude.ai 的 Artifact 生成能力:
import anthropic
import json
import re
def generate_artifact(
prompt: str,
artifact_type: str = "react",
additional_context: str = ""
) -> dict:
"""
通过 API 生成 Artifact
artifact_type: code | svg | html | react | mermaid | markdown
"""
client = anthropic.Anthropic()
type_instructions = {
"react": """生成一个完整的 React 组件作为 Artifact。
要求:
- 使用函数组件和 Hooks
- 可以使用 Tailwind CSS 类名
- 可以从 'recharts' 导入图表组件
- 导出为默认导出(export default)
- 组件必须完整可运行,不依赖外部文件
以 ```react 代码块包裹输出""",
"html": """生成完整的 HTML 页面作为 Artifact。
要求:
- 包含完整的 HTML5 文档结构
- CSS 写在 <style> 标签内
- JavaScript 写在 <script> 标签内
- 可以使用 CDN 引入第三方库
以 ```html 代码块包裹输出""",
"svg": """生成 SVG 图形作为 Artifact。
要求:
- 输出完整的 <svg> 元素
- 使用 viewBox 属性确保可缩放
- 图形清晰、专业、信息密度适当
以 ```svg 代码块包裹输出""",
"mermaid": """生成 Mermaid 图表作为 Artifact。
以 ```mermaid 代码块包裹输出""",
"python": """生成完整可运行的 Python 代码作为 Artifact。
以 ```python 代码块包裹输出""",
}
instruction = type_instructions.get(artifact_type,
f"生成 {artifact_type} 类型的 Artifact")
system = f"""你是一个专业的代码生成助手。
{instruction}
{additional_context}
只输出请求的 Artifact 内容,不需要额外解释。"""
response = client.messages.create(
model="claude-opus-4-5",
max_tokens=4096,
system=system,
messages=[{"role": "user", "content": prompt}]
)
content = response.content[0].text
# 提取代码块
pattern = rf"```{artifact_type}\n(.*?)```"
match = re.search(pattern, content, re.DOTALL)
if match:
artifact_content = match.group(1).strip()
else:
# 尝试通用代码块
generic_match = re.search(r"```\w*\n(.*?)```", content, re.DOTALL)
artifact_content = generic_match.group(1).strip() if generic_match else content
return {
"type": artifact_type,
"content": artifact_content,
"raw_response": content
}
# 使用示例
result = generate_artifact(
prompt="创建一个展示月度销售趋势的柱状图组件,使用 recharts",
artifact_type="react"
)
print(f"Artifact 类型: {result['type']}")
print(f"内容预览:\n{result['content'][:500]}...")
31.4 Artifact 的迭代修改
用户通常需要对 Artifact 进行多轮修改。设计一个支持上下文保留的迭代流程:
class ArtifactIterator:
"""支持多轮迭代的 Artifact 修改器"""
def __init__(self, artifact_type: str = "react"):
self.client = anthropic.Anthropic()
self.artifact_type = artifact_type
self.messages = []
self.current_artifact = None
self.version_history = []
def create(self, prompt: str) -> str:
"""创建初始 Artifact"""
self.messages.append({"role": "user", "content": prompt})
response = self.client.messages.create(
model="claude-opus-4-5",
max_tokens=4096,
system=self._get_system(),
messages=self.messages
)
assistant_text = response.content[0].text
self.messages.append({"role": "assistant", "content": assistant_text})
self.current_artifact = self._extract_artifact(assistant_text)
self.version_history.append(self.current_artifact)
return self.current_artifact
def modify(self, modification_request: str) -> str:
"""在当前版本基础上进行修改"""
# 将修改请求添加到对话历史
self.messages.append({
"role": "user",
"content": f"请修改当前的 {self.artifact_type}:{modification_request}"
})
response = self.client.messages.create(
model="claude-opus-4-5",
max_tokens=4096,
system=self._get_system(),
messages=self.messages
)
assistant_text = response.content[0].text
self.messages.append({"role": "assistant", "content": assistant_text})
new_artifact = self._extract_artifact(assistant_text)
if new_artifact:
self.current_artifact = new_artifact
self.version_history.append(new_artifact)
return self.current_artifact
def revert(self, version_index: int = -2) -> str:
"""回退到历史版本"""
if abs(version_index) <= len(self.version_history):
self.current_artifact = self.version_history[version_index]
return self.current_artifact
return self.current_artifact
def _get_system(self) -> str:
type_map = {
"react": "生成使用 Tailwind CSS 的 React 函数组件,用 ```react 包裹",
"html": "生成完整 HTML 页面,用 ```html 包裹",
"mermaid": "生成 Mermaid 图表,用 ```mermaid 包裹",
}
return type_map.get(self.artifact_type, f"生成 {self.artifact_type} 代码")
def _extract_artifact(self, text: str) -> str | None:
pattern = rf"```{self.artifact_type}\n(.*?)```"
match = re.search(pattern, text, re.DOTALL)
if match:
return match.group(1).strip()
generic = re.search(r"```\w*\n(.*?)```", text, re.DOTALL)
return generic.group(1).strip() if generic else None
# 使用示例
iterator = ArtifactIterator("react")
# 创建初始版本
v1 = iterator.create("创建一个简单的计数器组件,有加减按钮")
# 第一次修改
v2 = iterator.modify("添加一个重置按钮,将计数器归零")
# 第二次修改
v3 = iterator.modify("把背景色改为浅蓝色,按钮改为圆形")
# 如果不满意,回退到 v2
previous = iterator.revert(-2)
31.5 在产品中嵌入 Artifact 渲染
如果你在构建自己的 AI 产品,可以实现类似 Claude.ai 的 Artifact 渲染:
# 后端:判断输出类型,返回结构化数据
def parse_artifact_from_response(text: str) -> dict:
"""
从 Claude 回复中解析 Artifact
返回结构化的 artifact 对象供前端渲染
"""
# 检测各类型代码块
type_patterns = {
"react": r"```react\n(.*?)```",
"html": r"```html\n(.*?)```",
"svg": r"```svg\n(.*?)```",
"mermaid": r"```mermaid\n(.*?)```",
"python": r"```python\n(.*?)```",
}
for artifact_type, pattern in type_patterns.items():
match = re.search(pattern, text, re.DOTALL)
if match:
return {
"has_artifact": True,
"type": artifact_type,
"content": match.group(1).strip(),
"text_around": text[:match.start()].strip()
}
return {"has_artifact": False, "content": text}
// 前端:根据 artifact 类型渲染不同组件
function ArtifactRenderer({ artifact }) {
if (!artifact.has_artifact) {
return <ChatMessage text={artifact.content} />;
}
switch (artifact.type) {
case 'html':
return (
<div className="artifact-container">
<iframe
srcDoc={artifact.content}
sandbox="allow-scripts allow-same-origin"
className="artifact-iframe"
/>
</div>
);
case 'mermaid':
return <MermaidDiagram code={artifact.content} />;
case 'react':
// 需要使用 Babel standalone 在浏览器中编译
return <ReactSandbox code={artifact.content} />;
case 'svg':
return (
<div
dangerouslySetInnerHTML={{ __html: artifact.content }}
className="artifact-svg"
/>
);
default:
return <CodeBlock language={artifact.type} code={artifact.content} />;
}
}
小结
Artifacts 系统将 Claude 的价值从"建议提供者"升级为"可运行工件生产者"。六种类型各有其适用场景:
- 代码 Artifact:独立可运行的脚本,任意编程语言
- SVG Artifact:矢量图形、架构图、流程图
- HTML Artifact:带交互的完整网页,支持 CDN 引入第三方库
- React Artifact:最强大的交互式组件,支持 shadcn/ui 等预装库
- Mermaid Artifact:技术图表(时序图、ER图、流程图等)
- Markdown Artifact:可导出的独立文档
通过 API 可以在自己的产品中实现完整的 Artifact 生成和渲染能力,无需依赖 Claude.ai 界面。
下一章将介绍 Claude.ai API 集成——如何通过官方接口扩展 Managed Agent 的能力,以及企业级 API 访问模式。