metaagent

package
v0.9.13 Latest Latest
Warning

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

Go to latest
Published: Jul 20, 2026 License: Apache-2.0 Imports: 21 Imported by: 0

Documentation

Overview

Package metaagent provides a generic framework for building AI agents.

The framework is fully generic over three type parameters:

  • Req: The request type (must implement promptbuilder.Bindable)
  • Resp: The structured response type returned by the agent
  • CB: The callbacks type providing tool implementations

This design allows agents to be composed with any combination of tools from the toolcall package (worktree tools, finding tools, custom tools).

Model Support

The model parameter determines which provider implementation is used:

  • Models starting with "gemini-" use Google's Generative AI SDK (native)
  • Models starting with "claude-" use Anthropic's SDK via Vertex AI (native)
  • Models in "publisher/model" format use Vertex AI's OpenAI-compatible endpoint

Usage

Define your callback type by composing tool callbacks:

type MyCallbacks = toolcall.FindingTools[toolcall.WorktreeTools[toolcall.EmptyTools]]

Create the corresponding tool provider:

tools := toolcall.NewFindingToolsProvider[*Result, toolcall.WorktreeTools[toolcall.EmptyTools]](
    toolcall.NewWorktreeToolsProvider[*Result, toolcall.EmptyTools](
        toolcall.NewEmptyToolsProvider[*Result](),
    ),
)

Configure and create the agent:

config := metaagent.Config[*Result, MyCallbacks]{
    SystemInstructions: systemPrompt,
    UserPrompt:         userPrompt,
    Tools:              tools,
}

agent, err := metaagent.New[*Request, *Result, MyCallbacks](ctx, projectID, region, model, config)
result, err := agent.Execute(ctx, request, callbacks)

The agent uses the submit_result tool to return structured results. The Resp type's JSON tags define the schema for the tool's payload.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Agent

type Agent[Req promptbuilder.Bindable, Resp, CB any] interface {
	// Execute runs the agent with the given request and tool callbacks.
	Execute(ctx context.Context, request Req, callbacks CB) (Resp, error)
}

Agent is the interface for a configured meta-agent.

  • Req must implement promptbuilder.Bindable.
  • Resp is the structured response type.
  • CB is the type providing all tool callbacks.

func New

func New[Req promptbuilder.Bindable, Resp, CB any](
	ctx context.Context,
	projectID, region, model string,
	config Config[Resp, CB],
) (Agent[Req, Resp, CB], error)

New creates a new meta-agent with the given configuration. The model parameter determines which provider implementation is used:

  • Models starting with "gemini-" use Google's Generative AI SDK (native)
  • Models starting with "claude-" use Anthropic's SDK via Vertex AI (native)
  • Models in "publisher/model" format use Vertex AI's OpenAI-compatible endpoint
Example

ExampleNew demonstrates creating a new meta-agent with model selection. New selects the provider implementation based on the model name prefix: "gemini-" uses Google's Generative AI SDK, "claude-" uses Anthropic via Vertex AI.

package main

import (
	"context"
	"fmt"

	"chainguard.dev/driftlessaf/agents/metaagent"
	"chainguard.dev/driftlessaf/agents/promptbuilder"
	"chainguard.dev/driftlessaf/agents/toolcall"
)

// request is an example request type that implements promptbuilder.Bindable.
type request struct {
	Query string
}

func (r *request) Bind(p *promptbuilder.Prompt) (*promptbuilder.Prompt, error) {
	return p.BindXML("query", struct {
		XMLName struct{} `xml:"query"`
		Content string   `xml:",chardata"`
	}{
		Content: r.Query,
	})
}

// response is an example structured response type.
type response struct {
	Answer string `json:"answer"`
}

func main() {
	ctx := context.Background()

	tools := toolcall.NewEmptyToolsProvider[*response]()
	config := metaagent.Config[*response, toolcall.EmptyTools]{
		Tools: tools,
	}

	// An unsupported model prefix returns an error.
	_, err := metaagent.New[*request](ctx, "my-project", "us-central1", "unknown-model", config)
	if err != nil {
		fmt.Println("error:", err)
	}
}
Output:
error: unsupported model: unknown-model (expected gemini-*, claude-*, or publisher/model format)

type Config

type Config[Resp, CB any] struct {
	// SystemInstructions is the system prompt that defines the agent's role and behavior.
	SystemInstructions *promptbuilder.Prompt

	// UserPrompt is the template for formatting the user's request.
	// The Req type is bound to this template via its Bind method.
	UserPrompt *promptbuilder.Prompt

	// UserPromptSuffix is an optional static prompt appended as a separate
	// trailing block of the initial user message, after the bound UserPrompt.
	// When set, the leading block (UserPrompt with the request bound) gets a
	// cache breakpoint so executions that differ only in the suffix share its
	// cache entry. Intended for multi-pass agents reviewing one payload
	// through different lenses: the payload rides in UserPrompt, the per-pass
	// lens in the suffix. The request is never bound into the suffix — it
	// must be fully bound already. On the Gemini and OpenAI-compatible
	// backends (no per-block cache semantics) the built suffix is
	// concatenated onto the user prompt with a blank-line separator.
	UserPromptSuffix *promptbuilder.Prompt

	// Tools provides all tool definitions for this agent.
	// Compose providers using toolcall.NewFindingToolsProvider,
	// toolcall.NewWorktreeToolsProvider, and toolcall.NewEmptyToolsProvider.
	Tools toolcall.ToolProvider[Resp, CB]

	// MaxTurns sets the maximum number of conversation turns (LLM round-trips)
	// before the executor aborts. Zero means use the executor's default.
	MaxTurns int

	// ToolCallConcurrency bounds how many of a single turn's tool calls run
	// concurrently when the model emits more than one (parallel tool use).
	// Zero means use the executor's default (DefaultToolCallConcurrency). Set
	// to 1 to force strictly sequential tool dispatch — required for agents
	// whose tool handlers mutate shared state without their own synchronization.
	ToolCallConcurrency int

	// MaxTokens caps the model's output tokens per turn (the Anthropic
	// max_tokens parameter). Zero (the default) uses the meta-agent default of
	// 32000; the executor rejects values above 128000, the ceiling for current
	// Claude models. Because the executor streams every response, large values
	// do not risk the SDK's non-streaming HTTP timeout. Raise it for stages
	// whose turns need room for BOTH extended thinking and a tool call: at high
	// effort on a large context, adaptive thinking can otherwise consume the
	// whole budget and stop at max_tokens before the model emits its tool call,
	// which the executor surfaces as "no content in Claude's response". Claude
	// backend only; no effect on the Gemini or OpenAI backends.
	MaxTokens int64

	// ThinkingBudget enables Claude extended thinking with the given token
	// budget when running on the Claude backend. Zero (the default) leaves
	// thinking disabled. Must be at least 1024 and less than the executor's
	// max tokens (MaxTokens, or the 32000 default); see claudeexecutor.WithThinking.
	// On models where the Anthropic API has removed the explicit budget
	// parameter (Opus 4.7 and later), the executor automatically maps this to
	// adaptive thinking and the budget value is advisory only. No effect on
	// the Gemini backend.
	ThinkingBudget int64

	// Effort sets the Claude reasoning effort (output_config.effort): one of
	// "low", "medium", "high", "xhigh", "max". Empty (the default) leaves the
	// model default ("high"). "xhigh" is recommended for hard coding/agentic
	// work on Sonnet 5 / Opus 4.7+. Claude backend only; no effect on the
	// Gemini or OpenAI backends. See claudeexecutor.WithEffort.
	Effort string

	// ResultValidators gate the terminal submit_result tool. When the model
	// submits a result that parses into Resp, every validator runs
	// concurrently against it; any findings reject the submission back to the
	// model as the tool's result — the agent loop continues until a submission
	// passes — and a validator error aborts the run. Empty (the default)
	// accepts every parsed submission. Findings are concatenated in
	// registration order. Validators must be safe for concurrent use; see
	// callbacks.ResultValidator.
	ResultValidators []callbacks.ResultValidator[Resp]
}

Config defines the configuration for a meta-agent instance.

  • Resp is the structured response type returned by the agent.
  • CB is the type providing all tool callbacks.

Jump to

Keyboard shortcuts

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