Documentation
¶
Overview ¶
Package agent provides a convenience layer for building AI agents.
This package is the "Laravel layer" - syntactic sugar that makes building agents as simple as possible while retaining full power.
Quick start (1 line):
agent.Run("You are a helpful assistant.")
Query and get response:
response, err := agent.Query(ctx, "What is 2+2?")
Typed responses:
type Answer struct {
Result int `json:"result"`
Reason string `json:"reason"`
}
answer, err := agent.QueryAs[Answer](ctx, "What is 2+2?")
Fluent builder:
agent.New("assistant").
Model("opus").
System("You are helpful.").
MaxTurns(10).
Run()
Index ¶
- Constants
- Variables
- func ExpandModel(m string) string
- func ExtractJSON[T any](response string) (*T, error)
- func ExtractJSONArray[T any](response string) ([]T, error)
- func ExtractMarkdown(content string) string
- func Final(results []StepResult) string
- func Must[T any](val T, err error) T
- func MustExtractJSON[T any](response string) *T
- func MustExtractJSONArray[T any](response string) []T
- func ProviderEnv(p *Provider) map[string]string
- func Providers() map[string]*Provider
- func Query(ctx context.Context, prompt string, opts ...Option) (string, error)
- func QueryAs[T any](ctx context.Context, prompt string, opts ...Option) (*T, error)
- func QueryJSON[T any](c *SimpleClient, ctx context.Context, prompt string) (*T, error)
- func QueryJSONArray[T any](c *SimpleClient, ctx context.Context, prompt string) ([]T, error)
- func Run(systemPrompt string, opts ...Option) error
- func SchemaFor[T any]() map[string]any
- func SimplePrompt(template string, input string) string
- func Stream(ctx context.Context, prompt string, handler func(chunk string), opts ...Option) error
- type Approval
- type Builder
- func (b *Builder) AlsoAccess(paths ...string) *Builder
- func (b *Builder) AppendSystem(prompt string) *Builder
- func (b *Builder) Apply(opts ...Option) *Builder
- func (b *Builder) Beta(features ...string) *Builder
- func (b *Builder) BlockTools(tools ...string) *Builder
- func (b *Builder) Budget(usd float64) *Builder
- func (b *Builder) ClaudeCodeTools() *Builder
- func (b *Builder) Context(files ...string) *Builder
- func (b *Builder) Continue() *Builder
- func (b *Builder) Env(vars map[string]string) *Builder
- func (b *Builder) Fallback(m string) *Builder
- func (b *Builder) Fork(sessionID string) *Builder
- func (b *Builder) MaxThinking(tokens int) *Builder
- func (b *Builder) MaxTurns(n int) *Builder
- func (b *Builder) Model(m string) *Builder
- func (b *Builder) OnPostToolUse(fn func(tool string, result any)) *Builder
- func (b *Builder) OnPreToolUse(fn func(tool string, input map[string]any) bool) *Builder
- func (b *Builder) OnSessionEnd(fn func(sessionID string)) *Builder
- func (b *Builder) OnSessionStart(fn func(sessionID string)) *Builder
- func (b *Builder) OnlyTools(tools ...string) *Builder
- func (b *Builder) OutputSchema(schema map[string]any) *Builder
- func (b *Builder) PermissionMode(mode PermissionMode) *Builder
- func (b *Builder) Query(ctx context.Context, prompt string) (string, error)
- func (b *Builder) RequireApproval(fn func(tool string, input map[string]any) Approval) *Builder
- func (b *Builder) Resume(sessionID string) *Builder
- func (b *Builder) Run() error
- func (b *Builder) SDKOption(opt claude.ClientOption) *Builder
- func (b *Builder) Stream(ctx context.Context, prompt string, handler func(chunk string)) error
- func (b *Builder) StreamPartial() *Builder
- func (b *Builder) String() string
- func (b *Builder) System(prompt string) *Builder
- func (b *Builder) Timeout(d time.Duration) *Builder
- func (b *Builder) Tool(t ToolDef) *Builder
- func (b *Builder) TrackFiles() *Builder
- func (b *Builder) User(userID string) *Builder
- func (b *Builder) Version(v string) *Builder
- func (b *Builder) WorkDir(path string) *Builder
- type ClientOption
- type Option
- type PermissionMode
- type Pipeline
- func (p *Pipeline) OnError(handler func(name string, err error) (fallback string, skip bool)) *Pipeline
- func (p *Pipeline) OnProgress(fn func(name string, stepNum, total int)) *Pipeline
- func (p *Pipeline) Run(ctx context.Context, input string) (string, error)
- func (p *Pipeline) RunWithResults(ctx context.Context, input string) ([]StepResult, error)
- func (p *Pipeline) Step(name, template string) *Pipeline
- func (p *Pipeline) StepFunc(name string, builder func(input string) string) *Pipeline
- func (p *Pipeline) StepWithPost(name, template string, post func(string) string) *Pipeline
- type PromptRegistry
- func (r *PromptRegistry) Format(name string, args ...any) (string, error)
- func (r *PromptRegistry) List() []string
- func (r *PromptRegistry) Load(name string) (string, error)
- func (r *PromptRegistry) MustFormat(name string, args ...any) string
- func (r *PromptRegistry) MustLoad(name string) string
- func (r *PromptRegistry) MustRender(name string, data any) string
- func (r *PromptRegistry) Render(name string, data any) (string, error)
- type Provider
- type SimpleClient
- type StepResult
- type ToolDef
- func AsyncTool(name, description string, fn func(context.Context, string) error) ToolDef
- func SimpleTool(name, description string, fn func(string) (string, error)) ToolDef
- func Tool[I, O any](name, description string, fn func(context.Context, I) (O, error)) ToolDef
- func ToolWithSchema(name, description string, schema map[string]any, ...) ToolDef
Constants ¶
const ( // DefaultModel is the default model used when none is specified. DefaultModel = "claude-sonnet-4-20250514" // ModelOpus is the most capable model. ModelOpus = "claude-opus-4-20250514" // ModelSonnet is the balanced model (default). ModelSonnet = "claude-sonnet-4-20250514" // ModelHaiku is the fastest model. ModelHaiku = "claude-haiku-3-5-20241022" )
Model shortcuts
Variables ¶
var ( // ProviderAnthropic is the default Anthropic API. ProviderAnthropic = &Provider{ Name: "anthropic", Model: ModelOpus, } // ProviderZAI is Z.AI's Claude-compatible API. ProviderZAI = &Provider{ Name: "zai", BaseURL: "https://api.z.ai/api/anthropic", AuthEnvVar: "ZAI_API_KEY", Model: "GLM-4.7", } // ProviderSynthetic is Synthetic.new's API. ProviderSynthetic = &Provider{ Name: "synthetic", BaseURL: "https://api.synthetic.new/anthropic", AuthEnvVar: "SYNTHETIC_API_KEY", Model: "hf:zai-org/GLM-4.7", } )
Common providers with sensible defaults.
Functions ¶
func ExpandModel ¶
ExpandModel converts a short model name to its full ID. Returns the input unchanged if not a known shortcut.
Example:
ExpandModel("opus") // "claude-opus-4-20250514"
ExpandModel("sonnet") // "claude-sonnet-4-20250514"
ExpandModel("claude-3-opus") // "claude-3-opus" (unchanged)
func ExtractJSON ¶
ExtractJSON extracts and parses the first JSON object from an LLM response. Handles common LLM quirks: markdown code blocks, leading text, trailing text.
Example:
type Result struct {
Answer string `json:"answer"`
}
result, err := agent.ExtractJSON[Result](response)
func ExtractJSONArray ¶
ExtractJSONArray extracts and parses the first JSON array from an LLM response. Handles common LLM quirks: markdown code blocks, leading text, streaming duplicates.
Example:
type Item struct {
Name string `json:"name"`
}
items, err := agent.ExtractJSONArray[Item](response)
func ExtractMarkdown ¶
ExtractMarkdown removes markdown code block wrappers from LLM responses. Handles ```markdown, ```json, and bare ``` wrappers.
Example:
clean := agent.ExtractMarkdown(response)
func Final ¶
func Final(results []StepResult) string
Final returns the final output from a list of step results.
func Must ¶
Must wraps a (T, error) return and panics on error. Useful for scripts where error handling is verbose.
Example:
response := agent.Must(agent.Query(ctx, "Hello"))
func MustExtractJSON ¶
MustExtractJSON extracts JSON or panics. Use for tests and scripts.
func MustExtractJSONArray ¶
MustExtractJSONArray extracts JSON array or panics. Use for tests and scripts.
func ProviderEnv ¶
ProviderEnv returns environment variables for non-Anthropic providers. Pass to WithClientEnv() when creating a client.
Example:
client, err := agent.NewClient(ctx,
agent.WithClientModel(agent.ProviderZAI.Model),
agent.WithClientEnv(agent.ProviderEnv(agent.ProviderZAI)),
)
func Query ¶
Query sends a single prompt and returns the response. For scripts and one-shot tasks.
Example:
response, err := agent.Query(ctx, "Explain goroutines in one sentence.")
func QueryAs ¶
QueryAs sends a prompt and returns a typed response. The response is parsed as JSON into the type T.
Example:
type Summary struct {
Title string `json:"title"`
Points []string `json:"points"`
}
summary, err := agent.QueryAs[Summary](ctx, "Summarize this article...")
func QueryJSON ¶
QueryJSON sends a prompt and parses the response as JSON.
Example:
type Result struct {
Value int `json:"value"`
}
result, err := c.QueryJSON[Result](ctx, "What is 2+2? Reply as JSON.")
func QueryJSONArray ¶
QueryJSONArray sends a prompt and parses the response as a JSON array.
func Run ¶
Run starts an interactive agent with the given system prompt. This is the simplest possible entry point.
Example:
agent.Run("You are a helpful coding assistant.")
func SchemaFor ¶
SchemaFor generates a JSON Schema from a Go type using reflection. Supports structs, slices, maps, and primitive types.
Example:
type Response struct {
Name string `json:"name"`
Count int `json:"count"`
Tags []string `json:"tags"`
}
schema := agent.SchemaFor[Response]()
func SimplePrompt ¶
SimplePrompt formats a prompt with a single input placeholder. Convenience for the common case of "template with one %s".
Example:
prompt := agent.SimplePrompt("Summarize:\n\n%s", text)
Types ¶
type Approval ¶
type Approval struct {
// contains filtered or unexported fields
}
Approval represents the result of a permission check.
type Builder ¶
type Builder struct {
// contains filtered or unexported fields
}
Builder provides a fluent interface for configuring agents.
func New ¶
New creates a new agent builder with the given name.
Example:
agent.New("code-reviewer").
Model("opus").
System("You review code for bugs.").
Run()
func (*Builder) AlsoAccess ¶
AlsoAccess adds additional directories the agent can access.
func (*Builder) AppendSystem ¶
AppendSystem appends to the system prompt.
func (*Builder) BlockTools ¶
BlockTools prevents the agent from using specific tools (blacklist).
func (*Builder) ClaudeCodeTools ¶
ClaudeCodeTools enables standard Claude Code tools.
func (*Builder) MaxThinking ¶
MaxThinking limits thinking tokens.
func (*Builder) Model ¶
Model sets the AI model. Accepts shortcuts: "opus", "sonnet", "haiku".
Example:
agent.New("app").Model("opus") // claude-opus-4-20250514
agent.New("app").Model("sonnet") // claude-sonnet-4-20250514
agent.New("app").Model("haiku") // claude-haiku-3-5-20241022
func (*Builder) OnPostToolUse ¶
OnPostToolUse registers a hook called after each tool use.
func (*Builder) OnPreToolUse ¶
OnPreToolUse registers a hook called before each tool use. Return false to block the tool call.
func (*Builder) OnSessionEnd ¶
OnSessionEnd registers a hook called when a session ends.
func (*Builder) OnSessionStart ¶
OnSessionStart registers a hook called when a session starts.
func (*Builder) OutputSchema ¶
OutputSchema sets a JSON schema for structured output.
func (*Builder) PermissionMode ¶
func (b *Builder) PermissionMode(mode PermissionMode) *Builder
PermissionMode sets how permissions are handled.
func (*Builder) RequireApproval ¶
RequireApproval sets a callback for runtime tool approval.
func (*Builder) SDKOption ¶
func (b *Builder) SDKOption(opt claude.ClientOption) *Builder
SDKOption adds a raw SDK option for advanced use cases.
func (*Builder) StreamPartial ¶
StreamPartial includes partial/incomplete messages in streams.
func (*Builder) TrackFiles ¶
TrackFiles enables file change tracking for rollback.
type ClientOption ¶
type ClientOption func(*clientConfig)
ClientOption configures a SimpleClient.
func WithClientEnv ¶
func WithClientEnv(env map[string]string) ClientOption
WithClientEnv sets environment variables (for provider config).
func WithClientModel ¶
func WithClientModel(m string) ClientOption
WithClientModel sets the model for the client.
func WithClientRetry ¶
func WithClientRetry() ClientOption
WithClientRetry enables retry with exponential backoff.
func WithClientSystem ¶
func WithClientSystem(prompt string) ClientOption
WithClientSystem sets the system prompt.
type PermissionMode ¶
type PermissionMode string
Permission modes
const ( // PermissionDefault asks for permission on each action. PermissionDefault PermissionMode = "default" // PermissionAcceptEdits auto-accepts file edits. PermissionAcceptEdits PermissionMode = "acceptEdits" // PermissionBypass skips all permission checks. PermissionBypass PermissionMode = "bypassPermissions" // PermissionPlan enables plan mode. PermissionPlan PermissionMode = "plan" )
type Pipeline ¶
type Pipeline struct {
// contains filtered or unexported fields
}
Pipeline chains multiple LLM calls, passing output from each step as input to the next. This is common in spec (5-layer snowflake) and learn (extract → filter → format).
Example:
result, err := agent.NewPipeline(client).
Step("extract", extractPrompt).
Step("refine", refinePrompt).
Step("polish", polishPrompt).
Run(ctx, input)
func NewPipeline ¶
func NewPipeline(client *SimpleClient) *Pipeline
NewPipeline creates a new pipeline with the given client.
func (*Pipeline) OnError ¶
func (p *Pipeline) OnError(handler func(name string, err error) (fallback string, skip bool)) *Pipeline
OnError sets an error handler for all steps. The handler can return a fallback value and whether to skip to next step. If skip is false and fallback is empty, the error propagates.
Example:
pipeline.OnError(func(name string, err error) (string, bool) {
log.Printf("Step %s failed: %v", name, err)
return "", true // Skip failed step, continue with previous output
})
func (*Pipeline) OnProgress ¶
OnProgress sets a callback for step progress.
Example:
pipeline.OnProgress(func(name string, step, total int) {
fmt.Printf("Step %d/%d: %s\n", step, total, name)
})
func (*Pipeline) Run ¶
Run executes the pipeline with the given initial input. Each step receives the output of the previous step as input.
func (*Pipeline) RunWithResults ¶
RunWithResults executes the pipeline and returns all intermediate results.
func (*Pipeline) Step ¶
Step adds a step with a static prompt template. Use %s as placeholder for the input from the previous step.
Example:
pipeline.Step("extract", "Extract key points from:\n\n%s")
func (*Pipeline) StepFunc ¶
StepFunc adds a step with a dynamic prompt builder. Use when the prompt needs complex construction.
Example:
pipeline.StepFunc("analyze", func(input string) string {
return fmt.Sprintf("Analyze this code:\n```\n%s\n```", input)
})
func (*Pipeline) StepWithPost ¶
StepWithPost adds a step with output post-processing. The post function transforms the LLM output before passing to the next step.
Example:
pipeline.StepWithPost("extract", template, agent.ExtractMarkdown)
type PromptRegistry ¶
type PromptRegistry struct {
// contains filtered or unexported fields
}
PromptRegistry manages prompt templates with embed + runtime override support. Priority: runtime (~/.config/<app>/prompts/) > embedded > error
Example:
//go:embed prompts/*.prompt
var promptsFS embed.FS
prompts := agent.NewPromptRegistry("myapp", promptsFS)
text, err := prompts.Render("extraction", map[string]any{"input": data})
func NewPromptRegistry ¶
func NewPromptRegistry(appName string, embedded embed.FS) *PromptRegistry
NewPromptRegistry creates a prompt registry. appName is used for runtime config path: ~/.config/<appName>/prompts/ embedded is the embed.FS containing *.prompt files.
func (*PromptRegistry) Format ¶
func (r *PromptRegistry) Format(name string, args ...any) (string, error)
Format is a simpler alternative using fmt.Sprintf. Use when templates are overkill.
Example:
text, err := prompts.Format("simple", userInput)
func (*PromptRegistry) List ¶
func (r *PromptRegistry) List() []string
List returns all available prompt names.
func (*PromptRegistry) Load ¶
func (r *PromptRegistry) Load(name string) (string, error)
Load retrieves a prompt template by name (without .prompt extension). Checks runtime directory first, then embedded.
func (*PromptRegistry) MustFormat ¶
func (r *PromptRegistry) MustFormat(name string, args ...any) string
MustFormat formats a prompt or panics.
func (*PromptRegistry) MustLoad ¶
func (r *PromptRegistry) MustLoad(name string) string
MustLoad loads a prompt or panics. Use during init.
func (*PromptRegistry) MustRender ¶
func (r *PromptRegistry) MustRender(name string, data any) string
MustRender renders a prompt or panics.
type Provider ¶
type Provider struct {
Name string // Display name
BaseURL string // API base URL (empty = default)
AuthEnvVar string // Environment variable for auth token
Model string // Default model for this provider
}
Provider represents an LLM API provider configuration. Use for multi-provider support (Anthropic, Z.AI, Synthetic, etc.)
func GetProvider ¶
GetProvider returns a provider by name, or nil if not found.
type SimpleClient ¶
type SimpleClient struct {
// contains filtered or unexported fields
}
SimpleClient provides direct LLM access without the full app.App machinery. Use for pipeline tools, scripts, and batch processing.
func NewClient ¶
func NewClient(ctx context.Context, opts ...ClientOption) (*SimpleClient, error)
NewClient creates a SimpleClient for direct LLM queries. This is lighter weight than app.New() - no CLI, no tools, just queries.
Example:
c, err := agent.NewClient(ctx,
agent.WithClientModel("opus"),
agent.WithClientSystem("You are helpful."),
agent.WithClientRetry(),
)
defer c.Close()
response, err := c.Query(ctx, "Hello")
func (*SimpleClient) Model ¶
func (c *SimpleClient) Model() string
Model returns the model being used.
type StepResult ¶
StepResult holds the result of a single pipeline step.
type ToolDef ¶
type ToolDef struct {
Name string
Description string
Schema map[string]any
Handler func(ctx context.Context, input map[string]any) (any, error)
}
ToolDef represents a tool definition.
func AsyncTool ¶
AsyncTool creates a tool that runs asynchronously and returns immediately. The handler runs in a goroutine and results can be retrieved later.
Example:
downloadTool := agent.AsyncTool("download", "Download a file",
func(ctx context.Context, url string) error {
return downloadFile(url)
},
)
func SimpleTool ¶
SimpleTool creates a tool with a single string input and output. Perfect for simple transformations or queries.
Example:
reverseTool := agent.SimpleTool("reverse", "Reverse a string",
func(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
},
)
func Tool ¶
Tool creates a type-safe tool with schema inferred from the input type. The input type's JSON schema is automatically generated from struct tags.
Example:
type SearchInput struct {
Query string `json:"query" desc:"Search query" required:"true"`
Limit int `json:"limit" desc:"Max results" max:"100"`
}
type SearchOutput struct {
Results []string `json:"results"`
}
searchTool := agent.Tool("search", "Search the web",
func(ctx context.Context, in SearchInput) (SearchOutput, error) {
results := doSearch(in.Query, in.Limit)
return SearchOutput{Results: results}, nil
},
)
func ToolWithSchema ¶
func ToolWithSchema(name, description string, schema map[string]any, fn func(context.Context, map[string]any) (any, error)) ToolDef
ToolWithSchema creates a tool with an explicit schema. Use when you need precise control over the schema.
Example:
calcTool := agent.ToolWithSchema("calc", "Calculate expression",
map[string]any{
"type": "object",
"properties": map[string]any{
"expression": map[string]any{
"type": "string",
"pattern": "^[0-9+\\-*/()\\s]+$",
},
},
"required": []string{"expression"},
},
func(ctx context.Context, input map[string]any) (any, error) {
expr := input["expression"].(string)
return evaluate(expr), nil
},
)