Documentation
¶
Overview ¶
Package genkit provides a framework for building AI-powered applications in Go.
Genkit is an open-source framework that helps you build, deploy, and monitor production-ready AI features. It provides a unified interface for working with large language models (LLMs), managing prompts, defining workflows, and integrating with various AI service providers.
For comprehensive documentation, tutorials, and examples, visit https://genkit.dev
Getting Started ¶
Initialize Genkit with a plugin to connect to an AI provider:
ctx := context.Background()
g := genkit.Init(ctx,
genkit.WithPlugins(&googlegenai.GoogleAI{}),
)
Generate text with a simple prompt:
text, err := genkit.GenerateText(ctx, g,
ai.WithModelName("googleai/gemini-2.5-flash"),
ai.WithPrompt("Tell me a joke"),
)
if err != nil {
log.Fatal(err)
}
fmt.Println(text)
Models ¶
Models represent AI language models that generate content. Use plugins to access models from providers like Google AI, Vertex AI, Anthropic, or Ollama. Models are referenced by name and can include provider-specific configuration:
resp, err := genkit.Generate(ctx, g,
ai.WithModelName("googleai/gemini-2.5-flash"),
ai.WithPrompt("Explain quantum computing in simple terms"),
)
You can set a default model during initialization:
g := genkit.Init(ctx,
genkit.WithPlugins(&googlegenai.GoogleAI{}),
genkit.WithDefaultModel("googleai/gemini-2.5-flash"),
)
Flows ¶
Flows are reusable, observable functions that orchestrate AI operations. They provide automatic tracing, can be exposed as HTTP endpoints, and support both streaming and non-streaming execution.
Define a simple flow:
jokesFlow := genkit.DefineFlow(g, "jokesFlow",
func(ctx context.Context, topic string) (string, error) {
return genkit.GenerateText(ctx, g,
ai.WithPrompt("Share a joke about %s.", topic),
)
},
)
joke, err := jokesFlow.Run(ctx, "programming")
Define a streaming flow that sends chunks as they're generated:
streamingFlow := genkit.DefineStreamingFlow(g, "streamingJokes",
func(ctx context.Context, topic string, sendChunk ai.ModelStreamCallback) (string, error) {
resp, err := genkit.Generate(ctx, g,
ai.WithPrompt("Share a joke about %s.", topic),
ai.WithStreaming(sendChunk),
)
if err != nil {
return "", err
}
return resp.Text(), nil
},
)
Use Run within flows to create traced sub-steps for observability:
genkit.DefineFlow(g, "pipeline",
func(ctx context.Context, input string) (string, error) {
result, err := genkit.Run(ctx, "processStep", func() (string, error) {
return process(input), nil
})
return result, err
},
)
Prompts ¶
Prompts can be defined programmatically or loaded from .prompt files (Dotprompt format). They encapsulate model configuration, input schemas, and template logic for reuse.
Define a prompt in code:
jokePrompt := genkit.DefinePrompt(g, "joke",
ai.WithModelName("googleai/gemini-2.5-flash"),
ai.WithInputType(JokeRequest{Topic: "default topic"}),
ai.WithPrompt("Share a joke about {{topic}}."),
)
stream := jokePrompt.ExecuteStream(ctx, ai.WithInput(map[string]any{"topic": "cats"}))
for result, err := range stream {
if err != nil {
return err
}
if result.Done {
fmt.Println(result.Response.Text())
}
}
For type-safe prompts with structured input and output, use DefineDataPrompt:
type RecipeRequest struct {
Cuisine string `json:"cuisine"`
Dish string `json:"dish"`
ServingSize int `json:"servingSize"`
}
type Recipe struct {
Title string `json:"title"`
Ingredients []string `json:"ingredients"`
Instructions []string `json:"instructions"`
}
recipePrompt := genkit.DefineDataPrompt[RecipeRequest, *Recipe](g, "recipe",
ai.WithSystem("You are an experienced chef."),
ai.WithPrompt("Create a {{cuisine}} {{dish}} recipe for {{servingSize}} people."),
)
for result, err := range recipePrompt.ExecuteStream(ctx, RecipeRequest{
Cuisine: "Italian", Dish: "pasta", ServingSize: 4,
}) {
// result.Chunk is *Recipe, result.Output is final *Recipe
}
Load prompts from .prompt files by specifying a prompt directory:
g := genkit.Init(ctx,
genkit.WithPlugins(&googlegenai.GoogleAI{}),
genkit.WithPromptDir("./prompts"),
)
// Look up a loaded prompt
jokePrompt := genkit.LookupPrompt(g, "joke")
// Or with type parameters for structured I/O
recipePrompt := genkit.LookupDataPrompt[RecipeRequest, *Recipe](g, "recipe")
When using .prompt files with custom output schemas, register the schema first:
genkit.DefineSchemaFor[Recipe](g)
Tools ¶
Tools extend model capabilities by allowing them to call functions during generation. Define tools that the model can invoke to perform actions or retrieve information:
weatherTool := genkit.DefineTool(g, "getWeather",
"Gets the current weather for a city",
func(ctx *ai.ToolContext, city string) (string, error) {
// Fetch weather data...
return "Sunny, 72°F", nil
},
)
resp, err := genkit.Generate(ctx, g,
ai.WithPrompt("What's the weather in Paris?"),
ai.WithTools(weatherTool),
)
Structured Output ¶
Generate structured data that conforms to Go types using GenerateData or GenerateDataStream. Use jsonschema struct tags to provide descriptions and constraints that help the model understand the expected output:
type Joke struct {
Joke string `json:"joke" jsonschema:"description=The joke text"`
Category string `json:"category" jsonschema:"description=The joke category"`
}
joke, resp, err := genkit.GenerateData[*Joke](ctx, g,
ai.WithPrompt("Tell me a programming joke"),
)
For streaming structured output:
stream := genkit.GenerateDataStream[*Recipe](ctx, g,
ai.WithPrompt("Create a pasta recipe"),
)
for result, err := range stream {
if err != nil {
return nil, err
}
if result.Done {
return result.Output, nil
}
// result.Chunk contains partial Recipe as it streams
fmt.Printf("Got %d ingredients so far\n", len(result.Chunk.Ingredients))
}
Streaming ¶
Genkit supports streaming at multiple levels. Use GenerateStream for streaming model responses:
stream := genkit.GenerateStream(ctx, g,
ai.WithPrompt("Write a short story"),
)
for result, err := range stream {
if err != nil {
log.Fatal(err)
}
if result.Done {
fmt.Println("\n--- Complete ---")
} else {
fmt.Print(result.Chunk.Text())
}
}
Use DefineStreamingFlow for flows that stream custom data types:
genkit.DefineStreamingFlow(g, "countdown",
func(ctx context.Context, count int, sendChunk func(context.Context, int) error) (string, error) {
for i := count; i > 0; i-- {
if err := sendChunk(ctx, i); err != nil {
return "", err
}
time.Sleep(time.Second)
}
return "Liftoff!", nil
},
)
Development Mode and Dev UI ¶
Set GENKIT_ENV=dev to enable development features including the Reflection API server that powers the Genkit Developer UI:
$ export GENKIT_ENV=dev $ go run main.go
Then run the Dev UI to inspect flows, test prompts, and view traces:
$ npx genkit start -- go run main.go
The Dev UI provides:
- Interactive flow testing with input/output inspection
- Prompt playground for iterating on prompts
- Trace viewer for debugging and performance analysis
- Action browser for exploring registered actions
HTTP Server Integration ¶
Expose flows as HTTP endpoints for production deployment using Handler:
mux := http.NewServeMux()
for _, flow := range genkit.ListFlows(g) {
mux.HandleFunc("POST /"+flow.Name(), genkit.Handler(flow))
}
log.Fatal(server.Start(ctx, "127.0.0.1:8080", mux))
Handlers support streaming responses via Server-Sent Events when the client sends Accept: text/event-stream. For durable streaming that survives reconnects, use WithStreamManager:
mux.HandleFunc("POST /countdown", genkit.Handler(countdown,
genkit.WithStreamManager(streaming.NewInMemoryStreamManager(
streaming.WithTTL(10*time.Minute),
)),
))
Plugins ¶
Genkit's functionality is extended through plugins that provide models, tools, retrievers, and other capabilities. Common plugins include:
- googlegenai: Google AI (Gemini models)
- vertexai: Google Cloud Vertex AI
- ollama: Local Ollama models
Initialize plugins during Init:
g := genkit.Init(ctx,
genkit.WithPlugins(
&googlegenai.GoogleAI{},
&vertexai.VertexAI{ProjectID: "my-project"},
),
)
Messages and Parts ¶
Build conversation messages using helper functions from the ai package. These are used with ai.WithMessages or when building custom conversation flows:
// Create messages for a conversation
messages := []*ai.Message{
ai.NewSystemTextMessage("You are a helpful assistant."),
ai.NewUserTextMessage("Hello!"),
ai.NewModelTextMessage("Hi there! How can I help?"),
}
resp, err := genkit.Generate(ctx, g,
ai.WithMessages(messages...),
ai.WithPrompt("What can you do?"),
)
For multi-modal content, combine text and media parts:
userMsg := ai.NewUserMessage(
ai.NewTextPart("What's in this image?"),
ai.NewMediaPart("image/png", base64ImageData),
)
Available message constructors in the ai package:
- ai.NewUserTextMessage, ai.NewUserMessage: User messages
- ai.NewModelTextMessage, ai.NewModelMessage: Model responses
- ai.NewSystemTextMessage, ai.NewSystemMessage: System instructions
Available part constructors in the ai package:
- ai.NewTextPart: Text content
- ai.NewMediaPart: Images, audio, video (base64-encoded)
- ai.NewDataPart: Raw data strings
- ai.NewToolRequestPart, ai.NewToolResponsePart: Tool interactions
Generation Options ¶
Generation functions (Generate, GenerateText, GenerateData, GenerateStream) accept options from the ai package to control behavior. The most common options:
Model and Configuration:
- ai.WithModel: Specify the model (accepts ai.ModelRef or plugin model refs)
- ai.WithModelName: Specify model by name string (e.g., "googleai/gemini-2.5-flash")
- ai.WithConfig: Set generation parameters (temperature, max tokens, etc.)
Prompting:
- ai.WithPrompt: Set the user prompt (supports format strings)
- ai.WithSystem: Set system instructions
- ai.WithMessages: Provide conversation history
Tools and Output:
- ai.WithTools: Enable tools the model can call
- ai.WithOutputType: Request structured output matching a Go type
- ai.WithOutputFormat: Specify output format (json, text, etc.)
Streaming:
- ai.WithStreaming: Enable streaming with a callback function
Example combining multiple options:
resp, err := genkit.Generate(ctx, g,
ai.WithModelName("googleai/gemini-2.5-flash"),
ai.WithSystem("You are a helpful coding assistant."),
ai.WithMessages(conversationHistory...),
ai.WithPrompt("Explain this code: %s", code),
ai.WithTools(searchTool, calculatorTool),
// Config is provider-specific (e.g., genai.GenerateContentConfig for Google AI)
)
Unregistered Components ¶
For advanced use cases, the ai package provides New* functions to create components without registering them in Genkit. This is useful for plugins or when you need to pass components directly:
- ai.NewTool: Create an unregistered tool
- ai.NewModel: Create an unregistered model
- ai.NewRetriever: Create an unregistered retriever
- ai.NewEmbedder: Create an unregistered embedder
Use the corresponding Define* functions in this package to create and register components for use with Genkit's action system, tracing, and Dev UI.
Additional Resources ¶
- Documentation: https://genkit.dev
- Go Getting Started: https://genkit.dev/go/docs/get-started-go
- Samples: https://github.com/genkit-ai/genkit/tree/main/go/samples
- GitHub: https://github.com/genkit-ai/genkit
Package genkit provides Genkit functionality for application developers.
Example ¶
This example shows basic initialization and flow definition.
package main
import (
"context"
"fmt"
"log"
"github.com/firebase/genkit/go/genkit"
)
func main() {
ctx := context.Background()
// Initialize Genkit (without plugins for this example)
g := genkit.Init(ctx)
// Define a simple flow
greetFlow := genkit.DefineFlow(g, "greet",
func(ctx context.Context, name string) (string, error) {
return fmt.Sprintf("Hello, %s!", name), nil
},
)
// Run the flow
greeting, err := greetFlow.Run(ctx, "World")
if err != nil {
log.Fatal(err)
}
fmt.Println(greeting)
}
Output: Hello, World!
Index ¶
- func CheckModelOperation(ctx context.Context, g *Genkit, op *ai.ModelOperation) (*ai.ModelOperation, error)
- func DefineBackgroundModel(g *Genkit, name string, opts *ai.BackgroundModelOptions, ...) ai.BackgroundModel
- func DefineBatchEvaluator(g *Genkit, name string, opts *ai.EvaluatorOptions, fn ai.BatchEvaluatorFunc) ai.Evaluator
- func DefineDataPrompt[In, Out any](g *Genkit, name string, opts ...ai.PromptOption) *ai.DataPrompt[In, Out]
- func DefineEmbedder(g *Genkit, name string, opts *ai.EmbedderOptions, fn ai.EmbedderFunc) ai.Embedder
- func DefineEvaluator(g *Genkit, name string, opts *ai.EvaluatorOptions, fn ai.EvaluatorFunc) ai.Evaluator
- func DefineFlow[In, Out any](g *Genkit, name string, fn core.Func[In, Out]) *core.Flow[In, Out, struct{}]
- func DefineFormat(g *Genkit, name string, formatter ai.Formatter)
- func DefineHelper(g *Genkit, name string, fn any)
- func DefineMiddleware[M ai.Middleware](g *Genkit, description string, prototype M) *ai.MiddlewareDesc
- func DefineModel(g *Genkit, name string, opts *ai.ModelOptions, fn ai.ModelFunc) ai.Model
- func DefineMultipartTool[In any](g *Genkit, name, description string, fn ai.MultipartToolFunc[In], ...) *ai.ToolDef[In, *ai.MultipartToolResponse]
- func DefinePartial(g *Genkit, name string, source string)
- func DefinePrompt(g *Genkit, name string, opts ...ai.PromptOption) ai.Prompt
- func DefineResource(g *Genkit, name string, opts *ai.ResourceOptions, fn ai.ResourceFunc) ai.Resource
- func DefineRetriever(g *Genkit, name string, opts *ai.RetrieverOptions, fn ai.RetrieverFunc) ai.Retriever
- func DefineSchema(g *Genkit, name string, schema map[string]any)
- func DefineSchemaFor[T any](g *Genkit)
- func DefineStreamingFlow[In, Out, Stream any](g *Genkit, name string, fn core.StreamingFunc[In, Out, Stream]) *core.Flow[In, Out, Stream]
- func DefineTool[In, Out any](g *Genkit, name, description string, fn ai.ToolFunc[In, Out], ...) *ai.ToolDef[In, Out]
- func DefineToolWithInputSchema[Out any](g *Genkit, name, description string, inputSchema map[string]any, ...) *ai.ToolDef[any, Out]deprecated
- func Embed(ctx context.Context, g *Genkit, opts ...ai.EmbedderOption) (*ai.EmbedResponse, error)
- func Evaluate(ctx context.Context, g *Genkit, opts ...ai.EvaluatorOption) (*ai.EvaluatorResponse, error)
- func FindMatchingResource(g *Genkit, uri string) (ai.Resource, *ai.ResourceInput, error)
- func Generate(ctx context.Context, g *Genkit, opts ...ai.GenerateOption) (*ai.ModelResponse, error)
- func GenerateData[Out any](ctx context.Context, g *Genkit, opts ...ai.GenerateOption) (*Out, *ai.ModelResponse, error)
- func GenerateDataStream[Out any](ctx context.Context, g *Genkit, opts ...ai.GenerateOption) iter.Seq2[*ai.StreamValue[Out, Out], error]
- func GenerateOperation(ctx context.Context, g *Genkit, opts ...ai.GenerateOption) (*ai.ModelOperation, error)
- func GenerateStream(ctx context.Context, g *Genkit, opts ...ai.GenerateOption) iter.Seq2[*ai.ModelStreamValue, error]
- func GenerateText(ctx context.Context, g *Genkit, opts ...ai.GenerateOption) (string, error)
- func GenerateWithRequest(ctx context.Context, g *Genkit, actionOpts *ai.GenerateActionOptions, ...) (*ai.ModelResponse, error)
- func Handler(a api.Action, opts ...HandlerOption) http.HandlerFunc
- func HandlerFunc(a api.Action, opts ...HandlerOption) func(http.ResponseWriter, *http.Request) error
- func IsDefinedFormat(g *Genkit, name string) bool
- func ListFlows(g *Genkit) []api.Action
- func ListResources(g *Genkit) []ai.Resource
- func ListTools(g *Genkit) []ai.Tool
- func LoadPrompt(g *Genkit, path, namespace string) ai.Prompt
- func LoadPromptDir(g *Genkit, dir, namespace string)
- func LoadPromptDirFromFS(g *Genkit, fsys fs.FS, dir, namespace string)
- func LoadPromptFromSource(g *Genkit, source, name, namespace string) (ai.Prompt, error)
- func LookupBackgroundModel(g *Genkit, name string) ai.BackgroundModel
- func LookupDataPrompt[In, Out any](g *Genkit, name string) *ai.DataPrompt[In, Out]
- func LookupEmbedder(g *Genkit, name string) ai.Embedder
- func LookupEvaluator(g *Genkit, name string) ai.Evaluator
- func LookupMiddleware(g *Genkit, name string) *ai.MiddlewareDesc
- func LookupModel(g *Genkit, name string) ai.Model
- func LookupPlugin(g *Genkit, name string) api.Plugin
- func LookupPrompt(g *Genkit, name string) ai.Prompt
- func LookupRetriever(g *Genkit, name string) ai.Retriever
- func LookupTool(g *Genkit, name string) ai.Tool
- func NewFlow[In, Out any](name string, fn core.Func[In, Out]) *core.Flow[In, Out, struct{}]
- func NewResource(name string, opts *ai.ResourceOptions, fn ai.ResourceFunc) ai.Resource
- func NewStreamingFlow[In, Out, Stream any](name string, fn core.StreamingFunc[In, Out, Stream]) *core.Flow[In, Out, Stream]
- func RegisterAction(g *Genkit, action api.Registerable)
- func Retrieve(ctx context.Context, g *Genkit, opts ...ai.RetrieverOption) (*ai.RetrieverResponse, error)
- func Run[Out any](ctx context.Context, name string, fn func() (Out, error)) (Out, error)
- type Genkit
- type GenkitOption
- type HandlerOption
- type ReflectionCancelActionParams
- type ReflectionCancelActionResponse
- type ReflectionConfigureParams
- type ReflectionEndInputStreamParams
- type ReflectionListValuesParams
- type ReflectionListValuesResponse
- type ReflectionRegisterParams
- type ReflectionRunActionParams
- type ReflectionRunActionStateParams
- type ReflectionRunActionStateParamsState
- type ReflectionSendInputStreamChunkParams
- type ReflectionStreamChunkParams
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CheckModelOperation ¶ added in v1.3.0
func CheckModelOperation(ctx context.Context, g *Genkit, op *ai.ModelOperation) (*ai.ModelOperation, error)
CheckModelOperation checks the status of a background model operation by looking up the model and calling its Check method.
func DefineBackgroundModel ¶ added in v1.3.0
func DefineBackgroundModel(g *Genkit, name string, opts *ai.BackgroundModelOptions, startFn ai.StartModelOpFunc, checkFn ai.CheckModelOpFunc) ai.BackgroundModel
DefineBackgroundModel defines a background model, registers it as a ai.BackgroundModel, and returns an ai.BackgroundModel.
The `name` is the identifier the model uses to request the background model. The `opts` are the options for the background model. The `startFn` is the function that starts the background model. The `checkFn` is the function that checks the status of the background model.
func DefineBatchEvaluator ¶ added in v0.3.0
func DefineBatchEvaluator(g *Genkit, name string, opts *ai.EvaluatorOptions, fn ai.BatchEvaluatorFunc) ai.Evaluator
DefineBatchEvaluator defines an evaluator that processes the entire dataset at once, registers it as a core.Action of type Evaluator, and returns an ai.Evaluator.
This variant provides the full evaluation request (ai.EvaluatorRequest), including the entire dataset, to the `eval` function. This allows for more flexible processing, such as batching calls to external services or parallelizing computations.
The `provider` and `name` form the unique identifier. `options` provide metadata about the evaluator (ai.EvaluatorOptions). The `eval` function implements the logic to score the dataset and returns the aggregated results in an ai.EvaluatorResponse.
func DefineDataPrompt ¶ added in v1.3.0
func DefineDataPrompt[In, Out any](g *Genkit, name string, opts ...ai.PromptOption) *ai.DataPrompt[In, Out]
DefineDataPrompt creates a new ai.DataPrompt with strongly-typed input and output. It automatically infers input schema from the In type parameter and configures output schema and JSON format from the Out type parameter (unless Out is string).
This is a convenience wrapper around DefinePrompt that provides compile-time type safety for both input and output. For prompts that don't need to be registered, use ai.NewDataPrompt instead.
DefineDataPrompt accepts the same options as DefinePrompt. See DefinePrompt for the full list of available options. Note that input and output schemas are automatically inferred from the type parameters.
Example:
type GeoInput struct {
Country string `json:"country"`
}
type GeoOutput struct {
Capital string `json:"capital"`
}
capitalPrompt := genkit.DefineDataPrompt[GeoInput, GeoOutput](g, "findCapital",
ai.WithModelName("googleai/gemini-2.5-flash"),
ai.WithSystem("You are a helpful geography assistant."),
ai.WithPrompt("What is the capital of {{country}}?"),
)
output, resp, err := capitalPrompt.Execute(ctx, GeoInput{Country: "France"})
if err != nil {
log.Fatalf("Execute failed: %v", err)
}
fmt.Printf("Capital: %s\n", output.Capital)
Example ¶
This example demonstrates using type-safe data prompts with strongly-typed input and output.
package main
import (
"context"
"fmt"
"github.com/firebase/genkit/go/ai"
"github.com/firebase/genkit/go/genkit"
)
func main() {
ctx := context.Background()
g := genkit.Init(ctx)
// Define input and output types
type JokeRequest struct {
Topic string `json:"topic"`
}
type Joke struct {
Setup string `json:"setup"`
Punchline string `json:"punchline"`
}
// Define a type-safe prompt
// Note: In production, you'd also set ai.WithModel(...)
_ = genkit.DefineDataPrompt[JokeRequest, *Joke](g, "joke",
ai.WithPrompt("Tell a joke about {{topic}}. Return JSON with setup and punchline."),
)
// The prompt can now be executed with:
// for result, err := range jokePrompt.ExecuteStream(ctx, JokeRequest{Topic: "cats"}) {
// if result.Done {
// fmt.Println(result.Output.Setup)
// fmt.Println(result.Output.Punchline)
// }
// }
fmt.Println("DataPrompt registered: joke")
}
Output: DataPrompt registered: joke
func DefineEmbedder ¶ added in v0.3.0
func DefineEmbedder(g *Genkit, name string, opts *ai.EmbedderOptions, fn ai.EmbedderFunc) ai.Embedder
DefineEmbedder defines a custom text embedding implementation, registers it as a core.Action of type Embedder, and returns an ai.Embedder. Embedders convert text documents or queries into numerical vector representations (embeddings).
The `name` is the unique identifier for the embedder. The `fn` function contains the logic to process an ai.EmbedRequest (containing documents or a query) and return an ai.EmbedResponse (containing the corresponding embeddings).
For embedders that don't need to be registered (e.g., for plugin development), use ai.NewEmbedder instead.
func DefineEvaluator ¶ added in v0.3.0
func DefineEvaluator(g *Genkit, name string, opts *ai.EvaluatorOptions, fn ai.EvaluatorFunc) ai.Evaluator
DefineEvaluator defines an evaluator that processes test cases one by one, registers it as a core.Action of type Evaluator, and returns an ai.Evaluator. Evaluators are used to assess the quality or performance of AI models or flows based on a dataset of test cases.
This variant calls the provided `eval` function for each individual test case (ai.EvaluatorCallbackRequest) in the evaluation dataset.
The `provider` and `name` form the unique identifier. `options` provide metadata about the evaluator (ai.EvaluatorOptions). The `eval` function implements the logic to score a single test case and returns the results in an ai.EvaluatorCallbackResponse.
func DefineFlow ¶
func DefineFlow[In, Out any](g *Genkit, name string, fn core.Func[In, Out]) *core.Flow[In, Out, struct{}]
DefineFlow defines a non-streaming flow, registers it as a core.Action of type Flow, and returns a core.Flow runner. The provided function `fn` takes an input of type `In` and returns an output of type `Out`. Flows are the primary mechanism for orchestrating multi-step AI tasks in Genkit. Each run of a flow is traced, and steps within the flow can be traced using Run.
Example:
myFlow := genkit.DefineFlow(g, "mySimpleFlow",
func(ctx context.Context, name string) (string, error) {
greeting := fmt.Sprintf("Hello, %s!", name)
// You could add more steps here, potentially using genkit.Run()
return greeting, nil
},
)
// Later, run the flow:
result, err := myFlow.Run(ctx, "World")
if err != nil {
// handle error
}
fmt.Println(result) // Output: Hello, World!
Example ¶
This example demonstrates defining a simple non-streaming flow.
package main
import (
"context"
"fmt"
"log"
"strings"
"github.com/firebase/genkit/go/genkit"
)
func main() {
ctx := context.Background()
g := genkit.Init(ctx)
// Define a flow that processes input
uppercaseFlow := genkit.DefineFlow(g, "uppercase",
func(ctx context.Context, input string) (string, error) {
return strings.ToUpper(input), nil
},
)
// Run the flow
result, err := uppercaseFlow.Run(ctx, "hello")
if err != nil {
log.Fatal(err)
}
fmt.Println(result)
}
Output: HELLO
func DefineFormat ¶ added in v0.5.0
DefineFormat defines a new ai.Formatter and registers it in the registry. Formatters control how model responses are structured and parsed.
Formatters can be used with ai.WithOutputFormat to inject specific formatting instructions into prompts and automatically format the model response according to the desired output structure.
Built-in formatters include:
- "text": Plain text output (default if no format specified)
- "json": Structured JSON output (default when an output schema is provided)
- "jsonl": JSON Lines format for streaming structured data
Example:
// Define a custom formatter
type csvFormatter struct{}
func (f csvFormatter) Name() string { return "csv" }
func (f csvFormatter) Handler(schema map[string]any) (ai.FormatHandler, error) {
// Implementation details...
}
// Register the formatter
genkit.DefineFormat(g, "csv", csvFormatter{})
// Use the formatter in a generation request
resp, err := genkit.Generate(ctx, g,
ai.WithPrompt("List 3 countries and their capitals"),
ai.WithOutputFormat("csv"), // Use the custom formatter
)
func DefineHelper ¶ added in v0.5.0
DefineHelper wraps DefineHelper to register a helper function with the given name. This allows for extending the templating capabilities with custom logic.
Example usage:
genkit.DefineHelper(g, "uppercase", func(s string) string {
return strings.ToUpper(s)
})
In a template, you would use it as:
{{uppercase "hello"}} => "HELLO"
func DefineMiddleware ¶ added in v1.7.0
func DefineMiddleware[M ai.Middleware](g *Genkit, description string, prototype M) *ai.MiddlewareDesc
DefineMiddleware registers a middleware descriptor with the Genkit instance and returns the resulting *ai.MiddlewareDesc. Registered middleware is surfaced to the Dev UI and addressable by name for cross-runtime dispatch.
This is the path for application code that declares its own middleware directly. Plugins should instead construct descriptors with ai.NewMiddleware (no registration) and return them from ai.MiddlewarePlugin.Middlewares; Init registers those descriptors during plugin setup.
The `description` is a human-readable explanation shown in the Dev UI. The `prototype` is a value of a type that implements ai.Middleware. Its ai.Middleware.Name method supplies the registered name, and its fields (both exported JSON config and unexported plugin-level state) are captured by a value-copy inside the descriptor so JSON-dispatched invocations preserve prototype state across calls.
For pure Go use, registration is not strictly required: passing a middleware config directly to ai.WithUse invokes its ai.Middleware.New method on the local fast path without a registry lookup. Registration is what makes the middleware visible to the Dev UI and callable from other runtimes. For ad-hoc one-off middleware that doesn't need Dev UI visibility, use ai.MiddlewareFunc instead of defining a type.
Example:
type Trace struct {
Label string `json:"label,omitempty"`
}
func (Trace) Name() string { return "mine/trace" }
func (t Trace) New(ctx context.Context) (*ai.Hooks, error) {
return &ai.Hooks{
WrapModel: func(ctx context.Context, p *ai.ModelParams, next ai.ModelNext) (*ai.ModelResponse, error) {
start := time.Now()
resp, err := next(ctx, p)
log.Printf("[%s] model call took %s", t.Label, time.Since(start))
return resp, err
},
}, nil
}
// Register so it appears in the Dev UI and can be called by name:
genkit.DefineMiddleware(g, "logs model call latency", Trace{})
// Use it per-call:
resp, err := genkit.Generate(ctx, g,
ai.WithPrompt("hello"),
ai.WithUse(Trace{Label: "debug"}),
)
func DefineModel ¶ added in v0.3.0
DefineModel defines a custom model implementation, registers it as a core.Action of type Model, and returns an ai.Model interface.
The `name` argument is the unique identifier for the model (e.g., "myProvider/myModel"). The `opts` argument provides metadata about the model's capabilities (ai.ModelOptions). The `fn` argument (ai.ModelFunc) implements the actual generation logic, handling input requests (ai.ModelRequest) and producing responses (ai.ModelResponse), potentially streaming chunks (ai.ModelResponseChunk) via the callback.
For models that don't need to be registered (e.g., for plugin development or testing), use ai.NewModel instead.
Example:
echoModel := genkit.DefineModel(g, "custom/echo",
&ai.ModelOptions{
Label: "Echo Model",
Supports: &ai.ModelSupports{Multiturn: true},
},
func(ctx context.Context, req *ai.ModelRequest, cb ai.ModelStreamCallback) (*ai.ModelResponse, error) {
// Simple echo implementation
resp := &ai.ModelResponse{
Message: &ai.Message{
Role: ai.RoleModel,
Content: []*ai.Part{},
},
}
// Combine content from the last user message
var responseText strings.Builder
if len(req.Messages) > 0 {
lastMsg := req.Messages[len(req.Messages)-1]
if lastMsg.Role == ai.RoleUser {
for _, part := range lastMsg.Content {
if part.IsText() {
responseText.WriteString(part.Text)
}
}
}
}
if responseText.Len() == 0 {
responseText.WriteString("...")
}
resp.Message.Content = append(resp.Message.Content, ai.NewTextPart(responseText.String()))
// Example of streaming (optional)
if cb != nil {
chunk := &ai.ModelResponseChunk{ Index: 0, Content: resp.Message.Content }
if err := cb(ctx, chunk); err != nil {
return nil, err // Handle streaming error
}
}
resp.FinishReason = ai.FinishReasonStop
return resp, nil
},
)
func DefineMultipartTool ¶ added in v1.3.0
func DefineMultipartTool[In any](g *Genkit, name, description string, fn ai.MultipartToolFunc[In], opts ...ai.ToolOption) *ai.ToolDef[In, *ai.MultipartToolResponse]
DefineMultipartTool defines a multipart tool that can be used by models during generation, registers it as a core.Action of type Tool, and returns an *ai.ToolDef. Unlike regular tools that return just an output value, multipart tools can return both an output value and additional content parts (like images or other media).
The `name` is the identifier the model uses to request the tool. The `description` helps the model understand when to use the tool. The function `fn` implements the tool's logic, taking an ai.ToolContext and an input of type `In`, and returning an ai.MultipartToolResponse which contains both the output and optional content parts.
For multipart tools that don't need to be registered (e.g., dynamically created tools), use ai.NewMultipartTool instead.
Options ¶
- ai.WithInputSchema: Provide a custom JSON schema instead of inferring from the type parameter
- ai.WithInputSchemaName: Reference a pre-registered schema by name
Example:
type ImageGenInput struct {
Prompt string `json:"prompt"`
Style string `json:"style,omitempty"`
}
imageGenTool := genkit.DefineMultipartTool(g, "generateImage", "Generates an image from a text prompt",
func(ctx *ai.ToolContext, input ImageGenInput) (*ai.MultipartToolResponse, error) {
// In a real scenario, call an image generation API
log.Printf("Tool: Generating image for prompt: %s", input.Prompt)
// Generate image bytes (placeholder)
imageBytes := []byte{...}
return &ai.MultipartToolResponse{
Output: map[string]any{
"status": "success",
"prompt": input.Prompt,
},
Content: []*ai.Part{
ai.NewMediaPart("image/png", string(imageBytes)),
},
}, nil
},
)
// Use the tool in a generation request:
resp, err := genkit.Generate(ctx, g,
ai.WithPrompt("Create an image of a sunset over mountains"),
ai.WithTools(imageGenTool),
)
if err != nil {
log.Fatalf("Generate failed: %v", err)
}
fmt.Println(resp.Text())
func DefinePartial ¶ added in v0.5.0
DefinePartial wraps DefinePartial to register a partial template with the given name and source. Partials can be referenced in templates with the syntax {{>partialName}}.
func DefinePrompt ¶ added in v0.3.0
DefinePrompt defines a prompt programmatically, registers it as a core.Action of type Prompt, and returns an executable ai.Prompt.
This provides an alternative to defining prompts in `.prompt` files, offering more flexibility through Go code. Prompts encapsulate configuration (model, parameters), message templates (system, user, history), input/output schemas, and associated tools.
Prompts can be executed in two main ways:
- Render + Generate: Call ai.Prompt.Render to get ai.GenerateActionOptions, modify them if needed, and pass them to GenerateWithRequest.
- Execute: Call ai.Prompt.Execute directly, passing input and execution options.
For prompts that don't need to be registered (e.g., for single-use or testing), use ai.NewPrompt instead.
Options ¶
Model and Configuration:
- ai.WithModel: Specify the model (accepts ai.Model or ai.ModelRef)
- ai.WithModelName: Specify model by name string
- ai.WithConfig: Set generation parameters (temperature, max tokens, etc.)
Prompt Content:
- ai.WithPrompt: Set the user prompt template (supports {{variable}} syntax)
- ai.WithPromptFn: Set a function that generates the user prompt dynamically
- ai.WithSystem: Set system instructions template
- ai.WithSystemFn: Set a function that generates system instructions dynamically
- ai.WithMessages: Provide static conversation history
- ai.WithMessagesFn: Provide a function that generates conversation history
Input Schema:
- ai.WithInputType: Set input schema from a Go type (provides default values)
- ai.WithInputSchema: Provide a custom JSON schema for input
- ai.WithInputSchemaName: Reference a pre-registered schema by name
Output Schema:
- ai.WithOutputType: Set output schema from a Go type
- ai.WithOutputSchema: Provide a custom JSON schema for output
- ai.WithOutputSchemaName: Reference a pre-registered schema by name
- ai.WithOutputFormat: Specify output format (json, text, etc.)
Tools and Resources:
- ai.WithTools: Enable tools the model can call
- ai.WithToolChoice: Control whether tool calls are required, optional, or disabled
- ai.WithMaxTurns: Set maximum tool call iterations
- ai.WithResources: Attach resources available during generation
Metadata:
- ai.WithDescription: Set a description for the prompt
- ai.WithMetadata: Set arbitrary metadata
Example:
type GeoInput struct {
Country string `json:"country"`
}
type GeoOutput struct {
Capital string `json:"capital"`
}
// Define the prompt
capitalPrompt := genkit.DefinePrompt(g, "findCapital",
ai.WithDescription("Finds the capital of a country."),
ai.WithModelName("googleai/gemini-2.5-flash"),
ai.WithSystem("You are a helpful geography assistant."),
ai.WithPrompt("What is the capital of {{country}}?"),
ai.WithInputType(GeoInput{Country: "USA"}),
ai.WithOutputType(GeoOutput{}),
// Config is provider-specific, e.g., genai.GenerateContentConfig for Google AI
)
// Option 1: Render + Generate (using default input "USA")
actionOpts, err := capitalPrompt.Render(ctx, nil) // nil input uses default
if err != nil {
log.Fatalf("Render failed: %v", err)
}
resp1, err := genkit.GenerateWithRequest(ctx, g, actionOpts, nil, nil)
if err != nil {
log.Fatalf("GenerateWithRequest failed: %v", err)
}
var out1 GeoOutput
if err = resp1.Output(&out1); err != nil {
log.Fatalf("Output failed: %v", err)
}
fmt.Printf("Capital of USA: %s\n", out1.Capital) // Output: Capital of USA: Washington D.C.
// Option 2: Execute directly (with new input)
resp2, err := capitalPrompt.Execute(ctx, ai.WithInput(GeoInput{Country: "France"}))
if err != nil {
log.Fatalf("Execute failed: %v", err)
}
var out2 GeoOutput
if err = resp2.Output(&out2); err != nil {
log.Fatalf("Output failed: %v", err)
}
fmt.Printf("Capital of France: %s\n", out2.Capital) // Output: Capital of France: Paris
Example ¶
This example demonstrates defining a reusable prompt with a template.
package main
import (
"context"
"fmt"
"log"
"github.com/firebase/genkit/go/ai"
"github.com/firebase/genkit/go/genkit"
)
func main() {
ctx := context.Background()
g := genkit.Init(ctx)
// Define a prompt with Handlebars template syntax
prompt := genkit.DefinePrompt(g, "greeting",
ai.WithPrompt("Say hello to {{name}} in a {{style}} way."),
)
// Render the prompt (without executing - useful for inspection)
rendered, err := prompt.Render(ctx, map[string]any{
"name": "Alice",
"style": "friendly",
})
if err != nil {
log.Fatal(err)
}
// The rendered prompt contains the messages that would be sent
fmt.Println(rendered.Messages[0].Content[0].Text)
}
Output: Say hello to Alice in a friendly way.
func DefineResource ¶ added in v0.7.0
func DefineResource(g *Genkit, name string, opts *ai.ResourceOptions, fn ai.ResourceFunc) ai.Resource
DefineResource defines a resource and registers it with the Genkit instance. Resources provide content that can be referenced in prompts via URI.
Example:
DefineResource(g, "company-docs", &ai.ResourceOptions{
URI: "file:///docs/handbook.pdf",
Description: "Company handbook",
}, func(ctx context.Context, input *ai.ResourceInput) (*ai.ResourceOutput, error) {
content, err := os.ReadFile("/docs/handbook.pdf")
if err != nil {
return nil, err
}
return &ai.ResourceOutput{
Content: []*ai.Part{ai.NewTextPart(string(content))},
}, nil
})
func DefineRetriever ¶ added in v0.3.0
func DefineRetriever(g *Genkit, name string, opts *ai.RetrieverOptions, fn ai.RetrieverFunc) ai.Retriever
DefineRetriever defines a custom retriever implementation, registers it as a core.Action of type Retriever, and returns an ai.Retriever. Retrievers are used to find documents relevant to a given query, often by performing similarity searches in a vector database.
The `name` is the unique identifier for the retriever. The `fn` function contains the logic to process an ai.RetrieverRequest (containing the query) and return an ai.RetrieverResponse (containing the relevant documents).
For retrievers that don't need to be registered (e.g., for plugin development), use ai.NewRetriever instead.
func DefineSchema ¶ added in v1.3.0
DefineSchema defines a named JSON schema and registers it in the registry.
Registered schemas can be referenced by name in prompts (both `.prompt` files and programmatic definitions) to define input or output structures. The `schema` argument must be a JSON schema definition represented as a map.
Example:
genkit.DefineSchema(g, "User", map[string]any{
"type": "object",
"properties": map[string]any{
"name": map[string]any{"type": "string"},
"age": map[string]any{"type": "integer"},
},
"required": []string{"name"}
})
genkit.Generate(ctx, g, ai.WithOutputSchemaName("User"), ai.WithPrompt("What is your name?"))
func DefineSchemaFor ¶ added in v1.3.0
DefineSchemaFor defines a named JSON schema derived from a Go type and registers it in the registry.
This is an alternative to DefineSchema.
Example:
type User struct {
Name string `json:"name"`
Age int `json:"age"`
}
genkit.DefineSchemaFor[User](g)
genkit.Generate(ctx, g, ai.WithOutputSchemaName("User"), ai.WithPrompt("What is your name?"))
Example ¶
This example demonstrates registering a Go type as a named schema.
package main
import (
"context"
"fmt"
"github.com/firebase/genkit/go/genkit"
)
func main() {
ctx := context.Background()
g := genkit.Init(ctx)
// Define a struct type
type Person struct {
Name string `json:"name" jsonschema:"description=The person's name"`
Age int `json:"age" jsonschema:"description=The person's age"`
}
// Register the schema - this makes it available for .prompt files
// that reference it by name (e.g., "output: { schema: Person }")
genkit.DefineSchemaFor[Person](g)
fmt.Println("Schema registered: Person")
}
Output: Schema registered: Person
func DefineStreamingFlow ¶
func DefineStreamingFlow[In, Out, Stream any](g *Genkit, name string, fn core.StreamingFunc[In, Out, Stream]) *core.Flow[In, Out, Stream]
DefineStreamingFlow defines a streaming flow, registers it as a core.Action of type Flow, and returns a core.Flow runner capable of streaming.
The provided function `fn` takes an input of type `In`. It can optionally stream intermediate results of type `Stream` by invoking the provided callback function. Finally, it returns a final output of type `Out`.
If the function supports streaming and the callback is non-nil when the flow is run, it should invoke the callback periodically with `Stream` values. The final `Out` value, typically an aggregation of the streamed data, is returned at the end. If the callback is nil or the function doesn't support streaming for a given input, it should simply compute and return the `Out` value directly.
Example:
counterFlow := genkit.DefineStreamingFlow(g, "counter",
func(ctx context.Context, limit int, stream core.StreamCallback[int]) (string, error) {
if stream == nil { // Non-streaming case
return fmt.Sprintf("Counted up to %d", limit), nil
}
// Streaming case
for i := 1; i <= limit; i++ {
if err := stream(ctx, i); err != nil {
return "", fmt.Errorf("streaming error: %w", err)
}
// time.Sleep(100 * time.Millisecond) // Optional delay
}
return fmt.Sprintf("Finished counting to %d", limit), nil
},
)
// Later, run the flow with streaming:
streamCh, err := counterFlow.Stream(ctx, 5)
if err != nil {
// handle error
}
for result := range streamCh {
if result.Err != nil {
log.Printf("Stream error: %v", result.Err)
break
}
if result.Done {
fmt.Println("Final Output:", result.Output) // Output: Finished counting to 5
} else {
fmt.Println("Stream Chunk:", result.Stream) // Outputs: 1, 2, 3, 4, 5
}
}
Example ¶
This example demonstrates defining a streaming flow that sends chunks to the caller as they are produced.
package main
import (
"context"
"fmt"
"log"
"github.com/firebase/genkit/go/core"
"github.com/firebase/genkit/go/genkit"
)
func main() {
ctx := context.Background()
g := genkit.Init(ctx)
// Define a streaming flow that counts down
countdownFlow := genkit.DefineStreamingFlow(g, "countdown",
func(ctx context.Context, start int, sendChunk func(context.Context, int) error) (string, error) {
for i := start; i > 0; i-- {
if err := sendChunk(ctx, i); err != nil {
return "", err
}
}
return "Liftoff!", nil
},
)
// Stream results using the iterator
iter := countdownFlow.Stream(ctx, 3)
iter(func(val *core.StreamingFlowValue[string, int], err error) bool {
if err != nil {
log.Fatal(err)
}
if val.Done {
fmt.Println("Final:", val.Output)
} else {
fmt.Println("Count:", val.Stream)
}
return true
})
}
Output: Count: 3 Count: 2 Count: 1 Final: Liftoff!
func DefineTool ¶ added in v0.3.0
func DefineTool[In, Out any](g *Genkit, name, description string, fn ai.ToolFunc[In, Out], opts ...ai.ToolOption) *ai.ToolDef[In, Out]
DefineTool defines a tool that can be used by models during generation, registers it as a core.Action of type Tool, and returns an ai.Tool. Tools allow models to interact with external systems or perform specific computations.
The `name` is the identifier the model uses to request the tool. The `description` helps the model understand when to use the tool. The function `fn` implements the tool's logic, taking an ai.ToolContext and an input of type `In`, and returning an output of type `Out`. The input and output types determine the `inputSchema` and `outputSchema` in the tool's definition, which guide the model on how to provide input and interpret output.
For tools that don't need to be registered (e.g., dynamically created tools), use ai.NewTool instead.
Options ¶
- ai.WithInputSchema: Provide a custom JSON schema instead of inferring from the type parameter
- ai.WithInputSchemaName: Reference a pre-registered schema by name
Example:
weatherTool := genkit.DefineTool(g, "getWeather", "Fetches the weather for a given city",
func(ctx *ai.ToolContext, city string) (string, error) {
// In a real scenario, call a weather API
log.Printf("Tool: Fetching weather for %s", city)
if city == "Paris" {
return "Sunny, 25°C", nil
}
return "Cloudy, 18°C", nil
},
)
// Use the tool in a generation request:
resp, err := genkit.Generate(ctx, g,
ai.WithPrompt("What's the weather like in Paris?"),
ai.WithTools(weatherTool), // Make the tool available
// Optionally use ai.WithToolChoice(...)
)
if err != nil {
log.Fatalf("Generate failed: %v", err)
}
fmt.Println(resp.Text()) // Might output something like "The weather in Paris is Sunny, 25°C."
Example ¶
This example demonstrates defining a tool that models can call during generation.
package main
import (
"context"
"fmt"
"github.com/firebase/genkit/go/ai"
"github.com/firebase/genkit/go/genkit"
)
func main() {
ctx := context.Background()
g := genkit.Init(ctx)
// Define a tool that adds two numbers
_ = genkit.DefineTool(g, "add",
"Adds two numbers together",
func(ctx *ai.ToolContext, input struct {
A float64 `json:"a" jsonschema:"description=First number"`
B float64 `json:"b" jsonschema:"description=Second number"`
}) (float64, error) {
return input.A + input.B, nil
},
)
// The tool is now registered and can be used with ai.WithTools()
// when calling genkit.Generate()
fmt.Println("Tool registered: add")
}
Output: Tool registered: add
func DefineToolWithInputSchema
deprecated
added in
v0.6.0
func DefineToolWithInputSchema[Out any](g *Genkit, name, description string, inputSchema map[string]any, fn ai.ToolFunc[any, Out]) *ai.ToolDef[any, Out]
DefineToolWithInputSchema defines a tool with a custom input schema that can be used by models during generation, registers it as a core.Action of type Tool, and returns an *ai.ToolDef.
This variant of DefineTool allows specifying a JSON Schema for the tool's input, providing more control over input validation and model guidance. The input parameter to the tool function will be of type `any` and should be validated/processed according to the schema.
The `name` is the identifier the model uses to request the tool. The `description` helps the model understand when to use the tool. The `inputSchema` defines the expected structure and constraints of the input. The function `fn` implements the tool's logic, taking an ai.ToolContext and an input of type `any`, and returning an output of type `Out`.
Deprecated: Use DefineTool with ai.WithInputSchema instead.
Example:
// Define a custom input schema
inputSchema := map[string]any{
"type": "object",
"properties": map[string]any{
"city": map[string]any{"type": "string"},
"unit": map[string]any{
"type": "string",
"enum": []any{"C", "F"},
},
},
"required": []string{"city"},
}
// Define the tool with the schema
weatherTool := genkit.DefineTool(g, "getWeather",
"Fetches the weather for a given city with unit preference",
func(ctx *ai.ToolContext, input any) (string, error) {
// Parse and validate input
data := input.(map[string]any)
city := data["city"].(string)
unit := "C" // default
if u, ok := data["unit"].(string); ok {
unit = u
}
// Implementation...
return fmt.Sprintf("Weather in %s: 25°%s", city, unit), nil
},
ai.WithToolInputSchema(inputSchema),
)
func Embed ¶ added in v0.7.0
func Embed(ctx context.Context, g *Genkit, opts ...ai.EmbedderOption) (*ai.EmbedResponse, error)
Embed performs an embedding request using a flexible set of options provided via ai.EmbedderOption arguments. It's a convenient way to generate embeddings from registered embedders without directly calling the embedder instance.
Options ¶
- ai.WithEmbedder: Specify the embedder (accepts ai.Embedder or ai.EmbedderRef)
- ai.WithEmbedderName: Specify embedder by name string
- ai.WithConfig: Set embedder-specific configuration
- ai.WithTextDocs: Provide text to embed
- ai.WithDocs: Provide ai.Document instances to embed
Example:
resp, err := genkit.Embed(ctx, g,
ai.WithEmbedderName("myEmbedder"),
ai.WithTextDocs("Hello, world!"),
)
if err != nil {
log.Fatalf("Embed failed: %v", err)
}
for i, embedding := range resp.Embeddings {
fmt.Printf("Embedding %d: %v\n", i, embedding.Embedding)
}
func Evaluate ¶ added in v1.0.0
func Evaluate(ctx context.Context, g *Genkit, opts ...ai.EvaluatorOption) (*ai.EvaluatorResponse, error)
Evaluate performs an evaluation request using a flexible set of options provided via ai.EvaluatorOption arguments. It's a convenient way to run evaluations using registered evaluators without directly calling the evaluator instance.
Options ¶
- ai.WithEvaluator: Specify the evaluator (accepts ai.Evaluator or ai.EvaluatorRef)
- ai.WithEvaluatorName: Specify evaluator by name string
- ai.WithDataset: Provide the dataset of examples to evaluate
- ai.WithID: Set a unique identifier for this evaluation run
- ai.WithConfig: Set evaluator-specific configuration
Example:
dataset := []*ai.Example{
{
Input: "What is the capital of France?",
Reference: "Paris",
},
}
resp, err := genkit.Evaluate(ctx, g,
ai.WithEvaluatorName("myEvaluator"),
ai.WithDataset(dataset...),
)
if err != nil {
log.Fatalf("Evaluate failed: %v", err)
}
for _, result := range *resp {
fmt.Printf("Evaluation result: %+v\n", result)
}
func FindMatchingResource ¶ added in v0.7.0
FindMatchingResource finds a resource that matches the given URI.
func Generate ¶ added in v0.3.0
func Generate(ctx context.Context, g *Genkit, opts ...ai.GenerateOption) (*ai.ModelResponse, error)
Generate performs a model generation request using a flexible set of options provided via ai.GenerateOption arguments. It's a convenient way to make generation calls without pre-defining a prompt object.
Options ¶
Model and Configuration:
- ai.WithModel: Specify the model (accepts ai.Model or ai.ModelRef)
- ai.WithModelName: Specify model by name string (e.g., "googleai/gemini-2.5-flash")
- ai.WithConfig: Set generation parameters (temperature, max tokens, etc.)
Prompting:
- ai.WithPrompt: Set the user prompt (supports format strings)
- ai.WithPromptFn: Set a function that generates the user prompt dynamically
- ai.WithSystem: Set system instructions
- ai.WithSystemFn: Set a function that generates system instructions dynamically
- ai.WithMessages: Provide conversation history
- ai.WithMessagesFn: Provide a function that generates conversation history
Tools and Resources:
- ai.WithTools: Enable tools the model can call
- ai.WithToolChoice: Control whether tool calls are required, optional, or disabled
- ai.WithMaxTurns: Set maximum tool call iterations
- ai.WithReturnToolRequests: Return tool requests instead of executing them
- ai.WithResources: Attach resources available during generation
Output:
- ai.WithOutputType: Request structured output matching a Go type
- ai.WithOutputSchema: Provide a custom JSON schema for output
- ai.WithOutputSchemaName: Reference a pre-registered schema by name
- ai.WithOutputFormat: Specify output format (json, text, etc.)
- ai.WithOutputEnums: Constrain output to specific enum values
Context and Streaming:
- ai.WithDocs: Provide context documents
- ai.WithTextDocs: Provide context as text strings
- ai.WithStreaming: Enable streaming with a callback function
- ai.WithMiddleware: Apply middleware to the model request/response
Tool Continuation:
- ai.WithToolResponses: Resume generation with tool response parts
- ai.WithToolRestarts: Resume generation by restarting tool requests
Example:
resp, err := genkit.Generate(ctx, g,
ai.WithModelName("googleai/gemini-2.5-flash"),
ai.WithPrompt("Write a short poem about clouds."),
)
if err != nil {
log.Fatalf("Generate failed: %v", err)
}
fmt.Println(resp.Text())
func GenerateData ¶ added in v0.3.0
func GenerateData[Out any](ctx context.Context, g *Genkit, opts ...ai.GenerateOption) (*Out, *ai.ModelResponse, error)
GenerateData performs a model generation request, expecting structured output (typically JSON) that conforms to the schema inferred from the Out type parameter. It automatically sets output type and JSON format, unmarshals the response, and returns the typed result.
GenerateData accepts the same options as Generate. See Generate for the full list of available options. Note that output options like ai.WithOutputType are automatically applied based on the Out type parameter.
Example:
type BookInfo struct {
Title string `json:"title"`
Author string `json:"author"`
Year int `json:"year"`
}
book, _, err := genkit.GenerateData[BookInfo](ctx, g,
ai.WithPrompt("Tell me about 'The Hitchhiker's Guide to the Galaxy'."),
)
if err != nil {
log.Fatalf("GenerateData failed: %v", err)
}
log.Printf("Book: %+v\n", book) // Output: Book: {Title:The Hitchhiker's Guide to the Galaxy Author:Douglas Adams Year:1979}
func GenerateDataStream ¶ added in v1.3.0
func GenerateDataStream[Out any](ctx context.Context, g *Genkit, opts ...ai.GenerateOption) iter.Seq2[*ai.StreamValue[Out, Out], error]
GenerateDataStream generates a model response with streaming and returns strongly-typed output. It returns an iterator that yields streaming results.
If the yield function is passed a non-nil error, generation has failed with that error; the yield function will not be called again.
If the yield function's ai.StreamValue argument has Done == true, the value's Output and Response fields contain the final typed output and response; the yield function will not be called again.
Otherwise the Chunk field of the passed ai.StreamValue holds a streamed chunk.
GenerateDataStream accepts the same options as Generate. See Generate for the full list of available options. Note that output options are automatically applied based on the Out type parameter.
Example:
type Story struct {
Title string `json:"title"`
Content string `json:"content"`
}
for result, err := range genkit.GenerateDataStream[Story](ctx, g,
ai.WithPrompt("Write a short story about a brave knight."),
) {
if err != nil {
log.Fatalf("Stream error: %v", err)
}
if result.Done {
fmt.Printf("Story: %+v\n", result.Output)
} else {
fmt.Print(result.Chunk.Text())
}
}
func GenerateOperation ¶ added in v1.3.0
func GenerateOperation(ctx context.Context, g *Genkit, opts ...ai.GenerateOption) (*ai.ModelOperation, error)
GenerateOperation performs a model generation request using a flexible set of options provided via ai.GenerateOption arguments. It's designed for long-running generation tasks that may not complete immediately.
Unlike Generate, this function returns a ai.ModelOperation which can be used to check the status of the operation and get the result. Use CheckModelOperation to poll for completion.
GenerateOperation accepts the same options as Generate. See Generate for the full list of available options.
Example:
op, err := genkit.GenerateOperation(ctx, g,
ai.WithModelName("googleai/veo-2.0-generate-001"),
ai.WithPrompt("A banana riding a bicycle."),
)
if err != nil {
log.Fatalf("GenerateOperation failed: %v", err)
}
fmt.Println(op.ID)
// Check the status of the operation
op, err = genkit.CheckModelOperation(ctx, g, op)
if err != nil {
log.Fatalf("failed to check operation status: %v", err)
}
fmt.Println(op.Done)
// Get the result of the operation
fmt.Println(op.Output.Text())
func GenerateStream ¶ added in v1.3.0
func GenerateStream(ctx context.Context, g *Genkit, opts ...ai.GenerateOption) iter.Seq2[*ai.ModelStreamValue, error]
GenerateStream generates a model response and streams the output. It returns an iterator that yields streaming results.
If the yield function is passed a non-nil error, generation has failed with that error; the yield function will not be called again.
If the yield function's ai.ModelStreamValue argument has Done == true, the value's Response field contains the final response; the yield function will not be called again.
Otherwise the Chunk field of the passed ai.ModelStreamValue holds a streamed chunk.
GenerateStream accepts the same options as Generate. See Generate for the full list of available options.
Example:
for result, err := range genkit.GenerateStream(ctx, g,
ai.WithPrompt("Tell me a story about a brave knight."),
) {
if err != nil {
log.Fatalf("Stream error: %v", err)
}
if result.Done {
fmt.Println("\nFinal response:", result.Response.Text())
} else {
fmt.Print(result.Chunk.Text())
}
}
func GenerateText ¶ added in v0.3.0
GenerateText performs a model generation request similar to Generate, but directly returns the generated text content as a string. It's a convenience wrapper for cases where only the textual output is needed.
GenerateText accepts the same options as Generate. See Generate for the full list of available options.
Example:
joke, err := genkit.GenerateText(ctx, g,
ai.WithPrompt("Tell me a funny programming joke."),
)
if err != nil {
log.Fatalf("GenerateText failed: %v", err)
}
fmt.Println(joke)
func GenerateWithRequest ¶ added in v0.3.0
func GenerateWithRequest(ctx context.Context, g *Genkit, actionOpts *ai.GenerateActionOptions, mw []ai.ModelMiddleware, cb ai.ModelStreamCallback) (*ai.ModelResponse, error)
GenerateWithRequest performs a model generation request using explicitly provided ai.GenerateActionOptions. This function is typically used in conjunction with prompts defined via DefinePrompt, where [ai.prompt.Render] produces the `actionOpts`. It allows fine-grained control over the request sent to the model.
It accepts optional model middleware (`mw`) for intercepting/modifying the request/response, and an optional streaming callback (`cb`) of type ai.ModelStreamCallback to receive response chunks as they arrive.
Example (using options rendered from a prompt):
myPrompt := genkit.LookupPrompt(g, "myDefinedPrompt")
actionOpts, err := myPrompt.Render(ctx, map[string]any{"topic": "go programming"})
if err != nil {
// handle error
}
// Optional: Modify actionOpts here if needed (config is provider-specific)
resp, err := genkit.GenerateWithRequest(ctx, g, actionOpts, nil, nil) // No middleware or streaming
if err != nil {
// handle error
}
fmt.Println(resp.Text())
func Handler ¶ added in v0.3.0
func Handler(a api.Action, opts ...HandlerOption) http.HandlerFunc
Handler returns an HTTP handler function that serves the action with the provided options.
The provided HandlerOptions are applied during construction. If any option fails to apply, Handler panics.
Example:
genkit.Handler(
g,
genkit.WithContextProviders(func(ctx context.Context, req core.RequestData) (api.ActionContext, error) {
return api.ActionContext{"myKey": "myValue"}, nil
}))
Example ¶
This example demonstrates using Handler to expose a single flow as an HTTP endpoint.
package main
import (
"context"
"fmt"
"net/http"
"github.com/firebase/genkit/go/genkit"
)
func main() {
ctx := context.Background()
g := genkit.Init(ctx)
// Define a flow
greetFlow := genkit.DefineFlow(g, "greet",
func(ctx context.Context, name string) (string, error) {
return fmt.Sprintf("Hello, %s!", name), nil
},
)
// Create an HTTP handler for the flow
mux := http.NewServeMux()
mux.HandleFunc("POST /greet", genkit.Handler(greetFlow))
// The handler accepts JSON: {"data": "World"}
// and returns JSON: {"result": "Hello, World!"}
fmt.Println("Handler registered at POST /greet")
}
Output: Handler registered at POST /greet
func HandlerFunc ¶ added in v1.5.0
func HandlerFunc(a api.Action, opts ...HandlerOption) func(http.ResponseWriter, *http.Request) error
HandlerFunc returns an HTTP handler function that executes the given action and returns an error instead of writing it directly to the response.
It is intended for use with web frameworks that expect handlers with the signature:
func(http.ResponseWriter, *http.Request) error
so that errors can be handled centrally (e.g., by middleware).
The provided HandlerOptions are applied during construction. If any option fails to apply, HandlerFunc panics.
Example:
genkit.HandlerFunc(
g,
genkit.WithContextProviders(func(ctx context.Context, req core.RequestData) (api.ActionContext, error) {
return api.ActionContext{"myKey": "myValue"}, nil
}),
)
func IsDefinedFormat ¶ added in v0.5.0
IsDefinedFormat checks if a formatter with the given name is registered in the registry.
func ListFlows ¶ added in v0.3.0
ListFlows returns a slice of all api.Action instances that represent flows registered with the Genkit instance `g`. This is useful for introspection or for dynamically exposing flow endpoints, for example, in an HTTP server.
Example (HttpServer) ¶
This example demonstrates creating an HTTP server that exposes all registered flows as endpoints.
package main
import (
"context"
"fmt"
"net/http"
"github.com/firebase/genkit/go/genkit"
)
func main() {
ctx := context.Background()
g := genkit.Init(ctx)
// Define some flows
genkit.DefineFlow(g, "echo", func(ctx context.Context, s string) (string, error) {
return s, nil
})
genkit.DefineFlow(g, "reverse", func(ctx context.Context, s string) (string, error) {
runes := []rune(s)
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
runes[i], runes[j] = runes[j], runes[i]
}
return string(runes), nil
})
// Create HTTP handlers for all flows
mux := http.NewServeMux()
for _, flow := range genkit.ListFlows(g) {
mux.HandleFunc("POST /"+flow.Name(), genkit.Handler(flow))
}
// The mux now has:
// - POST /echo
// - POST /reverse
fmt.Printf("Registered %d flow handlers\n", len(genkit.ListFlows(g)))
}
Output: Registered 2 flow handlers
func ListResources ¶ added in v0.7.0
ListResources returns a slice of all resource actions
func ListTools ¶ added in v0.6.0
ListTools returns a slice of all ai.Tool instances that are registered with the Genkit instance `g`. This is useful for introspection and for exposing tools to external systems like MCP servers.
func LoadPrompt ¶ added in v0.3.0
LoadPrompt loads a single `.prompt` file specified by `path` into the registry, associating it with the given `namespace`, and returns the resulting [ai.prompt].
The `path` should be the full path to the `.prompt` file. The `namespace` acts as a prefix to the prompt name (e.g., namespace "myApp" and path "/path/to/greeting.prompt" results in prompt name "myApp/greeting"). Use an empty string for no namespace.
This provides a way to load specific prompt files programmatically, outside of the automatic loading done by Init or LoadPromptDir.
Example:
// Load a specific prompt file with a namespace
customPrompt := genkit.LoadPrompt(g, "./prompts/analyzer.prompt", "analysis")
if customPrompt == nil {
log.Fatal("Custom prompt not found or failed to parse.")
}
// Execute the loaded prompt
resp, err := customPrompt.Execute(ctx, ai.WithInput(map[string]any{"text": "some data"}))
// ... handle response and error ...
func LoadPromptDir ¶ added in v0.3.0
LoadPromptDir loads all `.prompt` files from the specified directory `dir` into the registry, associating them with the given `namespace`. Files starting with `_` are treated as partials and are not registered as executable prompts but can be included in other prompts.
If `dir` is empty, it defaults to "./prompts". If the directory doesn't exist, it logs a debug message (if using the default) or panics (if specified). The `namespace` acts as a prefix to the prompt name (e.g., namespace "myApp" and file "greeting.prompt" results in prompt name "myApp/greeting"). Use an empty string for no namespace.
This function is often called implicitly by Init using the directory specified by WithPromptDir, but can be called explicitly to load prompts from other locations or with different namespaces.
func LoadPromptDirFromFS ¶ added in v1.3.0
LoadPromptDirFromFS loads all `.prompt` files from the specified embedded filesystem `fsys` into the registry, associating them with the given `namespace`. Files starting with `_` are treated as partials and are not registered as executable prompts but can be included in other prompts.
The `fsys` parameter should be an fs.FS implementation (e.g., embed.FS). The `dir` parameter specifies the directory within the filesystem where prompts are located (e.g., "prompts" if using `//go:embed prompts/*`). The `namespace` acts as a prefix to the prompt name (e.g., namespace "myApp" and file "greeting.prompt" results in prompt name "myApp/greeting"). Use an empty string for no namespace.
This function provides an alternative to LoadPromptDir for loading prompts from embedded filesystems, enabling self-contained binaries without external prompt files.
Example:
import "embed"
//go:embed prompts/*
var promptsFS embed.FS
func main() {
g := genkit.Init(ctx)
genkit.LoadPromptDirFromFS(g, promptsFS, "prompts", "myNamespace")
}
func LoadPromptFromSource ¶ added in v1.3.0
LoadPromptFromSource loads a prompt from raw `.prompt` file content (frontmatter + template) into the registry and returns the resulting ai.Prompt.
The `source` parameter should contain the complete `.prompt` file text, including the YAML frontmatter (delimited by `---`) and the template body. The `name` parameter is the prompt name, which may include a variant suffix (e.g., "greeting" or "greeting.formal"). The `namespace` acts as a prefix to the prompt name. Use an empty string for no namespace.
This is useful for loading prompts from sources other than the filesystem, such as databases, environment variables, or embedded strings.
Example:
promptSource := `---
model: googleai/gemini-2.5-flash
input:
schema:
name: string
---
Hello, {{name}}!
`
prompt, err := genkit.LoadPromptFromSource(g, promptSource, "greeting", "myApp")
if err != nil {
log.Fatalf("Failed to load prompt: %v", err)
}
resp, err := prompt.Execute(ctx, ai.WithInput(map[string]any{"name": "World"}))
// ...
func LookupBackgroundModel ¶ added in v1.3.0
func LookupBackgroundModel(g *Genkit, name string) ai.BackgroundModel
LookupBackgroundModel retrieves a registered background model by its provider and name. It returns the background action instance if found, or `nil` if no background model with the given identifier is registered.
func LookupDataPrompt ¶ added in v1.3.0
func LookupDataPrompt[In, Out any](g *Genkit, name string) *ai.DataPrompt[In, Out]
LookupDataPrompt looks up a prompt by name and wraps it with type information. This is useful for wrapping prompts loaded from .prompt files with strong types. It returns nil if the prompt was not found.
func LookupEmbedder ¶ added in v0.3.0
LookupEmbedder retrieves a registered ai.Embedder by its provider and name. It returns the embedder instance if found, or `nil` if no embedder with the given identifier is registered (e.g., via DefineEmbedder or a plugin). It will try to resolve the embedder dynamically if the embedder is not found.
func LookupEvaluator ¶ added in v0.3.0
LookupEvaluator retrieves a registered ai.Evaluator by its provider and name. It returns the evaluator instance if found, or `nil` if no evaluator with the given identifier is registered (e.g., via DefineEvaluator, DefineBatchEvaluator, or a plugin).
func LookupMiddleware ¶ added in v1.7.0
func LookupMiddleware(g *Genkit, name string) *ai.MiddlewareDesc
LookupMiddleware retrieves a registered middleware descriptor by its name. It returns the descriptor if found, or `nil` if no middleware with the given name is registered (e.g., via DefineMiddleware or through a plugin's ai.MiddlewarePlugin.Middlewares method).
func LookupModel ¶ added in v0.3.0
LookupModel retrieves a registered ai.Model by its provider and name. It returns the model instance if found, or `nil` if no model with the given identifier is registered (e.g., via DefineModel or a plugin). It will try to resolve the model dynamically by matching the provider name; this does not necessarily mean the model is valid.
func LookupPlugin ¶ added in v0.3.0
LookupPlugin retrieves a registered plugin instance by its name. Plugins are registered during initialization via WithPlugins. It returns the plugin instance as `Plugin` if found, or `nil` otherwise. The caller is responsible for type-asserting the returned value to the specific plugin api.
func LookupPrompt ¶ added in v0.3.0
LookupPrompt retrieves a registered ai.Prompt by its name. Prompts can be registered via DefinePrompt or loaded automatically from `.prompt` files in the directory specified by WithPromptDir or LoadPromptDir. It returns the prompt instance if found, or `nil` otherwise.
Example ¶
This example demonstrates looking up a prompt that was loaded from a .prompt file.
package main
import (
"context"
"fmt"
"log"
"github.com/firebase/genkit/go/ai"
"github.com/firebase/genkit/go/genkit"
)
func main() {
ctx := context.Background()
// In production, you would initialize with a prompt directory:
// g := genkit.Init(ctx, genkit.WithPromptDir("./prompts"))
g := genkit.Init(ctx)
// Define a prompt programmatically (simulating a loaded prompt)
genkit.DefinePrompt(g, "greeting",
ai.WithPrompt("Hello {{name}}!"),
)
// Look up the prompt by name
prompt := genkit.LookupPrompt(g, "greeting")
if prompt == nil {
log.Fatal("Prompt not found")
}
fmt.Println("Found prompt:", prompt.Name())
}
Output: Found prompt: greeting
func LookupRetriever ¶ added in v0.3.0
LookupRetriever retrieves a registered ai.Retriever by its provider and name. It returns the retriever instance if found, or `nil` if no retriever with the given identifier is registered (e.g., via DefineRetriever or a plugin).
func LookupTool ¶ added in v0.3.0
LookupTool retrieves a registered tool by its name. It returns the tool instance if found, or `nil` if no tool with the given name is registered (e.g., via DefineTool). Since the types are not known at lookup time, it returns a type-erased tool.
func NewFlow ¶ added in v1.5.0
NewFlow creates a core.Flow without registering it as an action. To register the flow later, call RegisterAction.
func NewResource ¶ added in v0.7.0
func NewResource(name string, opts *ai.ResourceOptions, fn ai.ResourceFunc) ai.Resource
NewResource creates an unregistered resource action that can be temporarily attached during generation via WithResources option.
Example:
resource := NewResource("user-data", &ai.ResourceOptions{
Template: "user://profile/{id}",
}, func(ctx context.Context, input *ai.ResourceInput) (*ai.ResourceOutput, error) {
userID := input.Variables["id"]
// Load user data dynamically...
return &ai.ResourceOutput{Content: []*ai.Part{ai.NewTextPart(userData)}}, nil
})
// Use in generation:
ai.Generate(ctx, g,
ai.WithPrompt([]*ai.Part{
ai.NewTextPart("Analyze this user:"),
ai.NewResourcePart("user://profile/123"),
}),
ai.WithResources(resource),
)
func NewStreamingFlow ¶ added in v1.5.0
func NewStreamingFlow[In, Out, Stream any](name string, fn core.StreamingFunc[In, Out, Stream]) *core.Flow[In, Out, Stream]
NewStreamingFlow creates a streaming core.Flow without registering it as an action. To register the flow later, call RegisterAction.
func RegisterAction ¶ added in v0.7.0
func RegisterAction(g *Genkit, action api.Registerable)
RegisterAction registers a api.Action that was previously created by calling NewX instead of DefineX.
Example:
model := ai.NewModel(...) genkit.RegisterAction(g, model)
func Retrieve ¶ added in v0.7.0
func Retrieve(ctx context.Context, g *Genkit, opts ...ai.RetrieverOption) (*ai.RetrieverResponse, error)
Retrieve performs a document retrieval request using a flexible set of options provided via ai.RetrieverOption arguments. It's a convenient way to retrieve relevant documents from registered retrievers without directly calling the retriever instance.
Options ¶
- ai.WithRetriever: Specify the retriever (accepts ai.Retriever or ai.RetrieverRef)
- ai.WithRetrieverName: Specify retriever by name string
- ai.WithConfig: Set retriever-specific configuration
- ai.WithTextDocs: Provide query text as documents
- ai.WithDocs: Provide query as ai.Document instances
Example:
resp, err := genkit.Retrieve(ctx, g,
ai.WithRetrieverName("myRetriever"),
ai.WithTextDocs("What is the capital of France?"),
)
if err != nil {
log.Fatalf("Retrieve failed: %v", err)
}
for _, doc := range resp.Documents {
fmt.Printf("Document: %+v\n", doc)
}
func Run ¶
Run executes the given function `fn` within the context of the current flow run, creating a distinct trace span for this step. It's used to add observability to specific sub-operations within a flow defined by DefineFlow or DefineStreamingFlow. The `name` parameter provides a label for the trace span. It returns the output of `fn` and any error it produces.
Example (within a DefineFlow function):
complexFlow := genkit.DefineFlow(g, "complexTask",
func(ctx context.Context, input string) (string, error) {
// Step 1: Process input (traced as "process-input")
processedInput, err := genkit.Run(ctx, "process-input", func() (string, error) {
// ... some processing ...
return strings.ToUpper(input), nil
})
if err != nil {
return "", err
}
// Step 2: Generate response (traced as "generate-response")
response, err := genkit.Run(ctx, "generate-response", func() (string, error) {
// ... call an AI model or another service ...
return "Response for " + processedInput, nil
})
if err != nil {
return "", err
}
return response, nil
},
)
Example ¶
This example demonstrates using Run to create traced sub-steps within a flow for better observability.
package main
import (
"context"
"fmt"
"log"
"strings"
"github.com/firebase/genkit/go/genkit"
)
func main() {
ctx := context.Background()
g := genkit.Init(ctx)
// Define a flow with traced sub-steps
pipelineFlow := genkit.DefineFlow(g, "pipeline",
func(ctx context.Context, input string) (string, error) {
// Each Run call creates a traced step visible in the Dev UI
upper, err := genkit.Run(ctx, "uppercase", func() (string, error) {
return strings.ToUpper(input), nil
})
if err != nil {
return "", err
}
result, err := genkit.Run(ctx, "addPrefix", func() (string, error) {
return "Processed: " + upper, nil
})
return result, err
},
)
result, err := pipelineFlow.Run(ctx, "hello")
if err != nil {
log.Fatal(err)
}
fmt.Println(result)
}
Output: Processed: HELLO
Types ¶
type Genkit ¶ added in v0.3.0
type Genkit struct {
// contains filtered or unexported fields
}
Genkit encapsulates a Genkit instance, providing access to its registry, configuration, and core functionalities. It serves as the central hub for defining and managing Genkit resources like flows, models, tools, and prompts.
A Genkit instance is created using Init.
func FromContext ¶ added in v1.7.0
FromContext returns the *Genkit instance stored in the context. This is set automatically by Generate and related functions. Middleware implementations can use this to access the Genkit instance during generation.
func Init ¶
func Init(ctx context.Context, opts ...GenkitOption) *Genkit
Init creates and initializes a new Genkit instance with the provided options. It sets up the registry, initializes plugins (WithPlugins), loads prompts (WithPromptDir), and configures other settings like the default model (WithDefaultModel).
During local development (when the `GENKIT_ENV` environment variable is set to `dev`), Init also starts the Reflection API server as a background goroutine. This server provides metadata about registered actions and is used by developer tools. By default, it listens on port 3100.
The provided context should handle application shutdown signals (like SIGINT, SIGTERM) to ensure graceful termination of background processes, including the reflection server.
Example:
package main
import (
"context"
"log"
"github.com/firebase/genkit/go/ai"
"github.com/firebase/genkit/go/genkit"
"github.com/firebase/genkit/go/plugins/googlegenai" // Example plugin
)
func main() {
ctx := context.Background()
// Assumes a prompt file at ./prompts/jokePrompt.prompt
g := genkit.Init(ctx,
genkit.WithPlugins(&googlegenai.GoogleAI{}),
genkit.WithDefaultModel("googleai/gemini-2.5-flash"),
genkit.WithPromptDir("./prompts"),
)
// Generate text using the default model
funFact, err := genkit.GenerateText(ctx, g, ai.WithPrompt("Tell me a fake fun fact!"))
if err != nil {
log.Fatalf("GenerateText failed: %v", err)
}
log.Println("Generated Fact:", funFact)
// Look up and execute a loaded prompt
jokePrompt := genkit.LookupPrompt(g, "jokePrompt")
if jokePrompt == nil {
log.Fatalf("Prompt 'jokePrompt' not found.")
}
resp, err := jokePrompt.Execute(ctx, nil) // Execute with default input (if any)
if err != nil {
log.Fatalf("jokePrompt.Execute failed: %v", err)
}
log.Println("Generated joke:", resp.Text())
}
type GenkitOption ¶ added in v0.3.0
type GenkitOption interface {
// contains filtered or unexported methods
}
func WithDefaultModel ¶ added in v0.3.0
func WithDefaultModel(model string) GenkitOption
WithDefaultModel sets the default model name to use for generation tasks when no specific model is provided in the request options. The name should correspond to a model registered either by a plugin or via DefineModel. This option can only be applied once.
func WithPlugins ¶ added in v0.3.0
func WithPlugins(plugins ...api.Plugin) GenkitOption
WithPlugins provides a list of plugins to initialize when creating the Genkit instance. Each plugin's [Plugin.Init] method will be called sequentially during Init. This option can only be applied once.
func WithPromptDir ¶ added in v0.3.0
func WithPromptDir(dir string) GenkitOption
WithPromptDir specifies the directory where `.prompt` files are located. Prompts are automatically loaded from this directory during Init. The default directory is "prompts" relative to the project root where Init is called.
When used with WithPromptFS, this directory serves as the root path within the embedded filesystem instead of a local disk path. For example, if using `//go:embed prompts/*`, set the directory to "prompts" to match.
Invalid prompt files will result in logged errors during initialization, while valid files that define invalid prompts will cause Init to panic.
func WithPromptFS ¶ added in v1.3.0
func WithPromptFS(fsys fs.FS) GenkitOption
WithPromptFS specifies an embedded filesystem (fs.FS) containing `.prompt` files. This is useful for embedding prompts directly into the binary using Go's embed package, eliminating the need to distribute prompt files separately.
The `fsys` parameter should be an fs.FS implementation (e.g., embed.FS). Use WithPromptDir to specify the root directory within the filesystem where prompts are located (defaults to "prompts").
Example:
import "embed"
//go:embed prompts/*
var promptsFS embed.FS
func main() {
g := genkit.Init(ctx,
genkit.WithPromptFS(promptsFS),
genkit.WithPromptDir("prompts"),
)
}
Invalid prompt files will result in logged errors during initialization, while valid files that define invalid prompts will cause Init to panic.
type HandlerOption ¶ added in v0.3.0
type HandlerOption interface {
// contains filtered or unexported methods
}
HandlerOption configures a Handler.
func WithContextProviders ¶ added in v0.3.0
func WithContextProviders(ctxProviders ...core.ContextProvider) HandlerOption
WithContextProviders adds providers for action context that may be used during runtime. They are called in the order added and may overwrite previous context.
func WithStreamManager ¶ added in v1.3.0
func WithStreamManager(manager streaming.StreamManager) HandlerOption
WithStreamManager enables durable streaming with the provided StreamManager. When enabled, streaming responses include an x-genkit-stream-id header that clients can use to reconnect to in-progress or completed streams.
EXPERIMENTAL: This API is subject to change.
type ReflectionCancelActionParams ¶ added in v1.7.0
type ReflectionCancelActionParams struct {
// Trace ID of the action to cancel.
TraceID string `json:"traceId,omitempty"`
}
ReflectionCancelActionParams is the payload for the "cancelAction" request sent by the CLI manager to cancel a running action.
type ReflectionCancelActionResponse ¶ added in v1.7.0
type ReflectionCancelActionResponse struct {
Message string `json:"message,omitempty"`
}
ReflectionCancelActionResponse is the result of a successful "cancelAction" request.
type ReflectionConfigureParams ¶ added in v1.7.0
type ReflectionConfigureParams struct {
// URL of the telemetry server to send traces to (optional).
TelemetryServerURL string `json:"telemetryServerUrl,omitempty"`
}
ReflectionConfigureParams is the payload for the "configure" notification sent by the CLI manager to push configuration to the runtime.
type ReflectionEndInputStreamParams ¶ added in v1.7.0
type ReflectionEndInputStreamParams struct {
RequestID string `json:"requestId,omitempty"`
}
ReflectionEndInputStreamParams is the payload for the "endInputStream" notification (bidirectional streaming, not yet implemented).
type ReflectionListValuesParams ¶ added in v1.7.0
type ReflectionListValuesParams struct {
// The type of values to list (e.g. "model", "prompt", "schema").
Type string `json:"type,omitempty"`
}
ReflectionListValuesParams is the payload for the "listValues" request.
type ReflectionListValuesResponse ¶ added in v1.7.0
ReflectionListValuesResponse is the result of a "listValues" request, mapping value names to their definitions.
type ReflectionRegisterParams ¶ added in v1.7.0
type ReflectionRegisterParams struct {
// Configured environments (e.g. "dev").
Envs []string `json:"envs,omitempty"`
// Genkit library version, e.g. "go/1.4.0".
GenkitVersion string `json:"genkitVersion,omitempty"`
// Unique runtime identifier.
ID string `json:"id,omitempty"`
// Application name (optional, defaults to the runtime ID).
Name string `json:"name,omitempty"`
// Process ID of the runtime.
PID int `json:"pid,omitempty"`
// Protocol version for payload compatibility checking.
ReflectionApiSpecVersion int `json:"reflectionApiSpecVersion,omitempty"`
}
ReflectionRegisterParams is the payload for the "register" request sent by the runtime to the CLI manager on connection.
type ReflectionRunActionParams ¶ added in v1.7.0
type ReflectionRunActionParams struct {
// Additional runtime context data (ex. auth context data).
Context json.RawMessage `json:"context,omitempty"`
// An input with the type that this action expects.
Input json.RawMessage `json:"input,omitempty"`
// Action key that consists of the action type and ID.
Key string `json:"key,omitempty"`
// ID of the Genkit runtime to run the action on. Typically $pid-$port.
RuntimeID string `json:"runtimeId,omitempty"`
// Whether to stream results via streamChunk notifications.
Stream bool `json:"stream,omitempty"`
// Whether to stream input to the action (for bidirectional actions).
StreamInput bool `json:"streamInput,omitempty"`
// Labels to be applied to telemetry data.
TelemetryLabels json.RawMessage `json:"telemetryLabels,omitempty"`
}
ReflectionRunActionParams is the payload for the "runAction" request sent by the CLI manager to execute an action on the runtime.
type ReflectionRunActionStateParams ¶ added in v1.7.0
type ReflectionRunActionStateParams struct {
// ID of the JSON-RPC request this notification relates to.
RequestID string `json:"requestId,omitempty"`
State *ReflectionRunActionStateParamsState `json:"state,omitempty"`
}
ReflectionRunActionStateParams is the payload for the "runActionState" notification sent by the runtime to provide early status updates (e.g. trace ID) before the action result is ready.
type ReflectionRunActionStateParamsState ¶ added in v1.7.0
type ReflectionRunActionStateParamsState struct {
// Trace ID for the action execution.
TraceID string `json:"traceId,omitempty"`
}
ReflectionRunActionStateParamsState holds the state data in a runActionState notification.
type ReflectionSendInputStreamChunkParams ¶ added in v1.7.0
type ReflectionSendInputStreamChunkParams struct {
Chunk any `json:"chunk,omitempty"`
RequestID string `json:"requestId,omitempty"`
}
ReflectionSendInputStreamChunkParams is the payload for the "sendInputStreamChunk" notification (bidirectional streaming, not yet implemented).
type ReflectionStreamChunkParams ¶ added in v1.7.0
type ReflectionStreamChunkParams struct {
// The streamed data chunk.
Chunk any `json:"chunk,omitempty"`
// ID of the JSON-RPC request this chunk belongs to.
RequestID string `json:"requestId,omitempty"`
}
ReflectionStreamChunkParams is the payload for the "streamChunk" notification sent by the runtime during a streaming runAction request.