agent

package
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 16, 2026 License: Apache-2.0 Imports: 22 Imported by: 0

Documentation

Overview

Package agent wraps the Google ADK runner with sensible defaults (streaming mode, in-memory session service, app name) so consumers hit the same shape regardless of whether they're driving the agent from a one-shot CLI, a REPL, or an HTTP handler.

Multi-turn conversation history is preserved automatically when Run() is called repeatedly with the same userID + sessionID — by default ADK's session.InMemoryService accumulates events. Pass WithSessionService to plug in a durable backend (e.g. an eventlog-backed Service for SQLite/Postgres persistence + audit log + crash-resume).

Index

Constants

View Source
const DefaultAppName = "core-agent"

DefaultAppName tags this process in the ADK runner. Telemetry and session stores key off this; override with WithAppName when embedding in a host that wants its own identity.

Variables

This section is empty.

Functions

func CurrentSubagentDepth

func CurrentSubagentDepth(ctx context.Context) int

CurrentSubagentDepth returns the recursion depth of the current subagent invocation. Zero when we're not inside a subagent (i.e. the parent's top-level turn).

func NewSubagentTool

func NewSubagentTool(opts SubagentOptions) (tool.Tool, error)

NewSubagentTool wraps an *agent.Agent as a tool the parent's model can call. The subagent runs through ADK's runner using the parent's session.Service (so its events stream live into the same audit log as the parent), with session.Event.Branch set to "<parent_branch>.<this>" so the audit log stays distinguishable and ADK's contents-processor branch filter keeps the subagent's events from leaking into the parent's next-turn LLM request.

The parent's session.Service is captured from Inner — Inner is expected to have been constructed with the same WithEventLog (or WithSessionService) the parent uses. The agent.WithSubagents convenience option handles this wiring automatically; consumers who construct subagent tools directly via NewSubagentTool need to share the session.Service themselves.

Types

type Agent

type Agent struct {
	// contains filtered or unexported fields
}

Agent is the wrapper around an ADK llmagent + runner. One Agent represents one configured LLM-driven role.

func New

func New(model adkmodel.LLM, opts ...Option) (*Agent, error)

New constructs an Agent backed by model. Returns a clear error if the underlying ADK constructors reject the configuration.

func (*Agent) AgentName

func (a *Agent) AgentName() string

AgentName returns the configured agent name (the WithName value) stored on construction. Used by NewSubagentTool to derive a default tool name.

func (*Agent) AppName

func (a *Agent) AppName() string

AppName returns the AppName the agent was constructed with (the value passed to runner.Config). Used by callers that need to identify the session triple (app, user, session) for queries against the event log or session.Service.

func (*Agent) EventLog

func (a *Agent) EventLog() *eventlog.Handle

EventLog returns the *eventlog.Handle the agent was constructed with via WithEventLog, or nil when no event log was wired. Use to reach back to Stream.Since / Stream.Watch for replay or live tail without keeping a separate reference.

func (*Agent) Run

func (a *Agent) Run(ctx context.Context, prompt string) iter.Seq2[*session.Event, error]

Run executes one turn of the agent against prompt and returns the event iterator straight from ADK's runner. Callers are expected to range over the returned iter.Seq2 and consume events as they arrive — partial text chunks, tool calls, and the final TurnComplete event.

Multi-turn use: call Run() repeatedly on the same Agent. The configured session ID is reused across calls, so the ADK accumulates conversation history automatically.

func (*Agent) SessionID

func (a *Agent) SessionID() string

SessionID returns the session identifier the agent was constructed with. Combined with AppName + UserID this is the key the event log uses to scope ForSession queries.

func (*Agent) SessionService

func (a *Agent) SessionService() session.Service

SessionService returns the session.Service backing this agent. When no WithSessionService option was passed at construction this is the default in-memory service. Useful for callers that want to query session state directly (e.g. listing prior events) without keeping their own reference to the Service they passed in.

func (*Agent) Tools

func (a *Agent) Tools() []tool.Tool

Tools returns the resolved tool list the agent was constructed with — including any subagent tools materialized by WithSubagents. Useful for diagnostics ("does my parent know about the research subagent?") without introspecting ADK internals.

func (*Agent) UserID

func (a *Agent) UserID() string

UserID returns the user identifier the agent was constructed with.

type AutonomousOption

type AutonomousOption func(*autoConfig)

AutonomousOption mutates RunAutonomous configuration. Use the With* helpers below.

func WithContinuationPrompt

func WithContinuationPrompt(s string) AutonomousOption

WithContinuationPrompt overrides the prompt sent on every turn after the first. Default: "continue". Real consumers often pass something more specific to their loop ("what's your next step?").

func WithDoneToolDescription

func WithDoneToolDescription(desc string) AutonomousOption

WithDoneToolDescription overrides the description shown to the model for the internal done tool. Override when the default prose doesn't fit your task — for example to instruct the model to call done only after writing a summary.

func WithDoneToolName

func WithDoneToolName(name string) AutonomousOption

WithDoneToolName overrides the function name of the internal done tool. Useful when "report_done" collides with an existing tool the consumer has registered. Default: "report_done".

func WithMaxCost

func WithMaxCost(usd float64) AutonomousOption

WithMaxCost caps the cumulative dollar cost of the run. Requires a non-zero pricing source — either WithTracker(tracker, pricing) or the recorded UsageMetadata being priced via the same Pricing.

func WithMaxTokens

func WithMaxTokens(input, output int) AutonomousOption

WithMaxTokens caps the cumulative input + output token totals for the run. A zero value for either disables that side of the cap.

func WithMaxTurns

func WithMaxTurns(n int) AutonomousOption

WithMaxTurns caps the number of turns the loop will execute. Zero disables the cap (use with caution; pair with another budget). The default is 50.

func WithMaxWallclock

func WithMaxWallclock(d time.Duration) AutonomousOption

WithMaxWallclock caps the wall-clock duration of the run, measured from RunAutonomous entry. Checked between turns; a single rogue turn can still exceed this — pair with WithPerTurnTimeout to bound that.

func WithPerTurnTimeout

func WithPerTurnTimeout(d time.Duration) AutonomousOption

WithPerTurnTimeout wraps each turn's context with a timeout so a single hung turn cannot stall the whole run. Distinct from WithMaxWallclock, which bounds total time.

func WithPermissionsGate

func WithPermissionsGate(g *permissions.Gate) AutonomousOption

WithPermissionsGate hands the driver a reference to the permissions gate the consumer wired into their tools. The driver only uses this for one purpose: a startup check that rejects ask-mode + no-prompter configurations that would deadlock on the first tool call. The gate is otherwise enforced by the tools themselves; passing it here does not change runtime gating behavior.

Pass this when your build function constructs gated tools and your permission mode might be ask. Omit it for ModeYolo / ModeAllow runs where deadlock isn't a risk.

func WithPricing

func WithPricing(p usage.Pricing) AutonomousOption

WithPricing sets the Pricing used for cost rollup when a usage.Tracker is not supplied. Useful for headless runs that just want a final dollar number on RunResult.

func WithProgress

func WithProgress(cb func(turn int, ev *session.Event)) AutonomousOption

WithProgress invokes cb for every session.Event observed during the run. The turn index is the 1-based count of completed turns at the time the event is emitted (always at least 1 inside a turn).

func WithRetryPolicy

func WithRetryPolicy(p RetryPolicy) AutonomousOption

WithRetryPolicy installs a callback consulted whenever a turn returns an error. The callback receives the error and the 1-indexed attempt count and returns one of AbortRun, RetryTurn, or SkipTurn. Without a policy, the driver aborts on the first error.

func WithTracker

func WithTracker(t *usage.Tracker, p usage.Pricing) AutonomousOption

WithTracker hands the driver an existing usage.Tracker plus the Pricing to use for per-turn cost accounting. Each turn appends to the tracker; RunResult also rolls up totals independently so callers can read them without touching the tracker.

When omitted, RunResult still tracks tokens — but cost is zero unless a non-zero Pricing is supplied via WithPricing.

type Option

type Option func(*options)

Option mutates Agent construction. Use the With* helpers below.

func WithAppName

func WithAppName(s string) Option

WithAppName overrides the AppName handed to the ADK runner. Useful when embedding so telemetry and session stores can distinguish multiple agents inside one binary.

func WithDescription

func WithDescription(s string) Option

WithDescription overrides the agent's description.

func WithEventLog

func WithEventLog(h *eventlog.Handle) Option

WithEventLog wires an eventlog.Handle into the agent — the Handle's Service becomes the agent's session.Service (so every event lands in the durable log), and the Handle is stored on the agent so callers can reach back to it for replay/watch via Agent.EventLog().

Equivalent to WithSessionService(h.Service) plus a stash of the Handle for later access; passing nil is a no-op.

func WithInstruction

func WithInstruction(s string) Option

WithInstruction overrides the system instruction.

func WithName

func WithName(s string) Option

WithName overrides the agent's display name (visible in OTEL spans).

func WithSession

func WithSession(userID, sessionID string) Option

WithSession overrides the user/session IDs handed to the ADK runner. Reuse the same pair across Run() calls to preserve conversation history.

func WithSessionService

func WithSessionService(s session.Service) Option

WithSessionService overrides the session.Service handed to the ADK runner. The default is session.InMemoryService(), which loses all state when the process exits. Pass a durable Service (typically the one returned by eventlog.Open(...).Service when wiring the audit log + crash-resume substrate) to persist sessions across runs.

The supplied Service is also exposed via Agent.SessionService() so callers can query session state directly without keeping their own reference. Passing nil restores the default.

func WithStreaming

func WithStreaming(m adkagent.StreamingMode) Option

WithStreaming overrides the streaming mode. Default is StreamingModeSSE (required to receive Partial events).

func WithSubagents

func WithSubagents(agents []*Agent) Option

WithSubagents registers each agent as a callable tool the parent's model can invoke by name. The subagent runs through ADK's runner using the parent's session.Service (so its events stream live into the same audit log) with session.Event.Branch set to "<parent_branch>.<subagent_name>" — ADK's contents-processor branch filter then keeps the subagent's events from leaking back into the parent's next-turn LLM request, which preserves context isolation while keeping the audit log unified.

Each subagent's tool name comes from its own WithName value. Use NewSubagentTool directly for per-subagent overrides (custom name, description, depth cap, branch label).

Resolved at the end of New() so that the parent's session.Service and session triple — set by other With* options — are captured at the point the subagent tools are constructed.

func WithSystemInstructionPrefix

func WithSystemInstructionPrefix(prefix string) Option

WithSystemInstructionPrefix prepends prefix to the agent's default instruction. Used for memory loading: AGENTS.md / CLAUDE.md / GEMINI.md project memory becomes part of the system prompt rather than the user's first message.

func WithTools

func WithTools(ts []tool.Tool) Option

WithTools registers a set of tools the agent may call. Order is preserved but immaterial; ADK keys tools by Name.

func WithToolsets

func WithToolsets(ts []tool.Toolset) Option

WithToolsets registers groups of tools (MCP servers, skills, etc.). Each Toolset implements google.golang.org/adk/tool.Toolset and is passed to llmagent.Config.Toolsets.

type ResumeBuildFunc

type ResumeBuildFunc func(extras []tool.Tool, sessionID string) (*Agent, error)

ResumeBuildFunc is the agent constructor accepted by ResumeAutonomous. It mirrors RunAutonomous's BuildFunc signature but adds the sessionID the new agent must adopt — implementations pass it to agent.WithSession so the constructed agent reuses the session being resumed.

type RetryDecision

type RetryDecision int

RetryDecision tells the driver what to do after a turn fails.

const (
	// AbortRun stops the run immediately and propagates the error.
	AbortRun RetryDecision = iota
	// RetryTurn re-runs the same prompt for another attempt.
	RetryTurn
	// SkipTurn moves on to the continuation prompt as if the failed
	// turn had completed normally without a done signal.
	SkipTurn
)

type RetryPolicy

type RetryPolicy func(turnErr error, attempt int) RetryDecision

RetryPolicy decides what RunAutonomous does when a turn errors. The callback receives the error and the 1-indexed attempt count (the first failure is attempt=1, second is attempt=2, etc.).

type RunResult

type RunResult struct {
	// Reason explains why the loop stopped.
	Reason StopReason
	// FinalText is the accumulated streaming text from the last turn
	// that produced any output.
	FinalText string
	// Turns is the number of turns the driver actually executed
	// (including failed ones that were retried or skipped).
	Turns int
	// InputTokens / OutputTokens are summed from each turn's
	// UsageMetadata. Zero when no usage info was returned.
	InputTokens  int
	OutputTokens int
	// CostUSD is the cumulative dollar cost computed via the
	// configured Pricing. Zero when pricing is zero.
	CostUSD float64
	// Duration is the wall-clock time from RunAutonomous entry to
	// loop exit.
	Duration time.Duration
	// DoneDetail is the detail string the model passed to the done
	// tool when Reason==StopReasonCompleted.
	DoneDetail string
}

RunResult is the structured outcome of RunAutonomous.

func ResumeAutonomous

func ResumeAutonomous(ctx context.Context, build ResumeBuildFunc, ref SessionRef, opts ...AutonomousOption) (RunResult, error)

ResumeAutonomous reads the most recent checkpoint event from the session's event log, reconstructs RunResult totals, and continues the run from the next turn. The build function receives the resumed sessionID so the constructed agent rejoins the same session via agent.WithSession.

Behavior:

  • Acquires an exclusive SessionLock on (App, User, Session). A concurrent ResumeAutonomous on the same session returns ErrSessionLocked from eventlog.
  • If the session has no checkpoint events at all, the run starts from turn 0 with whatever event history the session already holds — "make this existing session autonomous from here" is a valid use case.
  • If the latest checkpoint has stop_reason set (terminal state), ResumeAutonomous returns that state immediately without constructing the agent or running any turns.
  • Otherwise, the loop continues with prompt = checkpoint.ContinuationPrompt; budgets carry forward.

func RunAutonomous

func RunAutonomous(ctx context.Context, build func(extraTools []tool.Tool) (*Agent, error), goal string, opts ...AutonomousOption) (RunResult, error)

RunAutonomous drives a multi-turn loop against an Agent built by build, sending goal as the first prompt and a continuation prompt thereafter, until one of the stop conditions fires. Returns a RunResult describing why it stopped and the totals it accumulated, plus any error.

The driver constructs the agent via build, passing in an extra "done" tool the model calls to signal completion. The tool name is "report_done" by default and can be overridden with WithDoneToolName. Consumers compose the done tool with their own tool registry inside build (see examples/autonomous for the pattern).

The constructor pattern keeps the driver from mutating a caller-supplied Agent (which would race with concurrent runs) and keeps agent.New's surface free of "extra tools" plumbing that only matters here.

type SessionRef

type SessionRef struct {
	Handle    *eventlog.Handle
	AppName   string
	UserID    string
	SessionID string
}

SessionRef identifies the session ResumeAutonomous resumes from. Handle supplies both the eventlog.Stream (used to find the latest checkpoint) and the session.Service (used by the constructed agent for live event reads + writes).

type StopReason

type StopReason string

StopReason explains why RunAutonomous returned.

const (
	// StopReasonCompleted means the model called the done tool.
	StopReasonCompleted StopReason = "completed"
	// StopReasonMaxTurns means WithMaxTurns was hit.
	StopReasonMaxTurns StopReason = "max_turns_exceeded"
	// StopReasonMaxTokens means WithMaxTokens (input or output) was hit.
	StopReasonMaxTokens StopReason = "max_tokens_exceeded" //nolint:gosec // not a credential
	// StopReasonMaxCost means WithMaxCost was hit.
	StopReasonMaxCost StopReason = "max_cost_exceeded"
	// StopReasonWallclockExceeded means WithMaxWallclock was hit.
	StopReasonWallclockExceeded StopReason = "wallclock_exceeded"
	// StopReasonContextCancelled means the supplied context was
	// cancelled or its deadline expired.
	StopReasonContextCancelled StopReason = "context_cancelled"
	// StopReasonRetryAborted means the configured RetryPolicy
	// returned AbortRun for a turn error.
	StopReasonRetryAborted StopReason = "retry_policy_aborted"
)

type SubagentOptions

type SubagentOptions struct {
	// Inner is the *agent.Agent to expose as a tool the parent's
	// model can call. The tool's function name comes from
	// Inner.AgentName() (set via agent.WithName), unless overridden
	// via Name. The tool's description comes from Inner's
	// llmagent.Description, unless overridden via Description.
	Inner *Agent

	// Name overrides the function name shown to the parent's model.
	// Empty falls back to Inner.AgentName().
	Name string

	// Description overrides the function description shown to the
	// parent's model. Empty falls back to Inner's Description (or a
	// generic fallback when that's also empty).
	Description string

	// MaxDepth caps recursion depth. A subagent at depth >= MaxDepth
	// that is invoked from another subagent gets an error result
	// rather than being allowed to recurse. Default 2; pass a
	// larger value if your agent topology genuinely needs deeper
	// nesting.
	MaxDepth int

	// Branch overrides the branch label appended to the parent's
	// branch on the subagent's events. Defaults to the tool name
	// (which is Inner.AgentName() unless Name overrides it). The
	// resulting branch is "<parent_branch>.<this>".
	Branch string

	// ParentService, when non-nil, overrides the session.Service
	// the subagent's runner uses. The agent.WithSubagents
	// convenience option fills this in automatically with the
	// parent agent's service so subagent events land in the
	// parent's audit log without any consumer plumbing.
	//
	// When nil, NewSubagentTool falls back to Inner.SessionService()
	// — which is fine for callers who construct subagents
	// pre-wired against the same Handle.
	ParentService session.Service

	// ParentAppName, ParentUserID, ParentSessionID identify the
	// parent's session triple. When set, the subagent runs through
	// the parent's session row (with branch isolation) so cross-
	// session audit queries find both. Empty values fall back to
	// Inner's own AppName/UserID/SessionID. Set automatically by
	// agent.WithSubagents.
	ParentAppName   string
	ParentUserID    string
	ParentSessionID string
}

SubagentOptions configures NewSubagentTool. Inner is required; everything else has sensible defaults.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL