> ## 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.

# Editing an Artifact in a Conversation

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

A key feature of conversational artifacts is the ability for users to modify them with follow-up prompts. This guide explains how to handle a user request like "add a slide about our competitors" by using a tool to edit an existing artifact.

<Note>
  This guide assumes you have already completed the **[Generating an Artifact in a Conversation](/guides/artifacts/artifacts-in-chat/generating)** guide.
</Note>

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

First, define the schema for a tool that allows the assistant to edit an artifact. The schema must include parameters to identify which artifact to edit (`artifactId` and `version`) and what changes to make (`instructions`).

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

  const editPresentationTool = {
    type: "function",
    function: {
      name: "edit_presentation",
      description: "Edits an existing slide presentation.",
      parameters: zodToJsonSchema(
        z.object({
          artifactId: z.string().describe("The ID of the artifact to edit."),
          version: z.string().describe("The version of the artifact to edit"), // this corresponds to the messageId of the assistant's response that contains the artifact
          instructions: z.string().describe("The user's instructions for what to change."),
        })
      ),
    },
  };
  ```

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

  class EditPresentationParams(BaseModel):
      artifactId: str = Field(..., description="The ID of the artifact to edit.")
      version: str = Field(..., description="The version of the artifact to edit") # this corresponds to the messageId of the assistant's response that contains the artifact
      instructions: str = Field(..., description="The user's instructions for what to change.")

  edit_presentation_tool = {
      "type": "function",
      "function": {
          "name": "edit_presentation",
          "description": "Edits an existing slide presentation.",
          "parameters": EditPresentationParams.model_json_schema(),
      },
  }
  ```
</CodeGroup>

### Step 2: The Role of the `version`

In our workflow, the `version` is the unique `messageId` of the assistant's response that contains the artifact.

Using the `messageId` as a version provides a **stable reference** to a specific, point-in-time snapshot of the artifact as it exists in the conversation history. When the LLM requests an edit, your backend can use this `version` to reliably retrieve the exact content that needs to be modified.

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

When a user asks to make a change, the LLM will use your `edit_presentation` tool. Your backend must handle this tool call by retrieving the old content, calling the C1 Artifacts API in "edit mode," and streaming back the updated result.

The key steps are:

1. Use the `version` from the tool call to fetch the previous assistant message content from your database.
2. Generate a new `messageId` which will serve as the **new version** of the artifact.
3. Call the C1 Artifacts API, providing the old content and the new editing instructions.
4. Stream the updated artifact into a C1 Response object.
5. Return a `tool_result` to the main LLM with the new version.
6. Stream the LLM's final text confirmation into the same C1 Response object.

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

  // When your edit tool handler is invoked...
  async function handleEditPresentation(
    { artifactId, version, instructions }: { artifactId: string, version: string, instructions: string },
    { messageId, c1Response }: { messageId: string, c1Response: ReturnType<typeof makeC1Response> }
  ) {
    // 1. Retrieve the old artifact content from your database using the version (messageId).
    const oldMessageContent = await getMessageFromDb(version);

    // 3. Call the Artifacts API in "edit mode".
    const updatedArtifactStream = await c1ArtifactsClient.chat.completions.create({
      model: "c1/artifact/v-20251030",
      messages: [
        { role: "assistant", content: oldMessageContent }, // Old content
        { role: "user", content: instructions },           // New instructions
      ],
      metadata: { thesys: JSON.stringify({ c1_artifact_type: "slides", id: artifactId }) },
      stream: true,
    });

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

    // 5. Return the result to the main LLM with the new version.
    return `Presentation edited successfully. New version: ${messageId}`
  }
  ```

  ```python theme={null}
  # (Inside your FastAPI route)
  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 edit tool handler is invoked...
  async def handle_edit_presentation(artifactId: str, version: str, instructions: str, message_id: str):
      # 1. Retrieve the old artifact content from your database using the version (messageId).
      old_message_content = await get_message_from_db(version)

      # 2. Call the Artifacts API in "edit mode".
      updated_artifact_stream = await c1_artifacts_client.chat.completions.create(
          model="c1/artifact/v-20251030",
          messages=[
              {"role": "assistant", "content": old_message_content}, # Old content
              {"role": "user", "content": instructions},            # New instructions
          ],
          metadata={"thesys": json.dumps({"c1_artifact_type": "slides", "id": artifactId})},
          stream=True,
      )

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

      # 4. Return the result to the main LLM with the new version.
      return f"Presentation edited successfully. New version: {message_id}"
  ```
</CodeGroup>

### Step 4: The Final Updated Response

As in the creation step, the main LLM will receive the successful `tool_result` and generate a final confirmation (e.g., "I've updated the presentation with the new slide."). Your backend streams this text into the same C1 Response object, completing the request. The frontend then receives and renders the new assistant message containing the fully updated 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>
