1package main
2
3// This example demonstrates provider-defined web search tools.
4// It auto-selects the provider based on which API key is set:
5//
6// ANTHROPIC_API_KEY → Anthropic (Claude)
7// OPENAI_API_KEY → OpenAI (GPT, Responses API)
8//
9// Provider tools are executed server-side by the model provider,
10// so there is no local tool implementation needed.
11
12import (
13 "context"
14 "fmt"
15 "os"
16 "strings"
17
18 "charm.land/fantasy"
19 "charm.land/fantasy/providers/anthropic"
20 "charm.land/fantasy/providers/openai"
21)
22
23func main() {
24 ctx := context.Background()
25
26 var (
27 model fantasy.LanguageModel
28 webSearch fantasy.ProviderDefinedTool
29 err error
30 )
31
32 switch {
33 case os.Getenv("ANTHROPIC_API_KEY") != "":
34 p, _ := anthropic.New(anthropic.WithAPIKey(os.Getenv("ANTHROPIC_API_KEY")))
35 model, err = p.LanguageModel(ctx, "claude-sonnet-4-20250514")
36 webSearch = anthropic.WebSearchTool(nil)
37
38 case os.Getenv("OPENAI_API_KEY") != "":
39 p, _ := openai.New(
40 openai.WithAPIKey(os.Getenv("OPENAI_API_KEY")),
41 openai.WithUseResponsesAPI(),
42 )
43 model, err = p.LanguageModel(ctx, "gpt-5.4")
44 webSearch = openai.WebSearchTool(nil)
45
46 default:
47 fmt.Fprintln(os.Stderr, "Set ANTHROPIC_API_KEY or OPENAI_API_KEY")
48 os.Exit(1)
49 }
50 if err != nil {
51 fmt.Fprintln(os.Stderr, err)
52 os.Exit(1)
53 }
54
55 agent := fantasy.NewAgent(model,
56 fantasy.WithProviderDefinedTools(webSearch),
57 )
58
59 result, err := agent.Generate(ctx, fantasy.AgentCall{
60 Prompt: "What is the population of Tokyo? Cite your source.",
61 })
62 if err != nil {
63 fmt.Fprintln(os.Stderr, err)
64 os.Exit(1)
65 }
66
67 var text strings.Builder
68 for _, c := range result.Response.Content {
69 if tc, ok := c.(fantasy.TextContent); ok {
70 text.WriteString(tc.Text)
71 }
72 }
73 fmt.Println(text.String())
74
75 for _, source := range result.Response.Content.Sources() {
76 fmt.Printf("Source: %s — %s\n", source.Title, source.URL)
77 }
78}