> ## Documentation Index
> Fetch the complete documentation index at: https://docs.thesys.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Generating an Artifact in a Conversation

> A step-by-step tutorial on using a tool call to create a new Artifact and embed it in an assistant's response.

To enable an assistant to create an artifact, you must provide it with a tool that it can call in response to a user's request. Your backend will then handle this tool call by invoking the C1 Artifacts API and streaming the result back to the user.

This guide covers the entire creation workflow, from defining the tool to handling the API calls.

### Step 1: Define the `create_artifact` Tool

First, define the schema for a tool that the assistant can use to create an artifact. This schema outlines the parameters the LLM needs to extract from the user's instructions. In this example, we'll create a `create_presentation` tool.

<CodeGroup dropdown>
  ```typescript theme={null}
  import { z } from "zod";
  import { zodToJsonSchema } from "zod-to-json-schema";

  const createPresentationTool = {
    type: "function",
    function: {
      name: "create_presentation",
      description: "Creates a slide presentation based on a topic.",
      parameters: zodToJsonSchema(
        z.object({
          instructions: z.string().describe("The instructions to generate the presentation."),
        })
      ),
    },
  };
  ```

  ```python theme={null}
  from pydantic import BaseModel, Field

  class CreatePresentationParams(BaseModel):
      instructions: str = Field(..., description="The instructions to generate the presentation.")

  create_presentation_tool = {
      "type": "function",
      "function": {
          "name": "create_presentation",
          "description": "Creates a slide presentation based on a instructions.",
          "parameters": CreatePresentationParams.model_json_schema(),
      },
  }
  ```
</CodeGroup>

### Step 2: Handle the Tool Call in Your Backend

When the LLM decides to use your `create_presentation` tool, your backend will receive the tool call. Your code must then orchestrate the process of generating the artifact and streaming it back as part of the assistant's final message.

The key steps are:

1. Generate a unique `artifactId` and `messageId`.
2. Call the C1 Artifacts API, passing the `artifactId`.
3. Stream the artifact content into a [C1 Response](/sdk-reference/c1-response).
4. Return a `tool_result` to the main LLM, including the `artifactId` and `messageId` (as the `version`).
5. Stream the LLM's final text confirmation into the same C1 Response.
6. Store the response in the database as the assistant message.

<CodeGroup dropdown>
  ```typescript theme={null}
  // (Inside your Next.js API route)
  import { nanoid } from "nanoid";
  import { makeC1Response } from "@thesysai/genui-sdk/server";

  // When your tool handler is invoked by the LLM...
  async function handleCreatePresentation(
    // following parameters are passed by the LLM
    { instructions }: { instructions: string },
    // following parameters are passed by your backend
    { messageId, c1Response }: { messageId: string, c1Response: ReturnType<typeof makeC1Response> }
  ) {
    // 2. Call the Artifacts API and stream the result.
    const artifactStream = await c1ArtifactsClient.chat.completions.create({
      model: "c1/artifact/v-20251030",
      messages: [{ role: "user", content: instructions }],
      metadata: { thesys: JSON.stringify({ c1_artifact_type: "slides", id: artifactId }) },
      stream: true,
    });

      // 3. Pipe the artifact stream into the C1 Response object.
      for await (const delta of artifactStream) {
        const content = delta.choices[0]?.delta?.content;
        if (content) {
          c1Response.writeContent(content);
        }
      }

      // 4. Return the result to the main LLM so it knows the tool succeeded.
      return `Presentation created with artifact_id: ${artifactId}, version: ${messageId}`,
  }
  // After the tool result is sent, the main LLM will generate its final text response.
  // You will then pipe that final text stream into the same `c1Response` object
  // before returning `c1Response.responseStream` from your API route.
  ```

  ```python theme={null}
  # (Inside your FastAPI route)
  import nanoid
  from thesys_genui_sdk.fast_api import with_c1_response
  from thesys_genui_sdk.context import write_content

  # for more details on how to use thesys_genui_sdk, see https://pypi.org/project/thesys-genui-sdk/.

  # When your tool handler is invoked by the LLM...
  async def handle_create_presentation(instructions: str, message_id: str):
      # 1. Developer generates unique IDs.
      artifact_id = nanoid.generate(size=10)
      message_id = nanoid.generate(size=10) # This will serve as the first version.

      # 2. Call the Artifacts API and stream the result.
      artifact_stream = await c1_artifacts_client.chat.completions.create(
          model="c1/artifact/v-20251030",
          messages=[{"role": "user", "content": f"Create a presentation about {topic}"}],
          metadata={"thesys": json.dumps({"c1_artifact_type": "slides", "id": artifact_id})},
          stream=True,
      )

      # 3. Pipe the artifact stream using the write_content helper.
      async for delta in artifact_stream:
          content = delta.choices[0].delta.content
          if content:
              await write_content(content)

      # 4. Return the result to the main LLM.
      return f"Presentation created with artifact_id: {artifact_id}, version: {message_id}"
  # Your main logic will then take this tool result, send it back to the LLM,
  # and stream the final text confirmation using the same `write_content` helper.
  ```
</CodeGroup>

### Step 3: The Final Assistant Response

After your backend returns the successful `tool_result`, the main LLM generates a final, user-facing response (e.g., "I've created the presentation for you. You can see it below.").

Your backend code must stream this final text into the *same* C1 Response object. The result is a single, composite assistant message that contains both the confirmation text and the fully rendered artifact, which is then sent to the frontend.

#### A Note on the `version`

In this guide, we use the unique `messageId` of the assistant's response as the `version`. This creates a clear link between a specific version of the artifact and the message that contains it. The importance of this `version` will become clear in the next guide, where we use it to edit the artifact.

<Card title="View the code" icon="github" href="https://github.com/thesysdev/examples/tree/main/c1-chat-artifact">
  Find more examples and complete code on our GitHub repository.
</Card>
