SDK · Playground
Pick a recipe, hit Run to see the simulated output, or Open in StackBlitz to get a live Node.js environment with @unified-product-graph/sdk pre-installed and the recipe ready to edit and run.
Cookbook · AI integration
A runnable agent that can read AND write the graph. Each UPGClient method becomes a typed tool; Claude picks which to call in a loop.
Code
import { query, tool } from '@anthropic-ai/claude-agent-sdk'
import { UPGClient } from '@unified-product-graph/sdk'
import { z } from 'zod'
const upg = new UPGClient({ file: './product.upg' })
const tools = [
tool('list_nodes', {
description: 'List nodes by type, optionally filtered by status.',
parameters: z.object({
type: z.string(),
status: z.string().optional(),
}),
handler: async ({ type, status }) => {
const { nodes, total } = await upg.nodes.list({ type, status })
return { count: total, nodes: nodes.map(n => ({ id: n.id, title: n.title })) }
},
}),
tool('create_node', {
description: 'Create a typed node. Pass parent_id to auto-link to a parent.',
parameters: z.object({
type: z.string(),
title: z.string(),
parent_id: z.string().optional(),
}),
handler: async (args) => {
const { node } = await upg.nodes.create(args)
return { id: node.id, type: node.type, title: node.title }
},
}),
tool('connect', {
description: 'Create an edge between two existing nodes (edge type inferred).',
parameters: z.object({
source_id: z.string(),
target_id: z.string(),
}),
handler: async ({ source_id, target_id }) => {
const edge = await upg.edges.connect(source_id, target_id)
return { edge_id: edge.id, edge_type: edge.type }
},
}),
tool('health', {
description: 'Return the graph health score (0-10) and a structural digest.',
parameters: z.object({}),
handler: async () => upg.health(),
}),
]
for await (const event of query({
prompt: `Find the persona "Busy Parent". Create a job
"Stay consistent over 30 days" under it. Then report graph health.`,
options: { tools, model: 'claude-sonnet-4-6' },
})) {
if (event.type === 'text_delta') process.stdout.write(event.text)
if (event.type === 'tool_use') console.error('\n→ tool:', event.name, event.input)
}
await upg.close()Output
// click ▶ Run to see what this snippet would print locally