diff --git a/README.md b/README.md index c97596b66638f563104b02d06a7061b5184d872e..c50762fb93b5d486cafb3b81d5a707f1b5956bc1 100644 --- a/README.md +++ b/README.md @@ -20,12 +20,20 @@ Build AI agents with Go. Multi-provider, multi-model, one API. import "charm.land/fantasy" import "charm.land/fantasy/providers/openrouter" -// Choose your fave provider-model combo. -provider := openrouter.New(openrouter.WithAPIKey(myHotKey)) -model, err := provider.LanguageModel("moonshotai/kimi-k2") +// Choose your fave provider. +provider, err := openrouter.New(openrouter.WithAPIKey(myHotKey)) if err != nil { - fmt.Fprintln(os.Stderr, "Dang:", err) - os.Exit(1) + fmt.Fprintln(os.Stderr, "Whoops:", err) + os.Exit(1) +} + +ctx := context.Background() + +// Pick your fave model. +model, err := provider.LanguageModel(ctx, "moonshotai/kimi-k2") +if err != nil { + fmt.Fprintln(os.Stderr, "Dang:", err) + os.Exit(1) } // Make your own tools. @@ -40,11 +48,11 @@ result, err := agent.Generate(context.Background(), fantasy.AgentCall{Prompt: pr if err != nil { fmt.Fprintln(os.Stderr, "Oof:", err) os.Exit(1) -} +} fmt.Println(result.Response.Content.Text()) ``` -🍔 Hungry for more? [See the examples](https://github.com/charmbracelet/fantasy/tree/main/examples). +🍔 For the full implementation and more [see the examples directory](https://github.com/charmbracelet/fantasy/tree/main/examples). ## Multi-model? Multi-provider? diff --git a/examples/go.mod b/examples/go.mod index 7102f6eedf3dcb09d9d4e2137422517b4efb74f0..fa56b429ffbd15c328891d9dfdf2aac61b5beb4b 100644 --- a/examples/go.mod +++ b/examples/go.mod @@ -29,7 +29,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 // indirect github.com/aws/smithy-go v1.23.1 // indirect - github.com/charmbracelet/anthropic-sdk-go v0.0.0-20251021163913-d29170d047bf // indirect + github.com/charmbracelet/anthropic-sdk-go v0.0.0-20251022202715-ec1499142678 // indirect github.com/charmbracelet/colorprofile v0.3.2 // indirect github.com/charmbracelet/ultraviolet v0.0.0-20250915111650-81d4262876ef // indirect github.com/charmbracelet/x/ansi v0.10.2 // indirect diff --git a/examples/go.sum b/examples/go.sum index f881eb7dbd5cdb212f349f8135e2ee8e7824a3f4..72ed2c6fafe342b33854aa0902cffdc1d4cc048e 100644 --- a/examples/go.sum +++ b/examples/go.sum @@ -34,8 +34,8 @@ github.com/aws/smithy-go v1.23.1 h1:sLvcH6dfAFwGkHLZ7dGiYF7aK6mg4CgKA/iDKjLDt9M= github.com/aws/smithy-go v1.23.1/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0= github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8= github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA= -github.com/charmbracelet/anthropic-sdk-go v0.0.0-20251021163913-d29170d047bf h1:toCE1GpniOr8JPJII2GH1AffivFVOzq8Rs2S0FUrkNU= -github.com/charmbracelet/anthropic-sdk-go v0.0.0-20251021163913-d29170d047bf/go.mod h1:8TIYxZxsuCqqeJ0lga/b91tBwrbjoHDC66Sq5t8N2R4= +github.com/charmbracelet/anthropic-sdk-go v0.0.0-20251022202715-ec1499142678 h1:ruB8GXJ6K6lbuU+NhHKsqoHbU/+E+/+0kfUxhWPLvFs= +github.com/charmbracelet/anthropic-sdk-go v0.0.0-20251022202715-ec1499142678/go.mod h1:8TIYxZxsuCqqeJ0lga/b91tBwrbjoHDC66Sq5t8N2R4= github.com/charmbracelet/colorprofile v0.3.2 h1:9J27WdztfJQVAQKX2WOlSSRB+5gaKqqITmrvb1uTIiI= github.com/charmbracelet/colorprofile v0.3.2/go.mod h1:mTD5XzNeWHj8oqHb+S1bssQb7vIHbepiebQ2kPKVKbI= github.com/charmbracelet/lipgloss/v2 v2.0.0-beta.3.0.20250917201909-41ff0bf215ea h1:g1HfUgSMvye8mgecMD1mPscpt+pzJoDEiSA+p2QXzdQ= diff --git a/examples/simple/main.go b/examples/simple/main.go new file mode 100644 index 0000000000000000000000000000000000000000..55d29fd0dd6ce12632e48d50cb4c442d3efe0956 --- /dev/null +++ b/examples/simple/main.go @@ -0,0 +1,60 @@ +package main + +// This is a basic example illustrting how to create an agent with a custom +// tool call. + +import ( + "context" + "fmt" + "os" + + "charm.land/fantasy" + "charm.land/fantasy/providers/openrouter" +) + +func main() { + // Choose your fave provider. + provider, err := openrouter.New(openrouter.WithAPIKey(os.Getenv("OPENROUTER_API_KEY"))) + if err != nil { + fmt.Fprintln(os.Stderr, "Whoops:", err) + os.Exit(1) + } + + ctx := context.Background() + + // Pick your fave model. + model, err := provider.LanguageModel(ctx, "moonshotai/kimi-k2") + if err != nil { + fmt.Fprintln(os.Stderr, "Dang:", err) + os.Exit(1) + } + + // Let's make a tool that fetches info about cute dogs. Here's a schema + // for the tool's input. + type cuteDogQuery struct { + Location string `json:"location" description:"The location to search for cute dogs."` + } + + // And here's the implementation of that tool. + fetchCuteDogInfo := func(ctx context.Context, input cuteDogQuery, _ fantasy.ToolCall) (fantasy.ToolResponse, error) { + if input.Location == "Silver Lake, Los Angeles" { + return fantasy.NewTextResponse("Cute dogs are everywhere!"), nil + } + return fantasy.NewTextResponse("No cute dogs found."), nil + } + + // Add the tool. + cuteDogTool := fantasy.NewAgentTool("cute_dog_tool", "Provide up-to-date info on cute dogs.", fetchCuteDogInfo) + + // Equip your agent. + agent := fantasy.NewAgent(model, fantasy.WithTools(cuteDogTool)) + + // Put that agent to work! + const prompt = "Find all the cute dogs in Silver Lake, Los Angeles." + result, err := agent.Generate(ctx, fantasy.AgentCall{Prompt: prompt}) + if err != nil { + fmt.Fprintln(os.Stderr, "Oof:", err) + os.Exit(1) + } + fmt.Println(result.Response.Content.Text()) +}