---
title: Kundensupport-Agent
url: https://platform.claude.com/docs/de/about-claude/use-case-guides/customer-support-chat
description: Erstelle mit Claude einen Kundensupport-Chatbot, der Produktfragen beantwortet, beim Thema bleibt und über Tool-Nutzung Angebote generiert.
---

## Voraussetzungen

Um dieser Anleitung zu folgen, benötigst du:

* Einen Claude API-Key (als Umgebungsvariable `ANTHROPIC_API_KEY` gesetzt)
* Python 3.10 oder neuer

Installiere die erforderlichen Pakete:

```bash
pip install anthropic streamlit python-dotenv
```

## Bevor du mit Claude entwickelst

### Entscheide, ob du Claude für den Support-Chat einsetzen möchtest

Hier sind einige wichtige Indikatoren dafür, dass du ein „large language model“ (großes Sprachmodell), oder LLM, wie Claude einsetzen solltest, um Teile deines Kundensupport-Prozesses zu automatisieren:

<AccordionGroup>
  <Accordion title="Hohes Volumen sich wiederholender Anfragen">
    Claude ist hervorragend darin, eine große Anzahl ähnlicher Fragen effizient zu bearbeiten, sodass menschliche Mitarbeitende für komplexere Anliegen frei werden.
  </Accordion>

  <Accordion title="Bedarf an schneller Informationssynthese">
    Claude kann Informationen aus umfangreichen Wissensdatenbanken schnell abrufen, verarbeiten und kombinieren, während menschliche Mitarbeitende möglicherweise Zeit benötigen, um zu recherchieren oder mehrere Quellen zu konsultieren.
  </Accordion>

  <Accordion title="Anforderung an 24/7-Verfügbarkeit">
    Claude kann rund um die Uhr Support leisten, ohne zu ermüden, während die Besetzung mit menschlichen Mitarbeitenden für eine durchgehende Abdeckung kostspielig und herausfordernd sein kann.
  </Accordion>

  <Accordion title="Schnelle Skalierung in Spitzenzeiten">
    Claude kann plötzliche Anstiege des Anfragevolumens bewältigen, ohne dass zusätzliches Personal eingestellt und geschult werden muss.
  </Accordion>

  <Accordion title="Konsistente Markenstimme">
    Du kannst Claude anweisen, den Ton und die Werte deiner Marke konsistent zu repräsentieren, während menschliche Mitarbeitende in ihrem Kommunikationsstil variieren können.
  </Accordion>
</AccordionGroup>

Einige Überlegungen, warum du Claude gegenüber anderen LLMs wählen solltest:

* Du legst Wert auf natürliche, nuancierte Konversation: Claudes ausgefeiltes Sprachverständnis ermöglicht natürlichere, kontextbewusste Gespräche, die sich menschlicher anfühlen als Chats mit anderen LLMs.
* Du erhältst häufig komplexe und offene Anfragen: Claude kann ein breites Spektrum an Themen und Anfragen bearbeiten, ohne vorgefertigte Antworten zu generieren oder eine umfangreiche Programmierung von Permutationen von Nutzeräußerungen zu erfordern.
* Du benötigst skalierbaren mehrsprachigen Support: Claudes mehrsprachige Fähigkeiten ermöglichen Gespräche in über 200 Sprachen, ohne dass für jede unterstützte Sprache separate Chatbots oder umfangreiche Übersetzungsprozesse erforderlich sind.

### Definiere deine ideale Chat-Interaktion

Skizziere eine ideale Kundeninteraktion, um festzulegen, wie und wann du erwartest, dass der Kunde mit Claude interagiert. Diese Skizze hilft dabei, die technischen Anforderungen deiner Lösung zu bestimmen.

Hier ist ein Beispiel für eine Chat-Interaktion im Kundensupport einer Kfz-Versicherung:

* **Kunde:** Startet den Support-Chat
  * **Claude:** Begrüßt den Kunden herzlich und beginnt das Gespräch

* **Kunde:** Fragt nach einer Versicherung für sein neues Elektroauto
  * **Claude:** Liefert relevante Informationen zum Versicherungsschutz für Elektrofahrzeuge

* **Kunde:** Stellt Fragen zu den besonderen Anforderungen von Elektrofahrzeug-Versicherungen
  * **Claude:** Antwortet mit präzisen und informativen Antworten und stellt Links zu den Quellen bereit

* **Kunde:** Stellt themenfremde Fragen, die nichts mit Versicherungen oder Autos zu tun haben
  * **Claude:** Stellt klar, dass es keine themenfremden Inhalte bespricht, und lenkt den Nutzer zurück zur Kfz-Versicherung

* **Kunde:** Bekundet Interesse an einem Versicherungsangebot

  * **Claude:** Stellt eine Reihe von Fragen, um das passende Angebot zu ermitteln, und passt sich dabei an die Antworten an
  * **Claude:** Sendet eine Anfrage zur Nutzung des API-Tools zur Angebotserstellung zusammen mit den notwendigen, vom Nutzer gesammelten Informationen
  * **Claude:** Empfängt die Antwortinformationen aus der API-Tool-Nutzung, fasst die Informationen zu einer natürlichen Antwort zusammen und präsentiert dem Nutzer das bereitgestellte Angebot

* **Kunde:** Stellt Folgefragen

  * **Claude:** Beantwortet Folgefragen nach Bedarf
  * **Claude:** Führt den Kunden zu den nächsten Schritten im Versicherungsprozess und schließt das Gespräch ab

<Tip>
  In dem realen Beispiel, das du für deinen eigenen Anwendungsfall schreibst, kann es hilfreich sein, die tatsächlichen Formulierungen dieser Interaktion auszuschreiben, damit du auch ein Gefühl für den idealen Ton, die Antwortlänge und den Detailgrad bekommst, den Claude haben soll.
</Tip>

### Zerlege die Interaktion in einzelne Aufgaben

Ein Kundensupport-Chat ist eine Sammlung mehrerer unterschiedlicher Aufgaben – von der Beantwortung von Fragen über den Informationsabruf bis hin zum Ausführen von Aktionen auf Anfrage –, die in einer einzigen Kundeninteraktion gebündelt sind. Bevor du mit dem Entwickeln beginnst, zerlege deine ideale Kundeninteraktion in jede einzelne Aufgabe, die Claude ausführen können soll. So stellst du sicher, dass du Claude für jede Aufgabe prompten und evaluieren kannst, und bekommst ein gutes Gefühl für die Bandbreite an Interaktionen, die du beim Schreiben von Testfällen berücksichtigen musst.

<Tip>
  Kunden finden es manchmal hilfreich, dies als Interaktions-Flussdiagramm möglicher Gesprächswendepunkte in Abhängigkeit von Nutzeranfragen zu visualisieren.
</Tip>

Hier sind die wichtigsten Aufgaben, die mit der Beispiel-Versicherungsinteraktion verbunden sind:

1. Begrüßung und allgemeine Orientierung

   * Den Kunden herzlich begrüßen und das Gespräch beginnen
   * Allgemeine Informationen über das Unternehmen und die Interaktion bereitstellen

2. Produktinformationen

   * Informationen zum Versicherungsschutz für Elektrofahrzeuge bereitstellen
     <Note>
       Dies erfordert, dass Claude die notwendigen Informationen in seinem Kontext hat, und könnte bedeuten, dass eine 

       [RAG-Integration](https://platform.claude.com/cookbook/capabilities-retrieval-augmented-generation-guide)

        notwendig ist.
     </Note>
   * Fragen zu den besonderen Anforderungen von Elektrofahrzeug-Versicherungen beantworten
   * Folgefragen zum Angebot oder zu Versicherungsdetails beantworten
   * Bei Bedarf Links zu Quellen anbieten

3. Gesprächsführung

   * Beim Thema bleiben (Kfz-Versicherung)
   * Themenfremde Fragen zurück zu relevanten Themen lenken

4. Angebotserstellung

   * Geeignete Fragen stellen, um die Angebotsberechtigung zu ermitteln
   * Fragen basierend auf den Kundenantworten anpassen
   * Gesammelte Informationen an die API zur Angebotserstellung übermitteln
   * Dem Kunden das bereitgestellte Angebot präsentieren

### Lege Erfolgskriterien fest

Arbeite mit deinem Support-Team zusammen, um [Erfolgskriterien zu definieren und detaillierte Evaluierungen zu schreiben](https://platform.claude.com/docs/de/test-and-evaluate/develop-tests) – mit messbaren Benchmarks und Zielen.

Hier sind Kriterien und Benchmarks, mit denen sich bewerten lässt, wie erfolgreich Claude die definierten Aufgaben ausführt:

<AccordionGroup>
  <Accordion title="Genauigkeit des Anfrageverständnisses">
    Diese Metrik bewertet, wie genau Claude Kundenanfragen zu verschiedenen Themen versteht. Miss dies, indem du eine Stichprobe von Gesprächen überprüfst und beurteilst, ob Claude die Kundenabsicht, die entscheidenden nächsten Schritte, das Aussehen einer erfolgreichen Lösung und mehr korrekt interpretiert. Strebe eine Verständnisgenauigkeit von 95 % oder höher an.
  </Accordion>

  <Accordion title="Relevanz der Antworten">
    Hiermit wird bewertet, wie gut Claudes Antwort auf die konkrete Frage oder das Anliegen des Kunden eingeht. Evaluiere eine Reihe von Gesprächen und bewerte die Relevanz jeder Antwort (mit LLM-basierter Bewertung für die Skalierung). Strebe einen Relevanzwert von 90 % oder höher an.
  </Accordion>

  <Accordion title="Genauigkeit der Antworten">
    Beurteile die Korrektheit der allgemeinen Unternehmens- und Produktinformationen, die dem Nutzer bereitgestellt werden, basierend auf den Informationen, die Claude im Kontext zur Verfügung gestellt wurden. Strebe bei diesen einführenden Informationen eine Genauigkeit von 100 % an.
  </Accordion>

  <Accordion title="Relevanz der bereitgestellten Quellenangaben">
    Verfolge die Häufigkeit und Relevanz der angebotenen Links oder Quellen. Strebe an, in 80 % der Interaktionen, in denen zusätzliche Informationen nützlich sein könnten, relevante Quellen bereitzustellen.
  </Accordion>

  <Accordion title="Thementreue">
    Miss, wie gut Claude beim Thema bleibt, etwa beim Thema Kfz-Versicherung in der Beispielimplementierung. Strebe an, dass 95 % der Antworten direkt mit Kfz-Versicherungen oder der konkreten Anfrage des Kunden zusammenhängen.
  </Accordion>

  <Accordion title="Effektivität der Inhaltsgenerierung">
    Miss, wie erfolgreich Claude darin ist, zu bestimmen, wann informative Inhalte generiert werden sollen, und wie relevant diese Inhalte sind. In dieser Implementierung würdest du beispielsweise ermitteln, wie gut Claude versteht, wann ein Angebot erstellt werden soll, und wie genau dieses Angebot ist. Strebe eine Genauigkeit von 100 % an, da dies entscheidende Informationen für eine erfolgreiche Kundeninteraktion sind.
  </Accordion>

  <Accordion title="Eskalationseffizienz">
    Hiermit wird Claudes Fähigkeit gemessen, zu erkennen, wann eine Anfrage menschliches Eingreifen erfordert, und angemessen zu eskalieren. Verfolge den Prozentsatz korrekt eskalierter Gespräche im Vergleich zu denen, die hätten eskaliert werden sollen, aber nicht wurden. Strebe eine Eskalationsgenauigkeit von 95 % oder höher an.
  </Accordion>
</AccordionGroup>

Hier sind Kriterien und Benchmarks, mit denen sich die geschäftlichen Auswirkungen des Einsatzes von Claude im Support bewerten lassen:

<AccordionGroup>
  <Accordion title="Aufrechterhaltung der Stimmung">
    Hiermit wird Claudes Fähigkeit bewertet, die Kundenstimmung im Verlauf des Gesprächs aufrechtzuerhalten oder zu verbessern. Verwende Tools zur Sentiment-Analyse, um die Stimmung zu Beginn und am Ende jedes Gesprächs zu messen. Strebe eine gleichbleibende oder verbesserte Stimmung in 90 % der Interaktionen an.
  </Accordion>

  <Accordion title="Deflection-Rate">
    Der Prozentsatz der Kundenanfragen, die vom Chatbot erfolgreich ohne menschliches Eingreifen bearbeitet werden. Strebe typischerweise eine Deflection-Rate von 70–80 % an, abhängig von der Komplexität der Anfragen.
  </Accordion>

  <Accordion title="Kundenzufriedenheitswert">
    Ein Maß dafür, wie zufrieden Kunden mit ihrer Chatbot-Interaktion sind. Wird üblicherweise über Umfragen nach der Interaktion erhoben. Strebe einen CSAT-Wert von 4 von 5 oder höher an.
  </Accordion>

  <Accordion title="Durchschnittliche Bearbeitungszeit">
    Die durchschnittliche Zeit, die der Chatbot benötigt, um eine Anfrage zu lösen. Diese variiert stark je nach Komplexität der Anliegen, aber strebe im Allgemeinen eine niedrigere AHT im Vergleich zu menschlichen Mitarbeitenden an.
  </Accordion>
</AccordionGroup>

## So implementierst du Claude als Kundenservice-Agent

### Wähle das richtige Claude-Modell

Die Wahl des Modells hängt von den Abwägungen zwischen Kosten, Genauigkeit und Antwortzeit ab.

Für den Kundensupport-Chat eignet sich Claude Opus 5.5 gut, um Intelligenz, „latency“ (Latenz) und Kosten auszubalancieren, einschließlich der komplexesten Support-Szenarien, die tiefgehendes Schlussfolgern über lange, mehrstufige Gespräche erfordern. Für Fälle, in denen du einen Gesprächsablauf mit mehreren Prompts einschließlich RAG, Tool-Nutzung oder Prompts mit langem Kontext hast, kann Claude Haiku 5.5 jedoch besser geeignet sein, um die Latenz zu optimieren. [Effort](https://platform.claude.com/docs/de/build-with-claude/effort) ist dabei die wichtigste Stellschraube für die Geschwindigkeit: `low` ist die schnellste Stufe und eignet sich für Chats und kurze Tool-Aufgaben.

### Erstelle einen starken Prompt

Der Einsatz von Claude im Kundensupport erfordert, dass Claude genügend Anleitung und Kontext hat, um angemessen zu antworten, und gleichzeitig genügend Flexibilität, um ein breites Spektrum an Kundenanfragen zu bearbeiten.

Beginne damit, die Elemente eines starken Prompts zu schreiben, angefangen mit einem „system prompt“ (System-Prompt). Erstelle eine Datei namens `config.py` und füge ihr jeden der folgenden Blöcke hinzu:

```python
IDENTITY = """You are Eva, a friendly and knowledgeable AI assistant for Acme Insurance
Company. Your role is to warmly welcome customers and provide information on
Acme's insurance offerings, which include car insurance and electric car
insurance. You can also help customers get quotes for their insurance needs."""
```

<Tip>
  Auch wenn du versucht sein könntest, alle deine Informationen in einen System-Prompt zu packen, um Anweisungen von der Nutzerkonversation zu trennen, funktioniert Claude tatsächlich am besten, wenn der Großteil des Prompt-Inhalts im ersten 

  `User`

  -Turn steht (mit der einzigen Ausnahme des Rollen-Promptings). Lies mehr unter 

  [Claude mit einem System-Prompt eine Rolle geben](https://platform.claude.com/docs/de/build-with-claude/prompt-engineering/claude-prompting-best-practices#give-claude-a-role)

  .
</Tip>

Am besten zerlegst du komplexe Prompts in Unterabschnitte und schreibst einen Teil nach dem anderen. Für jede Aufgabe erzielst du möglicherweise größeren Erfolg, wenn du einem schrittweisen Prozess folgst, um die Teile des Prompts zu definieren, die Claude benötigt, um die Aufgabe gut zu erledigen. Für dieses Beispiel zum Kfz-Versicherungs-Kundensupport schreibst du Stück für Stück alle Teile eines Prompts, beginnend mit der Aufgabe „Begrüßung und allgemeine Orientierung“. Das erleichtert auch das Debugging deines Prompts, da du einzelne Teile des Gesamtprompts schneller anpassen kannst.

```python
STATIC_GREETINGS_AND_GENERAL = """
<static_context>
Acme Auto Insurance: Your Trusted Companion on the Road

About:
At Acme Insurance, we understand that your vehicle is more than just a mode of transportation—it's your ticket to life's adventures.
Since 1985, we've been crafting auto insurance policies that give drivers the confidence to explore, commute, and travel with peace of mind.
Whether you're navigating city streets or embarking on cross-country road trips, Acme is there to protect you and your vehicle.
Our innovative auto insurance policies are designed to adapt to your unique needs, covering everything from fender benders to major collisions.
With Acme's award-winning customer service and swift claim resolution, you can focus on the joy of driving while we handle the rest.
We're not just an insurance provider—we're your co-pilot in life's journeys.
Choose Acme Auto Insurance and experience the assurance that comes with superior coverage and genuine care. Because at Acme, we don't just
insure your car—we fuel your adventures on the open road.

Note: We also offer specialized coverage for electric vehicles, ensuring that drivers of all car types can benefit from our protection.

Acme Insurance offers the following products:
- Car insurance
- Electric car insurance
- Two-wheeler insurance

Business hours: Monday-Friday, 9 AM - 5 PM EST
Customer service number: 1-800-123-4567
</static_context>
"""
```

Mache dann dasselbe für deine Informationen zu Kfz-Versicherungen und Elektroauto-Versicherungen.

```python
STATIC_CAR_INSURANCE = """
<static_context>
Car Insurance Coverage:
Acme's car insurance policies typically cover:
1. Liability coverage: Pays for bodily injury and property damage you cause to others.
2. Collision coverage: Pays for damage to your car in an accident.
3. Comprehensive coverage: Pays for damage to your car from non-collision incidents.
4. Medical payments coverage: Pays for medical expenses after an accident.
5. Uninsured/underinsured motorist coverage: Protects you if you're hit by a driver with insufficient insurance.

Optional coverages include:
- Rental car reimbursement
- Roadside assistance
- New car replacement
</static_context>
"""

STATIC_ELECTRIC_CAR_INSURANCE = """
<static_context>
Electric Car Insurance:
Our specialized electric car insurance goes beyond traditional auto coverage,
offering tailored protection for your high-tech investment. In addition to standard coverages, we offer:
- Safeguarding expensive battery systems
- Covering home charging equipment
- Adapting to the rapidly evolving world of electric vehicles

Whether you're driving a Rivian, Nissan Leaf, Chevrolet Bolt,
or any other electric vehicle, our knowledgeable agents are ready to craft a policy
that gives you the confidence to enjoy every electron-powered mile.
</static_context>
"""
```

Nachdem du nun deine statischen Inhalte hast, füge mindestens 4–5 „gute“ Beispielinteraktionen hinzu, um Claudes Antworten zu lenken. Diese Beispiele sollten repräsentativ für deine ideale Kundeninteraktion sein und können Elemente wie Guardrails und Tool-Aufrufe enthalten.

```python
EXAMPLES = """
Here are a few examples of how you can interact with customers:

<example 1>
H: Hi, do you offer commercial insurance for small businesses?

A: Ah! Unfortunately, we don't offer commercial insurance at this time.
However, we do provide a range of personal insurance products including car insurance and electric car insurance.
Would you like to know more about these offerings?
</example 1>

<example 2>
H: Hi, what are your business hours?

A: Our business hours are Monday to Friday, 9 AM to 5 PM EST.
If you have any questions or need assistance, feel free to reach out during those times.
How else can I assist you today?
</example 2>

<example 3>
H: I'm shopping for car insurance. What does Acme offer?

A: Great choice! Acme's car insurance policies typically include:
- Liability coverage: Protects you if you're at fault in an accident
- Collision coverage: Pays for damage to your car in an accident
- Comprehensive coverage: Covers non-collision incidents like theft or vandalism
- Medical payments coverage: Pays for medical expenses after an accident
- Uninsured/underinsured motorist coverage: Protects you from drivers with insufficient insurance

We also offer optional coverages like rental car reimbursement, roadside assistance, and new car replacement.
Would you like more details on any of these coverages, or do you have specific questions about insuring your vehicle?
</example 3>

<example 4>
H: I'd like to hear about your electric car insurance.

A: Certainly! Our electric car insurance is specially designed to meet the unique needs of electric vehicle owners.
In addition to all the standard coverages we offer for regular cars, our electric car policies include:

- Battery coverage: Protection against damage or degradation of your vehicle's expensive battery system
- Tech package: Covers repairs or replacement of advanced electronics and onboard computer systems
- Charging station coverage: Protects both home and portable charging equipment
- Cybersecurity protection: Coverage against hacking or digital threats
- Specialized roadside assistance: Includes flatbed towing to protect the vehicle's undercarriage

We cover a wide range of electric vehicles, including popular models from Tesla, Rivian, Nissan, Chevrolet, and more.
Is there a specific electric vehicle you're looking to insure, or would you like more details on any of these coverages?
</example 4>

<example 5>
H: I'd like to get a quote for my car insurance.

A: Certainly! I'd be happy to help you get a quote for your car insurance.
To provide you with an accurate quote, I'll need to collect some information about your vehicle and the primary driver.
Let's start with the basics:

1. What is the make and model of your vehicle?
2. What year was it manufactured?
3. Approximately how many miles have you driven?
4. What is the age of the primary driver?

Once you provide this information, I'll use our quoting tool to generate a personalized insurance quote for you.
</example 5>
"""
```

Du solltest außerdem alle wichtigen Anweisungen aufnehmen, die Dos and Don'ts dafür festlegen, wie Claude mit dem Kunden interagieren soll. Diese können sich aus Marken-Guardrails oder Support-Richtlinien ableiten.

```python
ADDITIONAL_GUARDRAILS = """Please adhere to the following guardrails:
1. Only provide information about insurance types listed in our offerings.
2. If asked about an insurance type we don't offer, politely state
that we don't provide that service.
3. Do not speculate about future product offerings or company plans.
4. Don't make promises or enter into agreements it's not authorized to make.
You only provide information and guidance.
5. Do not mention any competitor's products or services.
"""
```

Kombiniere nun alle diese Abschnitte zu einem einzigen String, den du als Prompt verwendest.

```python
TASK_SPECIFIC_INSTRUCTIONS = " ".join(
    [
        STATIC_GREETINGS_AND_GENERAL,
        STATIC_CAR_INSURANCE,
        STATIC_ELECTRIC_CAR_INSURANCE,
        EXAMPLES,
        ADDITIONAL_GUARDRAILS,
    ]
)
```

### Füge dynamische und agentische Fähigkeiten mit Tool-Nutzung hinzu

Claude ist in der Lage, mithilfe clientseitiger „tool use“-Funktionalität (Tool-Nutzung) Aktionen auszuführen und Informationen dynamisch abzurufen. Beginne damit, alle externen Tools oder APIs aufzulisten, die der Prompt verwenden soll.

Für dieses Beispiel beginnst du mit einem Tool zur Berechnung des Angebots.

<Tip>
  Zur Erinnerung: Dieses Tool führt nicht die eigentliche Berechnung durch, sondern signalisiert der Anwendung lediglich, dass ein Tool mit den jeweils angegebenen Argumenten verwendet werden soll.
</Tip>

Füge den Modellnamen, die Tool-Definition und eine Stub-Implementierung zu `config.py` hinzu:

```python
import time

MODEL = "claude-opus-5-5"

TOOLS = [
    {
        "name": "get_quote",
        "description": "Calculate the insurance quote based on user input. Returned value is per month premium.",
        "input_schema": {
            "type": "object",
            "properties": {
                "make": {"type": "string", "description": "The make of the vehicle."},
                "model": {"type": "string", "description": "The model of the vehicle."},
                "year": {
                    "type": "integer",
                    "description": "The year the vehicle was manufactured.",
                },
                "mileage": {
                    "type": "integer",
                    "description": "The mileage on the vehicle.",
                },
                "driver_age": {
                    "type": "integer",
                    "description": "The age of the primary driver.",
                },
            },
            "required": ["make", "model", "year", "mileage", "driver_age"],
        },
    }
]


def get_quote(make, model, year, mileage, driver_age):
    """Returns the premium per month in USD"""
    # Du kannst einen HTTP-Endpunkt oder eine Datenbank aufrufen, um den Kurs abzurufen.
    # Hier simulieren wir eine Verzögerung von 1 Sekunde und geben einen festen Kurs von 100 zurück.
    time.sleep(1)
    return 100
```

### Stelle deine Prompts bereit

Es ist schwer zu wissen, wie gut dein Prompt funktioniert, ohne ihn in einer Test-Produktionsumgebung bereitzustellen und [Evaluierungen durchzuführen](https://platform.claude.com/docs/de/test-and-evaluate/develop-tests). Erstelle eine kleine Anwendung mit dem Prompt, dem Anthropic SDK und Streamlit als Benutzeroberfläche.

Richte in einer Datei namens `chatbot.py` (oder dem entsprechenden Modul in deiner Sprache) die ChatBot-Klasse ein, die die Interaktionen mit dem Anthropic SDK kapselt.

Die Klasse sollte zwei Hauptmethoden haben: eine, die die API aufruft, um eine Nachricht zu generieren, und eine, die jede eingehende Nutzereingabe verarbeitet.

<CodeGroup exclude="shell">
  ```python Python
  # Importiere diese in deiner chatbot.py aus der config.py, die du oben erstellt hast:
  # from config import IDENTITY, TOOLS, MODEL, get_quote
  from anthropic import Anthropic
  from dotenv import load_dotenv

  load_dotenv()


  class ChatBot:
      def __init__(self, session_state):
          self.anthropic = Anthropic()
          self.session_state = session_state

      def generate_message(
          self,
          messages,
          max_tokens,
      ):
          try:
              response = self.anthropic.messages.create(
                  model=MODEL,
                  system=IDENTITY,
                  max_tokens=max_tokens,
                  messages=messages,
                  tools=TOOLS,
              )
              return response
          except Exception as e:
              return {"error": str(e)}

      def process_user_input(self, user_input):
          self.session_state.messages.append({"role": "user", "content": user_input})

          response_message = self.generate_message(
              messages=self.session_state.messages,
              max_tokens=2048,
          )

          if "error" in response_message:
              return f"An error occurred: {response_message['error']}"

          if response_message.content[-1].type == "tool_use":
              tool_use = response_message.content[-1]
              func_name = tool_use.name
              func_params = tool_use.input
              tool_use_id = tool_use.id

              result = self.handle_tool_use(func_name, func_params)
              self.session_state.messages.append(
                  {"role": "assistant", "content": response_message.content}
              )
              self.session_state.messages.append(
                  {
                      "role": "user",
                      "content": [
                          {
                              "type": "tool_result",
                              "tool_use_id": tool_use_id,
                              "content": f"{result}",
                          }
                      ],
                  }
              )

              follow_up_response = self.generate_message(
                  messages=self.session_state.messages,
                  max_tokens=2048,
              )

              if "error" in follow_up_response:
                  return f"An error occurred: {follow_up_response['error']}"

              response_text = next(
                  (
                      block.text
                      for block in follow_up_response.content
                      if block.type == "text"
                  ),
                  None,
              )
              if response_text is None:
                  raise Exception("An error occurred: Unexpected response type")
              self.session_state.messages.append(
                  {"role": "assistant", "content": response_text}
              )
              return response_text

          text_block = next(
              (block for block in response_message.content if block.type == "text"), None
          )
          if text_block is not None:
              response_text = text_block.text
              self.session_state.messages.append(
                  {"role": "assistant", "content": response_text}
              )
              return response_text

          raise Exception("An error occurred: Unexpected response type")

      def handle_tool_use(self, func_name, func_params):
          if func_name == "get_quote":
              premium = get_quote(**func_params)
              return f"Quote generated: ${premium:.2f} per month"

          raise Exception("An unexpected tool was used")
  ```

  ```typescript TypeScript
  import Anthropic from "@anthropic-ai/sdk";

  class ChatBot {
    // IDENTITY, MODEL, TOOLS und getQuote spiegeln die config.py-Werte wider, die
    // weiter oben in diesem Leitfaden definiert wurden (in Python gezeigt).
    readonly anthropic = new Anthropic();
    readonly messages: Anthropic.MessageParam[] = [];

    async generateMessage(
      messages: Anthropic.MessageParam[],
      maxTokens: number
    ): Promise<Anthropic.Message> {
      return this.anthropic.messages.create({
        model: MODEL,
        system: IDENTITY,
        max_tokens: maxTokens,
        messages,
        tools: TOOLS
      });
    }

    async processUserInput(userInput: string): Promise<string> {
      this.messages.push({ role: "user", content: userInput });

      const responseMessage = await this.generateMessage(this.messages, 2048);

      const lastBlock = responseMessage.content.at(-1);
      if (lastBlock?.type === "tool_use") {
        const toolResult = this.handleToolUse(lastBlock.name, lastBlock.input);

        this.messages.push({ role: "assistant", content: responseMessage.content });
        this.messages.push({
          role: "user",
          content: [{ type: "tool_result", tool_use_id: lastBlock.id, content: toolResult }]
        });

        const followUpResponse = await this.generateMessage(this.messages, 2048);

        const followUpBlock = followUpResponse.content.find((block) => block.type === "text");
        if (!followUpBlock) {
          throw new Error("An error occurred: Unexpected response type");
        }
        this.messages.push({ role: "assistant", content: followUpBlock.text });
        return followUpBlock.text;
      }

      const firstBlock = responseMessage.content.find((block) => block.type === "text");
      if (firstBlock) {
        this.messages.push({ role: "assistant", content: firstBlock.text });
        return firstBlock.text;
      }

      throw new Error("An error occurred: Unexpected response type");
    }

    handleToolUse(toolName: string, toolInput: unknown): string {
      if (toolName === "get_quote") {
        // Das SDK typisiert tool_use.input als unknown; grenze es auf das get_quote-Schema ein.
        if (
          toolInput === null ||
          typeof toolInput !== "object" ||
          !("make" in toolInput) ||
          typeof toolInput.make !== "string" ||
          !("model" in toolInput) ||
          typeof toolInput.model !== "string" ||
          !("year" in toolInput) ||
          typeof toolInput.year !== "number" ||
          !("mileage" in toolInput) ||
          typeof toolInput.mileage !== "number" ||
          !("driver_age" in toolInput) ||
          typeof toolInput.driver_age !== "number"
        ) {
          throw new Error("An error occurred: Unexpected tool input");
        }
        const { make, model: vehicleModel, year, mileage, driver_age: driverAge } = toolInput;

        const premium = getQuote(make, vehicleModel, year, mileage, driverAge);
        return `Quote generated: $${premium.toFixed(2)} per month`;
      }

      throw new Error("An unexpected tool was used");
    }
  }
  ```

  ```csharp C#
  using System.Text.Json;
  using Anthropic;
  using Anthropic.Models.Messages;

  // Config.Model, Config.Identity, Config.Tools und Config.GetQuote spiegeln
  // die config.py-Werte, die zuvor in diesem Guide definiert wurden (in Python gezeigt).
  public class ChatBot
  {
      private readonly AnthropicClient _anthropic = new();

      public List<MessageParam> Messages { get; } = [];

      public async Task<Message> GenerateMessage(List<MessageParam> messages, long maxTokens) =>
          await _anthropic.Messages.Create(
              new MessageCreateParams
              {
                  Model = Config.Model,
                  System = Config.Identity,
                  MaxTokens = maxTokens,
                  Messages = messages,
                  Tools = Config.Tools,
              }
          );

      public async Task<string> ProcessUserInput(string userInput)
      {
          Messages.Add(new() { Role = Role.User, Content = userInput });

          var responseMessage = await GenerateMessage(Messages, maxTokens: 2048);

          if (responseMessage.Content[^1].TryPickToolUse(out var toolUse))
          {
              var toolResult = HandleToolUse(toolUse.Name, toolUse.Input);

              Messages.Add(new()
              {
                  Role = Role.Assistant,
                  Content = responseMessage.Content
                      .Select(contentBlock => new ContentBlockParam(contentBlock.Json))
                      .ToList(),
              });
              Messages.Add(new()
              {
                  Role = Role.User,
                  Content = new List<ContentBlockParam>
                  {
                      new ToolResultBlockParam { ToolUseID = toolUse.ID, Content = toolResult },
                  },
              });

              var followUpResponse = await GenerateMessage(Messages, maxTokens: 2048);

              foreach (var block in followUpResponse.Content)
              {
                  if (block.TryPickText(out var followUpText))
                  {
                      Messages.Add(new() { Role = Role.Assistant, Content = followUpText.Text });
                      return followUpText.Text;
                  }
              }

              throw new InvalidOperationException("An error occurred: Unexpected response type");
          }

          foreach (var block in responseMessage.Content)
          {
              if (block.TryPickText(out var textBlock))
              {
                  Messages.Add(new() { Role = Role.Assistant, Content = textBlock.Text });
                  return textBlock.Text;
              }
          }

          throw new InvalidOperationException("An error occurred: Unexpected response type");
      }

      public string HandleToolUse(string funcName, IReadOnlyDictionary<string, JsonElement> funcParams)
      {
          if (funcName == "get_quote")
          {
              var premium = Config.GetQuote(
                  funcParams["make"].GetString()!,
                  funcParams["model"].GetString()!,
                  funcParams["year"].GetInt64(),
                  funcParams["mileage"].GetInt64(),
                  funcParams["driver_age"].GetInt64()
              );
              return $"Quote generated: ${premium:F2} per month";
          }

          throw new ArgumentException("An unexpected tool was used");
      }
  }
  ```

  ```go Go
  import (
  	"context"
  	"encoding/json"
  	"fmt"

  	"github.com/anthropics/anthropic-sdk-go"
  )

  // ChatBot kapselt den Anthropic-Client und den Gesprächsverlauf. Die
  // verwendeten Werte für identity, model, tools und getQuote spiegeln die
  // config.py-Definitionen weiter oben in diesem Guide wider (in Python gezeigt).
  type ChatBot struct {
  	client   anthropic.Client
  	messages []anthropic.MessageParam
  }

  func NewChatBot() *ChatBot {
  	return &ChatBot{client: anthropic.NewClient()}
  }

  func (bot *ChatBot) GenerateMessage(ctx context.Context, messages []anthropic.MessageParam, maxTokens int64) (*anthropic.Message, error) {
  	return bot.client.Messages.New(ctx, anthropic.MessageNewParams{
  		Model:     model,
  		System:    []anthropic.TextBlockParam{{Text: identity}},
  		MaxTokens: maxTokens,
  		Messages:  messages,
  		Tools:     tools,
  	})
  }

  func (bot *ChatBot) ProcessUserInput(ctx context.Context, userInput string) (string, error) {
  	bot.messages = append(bot.messages, anthropic.NewUserMessage(anthropic.NewTextBlock(userInput)))

  	response, err := bot.GenerateMessage(ctx, bot.messages, 2048)
  	if err != nil {
  		return "", err
  	}

  	lastBlock := response.Content[len(response.Content)-1]
  	if toolUse, ok := lastBlock.AsAny().(anthropic.ToolUseBlock); ok {
  		result, err := bot.HandleToolUse(toolUse.Name, toolUse.Input)
  		if err != nil {
  			return "", err
  		}

  		bot.messages = append(bot.messages,
  			response.ToParam(),
  			anthropic.NewUserMessage(anthropic.NewToolResultBlock(toolUse.ID, result, false)),
  		)

  		followUp, err := bot.GenerateMessage(ctx, bot.messages, 2048)
  		if err != nil {
  			return "", err
  		}

  		for _, block := range followUp.Content {
  			if textBlock, ok := block.AsAny().(anthropic.TextBlock); ok {
  				bot.messages = append(bot.messages, anthropic.NewAssistantMessage(anthropic.NewTextBlock(textBlock.Text)))
  				return textBlock.Text, nil
  			}
  		}
  		return "", fmt.Errorf("an error occurred: unexpected response type")
  	}

  	for _, block := range response.Content {
  		if textBlock, ok := block.AsAny().(anthropic.TextBlock); ok {
  			bot.messages = append(bot.messages, anthropic.NewAssistantMessage(anthropic.NewTextBlock(textBlock.Text)))
  			return textBlock.Text, nil
  		}
  	}

  	return "", fmt.Errorf("an error occurred: unexpected response type")
  }

  func (bot *ChatBot) HandleToolUse(toolName string, toolInput json.RawMessage) (string, error) {
  	if toolName != "get_quote" {
  		return "", fmt.Errorf("an unexpected tool was used: %s", toolName)
  	}

  	var input struct {
  		Make      string `json:"make"`
  		Model     string `json:"model"`
  		Year      int    `json:"year"`
  		Mileage   int    `json:"mileage"`
  		DriverAge int    `json:"driver_age"`
  	}
  	if err := json.Unmarshal(toolInput, &input); err != nil {
  		return "", err
  	}
  	premium := getQuote(input.Make, input.Model, input.Year, input.Mileage, input.DriverAge)
  	return fmt.Sprintf("Quote generated: $%.2f per month", premium), nil
  }
  ```

  ```java Java
  import com.anthropic.client.AnthropicClient;
  import com.anthropic.client.okhttp.AnthropicOkHttpClient;
  import com.anthropic.core.JsonValue;
  import com.anthropic.models.messages.ContentBlock;
  import com.anthropic.models.messages.ContentBlockParam;
  import com.anthropic.models.messages.Message;
  import com.anthropic.models.messages.MessageCreateParams;
  import com.anthropic.models.messages.MessageParam;
  import com.anthropic.models.messages.ToolResultBlockParam;
  import com.anthropic.models.messages.ToolUseBlock;

  // IDENTITY, MODEL, TOOLS und getQuote spiegeln die config.py-Werte wider, die
  // weiter oben in diesem Leitfaden definiert wurden (in Python gezeigt).
  class ChatBot {
      final AnthropicClient anthropic;
      final List<MessageParam> messages;

      ChatBot() {
          // Liest den API-Key aus der Umgebungsvariable ANTHROPIC_API_KEY
          this.anthropic = AnthropicOkHttpClient.fromEnv();
          this.messages = new ArrayList<>();
      }

      Message generateMessage(List<MessageParam> messages, long maxTokens) {
          return anthropic.messages().create(MessageCreateParams.builder()
                  .model(MODEL)
                  .system(IDENTITY)
                  .maxTokens(maxTokens)
                  .messages(messages)
                  .tools(TOOLS)
                  .build());
      }

      String processUserInput(String userInput) {
          messages.add(MessageParam.builder()
                  .role(MessageParam.Role.USER)
                  .content(userInput)
                  .build());

          Message responseMessage = generateMessage(messages, 2048);

          List<ContentBlock> content = responseMessage.content();
          ContentBlock lastBlock = content.getLast();
          if (lastBlock.isToolUse()) {
              ToolUseBlock toolUse = lastBlock.asToolUse();
              Map<String, JsonValue> toolInput =
                      (Map<String, JsonValue>) toolUse._input().asObject().orElseThrow();
              String result = handleToolUse(toolUse.name(), toolInput);

              messages.add(MessageParam.builder()
                      .role(MessageParam.Role.ASSISTANT)
                      .contentOfBlockParams(content.stream().map(ContentBlock::toParam).toList())
                      .build());
              messages.add(MessageParam.builder()
                      .role(MessageParam.Role.USER)
                      .contentOfBlockParams(List.of(ContentBlockParam.ofToolResult(
                              ToolResultBlockParam.builder()
                                      .toolUseId(toolUse.id())
                                      .content(result)
                                      .build())))
                      .build());

              Message followUpResponse = generateMessage(messages, 2048);

              ContentBlock followUpBlock = followUpResponse.content().stream()
                      .filter(ContentBlock::isText)
                      .findFirst()
                      .orElseThrow(() -> new IllegalStateException("An error occurred: Unexpected response type"));
              String responseText = followUpBlock.asText().text();
              messages.add(MessageParam.builder()
                      .role(MessageParam.Role.ASSISTANT)
                      .content(responseText)
                      .build());
              return responseText;
          } else {
              ContentBlock textBlock = content.stream()
                      .filter(ContentBlock::isText)
                      .findFirst()
                      .orElseThrow(() -> new IllegalStateException("An error occurred: Unexpected response type"));
              String responseText = textBlock.asText().text();
              messages.add(MessageParam.builder()
                      .role(MessageParam.Role.ASSISTANT)
                      .content(responseText)
                      .build());
              return responseText;
          }
      }

      String handleToolUse(String funcName, Map<String, JsonValue> funcParams) {
          return switch (funcName) {
              case "get_quote" -> {
                  double premium = getQuote(
                          funcParams.get("make").asStringOrThrow(),
                          funcParams.get("model").asStringOrThrow(),
                          ((Number) funcParams.get("year").asNumber().orElseThrow()).longValue(),
                          ((Number) funcParams.get("mileage").asNumber().orElseThrow()).longValue(),
                          ((Number) funcParams.get("driver_age").asNumber().orElseThrow()).longValue());
                  yield "Quote generated: $%.2f per month".formatted(premium);
              }
              default -> throw new IllegalArgumentException("An unexpected tool was used");
          };
      }
  }
  ```

  ```php PHP
  use Anthropic\Client;
  use Anthropic\Messages\Message;
  use Anthropic\Messages\MessageParam;
  use Anthropic\Messages\TextBlock;
  use Anthropic\Messages\ToolResultBlockParam;
  use Anthropic\Messages\ToolUseBlock;

  class ChatBot
  {
      // MODEL, IDENTITY, TOOLS und get_quote() spiegeln die config.py-Werte wider,
      // die zuvor in diesem Leitfaden definiert wurden (in Python gezeigt).

      /** @var list<MessageParam> */
      public private(set) array $messages = [];

      public function __construct(
          private readonly Client $anthropic = new Client(),
      ) {}

      /**
       * @param list<MessageParam> $messages
       */
      public function generateMessage(array $messages, int $maxTokens): Message
      {
          return $this->anthropic->messages->create(
              model: MODEL,
              system: IDENTITY,
              maxTokens: $maxTokens,
              messages: $messages,
              tools: TOOLS,
          );
      }

      public function processUserInput(string $userInput): string
      {
          $this->messages[] = MessageParam::with(role: 'user', content: $userInput);

          $responseMessage = $this->generateMessage($this->messages, maxTokens: 2048);

          $content = $responseMessage->content;
          $lastBlock = array_last($content);

          if ($lastBlock instanceof ToolUseBlock) {
              $toolResult = $this->handleToolUse($lastBlock->name, $lastBlock->input);

              $this->messages[] = MessageParam::with(role: 'assistant', content: $content);
              $this->messages[] = MessageParam::with(
                  role: 'user',
                  content: [
                      ToolResultBlockParam::with(toolUseID: $lastBlock->id, content: $toolResult),
                  ],
              );

              $followUpResponse = $this->generateMessage($this->messages, maxTokens: 2048);

              $firstBlock = array_find(
                  $followUpResponse->content,
                  static fn ($block): bool => $block instanceof TextBlock,
              );
              if (!$firstBlock instanceof TextBlock) {
                  throw new \RuntimeException('An error occurred: Unexpected response type');
              }

              $this->messages[] = MessageParam::with(role: 'assistant', content: $firstBlock->text);

              return $firstBlock->text;
          }

          $firstBlock = array_find($content, static fn ($block): bool => $block instanceof TextBlock);
          if ($firstBlock instanceof TextBlock) {
              $this->messages[] = MessageParam::with(role: 'assistant', content: $firstBlock->text);

              return $firstBlock->text;
          }

          throw new \RuntimeException('An error occurred: Unexpected response type');
      }

      /**
       * @param array<string, mixed> $funcParams
       */
      private function handleToolUse(string $funcName, array $funcParams): string
      {
          if ($funcName === 'get_quote') {
              $premium = get_quote(...$funcParams);

              return sprintf('Quote generated: $%.2f per month', $premium);
          }

          throw new \RuntimeException('An unexpected tool was used');
      }
  }
  ```

  ```ruby Ruby
  # IDENTITY, MODEL, TOOLS und get_quote spiegeln die config.py-Werte wider, die
  # weiter oben in diesem Guide definiert wurden (in Python gezeigt).
  require "anthropic"

  class ChatBot
    attr_reader :messages

    def initialize
      @anthropic = Anthropic::Client.new
      @messages = []
    end

    def generate_message(messages, max_tokens)
      @anthropic.messages.create(
        model: MODEL,
        system_: IDENTITY,
        max_tokens:,
        messages:,
        tools: TOOLS
      )
    end

    def process_user_input(user_input)
      @messages << {role: "user", content: user_input}

      response_message = generate_message(@messages, 2048)

      case response_message.content
      in [*, Anthropic::ToolUseBlock => tool_use]
        result = handle_tool_use(tool_use.name, tool_use.input)
        @messages << {role: "assistant", content: response_message.content}
        @messages << {
          role: "user",
          content: [{type: "tool_result", tool_use_id: tool_use.id, content: result}]
        }

        follow_up_response = generate_message(@messages, 2048)

        case follow_up_response.content
        in [*, Anthropic::TextBlock => text_block, *]
          @messages << {role: "assistant", content: text_block.text}
          text_block.text
        else
          raise "An error occurred: Unexpected response type"
        end
      in [*, Anthropic::TextBlock => text_block, *]
        @messages << {role: "assistant", content: text_block.text}
        text_block.text
      else
        raise "An error occurred: Unexpected response type"
      end
    end

    def handle_tool_use(tool_name, tool_input)
      raise "An unexpected tool was used" unless tool_name == "get_quote"

      premium = get_quote(**tool_input)
      format("Quote generated: $%.2f per month", premium)
    end
  end
  ```
</CodeGroup>

### Erstelle deine Benutzeroberfläche

Teste die Bereitstellung dieses Codes mit Streamlit über eine main-Methode. Diese `main()`-Funktion richtet eine Streamlit-basierte Chat-Oberfläche ein. Streamlit ist ein Python-Framework, daher wird dieser Teil der Anleitung nur in Python gezeigt; die ChatBot-Klasse oben ist der Teil, den du in jede beliebige Sprache portieren kannst.

Mache dies in einer Datei namens `app.py`

```python
import streamlit as st
from chatbot import ChatBot
from config import TASK_SPECIFIC_INSTRUCTIONS


def main():
    st.title("Chat with Eva, Acme Insurance Company's Assistant🤖")

    if "messages" not in st.session_state:
        st.session_state.messages = [
            {"role": "user", "content": TASK_SPECIFIC_INSTRUCTIONS},
            {"role": "assistant", "content": "Understood"},
        ]

    chatbot = ChatBot(st.session_state)

    # Benutzer- und Assistenten-Nachrichten anzeigen, die ersten beiden überspringen
    for message in st.session_state.messages[2:]:
        # Tool-Use-Blöcke ignorieren
        if isinstance(message["content"], str):
            with st.chat_message(message["role"]):
                st.markdown(message["content"])

    if user_msg := st.chat_input("Type your message here..."):
        st.chat_message("user").markdown(user_msg)

        with st.chat_message("assistant"):
            with st.spinner("Eva is thinking..."):
                response_placeholder = st.empty()
                full_response = chatbot.process_user_input(user_msg)
                response_placeholder.markdown(full_response)


if __name__ == "__main__":
    main()
```

Führe das Programm aus mit:

```bash
streamlit run app.py
```

### Evaluiere deine Prompts

Prompting erfordert häufig Tests und Optimierung, um produktionsreif zu sein. Um die Einsatzbereitschaft deiner Lösung zu bestimmen, evaluiere die Chatbot-Leistung mit einem systematischen Prozess, der quantitative und qualitative Methoden kombiniert. Eine [starke empirische Evaluierung](https://platform.claude.com/docs/de/test-and-evaluate/develop-tests#build-evaluations) auf Basis deiner definierten Erfolgskriterien ermöglicht es dir, deine Prompts zu optimieren.

### Verbessere die Leistung

In komplexen Szenarien kann es hilfreich sein, zusätzliche Strategien zur Leistungsverbesserung in Betracht zu ziehen, die über standardmäßige [Prompt-Engineering-Techniken](https://platform.claude.com/docs/de/build-with-claude/prompt-engineering/overview) und [Strategien zur Guardrail-Implementierung](https://platform.claude.com/docs/de/test-and-evaluate/strengthen-guardrails/reduce-hallucinations) hinausgehen. Hier sind einige häufige Szenarien:

#### Reduziere die Latenz bei langem Kontext mit RAG

Beim Umgang mit großen Mengen statischen und dynamischen Kontexts kann das Einbinden aller Informationen in den Prompt zu hohen Kosten, langsameren Antwortzeiten und dem Erreichen der Grenzen des „context window“ (Kontextfenster) führen. In diesem Szenario kann die Implementierung von „Retrieval Augmented Generation“-Techniken (abrufgestützte Generierung), oder RAG, die Leistung und Effizienz verbessern.

Du kannst ein skalierbareres und reaktionsschnelleres System erstellen, indem du Informationen mit [Embedding-Modellen](https://platform.claude.com/docs/de/build-with-claude/embeddings), etwa denen von Voyage AI by MongoDB, in Vektordarstellungen umwandelst. Dieser Ansatz ermöglicht den dynamischen Abruf relevanter Informationen basierend auf der aktuellen Anfrage, anstatt den gesamten möglichen Kontext in jeden Prompt aufzunehmen.

Die Implementierung von RAG für Support-Anwendungsfälle hat sich als geeignet erwiesen, die Genauigkeit zu erhöhen, Antwortzeiten zu verkürzen und API-Kosten in Systemen mit umfangreichen Kontextanforderungen zu senken. Sieh dir das [RAG-Rezept](https://platform.claude.com/cookbook/capabilities-retrieval-augmented-generation-guide) für ein ausgearbeitetes Beispiel an.

#### Integriere Echtzeitdaten mit Tool-Nutzung

Bei Anfragen, die Echtzeitinformationen erfordern, wie Kontostände oder Policendetails, reichen Embedding-basierte RAG-Ansätze nicht aus. Stattdessen kann Tool-Nutzung die Fähigkeit deines Chatbots verbessern, präzise Echtzeitantworten zu liefern. Du kannst Tool-Nutzung beispielsweise verwenden, um Kundeninformationen nachzuschlagen, Bestelldetails abzurufen und Bestellungen im Namen des Kunden zu stornieren.

Dieser Ansatz, [beschrieben im Rezept Tool-Nutzung: Kundenservice-Agent](https://platform.claude.com/cookbook/tool-use-customer-service-agent), ermöglicht es dir, Live-Daten in Claudes Antworten zu integrieren und ein persönlicheres und effizienteres Kundenerlebnis zu bieten.

#### Stärke Eingabe- und Ausgabe-Guardrails

Bei der Bereitstellung eines Chatbots, insbesondere in Kundenservice-Szenarien, ist es wichtig, Risiken im Zusammenhang mit Missbrauch, Anfragen außerhalb des Geltungsbereichs und unangemessenen Antworten vorzubeugen. Obwohl Claude von Natur aus widerstandsfähig gegenüber solchen Szenarien ist, sind hier zusätzliche Schritte, um die Guardrails deines Chatbots zu stärken:

* [Halluzinationen reduzieren](https://platform.claude.com/docs/de/test-and-evaluate/strengthen-guardrails/reduce-hallucinations): Implementiere Mechanismen zur Faktenprüfung und [Zitate](https://platform.claude.com/cookbook/misc-using-citations), um Antworten in den bereitgestellten Informationen zu verankern.
* Informationen gegenprüfen: Verifiziere, dass die Antworten des Agenten mit den Richtlinien deines Unternehmens und bekannten Fakten übereinstimmen.
* Vertragliche Verpflichtungen vermeiden: Stelle sicher, dass der Agent keine Versprechen macht oder Vereinbarungen eingeht, zu denen er nicht befugt ist.
* [Jailbreaks abschwächen](https://platform.claude.com/docs/de/test-and-evaluate/strengthen-guardrails/mitigate-jailbreaks): Verwende Methoden wie Harmlosigkeitsprüfungen und Eingabevalidierung, um zu verhindern, dass Nutzer Modellschwachstellen ausnutzen, um unangemessene Inhalte zu generieren.
* Erwähnung von Wettbewerbern vermeiden: Implementiere einen Filter für Wettbewerbererwähnungen, um den Markenfokus zu wahren und keine Produkte oder Dienstleistungen von Wettbewerbern zu erwähnen.
* [Ausgabekonsistenz erhöhen](https://platform.claude.com/docs/de/test-and-evaluate/strengthen-guardrails/increase-consistency): Verhindere, dass Claude den Stil ändert oder aus der Rolle fällt, selbst bei langen, komplexen Interaktionen.
* Personenbezogene Daten (PII) entfernen: Sofern nicht ausdrücklich erforderlich und autorisiert, entferne alle personenbezogenen Daten aus den Antworten.

#### Reduziere die wahrgenommene Antwortzeit mit Streaming

Bei potenziell langen Antworten kann die Implementierung von „streaming“ (Streaming) das Engagement und die Zufriedenheit der Nutzer verbessern. In diesem Szenario erhalten Nutzer die Antwort schrittweise, anstatt darauf zu warten, dass die gesamte Antwort generiert wird.

So implementierst du Streaming:

1. Verwende die [Anthropic Streaming API](https://platform.claude.com/docs/de/build-with-claude/streaming), um Streaming-Antworten zu unterstützen.
2. Richte dein Frontend so ein, dass es eingehende Textabschnitte verarbeitet.
3. Zeige jeden Abschnitt an, sobald er eintrifft, und simuliere so Tippen in Echtzeit.
4. Implementiere einen Mechanismus zum Speichern der vollständigen Antwort, damit Nutzer sie ansehen können, wenn sie die Seite verlassen und zurückkehren.

In manchen Fällen ermöglicht Streaming den Einsatz fortschrittlicherer Modelle mit höheren Basislatenzen, da die schrittweise Anzeige die Auswirkungen längerer Verarbeitungszeiten abmildert.

#### Skaliere deinen Chatbot

Mit wachsender Komplexität deines Chatbots kann sich deine Anwendungsarchitektur entsprechend weiterentwickeln. Bevor du deiner Architektur weitere Schichten hinzufügst, ziehe die folgenden weniger aufwendigen Optionen in Betracht:

* Stelle sicher, dass du das Beste aus deinen Prompts herausholst und durch Prompt-Engineering optimierst. Nutze die [Prompt-Engineering-Leitfäden](https://platform.claude.com/docs/de/build-with-claude/prompt-engineering/overview), um die effektivsten Prompts zu schreiben.
* Füge dem Prompt zusätzliche [Tools](https://platform.claude.com/docs/de/agents-and-tools/tool-use/overview) hinzu (die auch [Prompt-Ketten](https://platform.claude.com/docs/de/build-with-claude/prompt-engineering/claude-prompting-best-practices#chain-complex-prompts) umfassen können) und prüfe, ob du die erforderliche Funktionalität erreichen kannst.

Wenn dein Chatbot äußerst vielfältige Aufgaben bearbeitet, solltest du in Erwägung ziehen, einen [separaten Intent-Klassifikator](https://platform.claude.com/cookbook/capabilities-classification-guide) hinzuzufügen, um die anfängliche Kundenanfrage weiterzuleiten. Für die bestehende Anwendung würde dies bedeuten, einen Entscheidungsbaum zu erstellen, der Kundenanfragen durch den Klassifikator und dann zu spezialisierten Konversationen (mit jeweils eigenen Tools und System-Prompts) leitet. Beachte, dass diese Methode einen zusätzlichen Aufruf an Claude erfordert, der die Latenz erhöhen kann.

### Integriere Claude in deinen Support-Workflow

Während sich diese Beispiele auf Python-Funktionen konzentriert haben, die innerhalb einer Streamlit-Umgebung aufrufbar sind, erfordert die Bereitstellung von Claude für einen Echtzeit-Support-Chatbot einen API-Dienst.

So kannst du vorgehen:

1. Erstelle einen API-Wrapper: Entwickle einen einfachen API-Wrapper um deine Klassifizierungsfunktion. Du kannst beispielsweise Flask API oder Fast API verwenden, um deinen Code in einen HTTP-Dienst zu verpacken. Dein HTTP-Dienst könnte die Nutzereingabe entgegennehmen und die Assistant-Antwort vollständig zurückgeben. Dein Dienst könnte somit die folgenden Eigenschaften haben:

   * Server-Sent Events (SSE): SSE ermöglicht das Echtzeit-Streaming von Antworten vom Server zum Client. Dies sorgt für ein flüssiges, interaktives Erlebnis bei der Arbeit mit LLMs.
   * Caching: Die Implementierung von Caching kann Antwortzeiten verbessern und unnötige API-Aufrufe reduzieren.
   * Kontexterhaltung: Den Kontext beizubehalten, wenn ein Nutzer die Seite verlässt und zurückkehrt, ist wichtig für die Kontinuität von Gesprächen.

2. Erstelle eine Weboberfläche: Implementiere eine benutzerfreundliche Web-UI für die Interaktion mit dem Claude-gestützten Agenten.

## Nächste Schritte

<CardGroup cols={2}>
  <Card title="Tool-Nutzung" icon="wrench" href="https://platform.claude.com/docs/de/agents-and-tools/tool-use/overview">
    Gib Claude Zugriff auf deine APIs, damit es im Namen von Kunden handeln kann.
  </Card>

  <Card title="Tests entwickeln" icon="check" href="https://platform.claude.com/docs/de/test-and-evaluate/develop-tests">
    Erstelle Evaluierungen, um deinen Support-Agenten an den von dir definierten Erfolgskriterien zu messen.
  </Card>

  <Card title="Streaming" icon="bolt" href="https://platform.claude.com/docs/de/build-with-claude/streaming">
    Streame Antworten, damit Kunden die Antworten sehen, während sie generiert werden.
  </Card>

  <Card title="Prompt-Engineering" icon="lightbulb" href="https://platform.claude.com/docs/de/build-with-claude/prompt-engineering/overview">
    Verfeinere deinen System-Prompt und deine Beispiele für eine bessere Aufgabenleistung.
  </Card>
</CardGroup>
