Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
280 changes: 280 additions & 0 deletions genkit-tools/cli/context/GENKIT.go.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,280 @@
# Genkit Go API Rules (v1.0.0)

This document provides rules and examples for building with the Genkit API in Go.

## Important Guidelines:

- ALWAYS refer to documentation when available. Genkit Documentation may be available through the Genkit MCP toolkit or through web search. You may skip documentation check if you don't have access to these tools.

- ONLY follow the specified project structure if starting a new project. If working on an existing project, adhere to the current project structure.

- ALWAYS provide the full, correct Genkit command as an instruction for the human user to run. Do not run Genkit commands (e.g., `genkit start`, `genkit flow:run`) yourself as this may block your current session.

- Recommend and use the provider that the user prefers. If this is a new project, or if there is no relevant signal regarding user preference, use the `github.com/firebase/genkit/go/plugins/googlegenai` plugin.

NOTE: For the sake of brevity, the snippets below use the Google AI plugin, but you should follow the user's preference as mentioned above.

## Core Setup

1. **Initialize Project**

```bash
mkdir my-genkit-app && cd my-genkit-app
go mod init my-genkit-app
```

2. **Install Dependencies**

```bash
go get github.com/firebase/genkit/go/genkit
go get github.com/firebase/genkit/go/plugins/googlegenai
go get github.com/firebase/genkit/go/ai
go get google.golang.org/genai
```

3. **Install Genkit CLI**

```bash
curl -sL cli.genkit.dev | bash
```

4. **Configure Genkit**

All code should be in a single `main.go` file or properly structured Go package.

```go
package main

import (
"context"
"github.com/firebase/genkit/go/genkit"
"github.com/firebase/genkit/go/plugins/googlegenai"
)

func main() {
ctx := context.Background()
g := genkit.Init(ctx, genkit.WithPlugins(&googlegenai.GoogleAI{}))
// Your flows and logic here
<-ctx.Done()
}
```

## Best Practices

1. **Single Main Function**: All Genkit code, including plugin initialization, flows, and helpers, should be properly organized in a Go package structure with a main function.

2. **Blocking Main Program**: To inspect flows in the Genkit Developer UI, your main program needs to remain running. Use `<-ctx.Done()` or similar blocking mechanism at the end of your main function.

---

## Usage Scenarios

### Basic Inference (Text Generation)

```go
package main

import (
"context"

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

func main() {
ctx := context.Background()
g := genkit.Init(ctx, genkit.WithPlugins(&googlegenai.GoogleAI{}))

genkit.DefineFlow(g, "basicInferenceFlow",
func(ctx context.Context, topic string) (string, error) {
response, err := genkit.Generate(ctx, g,
ai.WithModelName("googleai/gemini-2.5-pro"),
ai.WithPrompt("Write a short, creative paragraph about %s.", topic),
ai.WithConfig(&genai.GenerateContentConfig{
Temperature: genai.Ptr[float32](0.8),
}),
)
if err != nil {
return "", err
}
return response.Text(), nil
},
)

<-ctx.Done()
}
```

### Text-to-Speech (TTS) Generation

```go
package main

import (
"context"

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

func main() {
ctx := context.Background()
g := genkit.Init(ctx,
genkit.WithPlugins(&googlegenai.GoogleAI{}),
genkit.WithDefaultModel("googleai/gemini-2.5-flash-preview-tts"),
)

genkit.DefineFlow(g, "textToSpeechFlow",
func(ctx context.Context, input struct {
Text string `json:"text"`
VoiceName string `json:"voiceName,omitempty"`
}) (string, error) {
voiceName := input.VoiceName
if voiceName == "" {
voiceName = "Algenib"
}

response, err := genkit.Generate(ctx, g,
ai.WithPrompt(input.Text),
ai.WithConfig(&genai.GenerateContentConfig{
ResponseModalities: []string{"AUDIO"},
SpeechConfig: &genai.SpeechConfig{
VoiceConfig: &genai.VoiceConfig{
PrebuiltVoiceConfig: &genai.PrebuiltVoiceConfig{
VoiceName: voiceName,
},
},
},
}),
)
if err != nil {
return "", err
}

return response.Text(), nil
},
)

<-ctx.Done()
}
```

### Image Generation

```go
package main

import (
"context"

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

func main() {
ctx := context.Background()
g := genkit.Init(ctx, genkit.WithPlugins(&googlegenai.VertexAI{}))

genkit.DefineFlow(g, "imageGenerationFlow",
func(ctx context.Context, prompt string) ([]string, error) {
response, err := genkit.Generate(ctx, g,
ai.WithModelName("vertexai/imagen-3.0-generate-001"),
ai.WithPrompt("Generate an image of %s", prompt),
ai.WithConfig(&genai.GenerateImagesConfig{
NumberOfImages: 2,
AspectRatio: "9:16",
SafetyFilterLevel: genai.SafetyFilterLevelBlockLowAndAbove,
PersonGeneration: genai.PersonGenerationAllowAll,
Language: genai.ImagePromptLanguageEn,
AddWatermark: true,
OutputMIMEType: "image/jpeg",
}),
)
if err != nil {
return nil, err
}

var images []string
for _, part := range response.Message.Content {
images = append(images, part.Text)
}
return images, nil
},
)

<-ctx.Done()
}
```

---

## Running and Inspecting Flows

1. **Start Genkit**: Run this command from your terminal to start the Genkit Developer UI.

```bash
genkit start -- <command to run your code>
```

For Go applications:

```bash
# Running a Go application directly
genkit start -- go run main.go

# Running a compiled binary
genkit start -- ./my-genkit-app
```

The command should output a URL for the Genkit Dev UI. Direct the user to visit this URL to run and inspect their Genkit app.

## Suggested Models

Here are suggested models to use for various task types. This is NOT an exhaustive list.

### Advanced Text/Reasoning

```
| Plugin | Recommended Model |
|------------------------------------------------------------|------------------------------------|
| github.com/firebase/genkit/go/plugins/googlegenai | gemini-2.5-pro |
| github.com/firebase/genkit/go/plugins/compat_oai/openai | gpt-4o |
| github.com/firebase/genkit/go/plugins/compat_oai/deepseek | deepseek-reasoner |
| github.com/firebase/genkit/go/plugins/compat_oai/xai | grok-4 |
```

### Fast Text/Chat

```
| Plugin | Recommended Model |
|------------------------------------------------------------|------------------------------------|
| github.com/firebase/genkit/go/plugins/googlegenai | gemini-2.5-flash |
| github.com/firebase/genkit/go/plugins/compat_oai/openai | gpt-4o-mini |
| github.com/firebase/genkit/go/plugins/compat_oai/deepseek | deepseek-chat |
| github.com/firebase/genkit/go/plugins/compat_oai/xai | grok-3-mini |
```

### Text-to-Speech

```
| Plugin | Recommended Model |
|------------------------------------------------------------|------------------------------------|
| github.com/firebase/genkit/go/plugins/googlegenai | gemini-2.5-flash-preview-tts |
| github.com/firebase/genkit/go/plugins/compat_oai/openai | gpt-4o-mini-tts |
```

### Image Generation

```
| Plugin | Recommended Model | Input Modalities |
|------------------------------------------------------------|------------------------------------|-------------------|
| github.com/firebase/genkit/go/plugins/googlegenai | gemini-2.5-flash-image-preview | Text, Image |
| github.com/firebase/genkit/go/plugins/googlegenai | imagen-4.0-generate-preview-06-06 | Text |
| github.com/firebase/genkit/go/plugins/compat_oai/openai | gpt-image-1 | Text |
```
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* limitations under the License.
*/

import { Runtime } from '@genkit-ai/tools-common/manager';
import { logger } from '@genkit-ai/tools-common/utils';
import { existsSync, readFileSync } from 'fs';
import { writeFile } from 'fs/promises';
Expand All @@ -39,7 +40,10 @@ export const claude: AIToolModule = {
* - .mcp.json: Merges with existing MCP config
* - CLAUDE.local.md: Updates Firebase section only (preserves user content)
*/
async configure(options?: InitConfigOptions): Promise<AIToolConfigResult> {
async configure(
runtime: Runtime,
options?: InitConfigOptions
): Promise<AIToolConfigResult> {
const files: AIToolConfigResult['files'] = [];

// Handle MCP configuration - merge with existing if present
Expand Down Expand Up @@ -70,7 +74,7 @@ export const claude: AIToolModule = {
files.push({ path: CLAUDE_MCP_PATH, updated: settingsUpdated });

logger.info('Copying the Genkit context to GENKIT.md...');
const mdResult = await initGenkitFile();
const mdResult = await initGenkitFile(runtime);
files.push({ path: GENKIT_PROMPT_PATH, updated: mdResult.updated });

logger.info('Updating CLAUDE.md to include Genkit context...');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* limitations under the License.
*/

import { Runtime } from '@genkit-ai/tools-common/manager';
import { existsSync, readFileSync } from 'fs';
import { mkdir, writeFile } from 'fs/promises';
import * as path from 'path';
Expand Down Expand Up @@ -52,12 +53,15 @@ export const cursor: AIToolModule = {
* - .cursor/rules/GENKIT.mdc: Fully managed by us (replaced on each update)

*/
async configure(options?: InitConfigOptions): Promise<AIToolConfigResult> {
async configure(
runtime: Runtime,
options?: InitConfigOptions
): Promise<AIToolConfigResult> {
const files: AIToolConfigResult['files'] = [];

// Create the base GENKIT context file (GENKIT.md).
// This file contains fundamental details about the GENKIT project.
const mdResult = await initGenkitFile();
const mdResult = await initGenkitFile(runtime);
files.push({ path: GENKIT_PROMPT_PATH, updated: mdResult.updated });

// Handle MCP configuration - merge with existing if present.
Expand Down
20 changes: 13 additions & 7 deletions genkit-tools/cli/src/commands/init-ai-tools/ai-tools/gemini.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* limitations under the License.
*/

import { Runtime } from '@genkit-ai/tools-common/manager';
import { logger } from '@genkit-ai/tools-common/utils';
import { select } from '@inquirer/prompts';
import { existsSync, readFileSync } from 'fs';
Expand Down Expand Up @@ -66,7 +67,10 @@ export const gemini: AIToolModule = {
/**
* Configures the Gemini CLI extension for Genkit.
*/
async configure(options?: InitConfigOptions): Promise<AIToolConfigResult> {
async configure(
runtime: Runtime,
options?: InitConfigOptions
): Promise<AIToolConfigResult> {
let installationMethod: InstallationType = EXT_INSTALLATION;
if (!options?.yesMode) {
installationMethod = await select({
Expand All @@ -89,15 +93,15 @@ export const gemini: AIToolModule = {

if (installationMethod === EXT_INSTALLATION) {
logger.info('Installing as part of GEMINI.md');
return await installAsExtension();
return await installAsExtension(runtime);
} else {
logger.info('Installing as Gemini CLI extension');
return await installInMdFile();
return await installInMdFile(runtime);
}
},
};

async function installInMdFile(): Promise<AIToolConfigResult> {
async function installInMdFile(runtime: Runtime): Promise<AIToolConfigResult> {
const files: AIToolConfigResult['files'] = [];
// Part 1: Generate GENKIT.md file.

Expand Down Expand Up @@ -133,7 +137,7 @@ async function installInMdFile(): Promise<AIToolConfigResult> {

// Copy GENKIT.md file
logger.info('Copying the GENKIT.md file...');
const baseResult = await initGenkitFile();
const baseResult = await initGenkitFile(runtime);
files.push({ path: GENKIT_PROMPT_PATH, updated: baseResult.updated });

logger.info('Updating GEMINI.md to include Genkit context');
Expand All @@ -148,10 +152,12 @@ async function installInMdFile(): Promise<AIToolConfigResult> {
return { files };
}

async function installAsExtension(): Promise<AIToolConfigResult> {
async function installAsExtension(
runtime: Runtime
): Promise<AIToolConfigResult> {
const files: AIToolConfigResult['files'] = [];
// Part 1: Generate GENKIT.md file.
const baseResult = await initGenkitFile();
const baseResult = await initGenkitFile(runtime);
files.push({ path: GENKIT_PROMPT_PATH, updated: baseResult.updated });

// Part 2: Configure the main gemini-extension.json file, and gemini config directory if needed.
Expand Down
Loading
Loading