Build AI agents with Go. Multi-provider, multi-model, one API.
- Choose a model and provider
- Add some tools
- Compile to native machine code and let it rip
import "charm.land/fantasy"
import "charm.land/fantasy/providers/openrouter"
// Choose your fave provider.
provider, err := openrouter.New(openrouter.WithAPIKey(myHotKey))
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)
}
// Make your own tools.
cuteDogTool := fantasy.NewAgentTool(
"cute_dog_tool",
"Provide up-to-date info on cute dogs.",
fetchCuteDogInfoFunc,
)
// Equip your agent.
agent := fantasy.NewAgent(
model,
fantasy.WithSystemPrompt("You are a moderately helpful, dog-centric assistant."),
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())🍔 For the full implementation and more see the examples directory.
Yeah! Fantasy is designed to support a wide variety of providers and models under a single API. While many providers such as Microsoft Azure, Amazon Bedrock, and OpenRouter have dedicated packages in Fantasy, many others work just fine with openaicompat, the generic OpenAI-compatible layer. That said, if you find a provider that’s not compatible and needs special treatment, please let us know in an issue (or open a PR).
Beyond chat and embeddings, Fantasy supports evaluation models such as TypeSafe's Jev and the open-weight Kev.
These answer typed questions about a state with calibrated probabilities instead of generating text.
Providers that support them implement fantasy.EvaluationProvider: providers/vercel (AI Gateway, model typesafe-ai/jev), providers/typesafe (native API, or a running Kev server via WithBaseURL), and providers/kev (Kev fully in-process via llama.cpp, weights downloaded on first use).
ep := provider.(fantasy.EvaluationProvider)
model, _ := ep.EvaluationModel(ctx, vercel.ModelJev)
resp, err := model.Evaluate(ctx, fantasy.EvaluationCall{
State: "I was charged twice. Fix this today.",
Questions: map[string]fantasy.EvaluationQuestion{
"refund": fantasy.BoolQuestion("Is the customer asking for money back?"),
"route": fantasy.ChoiceQuestion("Route this ticket.", map[string]string{"billing": "", "shipping": ""}),
"urgency": fantasy.ScoreQuestion("How urgent?", "low", "medium", "high"),
},
})
resp.Answers["refund"].Yes()
resp.Answers["route"].Choice
resp.Answers["urgency"].Level()We built Fantasy to power Crush, a hot coding agent for glamourously invincible development. Given that, Fantasy does not yet support things like:
- Image models
- Audio models
- PDF uploads
For things you’d like to see supported, PRs are welcome.
We’d love to hear your thoughts on this project. Need help? We gotchu. You can find us on:
Part of Charm.
Charm热爱开源 • Charm loves open source

