With the Messages API the system prompt is its own field, system, not a message.
npm i @gistui/catalog @gistui/serveryarn add @gistui/catalog @gistui/serverpnpm add @gistui/catalog @gistui/serverbun add @gistui/catalog @gistui/serverWith fetch
import { prompt } from "@gistui/catalog";
import { textDeltas, toReadable } from "@gistui/server";
export async function POST(req: Request) {
const { messages } = await req.json();
const res = await fetch("https://api.anthropic.com/v1/messages", {
method: "POST",
headers: {
"x-api-key": process.env.ANTHROPIC_API_KEY!,
"anthropic-version": "2023-06-01",
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "claude-sonnet-5-5",
max_tokens: 4096,
stream: true,
system: prompt().text,
messages,
}),
});
if (!res.ok) return new Response(await res.text(), { status: res.status });
return new Response(toReadable(textDeltas(res, "anthropic")));
}With @anthropic-ai/sdk
import Anthropic from "@anthropic-ai/sdk";
import { prompt } from "@gistui/catalog";
import { toReadable } from "@gistui/server";
const client = new Anthropic();
export async function POST(req: Request) {
const { messages } = await req.json();
const stream = client.messages.stream({
model: "claude-sonnet-5-5",
max_tokens: 4096,
system: prompt().text,
messages,
});
async function* text() {
for await (const event of stream) {
if (event.type === "content_block_delta" && event.delta.type === "text_delta") yield event.delta.text;
}
}
return new Response(toReadable(text()));
}Prompt caching
GistUI’s prompt is byte-stable, so it is a good cache target. Mark it as cacheable and put anything that changes per request (the tool list, the user’s context) after it.
system: [{ type: "text", text: prompt().text, cache_control: { type: "ephemeral" } }],Render it
import "@gistui/styles/styles.css";
import { GistUI } from "@gistui/react";
import { ui } from "@gistui/react/ui";
const res = await fetch("/api/answer", { method: "POST", body: JSON.stringify({ messages }) });
<GistUI library={ui} stream={res.body} onAction={handle} />;In a chat
import { anthropic, createChat } from "@gistui/chat";
// url: your own endpoint that forwards to Anthropic and adds the key and the system prompt.
const store = createChat({ adapter: anthropic({ model: "claude-sonnet-5-5", url: "/api/chat" }) });