Startseite / Artikel / Praktische Hinweise: Gemini für Go-Entwickler: Agenten in Go erstellen

Praktische Hinweise: Gemini für Go-Entwickler: Agenten in Go erstellen

Schritt-für-Schritt-Anleitung zu den Praktischen Hinweisen: Gemini für Go-Entwickler – Erstellung von Agenten in Go: Verträge, Überprüfungen sowie Code-Blöcke für Teams, die dieses Muster einsetzen.

4187 Wörter

Dieser Leitfaden zeigt Schritt für Schritt den Weg von Rohstoffen bis zu einem funktionsfähigen System für „Gemini for Go Developers: Building Agents in Go“. Der Schwerpunkt liegt auf ausführbaren Schritten, expliziten Überprüfungen sowie Code, den man ohne Rätseln über die Absicht direkt in ein Repository einfügen kann. In der Übersichtsphase sollten Eingaben, Verantwortliche für die Schritte sowie Abbruchkriterien definiert werden, bevor Code geändert wird. Operator:innen sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckten Zuständen schließen zu müssen. Halten Sie Konfigurationen außerhalb des Anwendungscode. Umgebungsdateien, Geheimdatenspeicher und Feature-Flags sollten an einem Ort gesammelt sein, den Operator:innen überprüfen können, ohne den gesamten Ablauf durchzulesen.

Die Struktur eines Agents

Beim Arbeiten an „The anatomy of an stage“ sollten Sie zunächst den Vertrag aufschreiben: erforderliche Eingaben, Erfolgsignal sowie das Vorgehen bei teilweisen Fehlern. Diese Checkliste sorgt dafür, dass spätere Codeänderungen transparent bleiben. Dokumentieren Sie gleichzeitig den erfolgreichen Ablauf sowie den Notfallweg. Wiederholte Versuche, menschliche Überprüfungen und die Handhabung von Fehlern gehören zum Produkt selbst, nicht zu späteren Optimierungen. Protokollieren Sie bei jedem Aufruf die Anfrage-ID, die Modell-ID sowie die Latenzzeit. Ohne diese Aufzeichnungen wirken intermittierende Fehler des Anbieters wie Programmfehler.

Agentenentwurf: Der Retro Game Appraiser

Beim Entwerfen der Retro-Phase des Agents sollten Sie zunächst den Vertrag aufschreiben: erforderliche Eingaben, Erfolgsignal sowie das Vorgehen bei teilweisen Fehlern. Diese Checkliste sorgt dafür, dass spätere Codeänderungen transparent bleiben. Ziehen Sie kleine, testbare Einheiten vor großen Skripten. Wenn ein Schritt fehlschlägt, sollte der Fehler auf eine einzige Verantwortung verweisen und nicht auf ein verworrenes Ablaufschema. Protokollieren Sie bei jedem Aufruf die Anfrage-ID, die Modell-ID sowie die Latenzzeit. Ohne diese Aufzeichnungen wirken intermittierende Fehler des Anbieters wie Programmfehler.

Funktionen und Benutzerinteraktion

Während der Phase „Funktionalitäten und Benutzerinteraktion“ sollte man zunächst den Vertrag aufschreiben: erforderliche Eingaben, Erfolgssignal sowie das Vorgehen bei teilweisen Fehlern. Diese Checkliste sorgt dafür, dass spätere Codeänderungen transparent bleiben. Betrachten Sie diese Phase als Vertrag zwischen Eingaben und validierten Ausgaben. Benennen Sie die Artefakte, definieren Sie Erfolgsprüfungen und lehnen Sie stille, teilweise abgeschlossene Abläufe ab. Protokollieren Sie bei jedem Aufruf die Anfrage-ID, die Modell-ID sowie die Latenzzeit. Ohne diese Aufzeichnungen wirken intermittierende Fehler des Anbieters wie Programmfehler. Während der Phase „Funktionalitäten und Benutzerinteraktion“ sollte man zunächst den Vertrag aufschreiben: erforderliche Eingaben, Erfolgssignal sowie das Vorgehen bei teilweisen Fehlern. Diese Checkliste sorgt dafür, dass spätere Codeänderungen transparent bleiben. Bewahren Sie die Konfiguration außerhalb des Anwendungscode auf. Umgebungsdateien, Geheimdatenspeicher sowie Feature-Flags sollten an einem Ort gesammelt sein, den Betreiber ohne das Durchlesen des gesamten Systems überprüfen können.

Toolverträge

Die Phase der Toolverträge funktioniert am besten, wenn sie als messbarer Bereich betrachtet wird. Erfassen Sie ein „goldenes“ Transkript, einen Fehlerfall sowie eine Notiz zur Rücksetzung, bevor Sie den Umfang erweitern. Dokumentieren Sie gleichzeitig den erfolgreichen Ablauf sowie den Wiederherstellungsprozess. Wiederholversuche, menschliche Kontrollen sowie die Handhabung von Fehlern gehören zum Produkt selbst und nicht zu späteren Optimierungen. Fixieren Sie den Interpreter sowie die Abhängigkeitsdatei, bevor Sie Schleifen implementieren. Unterschiede zwischen dem Laptop und den CI-Systemen sind die häufigsten stillen Störungen bei API-Demos.

Strategie der Argumentation

Die Strategiephase der Argumentation funktioniert am besten, wenn sie als messbarer Bereich betrachtet wird. Erfassen Sie ein gelungenes Beispiel, einen Fehlerfall sowie die Notizen zum Rollback, bevor Sie den Umfang erweitern. Ziehen Sie kleine, testbare Einheiten vor großen, komplexen Skripten vor. Wenn ein Schritt fehlschlägt, sollte der Fehler auf eine einzige Verantwortung verweisen und nicht auf einen verworrenen Ablauf. Fixieren Sie den Interpreter sowie die Abhängigkeitsdatei, bevor Sie Schleifen erklären. Unterschiede zwischen dem Laptop und den CI-Systemen sind die häufigste Ursache für stillschweigende Ausfälle bei API-Demos.

Implementierung des Agents mit dem Go GenAI SDK

Die Implementierung des Agenten in Phasen funktioniert am besten, wenn sie als messbarer Rahmen betrachtet wird. Erfassen Sie ein „goldenes“ Transkript, einen Fehlerfall sowie eine Notiz zum Rollback, bevor Sie den Umfang erweitern. Betrachten Sie diese Phase als Vertrag zwischen Eingaben und validierten Ausgaben. Benennen Sie die Artefakte, definieren Sie Erfolgskontrollen und lehnen Sie stille, unvollständige Abschlüsse ab. Fixieren Sie den Interpreter sowie die Abhängigkeitsdateien, bevor Sie Schleifen implementieren. Unterschiede zwischen Laptop und CI sind die häufigsten stillen Störungen bei API-Demos. Die Implementierung des Agenten in Phasen funktioniert am besten, wenn sie als messbarer Rahmen betrachtet wird. Erfassen Sie ein „goldenes“ Transkript, einen Fehlerfall sowie eine Notiz zum Rollback, bevor Sie den Umfang erweitern. Bewahren Sie die Konfiguration außerhalb des Anwendungscode auf. Umgebungsdateien, Geheimdatenspeicher sowie Feature-Flags sollten an einem Ort gespeichert werden, den Betreuer ohne Durchsicht des gesamten Systems prüfen können.

package main

import (
 "bufio"
 "context"
 "fmt"
 "log"
 "os"
 "os/signal"
 "strings"
 "syscall"

 "google.golang.org/genai"
)

// GameItem represents a collectible item in the user's personal inventory.
type GameItem struct {
 Title     string  `json:"title"`
 Platform  string  `json:"platform"`
 Year      int     `json:"year"`
 Condition string  `json:"condition"` // e.g. "Loose Cartridge", "CIB (Complete in Box)", "Mint"
 PricePaid float64 `json:"price_paid"`
 Notes     string  `json:"notes"`
}

// localCatalog simulates an inventory database for retro games.
var localCatalog = []GameItem{
 {
  Title:     "Chrono Trigger",
  Platform:  "Super Nintendo (SNES)",
  Year:      1995,
  Condition: "CIB (Complete in Box)",
  PricePaid: 210.00,
  Notes:     "Includes original map and registration card.",
 },
 {
  Title:     "EarthBound",
  Platform:  "Super Nintendo (SNES)",
  Year:      1994,
  Condition: "Loose Cartridge",
  PricePaid: 180.00,
  Notes:     "Authentic board verified; label in excellent shape.",
 },
 {
  Title:     "Castlevania: Symphony of the Night",
  Platform:  "Sony PlayStation",
  Year:      1997,
  Condition: "CIB (Black Label)",
  PricePaid: 135.00,
  Notes:     "Original soundtrack disc included.",
 },
}

// searchCatalogTool searches the local collection for matching games.
func searchCatalogTool(args map[string]any) map[string]any {
 query, _ := args["query"].(string)
 queryLower := strings.ToLower(strings.TrimSpace(query))

 var matches []GameItem
 for _, item := range localCatalog {
  if strings.Contains(strings.ToLower(item.Title), queryLower) ||
   strings.Contains(strings.ToLower(item.Platform), queryLower) {
   matches = append(matches, item)
  }
 }

 if len(matches) == 0 {
  return map[string]any{
   "found":   false,
   "message": fmt.Sprintf("No items matching %q found in your collection.", query),
  }
 }

 return map[string]any{
  "found":   true,
  "count":   len(matches),
  "results": matches,
 }
}

func main() {
 ctx := context.Background()

 // Initialise GenAI client for Gemini Enterprise
 client, err := genai.NewClient(ctx, &genai.ClientConfig{
  Project:  os.Getenv("GOOGLE_CLOUD_PROJECT"),
  Location: "global",
  Backend:  genai.BackendEnterprise,
 })
 if err != nil {
  log.Fatalf("failed to create client: %v", err)
 }

 // 1. Declare custom function schema for collection lookup
 catalogToolDecl := &genai.FunctionDeclaration{
  Name:        "search_catalog",
  Description: "Search the collector's personal inventory for owned games by title or platform.",
  Parameters: &genai.Schema{
   Type: genai.TypeObject,
   Properties: map[string]*genai.Schema{
    "query": {
     Type:        genai.TypeString,
     Description: "Game title or platform to search (e.g. 'EarthBound', 'SNES').",
    },
   },
   Required: []string{"query"},
  },
 }

 // 2. Configure model tools: custom function declaration + Google Search grounding
 config := &genai.GenerateContentConfig{
  SystemInstruction: &genai.Content{
   Parts: []*genai.Part{
    {Text: "You are an expert Retro Game Appraiser. When evaluating purchases, check the user's " +
     "collection catalog first to see if they already own the item, then check current market " +
     "prices using Google Search to evaluate whether the deal is fair, overpriced, or a bargain."},
   },
  },
  Tools: []*genai.Tool{
   {
    FunctionDeclarations: []*genai.FunctionDeclaration{catalogToolDecl},
   },
   {
    GoogleSearch: &genai.GoogleSearch{},
   },
  },
 }

 // 3. Graceful shutdown on Ctrl+C (SIGINT) or SIGTERM
 sigChan := make(chan os.Signal, 1)
 signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
 go func() {
  <-sigChan
  fmt.Println("\nGoodbye!")
  os.Exit(0)
 }()

 model := "gemini-3.8-flash"
 var contents []*genai.Content

 fmt.Println("Retro Game Appraiser (SDK Agent)")
 fmt.Println("Type your question below, or 'exit' (Ctrl+C / Ctrl+D) to quit.")
 fmt.Println("-----------------------------------------------------------------")

 scanner := bufio.NewScanner(os.Stdin)
 for {
  fmt.Print("\nUser: ")
  if !scanner.Scan() {
   fmt.Println("\nGoodbye!")
   break
  }

  input := strings.TrimSpace(scanner.Text())
  if input == "" {
   continue
  }
  if strings.EqualFold(input, "exit") {
   fmt.Println("Goodbye!")
   break
  }

  contents = append(contents, &genai.Content{
   Role:  "user",
   Parts: []*genai.Part{genai.NewPartFromText(input)},
  })

  // 4. The Agent Loop: model generation -> tool dispatch -> feedback -> until final answer
  for {
   resp, err := client.Models.GenerateContent(ctx, model, contents, config)
   if err != nil {
    log.Printf("error generating content: %v", err)
    break
   }

   if len(resp.Candidates) == 0 || resp.Candidates[0].Content == nil {
    log.Println("received empty response candidate from model")
    break
   }

   // Append the model's response to the conversation history
   modelContent := resp.Candidates[0].Content
   contents = append(contents, modelContent)

   // Check if the model requested any client-side tool executions
   funcCalls := resp.FunctionCalls()
   if len(funcCalls) == 0 {
    fmt.Printf("\nAppraiser: %s\n", resp.Text())
    break
   }

   // Execute each requested tool and prepare response parts
   var responseParts []*genai.Part
   for _, call := range funcCalls {
    fmt.Printf("[Harness] Executing tool: %s(args=%v)\n", call.Name, call.Args)

    var result map[string]any
    switch call.Name {
    case "search_catalog":
     result = searchCatalogTool(call.Args)
    default:
     result = map[string]any{"error": fmt.Sprintf("unsupported tool: %s", call.Name)}
    }

    responseParts = append(responseParts, genai.NewPartFromFunctionResponse(call.Name, result))
   }

   // Return tool execution results as a user turn
   contents = append(contents, &genai.Content{
    Role:  "user",
    Parts: responseParts,
   })
  }
 }
}
export GOOGLE_CLOUD_PROJECT="your-gcp-project-id"
go run main.go
Retro Game Appraiser (SDK Agent)
Type your question below, or 'exit' (Ctrl+C / Ctrl+D) to quit.
-----------------------------------------------------------------

User: I found a copy of EarthBound for SNES in mint Complete-in-Box (CIB) condition for $350. Do I already own it, and is $350 a good deal compared to current market prices?
[Harness] Executing tool: search_catalog(args=map[query:EarthBound])

Appraiser: Here is your collection check and appraisal for **EarthBound (SNES)**:

1. **Current Collection Status**:
   - You currently own **EarthBound** on Super Nintendo as a **Loose Cartridge**, purchased for **$180.00**.

2. **Market Price Appraisal**:
   - Verified market sales for an authentic, **Complete-in-Box (CIB)** copy of EarthBound typically range between **$1,200.00 and $1,500.00** depending on the condition of the box, tray, and original player's guide.

3. **Recommendation**:
   - At **$350.00**, a genuine Mint CIB copy is an **exceptional deal** (more than 70% below prevailing market value).
   - **Caution**: Because EarthBound is one of the most heavily counterfeited SNES titles, inspect the box printing, registration card, and PCB board carefully before completing the transaction. If verified authentic, this is an outstanding opportunity to upgrade your loose copy to CIB.

User: exit
Goodbye!

Entwicklungsframeworks für Agenten

In der Phase der Entwicklungsframeworks für Agenten sollten Eingaben, Verantwortliche für die einzelnen Schritte sowie Abbruchkriterien vor der Codeänderung definiert werden. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen. Dokumentieren Sie sowohl den erfolgreichen Ablauf als auch den Notfallweg gemeinsam. Wiederholungsversuche, menschliche Überprüfungen sowie die Handhabung von Fehlnachrichten gehören zum Produkt selbst und nicht zu späteren Optimierungen. Trennen Sie den Aufbau des Clients vom Nachrichtenzyklus, damit Provider ausgetauscht werden können, ohne die Zustandsmaschine der Konversation umschreiben zu müssen.

Implementierung des Agenten mit Genkit

Zur Implementierung des Agenten mit Phasen sollten vor dem Ändern des Codes die Eingaben, der Verantwortliche für den Schritt sowie die Abbruchkriterien definiert werden. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen. Bevorzugen Sie kleine, testbare Einheiten vor umfangreichen Skripten. Wenn ein Schritt fehlschlägt, sollte der Fehler auf eine einzige Verantwortung verweisen und nicht auf ein verworrenes Ablaufschema. Trennen Sie den Aufbau des Clients von der Nachrichtenschleife, damit Provider ausgetauscht werden können, ohne die Zustandsmaschine des Dialogs neu schreiben zu müssen.

package main

import (
 "context"
 "fmt"
 "log"
 "net/http"
 "os"
 "os/signal"
 "strings"
 "syscall"
 "time"

 "github.com/firebase/genkit/go/ai"
 "github.com/firebase/genkit/go/genkit"
 "github.com/firebase/genkit/go/plugins/googlegenai"
 "google.golang.org/genai"
)

// GameItem represents a collectible item in the user's personal inventory.
type GameItem struct {
 Title     string  `json:"title"`
 Platform  string  `json:"platform"`
 Year      int     `json:"year"`
 Condition string  `json:"condition"`
 PricePaid float64 `json:"price_paid"`
 Notes     string  `json:"notes"`
}

// localCatalog simulates an inventory database for retro games.
var localCatalog = []GameItem{
 {
  Title:     "Chrono Trigger",
  Platform:  "Super Nintendo (SNES)",
  Year:      1995,
  Condition: "CIB (Complete in Box)",
  PricePaid: 210.00,
  Notes:     "Includes original map and registration card.",
 },
 {
  Title:     "EarthBound",
  Platform:  "Super Nintendo (SNES)",
  Year:      1994,
  Condition: "Loose Cartridge",
  PricePaid: 180.00,
  Notes:     "Authentic board verified; label in excellent shape.",
 },
 {
  Title:     "Castlevania: Symphony of the Night",
  Platform:  "Sony PlayStation",
  Year:      1997,
  Condition: "CIB (Black Label)",
  PricePaid: 135.00,
  Notes:     "Original soundtrack disc included.",
 },
}

type CatalogRequest struct {
 Query string `json:"query" jsonschema:"description=The game title or platform to search in the inventory"`
}

type CatalogResponse struct {
 Found   bool       `json:"found"`
 Message string     `json:"message,omitempty"`
 Count   int        `json:"count,omitempty"`
 Results []GameItem `json:"results,omitempty"`
}

type AppraiserRequest struct {
 Prompt string `json:"prompt" jsonschema:"description=The collector's question or purchase offer to evaluate"`
}

type AppraiserResponse struct {
 Appraisal string `json:"appraisal"`
}

func main() {
 ctx := context.Background()

 // 1. Initialise Genkit with Vertex AI plugin
 g := genkit.Init(ctx,
  genkit.WithPlugins(&googlegenai.VertexAI{
   ProjectID: os.Getenv("GOOGLE_CLOUD_PROJECT"),
   Location:  "global",
  }),
 )

 // 2. Define strongly-typed tool with automatic schema generation
 catalogTool := genkit.DefineTool(
  g,
  "search_catalog",
  "Search the collector's personal inventory for owned games by title or platform.",
  func(ctx *ai.ToolContext, req CatalogRequest) (CatalogResponse, error) {
   queryLower := strings.ToLower(strings.TrimSpace(req.Query))
   queryWords := strings.Fields(queryLower)
   var matches []GameItem

   for _, item := range localCatalog {
    itemText := strings.ToLower(item.Title + " " + item.Platform)
    allMatch := true
    for _, word := range queryWords {
     if !strings.Contains(itemText, word) {
      allMatch = false
      break
     }
    }
    if allMatch {
     matches = append(matches, item)
    }
   }

   if len(matches) == 0 {
    return CatalogResponse{
     Found:   false,
     Message: fmt.Sprintf("No items matching %q found in personal collection.", req.Query),
    }, nil
   }

   return CatalogResponse{
    Found:   true,
    Count:   len(matches),
    Results: matches,
   }, nil
  },
 )

 // 3. Define structured appraisal flow with typed request and response
 appraiserFlow := genkit.DefineFlow(
  g,
  "appraise_game",
  func(ctx context.Context, req AppraiserRequest) (AppraiserResponse, error) {
   resp, err := genkit.Generate(ctx, g,
    ai.WithModelName("vertexai/gemini-3.8-flash"),
    ai.WithSystem(
     "You are an expert Retro Game Appraiser. Assist collectors by evaluating prospective purchases, "+
      "cross-referencing their personal inventory, and assessing fair market valuations. "+
      "Always search the collection catalog using search_catalog before providing purchase recommendations.",
    ),
    ai.WithConfig(&genai.GenerateContentConfig{
     ThinkingConfig: &genai.ThinkingConfig{IncludeThoughts: true},
     Tools: []*genai.Tool{
      {
       GoogleSearch: &genai.GoogleSearch{},
      },
     },
    }),
    ai.WithPrompt(req.Prompt),
    ai.WithTools(catalogTool),
   )
   if err != nil {
    return AppraiserResponse{}, fmt.Errorf("appraisal generation failed: %w", err)
   }
   return AppraiserResponse{Appraisal: resp.Text()}, nil
  },
 )

 // 4. Mount flow directly using Genkit's built-in HTTP handler
 mux := http.NewServeMux()
 mux.Handle("POST /api/appraise", genkit.Handler(appraiserFlow))

 port := os.Getenv("PORT")
 if port == "" {
  port = "8080"
 }

 server := &http.Server{
  Addr:    ":" + port,
  Handler: mux,
 }

 // Graceful shutdown on Ctrl+C (SIGINT) or SIGTERM
 serverCtx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
 defer stop()

 go func() {
  log.Printf("Retro Game Appraiser (Genkit) listening on :%s", port)
  if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
   log.Fatalf("server failed: %v", err)
  }
 }()

 <-serverCtx.Done()
 log.Println("\nShutting down server gracefully...")

 shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
 defer cancel()

 if err := server.Shutdown(shutdownCtx); err != nil {
  log.Fatalf("server forced shutdown: %v", err)
 }
 log.Println("Server exited cleanly.")
}

Ausführung des Genkit-Flusses

Bei der Phase „Ausführung des Genkit-Flusses“ sollten die Eingaben, der Verantwortliche für den Schritt sowie die Abbruchkriterien vor dem Ändern des Codes definiert werden. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf verborgene Zustände schließen zu müssen. Betrachten Sie diese Phase als Vertrag zwischen den Eingaben und den validierten Ausgaben. Benennen Sie die Artefakte, definieren Sie Erfolgskontrollen und lehnen Sie stille, teilweise abgeschlossene Abläufe ab. Trennen Sie den Aufbau des Clients von dem Nachrichtenzyklus, damit Provider ausgetauscht werden können, ohne den Zustandsautomaten der Konversation neu schreiben zu müssen. Bei der Phase „Ausführung des Genkit-Flusses“ sollten die Eingaben, der Verantwortliche für den Schritt sowie die Abbruchkriterien vor dem Ändern des Codes definiert werden. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf verborgene Zustände schließen zu müssen. Bewahren Sie die Konfiguration außerhalb des Anwendungscode auf. Umgebungsdateien, Geheimdatenspeicher und Feature-Flags sollten an einem Ort gespeichert werden, den die Operator überprüfen können, ohne den gesamten Ablaufverlauf durchlesen zu müssen.

/p>
export GOOGLE_CLOUD_PROJECT="your-gcp-project-id"
export PORT=8080
go run main.go
curl -s -X POST http://localhost:8080/api/appraise \
  -H "Content-Type: application/json" \
  -d '{"data": {"prompt": "I found a copy of EarthBound for SNES for $350. Do I own it, and is it a good deal?"}}' | jq .
{
  "appraisal": "### 1. Catalog Check\n**Yes, you already own it.**\n* **Title:** *EarthBound* (SNES, 1994)\n* **Status in Collection:** Loose Cartridge\n* **Condition/Notes:** Authentic board verified; label in excellent shape.\n* **Price Paid:** $180\n\n---\n\n### 2. Market Appraisal & Deal Analysis\n* **Loose Cartridge:** The current going market rate for an authentic loose copy ranges between **$320 and $380**. At **$350**, it is priced right at **fair market value**—neither an overpriced listing nor a significant bargain.\n* **Complete in Box (CIB) / Boxed with Guide:** If this listing happens to include the original big box and strategy guide with scratch-and-sniff cards, $350 would be an extraordinary steal (CIB copies regularly sell for **$1,500–$2,500+**).\n\n---\n\n### 3. Recommendation\n* **Pass (if Loose):** Since you already have an authentic copy in excellent condition, paying retail market price ($350) for a duplicate loose cart does not offer strong value or upside.\n* **Buy immediately (if Complete/Boxed):** Only pull the trigger if it includes the original packaging or represents a major condition upgrade/variant.\n* **Buyer Beware:** If you do ever consider another copy, always inspect the PCB (printed circuit board) screws and chips, as *EarthBound* is one of the most frequently counterfeited games on the SNES."
}

Implementierung des Agenten mit dem Agent Development Kit (ADK)

Beim Durchlaufen des Schritts zur Implementierung des Agenten sollten Sie zunächst den Vertrag aufschreiben: erforderliche Eingaben, Erfolgsignal sowie das Vorgehen bei teilweisen Fehlern. Diese Checkliste sorgt dafür, dass spätere Codeänderungen transparent bleiben. Dokumentieren Sie sowohl den erfolgreichen Ablauf als auch den Fehlerbehebungsprozess gemeinsam. Wiederholte Versuche, menschliche Überprüfungen sowie die Handhabung von Fehlern gehören zum Produkt selbst und nicht zu späteren Optimierungen. Protokollieren Sie bei jedem Aufruf die Anfrage-ID, die Modell-ID sowie die Latenzzeit. Ohne diese Aufzeichnungen wirken intermittierende Fehler des Anbieters wie Programmfehler.

package main

import (
 "context"
 "fmt"
 "log"
 "os"
 "strings"

 "google.golang.org/genai"

 "google.golang.org/adk/v2/agent"
 "google.golang.org/adk/v2/agent/llmagent"
 "google.golang.org/adk/v2/cmd/launcher"
 "google.golang.org/adk/v2/cmd/launcher/full"
 "google.golang.org/adk/v2/model/gemini"
 "google.golang.org/adk/v2/tool"
 "google.golang.org/adk/v2/tool/functiontool"
 "google.golang.org/adk/v2/tool/geminitool"
)

// GameItem represents a collectible item in the user's personal inventory.
type GameItem struct {
 Title     string  `json:"title"`
 Platform  string  `json:"platform"`
 Year      int     `json:"year"`
 Condition string  `json:"condition"`
 PricePaid float64 `json:"price_paid"`
 Notes     string  `json:"notes"`
}

// localCatalog simulates an inventory database for retro games.
var localCatalog = []GameItem{
 {
  Title:     "Chrono Trigger",
  Platform:  "Super Nintendo (SNES)",
  Year:      1995,
  Condition: "CIB (Complete in Box)",
  PricePaid: 210.00,
  Notes:     "Includes original map and registration card.",
 },
 {
  Title:     "EarthBound",
  Platform:  "Super Nintendo (SNES)",
  Year:      1994,
  Condition: "Loose Cartridge",
  PricePaid: 180.00,
  Notes:     "Authentic board verified; label in excellent shape.",
 },
 {
  Title:     "Castlevania: Symphony of the Night",
  Platform:  "Sony PlayStation",
  Year:      1997,
  Condition: "CIB (Black Label)",
  PricePaid: 135.00,
  Notes:     "Original soundtrack disc included.",
 },
}

type CatalogRequest struct {
 Query string `json:"query" jsonschema:"The game title or platform to search in the inventory."`
}

type CatalogResponse struct {
 Found   bool       `json:"found"`
 Message string     `json:"message,omitempty"`
 Count   int        `json:"count,omitempty"`
 Results []GameItem `json:"results,omitempty"`
}

func main() {
 ctx := context.Background()

 // 1. Initialise Gemini Model adapter for Gemini Enterprise
 model, err := gemini.NewModel(ctx, "gemini-3.8-flash", &genai.ClientConfig{
  Project:  os.Getenv("GOOGLE_CLOUD_PROJECT"),
  Location: "global",
  Backend:  genai.BackendEnterprise,
 })
 if err != nil {
  log.Fatalf("failed to create Gemini model: %v", err)
 }

 // 2. Wrap collection lookup as an ADK Function Tool
 catalogTool, err := functiontool.New(functiontool.Config{
  Name:        "search_catalog",
  Description: "Search the collector's personal inventory for owned games by title or platform.",
 }, func(ctx agent.Context, req CatalogRequest) (CatalogResponse, error) {
  queryLower := strings.ToLower(strings.TrimSpace(req.Query))
  var matches []GameItem

  for _, item := range localCatalog {
   if strings.Contains(strings.ToLower(item.Title), queryLower) ||
    strings.Contains(strings.ToLower(item.Platform), queryLower) {
    matches = append(matches, item)
   }
  }

  if len(matches) == 0 {
   return CatalogResponse{
    Found:   false,
    Message: fmt.Sprintf("No items matching %q found in personal collection.", req.Query),
   }, nil
  }

  return CatalogResponse{
   Found:   true,
   Count:   len(matches),
   Results: matches,
  }, nil
 })
 if err != nil {
  log.Fatalf("failed to create catalog tool: %v", err)
 }

 // 3. Define autonomous LLM Agent
 appraiserAgent, err := llmagent.New(llmagent.Config{
  Name:        "retro_game_appraiser",
  Model:       model,
  Description: "Expert appraiser that analyzes retro video game purchases and collection inventory.",
  Instruction: "You are an expert Retro Game Appraiser. Assist collectors by verifying collection " +
   "status with search_catalog, assessing condition variants, and offering objective buying recommendations.",
  Tools: []tool.Tool{
   catalogTool,
   geminitool.GoogleSearch{},
  },
 })
 if err != nil {
  log.Fatalf("failed to create appraiser agent: %v", err)
 }

 // 4. Configure launcher and execute
 config := &launcher.Config{
  AgentLoader: agent.NewSingleLoader(appraiserAgent),
 }

 l := full.NewLauncher()
 if err = l.Execute(ctx, config, os.Args[1:]); err != nil {
  log.Fatalf("run failed: %v\n\n%s", err, l.CommandLineSyntax())
 }
}

Ausführung des ADK-Agenten

Beim Bearbeiten des Schritts „Ausführung des ADK-Agenten“ sollten Sie zunächst den Ablaufplan aufschreiben: erforderliche Eingaben, Erfolgsindikator sowie das Vorgehen bei teilweisen Fehlern. Diese Checkliste sorgt dafür, dass spätere Codeänderungen transparent bleiben. Ziehen Sie kleine, testbare Einheiten vor großen Skripten. Wenn ein Schritt fehlschlägt, sollte der Fehler auf eine einzige Verantwortungsbereich verweisen und nicht auf ein verworrenes Ablaufschema. Protokollieren Sie bei jedem Aufruf die Anfrage-ID, die Modell-ID sowie die Latenzzeit. Ohne diese Aufzeichnungen wirken intermittierende Fehler des Anbieters wie Programmfehler.

export GOOGLE_CLOUD_PROJECT="your-gcp-project-id"
go run main.go
User: Do I have Chrono Trigger in my collection?
Agent: Yes, you have Chrono Trigger in your collection! Here are the details from your inventory:

* Title: Chrono Trigger
* Platform: Super Nintendo (SNES)
* Release Year: 1995
* Condition: CIB (Complete in Box)
* Price Paid: $210.00
* Notes: Includes original map and registration card.

User: What did I pay for it?
Agent: You paid $210.00 for it.
go run main.go web webui api

Agenten-Laufzeiten

Während der Arbeit in der Phase der Agent-Runtimes sollte man zunächst den Vertrag aufschreiben: erforderliche Eingaben, Erfolgssignal sowie das Vorgehen bei teilweisen Fehlern. Diese Checkliste sorgt dafür, dass spätere Codeänderungen transparent bleiben. Betrachten Sie diese Phase als Vertrag zwischen Eingaben und validierten Ausgaben. Benennen Sie die Artefakte, definieren Sie Erfolgsprüfungen und lehnen Sie stille, teilweise abgeschlossene Abläufe ab. Protokollieren Sie bei jedem Aufruf die Anfrage-ID, die Modell-ID sowie die Latenzzeit. Ohne diese Aufzeichnungen wirken intermittierende Fehler des Anbieters wie Programmfehler. Während der Arbeit in der Phase der Agent-Runtimes sollte man zunächst den Vertrag aufschreiben: erforderliche Eingaben, Erfolgssignal sowie das Vorgehen bei teilweisen Fehlern. Diese Checkliste sorgt dafür, dass spätere Codeänderungen transparent bleiben. Legen Sie die Konfiguration außerhalb des Anwendungscode ab. Umgebungsdateien, Geheimdatenspeicher sowie Feature-Flags sollten an einem Ort gesammelt sein, den Betreiber ohne das Durchlesen des gesamten Systems überprüfen können.

Cloud Run: der ideale universelle Backend-Lösungspunkt

Cloud Run funktioniert am besten als messbarer Ansatz. Erfassen Sie vor der Erweiterung des Umfangs ein perfektes Beispiel, einen Fehlerfall sowie eine Notiz zur Rücksetzung. Dokumentieren Sie gleichzeitig den erfolgreichen Ablauf und den Wiederherstellungsprozess. Wiederholversuche, menschliche Überprüfungen sowie die Handhabung von Fehlern gehören zum Produkt selbst und nicht zu späteren Optimierungen. Fixieren Sie den Interpreter sowie die Abhängigkeitsdateien, bevor Sie mit dem Testprozess beginnen. Unterschiede zwischen Laptop und CI sind die häufigsten stillen Störungen bei API-Demos.

Gemini Enterprise Agent Platform: verwaltete Sitzungen und enterprise RAG

Die Gemini Enterprise Agent Platform funktioniert am besten, wenn sie als messbarer Ansatz betrachtet wird. Erfassen Sie vor der Erweiterung des Umfangs ein „goldenes“ Transkript, einen Fehlerfall sowie eine Notiz zur Rücksetzung. Ziehen Sie kleine, testbare Einheiten vor umfangreichen Skripten vor. Wenn ein Schritt fehlschlägt, sollte der Fehler auf eine einzige Verantwortung verweisen und nicht auf einen verworrenen Ablauf. Fixieren Sie den Interpreter sowie die Abhängigkeitsdatei, bevor Sie Schleifen erklären. Unterschiede zwischen Laptop und CI sind die häufigsten stillen Störungen bei API-Demos.

Was kommt als Nächstes?

Die Phase „Was kommt als Nächstes“ funktioniert am besten, wenn sie als messbarer Bereich betrachtet wird. Erfassen Sie ein „goldenes Transkript“, einen Fehlerfall sowie eine Notiz zum Rollback, bevor Sie den Umfang erweitern. Betrachten Sie diese Phase als Vertrag zwischen Eingaben und validierten Ausgaben. Benennen Sie die Artefakte, definieren Sie Erfolgskontrollen und lehnen Sie stille, unvollständige Abschlüsse ab. Sichern Sie den Interpreter sowie die Abhängigkeitsdateien, bevor Sie Schleifen erklären. Abweichungen zwischen Laptop und CI sind die häufigste Ursache für stille Ausfälle bei API-Demos. Die Phase „Was kommt als Nächstes“ funktioniert am besten, wenn sie als messbarer Bereich betrachtet wird. Erfassen Sie ein „goldenes Transkript“, einen Fehlerfall sowie eine Notiz zum Rollback, bevor Sie den Umfang erweitern. Legen Sie die Konfiguration außerhalb des Anwendungscode ab. Umgebungsdateien, Geheimdatenspeicher sowie Feature-Flags sollten an einem Ort gespeichert werden, den Betreuer ohne Durchsicht des gesamten Systems prüfen können.

Operative Kontrollliste

Die Phase der Betriebskontrollliste funktioniert am besten, wenn sie als messbarer Rahmen betrachtet wird. Erfassen Sie eine „goldene“ Transkription, einen Fehlerfall sowie eine Notiz zur Rücksetzung, bevor Sie den Umfang erweitern.

Erhalten Sie Zeitenangaben sowie Kosten für Token oder Abfragen zusammen mit den funktionalen Ergebnissen fest. Eine frühzeitige Sichtbarkeit der Kosten verhindert überraschende Rechnungen, wenn der Prozess von einer Demo in gemeinsam genutzte Umgebungen übergeht.

Sichern Sie den Interpreter sowie die Abhängigkeitsdatei ab, bevor Sie Schleifen erklären. Unterschiede zwischen Laptop und CI sind die häufigste stillschweigende Störquelle bei API-Demos.

Setzen Sie menschliche Freigabe für Bereiche voraus, in denen Geld ausgegeben oder Produktionsdaten geändert werden. Kompilierzeitbezogene Konfigurationen entsprechen nicht notwendigerweise vollständigen Geschäftsprozessen.

Schreiben Sie ein kurzes Handbuch: Wie man Schlüssel rotiert, wie man die Warteschlange leert und wie man den letzten Eingang rückgängig macht.

Man sollte kleine, testbare Einheiten vor umfangreichen Skripten bevorzugen. Wenn ein Schritt fehlschlägt, sollte der Fehler auf eine einzige Verantwortung verweisen und nicht auf ein verworrenes Ablaufverfahren.

Vor der Einführung des Stack sollte man Versionen einfrieren, ein „goldenes“ Protokoll für den kritischen Ablauf erstellen und die Rollback-Schritte überprüfen. Gemeinsame Umgebungen benötigen Geschwindigkeitsbeschränkungen, Überprüfungen der Nutzerrechte sowie einen klaren Verantwortlichen für die Rotation von Geheimnissen. Man sollte langweilige Zuverlässigkeit vor cleveren, einmaligen Demonstrationen bevorzugen.

Batch-Hinweis für 05c61bdde7aa: Halten Sie die Anbieter-Schlüssel außerhalb des Repositoriums, legen Sie eine Obergrenze für Session-Tokens fest und speichern Sie die Protokolle neben den Evaluierungs-Dateien, damit spätere Modellwechsel vergleichbar bleiben.

Für die Stufe 0 der Verstärkungsmaßnahmen sollten vor dem Ändern des Codes die Eingabedaten, der Verantwortliche für den Schritt sowie die Abbruchkriterien definiert werden. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen. Es ist vorzuziehen, kleine, testbare Einheiten statt umfangreicher Skripte zu verwenden. Wenn ein Schritt fehlschlägt, sollte der Fehler auf eine einzige Verantwortung verweisen und nicht auf ein verworrenes Ablaufverfahren.

Detail der Verstärkungsmaßnahme 0/951: Messen Sie die Ausführungsdauer, die Fehlerklasse sowie den Tokenverbrauch für diese Maßnahme und entscheiden Sie anschließend anhand eines festgelegten Fragebogens statt aufgrund von Einzelfällen, ob die Änderung beibehalten werden soll.

Beim Bearbeiten der ersten Stufe der Verstärkungsmaßnahmen sollten Sie zunächst den Ablaufplan aufschreiben: erforderliche Eingaben, Erfolgsindikatoren sowie das Vorgehen bei teilweisen Fehlern. Diese Checkliste sorgt dafür, dass spätere Codeänderungen transparent bleiben. Notieren Sie außerdem die Laufzeiten sowie die Kosten für Tokens oder Abfragen neben den funktionalen Ergebnissen. Eine frühzeitige Sichtbarkeit der Kosten verhindert überraschende Rechnungen, wenn der Prozess von einer Demo-Umgebung in gemeinsam genutzte Umgebungen übergeht.

Detail 1/951 zur Verstärkung: Messen Sie für diese Maßnahme die Gesamtlaufzeit, die Fehlerklasse sowie den Tokenverbrauch und entscheiden Sie anschließend anhand eines festgelegten Fragekatalogs statt aufgrund von Einzelfallbeobachtungen, ob die Änderung beibehalten werden soll.