From f5a89f686f2624ed22bf9945c8da1e180ff74b49 Mon Sep 17 00:00:00 2001 From: Visharad Kashyap <154831195+vishxrad@users.noreply.github.com> Date: Wed, 9 Sep 2026 14:51:28 +0530 Subject: [PATCH 1/3] docs: add standalone artifact API guide --- .../docs/agent/core-concepts/artifacts.mdx | 2 + docs/content/docs/gateway/api/artifacts.mdx | 120 ++++++++++++++++++ .../docs/gateway/api/chat-completions.mdx | 4 + docs/content/docs/gateway/meta.json | 1 + docs/next.config.mjs | 5 + 5 files changed, 132 insertions(+) create mode 100644 docs/content/docs/gateway/api/artifacts.mdx diff --git a/docs/content/docs/agent/core-concepts/artifacts.mdx b/docs/content/docs/agent/core-concepts/artifacts.mdx index 408e435e6..557331b54 100644 --- a/docs/content/docs/agent/core-concepts/artifacts.mdx +++ b/docs/content/docs/agent/core-concepts/artifacts.mdx @@ -5,6 +5,8 @@ description: Durable, first-class conversation outputs like slides, reports, and An **artifact** is a first-class output of a conversation. Slides, reports, dashboards, a small app: things the user opens, reads, and returns to. An artifact is not a chat message and not a tool result. Once it exists, it stands on its own. +To generate and render standalone slides or reports in your own application, see the [Artifact API guide](/docs/gateway/api/artifacts). + ## Where an artifact shows up The same renderer drives two surfaces: diff --git a/docs/content/docs/gateway/api/artifacts.mdx b/docs/content/docs/gateway/api/artifacts.mdx new file mode 100644 index 000000000..675c903d6 --- /dev/null +++ b/docs/content/docs/gateway/api/artifacts.mdx @@ -0,0 +1,120 @@ +--- +title: Artifact API +description: "Generate, stream, render, and edit standalone slides and reports with the artifact Chat Completions API." +--- + +Use the Artifact API to generate a standalone presentation or report and display it in your own application. Your application manages the artifact program and the history sent with edit requests. + +For artifacts displayed inside an agent conversation, see [Agent Interface artifacts](/docs/agent/core-concepts/artifacts). + +## Generate an artifact + +Artifacts use a Chat Completions-compatible endpoint: + +**Endpoint:** `POST https://api.thesys.dev/v1/artifact/chat/completions` + +Create an API key in the [Thesys console](https://console.thesys.dev/keys) and configure `THESYS_API_KEY` in your server environment. Keep this key on the server. Point the OpenAI client at the artifact base URL. Every request must include `metadata.thesys` as a JSON string with your artifact `id` and a `c1_artifact_type` of `"slides"` or `"report"`. + +```ts +import OpenAI from "openai"; + +const artifactClient = new OpenAI({ + apiKey: process.env.THESYS_API_KEY, + baseURL: "https://api.thesys.dev/v1/artifact", +}); + +const artifact = await artifactClient.chat.completions.create({ + model: "openai/gpt-5", + messages: [{ role: "user", content: "Create a three-slide deck on Q4 results." }], + metadata: { + thesys: JSON.stringify({ + id: "art_1", + c1_artifact_type: "slides", + }), + }, +}); + +const program = artifact.choices[0]?.message.content; +if (!program) throw new Error("The artifact response was empty."); +``` + +Provider models use the same native routing and BYOK behavior as the embed endpoint. The response content is a raw OpenUI Lang program rooted at `SlideShow` or `ReportView`. It is validated and repaired before being returned. Set `stream: true` to receive it progressively. + +## Render an artifact + +Render the returned program with the matching managed viewer: + +```tsx +"use client"; + +import { Presentation, Report } from "@openuidev/thesys"; +import "@openuidev/thesys/styles.css"; + +export function Artifact({ + kind, + program, + isStreaming = false, +}: { + kind: "slides" | "report"; + program: string; + isStreaming?: boolean; +}) { + return kind === "slides" ? ( + + ) : ( + + ); +} +``` + +Install the viewer package with `pnpm add @openuidev/thesys`. In Next.js, use a client component for the viewer and load its stylesheet once in your application. + +## Stream an artifact + +Set `stream: true` and accumulate the content deltas in order: + +```ts +const stream = await artifactClient.chat.completions.create({ + model: "openai/gpt-5", + messages: [{ role: "user", content: "Create a report on Q4 results." }], + metadata: { + thesys: JSON.stringify({ + id: "art_report_1", + c1_artifact_type: "report", + }), + }, + stream: true, +}); + +let program = ""; +for await (const chunk of stream) { + program += chunk.choices[0]?.delta?.content ?? ""; + // Forward the accumulated program to your application's viewer. +} +``` + +Pass the accumulated program as `response` and keep `isStreaming={true}` while the request is running. Set it to `false` when the stream ends. Use `Presentation` for `"slides"` and `Report` for `"report"`. + +## Edit an artifact + +Send the current OpenUI Lang program as an assistant message, describe the change in the next user message, and set `is_edit: true`. + +```ts +const edited = await artifactClient.chat.completions.create({ + model: "openai/gpt-5", + messages: [ + { role: "assistant", content: previousProgram }, + { role: "user", content: "Make slide 2 about European revenue." }, + ], + metadata: { + thesys: JSON.stringify({ + id: "art_1", + c1_artifact_type: "slides", + is_edit: true, + }), + }, + stream: true, +}); +``` + +The response uses patch-mode OpenUI Lang, merged against the assistant-message base. Preserve the current complete program as the base for edits; an edit response must be interpreted in that context, rather than treated as an unrelated new artifact. Use the same artifact `id` and `c1_artifact_type` when editing it. diff --git a/docs/content/docs/gateway/api/chat-completions.mdx b/docs/content/docs/gateway/api/chat-completions.mdx index f7fccb4d2..abd246225 100644 --- a/docs/content/docs/gateway/api/chat-completions.mdx +++ b/docs/content/docs/gateway/api/chat-completions.mdx @@ -70,3 +70,7 @@ Chat Completions returns function tool calls to the application; it does not exe 3. Execute each function in your application. 4. Append the assistant tool-call message and each tool result. 5. Continue until the model returns the final OpenUI Lang response. + +## Generate slides and reports + +Use the separate [Artifact API](/docs/gateway/api/artifacts) to generate standalone slides and reports. The guide covers request metadata, streaming, the `Presentation` and `Report` viewers, and editing an existing artifact. diff --git a/docs/content/docs/gateway/meta.json b/docs/content/docs/gateway/meta.json index 4ef188263..5442c716d 100644 --- a/docs/content/docs/gateway/meta.json +++ b/docs/content/docs/gateway/meta.json @@ -13,6 +13,7 @@ "migrate-to-openui-gateway", "---APIs---", "api/chat-completions", + "api/artifacts", "api/responses", "api/conversations" ] diff --git a/docs/next.config.mjs b/docs/next.config.mjs index f901ef2dd..ff2e88c18 100644 --- a/docs/next.config.mjs +++ b/docs/next.config.mjs @@ -234,6 +234,11 @@ const config = { destination: "/docs/gateway", permanent: true, }, + { + source: "/docs/openui-cloud/api/artifacts", + destination: "/docs/gateway/api/artifacts", + permanent: true, + }, { source: "/docs/openui-cloud/:path*", destination: "/docs/gateway", From 8f339c2508793c8b2c3523e3eb5f475291b93dfe Mon Sep 17 00:00:00 2001 From: Visharad Kashyap <154831195+vishxrad@users.noreply.github.com> Date: Wed, 9 Sep 2026 14:59:01 +0530 Subject: [PATCH 2/3] docs: consolidate managed generation into Artifacts page --- .../docs/agent/core-concepts/artifacts.mdx | 125 +++++++++++++++++- docs/content/docs/gateway/api/artifacts.mdx | 120 ----------------- .../docs/gateway/api/chat-completions.mdx | 2 +- docs/content/docs/gateway/meta.json | 1 - docs/next.config.mjs | 3 +- 5 files changed, 126 insertions(+), 125 deletions(-) delete mode 100644 docs/content/docs/gateway/api/artifacts.mdx diff --git a/docs/content/docs/agent/core-concepts/artifacts.mdx b/docs/content/docs/agent/core-concepts/artifacts.mdx index 557331b54..03087422b 100644 --- a/docs/content/docs/agent/core-concepts/artifacts.mdx +++ b/docs/content/docs/agent/core-concepts/artifacts.mdx @@ -1,11 +1,11 @@ --- title: Artifacts -description: Durable, first-class conversation outputs like slides, reports, and apps that the user can open and return to. +description: Understand artifacts in Agent Interface and generate, stream, render, and edit managed slides and reports. --- An **artifact** is a first-class output of a conversation. Slides, reports, dashboards, a small app: things the user opens, reads, and returns to. An artifact is not a chat message and not a tool result. Once it exists, it stands on its own. -To generate and render standalone slides or reports in your own application, see the [Artifact API guide](/docs/gateway/api/artifacts). +For managed presentations and reports in your own application, see [Generate and edit managed slides and reports](#generate-and-edit-managed-slides-and-reports) below. For your own artifact types, see [Custom artifacts](#custom-artifacts). ## Where an artifact shows up @@ -33,6 +33,127 @@ Static and live describe how an artifact behaves, not two different APIs. If the user expects a fixed record, it is static. If they expect fresh data, it is live. There is no `static: true` or `live: true` flag. It is how the renderer is written. +## Generate and edit managed slides and reports + +Choose the generation path based on where the artifact lives: + +- **Inside a managed agent conversation:** use the [Responses API](/docs/gateway/api/responses) with `artifactTool({ artifacts: ["slides", "report"] })` from `@openuidev/thesys-server`, and configure [conversation persistence](/docs/gateway/api/conversations). The default `openui-cloud` CLI template includes the [server tool declaration](https://github.com/thesysdev/openui/blob/main/templates/openui-cloud/src/app/api/chat/route.ts) and [managed renderer and storage wiring](https://github.com/thesysdev/openui/blob/main/templates/openui-cloud/src/components/cloud-chat.tsx). +- **Standalone in your application:** use the Artifact Chat Completions endpoint below. Your application stores the returned program and supplies it again for edits; this endpoint is not a conversation store. + +The following examples cover the standalone path. You use the built-in `Presentation` and `Report` viewers; you do not need to define a custom artifact renderer for this path. + +### Generate an artifact + +Artifacts use a Chat Completions-compatible endpoint: + +**Endpoint:** `POST https://api.thesys.dev/v1/artifact/chat/completions` + +Create an API key in the [Thesys console](https://console.thesys.dev/keys) and configure `THESYS_API_KEY` in your server environment. Keep this key on the server; call the API from your application's server route, not directly from the browser. Point the OpenAI client at the artifact base URL. Every request must include `metadata.thesys` as a JSON string with your artifact `id` and a `c1_artifact_type` of `"slides"` or `"report"`. + +```ts +import OpenAI from "openai"; + +const artifactClient = new OpenAI({ + apiKey: process.env.THESYS_API_KEY, + baseURL: "https://api.thesys.dev/v1/artifact", +}); + +const artifact = await artifactClient.chat.completions.create({ + model: "openai/gpt-5", + messages: [{ role: "user", content: "Create a three-slide deck on Q4 results." }], + metadata: { + thesys: JSON.stringify({ + id: "art_1", + c1_artifact_type: "slides", + }), + }, +}); + +const program = artifact.choices[0]?.message.content; +if (!program) throw new Error("The artifact response was empty."); +``` + +Use a supported provider/model identifier from [Models](/docs/gateway/models). The response content is a raw OpenUI Lang program rooted at `SlideShow` or `ReportView`. It is validated and repaired before being returned. Set `stream: true` to receive it progressively. + +### Render an artifact + +Render the returned program with the matching managed viewer: + +```tsx +"use client"; + +import { Presentation, Report } from "@openuidev/thesys"; +import "@openuidev/thesys/styles.css"; + +export function Artifact({ + kind, + program, + isStreaming = false, +}: { + kind: "slides" | "report"; + program: string; + isStreaming?: boolean; +}) { + return kind === "slides" ? ( + + ) : ( + + ); +} +``` + +Install the viewer package with `pnpm add @openuidev/thesys`. In Next.js, use a client component for the viewer and load its stylesheet once in your application. + +### Stream an artifact + +Set `stream: true` and accumulate the content deltas in order on the server: + +```ts +const stream = await artifactClient.chat.completions.create({ + model: "openai/gpt-5", + messages: [{ role: "user", content: "Create a report on Q4 results." }], + metadata: { + thesys: JSON.stringify({ + id: "art_report_1", + c1_artifact_type: "report", + }), + }, + stream: true, +}); + +let program = ""; +for await (const chunk of stream) { + program += chunk.choices[0]?.delta?.content ?? ""; + // Forward the accumulated program to your application's viewer. +} +``` + +Forward updates from your server route to the browser using your application's streaming transport. Pass the accumulated program as `response` and keep `isStreaming={true}` while the request is running. Set it to `false` when the stream ends. Use `Presentation` for `"slides"` and `Report` for `"report"`. + +### Edit an artifact + +Load the current complete OpenUI Lang program from your application's storage, authorize the user's access to it, and send it as an assistant message. Describe the change in the next user message and set `is_edit: true`. + +```ts +const edited = await artifactClient.chat.completions.create({ + model: "openai/gpt-5", + messages: [ + { role: "assistant", content: previousProgram }, + { role: "user", content: "Make slide 2 about European revenue." }, + ], + metadata: { + thesys: JSON.stringify({ + id: "art_1", + c1_artifact_type: "slides", + is_edit: true, + }), + }, + stream: true, +}); +``` + +The response uses patch-mode OpenUI Lang, merged against the assistant-message base. Preserve the current complete program as the base for edits; an edit response must be interpreted in that context, rather than treated as an unrelated new artifact. Use the same artifact `id` and `c1_artifact_type` when editing it. Persist the resulting complete program for subsequent views and edits. + ## Custom artifacts To render an artifact, like an interactive app or a domain-specific view, you register a renderer for it through the `artifactRenderers` prop. diff --git a/docs/content/docs/gateway/api/artifacts.mdx b/docs/content/docs/gateway/api/artifacts.mdx deleted file mode 100644 index 675c903d6..000000000 --- a/docs/content/docs/gateway/api/artifacts.mdx +++ /dev/null @@ -1,120 +0,0 @@ ---- -title: Artifact API -description: "Generate, stream, render, and edit standalone slides and reports with the artifact Chat Completions API." ---- - -Use the Artifact API to generate a standalone presentation or report and display it in your own application. Your application manages the artifact program and the history sent with edit requests. - -For artifacts displayed inside an agent conversation, see [Agent Interface artifacts](/docs/agent/core-concepts/artifacts). - -## Generate an artifact - -Artifacts use a Chat Completions-compatible endpoint: - -**Endpoint:** `POST https://api.thesys.dev/v1/artifact/chat/completions` - -Create an API key in the [Thesys console](https://console.thesys.dev/keys) and configure `THESYS_API_KEY` in your server environment. Keep this key on the server. Point the OpenAI client at the artifact base URL. Every request must include `metadata.thesys` as a JSON string with your artifact `id` and a `c1_artifact_type` of `"slides"` or `"report"`. - -```ts -import OpenAI from "openai"; - -const artifactClient = new OpenAI({ - apiKey: process.env.THESYS_API_KEY, - baseURL: "https://api.thesys.dev/v1/artifact", -}); - -const artifact = await artifactClient.chat.completions.create({ - model: "openai/gpt-5", - messages: [{ role: "user", content: "Create a three-slide deck on Q4 results." }], - metadata: { - thesys: JSON.stringify({ - id: "art_1", - c1_artifact_type: "slides", - }), - }, -}); - -const program = artifact.choices[0]?.message.content; -if (!program) throw new Error("The artifact response was empty."); -``` - -Provider models use the same native routing and BYOK behavior as the embed endpoint. The response content is a raw OpenUI Lang program rooted at `SlideShow` or `ReportView`. It is validated and repaired before being returned. Set `stream: true` to receive it progressively. - -## Render an artifact - -Render the returned program with the matching managed viewer: - -```tsx -"use client"; - -import { Presentation, Report } from "@openuidev/thesys"; -import "@openuidev/thesys/styles.css"; - -export function Artifact({ - kind, - program, - isStreaming = false, -}: { - kind: "slides" | "report"; - program: string; - isStreaming?: boolean; -}) { - return kind === "slides" ? ( - - ) : ( - - ); -} -``` - -Install the viewer package with `pnpm add @openuidev/thesys`. In Next.js, use a client component for the viewer and load its stylesheet once in your application. - -## Stream an artifact - -Set `stream: true` and accumulate the content deltas in order: - -```ts -const stream = await artifactClient.chat.completions.create({ - model: "openai/gpt-5", - messages: [{ role: "user", content: "Create a report on Q4 results." }], - metadata: { - thesys: JSON.stringify({ - id: "art_report_1", - c1_artifact_type: "report", - }), - }, - stream: true, -}); - -let program = ""; -for await (const chunk of stream) { - program += chunk.choices[0]?.delta?.content ?? ""; - // Forward the accumulated program to your application's viewer. -} -``` - -Pass the accumulated program as `response` and keep `isStreaming={true}` while the request is running. Set it to `false` when the stream ends. Use `Presentation` for `"slides"` and `Report` for `"report"`. - -## Edit an artifact - -Send the current OpenUI Lang program as an assistant message, describe the change in the next user message, and set `is_edit: true`. - -```ts -const edited = await artifactClient.chat.completions.create({ - model: "openai/gpt-5", - messages: [ - { role: "assistant", content: previousProgram }, - { role: "user", content: "Make slide 2 about European revenue." }, - ], - metadata: { - thesys: JSON.stringify({ - id: "art_1", - c1_artifact_type: "slides", - is_edit: true, - }), - }, - stream: true, -}); -``` - -The response uses patch-mode OpenUI Lang, merged against the assistant-message base. Preserve the current complete program as the base for edits; an edit response must be interpreted in that context, rather than treated as an unrelated new artifact. Use the same artifact `id` and `c1_artifact_type` when editing it. diff --git a/docs/content/docs/gateway/api/chat-completions.mdx b/docs/content/docs/gateway/api/chat-completions.mdx index abd246225..bd47ba8e8 100644 --- a/docs/content/docs/gateway/api/chat-completions.mdx +++ b/docs/content/docs/gateway/api/chat-completions.mdx @@ -73,4 +73,4 @@ Chat Completions returns function tool calls to the application; it does not exe ## Generate slides and reports -Use the separate [Artifact API](/docs/gateway/api/artifacts) to generate standalone slides and reports. The guide covers request metadata, streaming, the `Presentation` and `Report` viewers, and editing an existing artifact. +Use the separate Artifact Chat Completions endpoint to [generate and edit managed slides and reports](/docs/agent/core-concepts/artifacts#generate-and-edit-managed-slides-and-reports). The Artifacts page covers request metadata, streaming, the `Presentation` and `Report` viewers, and editing an existing artifact. diff --git a/docs/content/docs/gateway/meta.json b/docs/content/docs/gateway/meta.json index 5442c716d..4ef188263 100644 --- a/docs/content/docs/gateway/meta.json +++ b/docs/content/docs/gateway/meta.json @@ -13,7 +13,6 @@ "migrate-to-openui-gateway", "---APIs---", "api/chat-completions", - "api/artifacts", "api/responses", "api/conversations" ] diff --git a/docs/next.config.mjs b/docs/next.config.mjs index ff2e88c18..48e29a41e 100644 --- a/docs/next.config.mjs +++ b/docs/next.config.mjs @@ -236,7 +236,8 @@ const config = { }, { source: "/docs/openui-cloud/api/artifacts", - destination: "/docs/gateway/api/artifacts", + destination: + "/docs/agent/core-concepts/artifacts#generate-and-edit-managed-slides-and-reports", permanent: true, }, { From 1b6dbd3a23552a2cddcf879efc2809b2e09b1f01 Mon Sep 17 00:00:00 2001 From: Visharad Kashyap <154831195+vishxrad@users.noreply.github.com> Date: Wed, 9 Sep 2026 15:09:52 +0530 Subject: [PATCH 3/3] docs: simplify Artifacts page description --- docs/content/docs/agent/core-concepts/artifacts.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/docs/agent/core-concepts/artifacts.mdx b/docs/content/docs/agent/core-concepts/artifacts.mdx index 03087422b..638eb0cf5 100644 --- a/docs/content/docs/agent/core-concepts/artifacts.mdx +++ b/docs/content/docs/agent/core-concepts/artifacts.mdx @@ -1,6 +1,6 @@ --- title: Artifacts -description: Understand artifacts in Agent Interface and generate, stream, render, and edit managed slides and reports. +description: Artifacts in Agent Interface, including generation, streaming, rendering, and editing of managed slides and reports. --- An **artifact** is a first-class output of a conversation. Slides, reports, dashboards, a small app: things the user opens, reads, and returns to. An artifact is not a chat message and not a tool result. Once it exists, it stands on its own.