Skip to content

Define agents

In Genkit, agents are actions with conversation state. A standard agent renders a prompt on each turn, appends conversation history, calls the model, streams chunks, updates state, and optionally persists a snapshot. A custom agent keeps that runtime shell, but replaces the prompt-backed loop with your own code.

This page covers defining the agent itself. For when to choose an agent over a plain flow, see Full-stack agents.

  • genkitx.DefineAgent keeps inline prompt configuration beside the agent wiring. Use it for most prompt-backed agents.
  • genkitx.DefinePromptAgent wraps a prompt that is already registered, including prompts loaded from Dotprompt files.
  • genkitx.DefineCustomAgent replaces the prompt loop with your own code, for a custom per-turn loop, direct session control, or multiple model calls.

All agents implement api.BidiAction, so transports and route helpers can serve them directly. Server-managed agents also expose typed snapshot helpers and companion actions.

DefineAgent registers a prompt-backed agent from an aix.InlinePrompt. The inline prompt is a list of prompt options.

import (
aix "github.com/firebase/genkit/go/ai/exp"
"github.com/firebase/genkit/go/ai/exp/localstore"
genkitx "github.com/firebase/genkit/go/genkit/exp"
)
store, err := localstore.NewFileSessionStore[TaskState]("./.genkit/snapshots/tasks")
if err != nil {
// Fails if the snapshot directory cannot be created or is not writable.
log.Fatalf("open task store: %v", err)
}
taskAgent := genkitx.DefineAgent(g, "taskAgent",
aix.InlinePrompt{
ai.WithModelName("googleai/gemini-flash-latest"),
ai.WithSystem("Manage a task list. Use tools when changing tasks."),
ai.WithTools(addTaskTool, toggleTaskTool),
},
aix.WithSessionStore(store),
aix.WithDescription[TaskState]("Task management assistant"),
)

The agent’s custom state type is inferred from typed options such as WithSessionStore[TaskState], WithStateTransform[TaskState], or the explicit type argument on DefineAgent[TaskState].

  • aix.WithSessionStore(store) persists snapshots and switches the agent to server-managed state.
  • aix.WithStateTransform(fn) redacts or reshapes session state returned to clients and snapshot readers.
  • aix.WithStreamTransform[State](fn) redacts or reshapes each streamed chunk before it is sent to clients.
  • aix.WithDescription[State](text) adds a human-readable description to action metadata and developer tooling.
  • aix.WithNamedPrompt[State](name, input) points DefinePromptAgent at a specific registered prompt and renders input.

Typed options are deliberately strict. Passing a state option with the wrong State type fails at compile time.

DefinePromptAgent wraps a prompt already registered in the prompt registry. With no prompt-source option, it uses a prompt with the same name as the agent.

chef := genkitx.DefinePromptAgent[ChefState](g, "chef",
aix.WithSessionStore(store),
aix.WithDescription[ChefState]("Chef assistant loaded from ./prompts/chef.prompt"),
)

Use WithNamedPrompt when several agents share one prompt or when the prompt name differs from the agent name.

friendlyChef := genkitx.DefinePromptAgent[ChefState](g, "friendlyChef",
aix.WithNamedPrompt[ChefState]("chef", map[string]any{
"personality": "friendly",
}),
aix.WithSessionStore(store),
)

The prompt input is rendered at definition time as a smoke test. If it does not satisfy the prompt schema, the constructor panics during setup rather than during the first request.

DefineCustomAgent gives you the agent runtime without the built-in prompt loop. Use it for a custom per-turn loop, multiple model calls in one turn, or direct session control. The function receives a Responder for streaming and a SessionRunner for turn processing, messages, custom state, artifacts, and snapshots.

coder := genkitx.DefineCustomAgent(g, "coder",
func(ctx context.Context, resp aix.Responder, sess *aix.SessionRunner[CoderState]) (*aix.AgentResult, error) {
// Your own per-turn loop. See Custom orchestration for the full pattern.
},
aix.WithSessionStore(store),
aix.WithDescription[CoderState]("Concise code helper"),
)

See Custom orchestration for the runtime contract, a complete example, turn context, responder behavior, and failure handling.