Skip to content

Commit 9adb9a6

Browse files
chore: sync skill references (#231)
Co-authored-by: torbratsberg <[email protected]>
1 parent 8966329 commit 9adb9a6

2 files changed

Lines changed: 49 additions & 8 deletions

File tree

  • skills/create-agent-with-sanity-context/references/ecommerce

skills/create-agent-with-sanity-context/references/ecommerce/.env.example

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ SANITY_STUDIO_PROJECT_ID=
66
SANITY_STUDIO_DATASET=
77
# SANITY_STUDIO_API_HOST= # Optional, defaults to https://api.sanity.io
88

9-
# Next.js app (same values, NEXT_PUBLIC_ prefix exposes to browser)
10-
NEXT_PUBLIC_SANITY_PROJECT_ID=
11-
NEXT_PUBLIC_SANITY_DATASET=
9+
# Next.js app (derived from above, NEXT_PUBLIC_ prefix exposes to browser)
10+
NEXT_PUBLIC_SANITY_PROJECT_ID=${SANITY_STUDIO_PROJECT_ID}
11+
NEXT_PUBLIC_SANITY_DATASET=${SANITY_STUDIO_DATASET}
12+
# NEXT_PUBLIC_SANITY_API_HOST=${SANITY_STUDIO_API_HOST}
1213

1314
# Chat assistant
1415
# Read token: Create in Sanity Manage with "Viewer" role for MCP context queries

skills/create-agent-with-sanity-context/references/ecommerce/app/src/app/api/chat/route.ts

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,55 @@ import {writeClient} from '@/sanity/lib/write-client'
1616
const DEFAULT_MODEL = 'claude-sonnet-4-5'
1717
const MAX_STEPS = 20
1818

19+
let cachedInitialContext: string | null = null
20+
let cacheTimestamp = 0
21+
const CACHE_TTL_MS = 5 * 60 * 1000
22+
23+
function initialContextUrl(mcpUrl: string): string {
24+
const url = new URL(mcpUrl)
25+
url.pathname = `${url.pathname.replace(/\/$/, '')}/initial-context`
26+
return url.toString()
27+
}
28+
29+
// Slow on cold start — subsequent calls return the cached result
30+
async function fetchInitialContext(): Promise<string | null> {
31+
const mcpUrl = process.env.SANITY_CONTEXT_MCP_URL
32+
if (!mcpUrl) return null
33+
34+
const isStale = Date.now() - cacheTimestamp > CACHE_TTL_MS
35+
const fetchPromise = isStale
36+
? fetch(initialContextUrl(mcpUrl), {
37+
headers: {Authorization: `Bearer ${process.env.SANITY_API_READ_TOKEN}`},
38+
})
39+
.then(async (res) => {
40+
if (res.ok) {
41+
cachedInitialContext = await res.text()
42+
cacheTimestamp = Date.now()
43+
}
44+
})
45+
.catch(() => {})
46+
: null
47+
48+
if (!cachedInitialContext) await fetchPromise
49+
50+
return cachedInitialContext
51+
}
52+
1953
interface BuildSystemPromptParams {
2054
basePrompt: string
2155
documentContext: DocumentContext
56+
initialContext?: string | null
2257
}
2358

2459
/**
2560
* Combines base prompt from Sanity with page context and tool instructions.
2661
*/
2762
function buildSystemPrompt(props: BuildSystemPromptParams): string {
28-
const {basePrompt, documentContext} = props
63+
const {basePrompt, documentContext, initialContext} = props
2964

3065
return `
3166
${basePrompt}
32-
67+
${initialContext ? `\n# Data reference\n\nUse this to understand what's available and write better queries.\n\n${initialContext}\n` : ''}
3368
# Current page
3469
3570
<page-context>
@@ -95,8 +130,7 @@ export async function POST(req: Request) {
95130
let mcpClient: MCPClient | null = null
96131

97132
try {
98-
// Initialize MCP client and fetch system prompt from Sanity document
99-
const [mcpClientResult, agentConfig] = await Promise.all([
133+
const [mcpClientResult, agentConfig, initialContext] = await Promise.all([
100134
createMCPClient({
101135
transport: {
102136
type: 'http',
@@ -110,6 +144,7 @@ export async function POST(req: Request) {
110144
`*[_type == "agent.config" && slug.current == $slug][0] { systemPrompt }`,
111145
{slug: process.env.AGENT_CONFIG_SLUG || 'default'},
112146
),
147+
fetchInitialContext(),
113148
])
114149

115150
mcpClient = mcpClientResult
@@ -125,9 +160,14 @@ export async function POST(req: Request) {
125160
const systemPrompt = buildSystemPrompt({
126161
basePrompt: agentConfig.systemPrompt,
127162
documentContext,
163+
initialContext,
128164
})
129165

130-
const mcpTools = await mcpClient.tools()
166+
const allMcpTools = await mcpClient.tools()
167+
168+
// Exclude initial_context tool, its data is already in the system prompt
169+
const {initial_context: _, ...mcpTools} = allMcpTools
170+
131171
const modelId = process.env.ANTHROPIC_MODEL || DEFAULT_MODEL
132172

133173
const result = streamText({

0 commit comments

Comments
 (0)