agents

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Mar 30, 2026 License: EUPL-1.2 Imports: 19 Imported by: 0

Documentation

Overview

Package agents implements infrastructure adapters for AI agent integration.

The agents package provides concrete implementations of the AgentProvider and AgentRegistry ports defined in the domain layer, enabling workflow steps to invoke AI agents (Claude, Gemini, Codex, OpenCode, and OpenAI-compatible endpoints) for code generation, analysis, and decision-making tasks. Each provider wraps a CLI executor and handles model-specific invocation patterns, streaming output, and error mapping.

Architecture Role

In the hexagonal architecture:

  • Implements domain/ports.AgentProvider (per-provider adapters)
  • Implements domain/ports.AgentRegistry (provider registration and lookup)
  • Implements domain/ports.CLIExecutor (CLI command execution)
  • Application layer orchestrates agent steps via these port interfaces
  • Domain layer defines agent contracts without implementation coupling

All agent providers delegate CLI execution to an injected CLIExecutor, allowing test isolation via mock executors. The registry supports runtime provider registration and enables workflow steps to reference agents by name (e.g., "claude", "gemini").

Agent Providers

## ClaudeProvider (claude_provider.go)

Anthropic Claude provider:

  • Execute: Single-shot prompt execution via Claude CLI
  • ExecuteConversation: Multi-turn conversation with context preservation
  • Name: Returns "claude" for registry lookup
  • Validate: Checks required options (model, temperature)

Supported models: claude-3-opus, claude-3-sonnet, claude-3-haiku, claude-2.1, claude-2

## GeminiProvider (gemini_provider.go)

Google Gemini provider:

  • Execute: Single-shot prompt execution via Gemini CLI
  • ExecuteConversation: Multi-turn conversation support
  • Name: Returns "gemini"
  • Validate: Checks model and API key configuration

## CodexProvider (codex_provider.go)

OpenAI Codex provider (code-focused GPT models):

  • Execute: Single-shot code generation via OpenAI CLI
  • ExecuteConversation: Not supported (returns error)
  • Name: Returns "codex"
  • Validate: Checks API key and model configuration

## OpenCodeProvider (opencode_provider.go)

Open-source code generation models (StarCoder, CodeLlama, etc.):

  • Execute: Single-shot execution via custom CLI wrapper
  • ExecuteConversation: Limited support (model-dependent)
  • Name: Returns "opencode"
  • Validate: Checks CLI tool availability

## OpenAICompatibleProvider (openai_compatible_provider.go)

HTTP adapter for any OpenAI-compatible API endpoint (Ollama, LM Studio, vLLM, etc.):

  • Execute: Single-shot prompt via Chat Completions API
  • ExecuteConversation: Multi-turn conversation with history
  • Name: Returns "openai_compatible" for registry lookup
  • Validate: Checks base_url and model configuration

Configuration via agent options: base_url, api_key, model, temperature. Falls back to OPENAI_BASE_URL / OPENAI_MODEL / OPENAI_API_KEY env vars.

Registry and Discovery

## AgentRegistry (registry.go)

Provider registration and lookup:

  • Register: Add provider by name (thread-safe)
  • Get: Retrieve provider by name
  • List: Enumerate registered provider names
  • Has: Check if provider exists
  • RegisterDefaults: Pre-populate with built-in providers

CLI Execution

## ExecCLIExecutor (cli_executor.go)

External binary execution:

  • Run: Execute command with streaming stdout/stderr, context cancellation
  • Process cleanup: Kills descendant processes on cancellation
  • Signal propagation: Forwards SIGINT/SIGTERM to child processes

Used by all agent providers to invoke CLI tools (claude, gemini, gpt, etc.).

Provider Options

## Functional Options Pattern (options.go)

Provider configuration via option functions:

  • WithClaudeExecutor: Inject custom executor for Claude provider
  • WithGeminiExecutor: Inject custom executor for Gemini provider
  • WithCodexExecutor: Inject custom executor for Codex provider
  • WithOpenCodeExecutor: Inject custom executor for OpenCode provider
  • WithHTTPClient: Inject custom HTTP client for OpenAICompatible provider

Each provider accepts zero or more options at construction time for dependency injection.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AgentRegistry

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

AgentRegistry manages registered agent providers.

func NewAgentRegistry

func NewAgentRegistry() *AgentRegistry

func (*AgentRegistry) Get

func (r *AgentRegistry) Get(name string) (ports.AgentProvider, error)

func (*AgentRegistry) Has

func (r *AgentRegistry) Has(name string) bool

func (*AgentRegistry) List

func (r *AgentRegistry) List() []string

func (*AgentRegistry) Register

func (r *AgentRegistry) Register(provider ports.AgentProvider) error

func (*AgentRegistry) RegisterDefaults

func (r *AgentRegistry) RegisterDefaults() error

RegisterDefaults registers all default providers. It continues registering even if individual providers fail, collecting all errors and returning them aggregated.

type ClaudeProvider

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

ClaudeProvider implements AgentProvider for Claude CLI. Invokes: claude -p "prompt" --output-format json

func NewClaudeProvider

func NewClaudeProvider(l ...ports.Logger) *ClaudeProvider

func NewClaudeProviderWithOptions

func NewClaudeProviderWithOptions(opts ...ClaudeProviderOption) *ClaudeProvider

func (*ClaudeProvider) Execute

func (p *ClaudeProvider) Execute(ctx context.Context, prompt string, options map[string]any) (*workflow.AgentResult, error)

func (*ClaudeProvider) ExecuteConversation

func (p *ClaudeProvider) ExecuteConversation(ctx context.Context, state *workflow.ConversationState, prompt string, options map[string]any) (*workflow.ConversationResult, error)

ExecuteConversation invokes the Claude CLI with conversation history for multi-turn interactions.

func (*ClaudeProvider) Name

func (p *ClaudeProvider) Name() string

func (*ClaudeProvider) Validate

func (p *ClaudeProvider) Validate() error

type ClaudeProviderOption

type ClaudeProviderOption func(*ClaudeProvider)

func WithClaudeExecutor

func WithClaudeExecutor(executor ports.CLIExecutor) ClaudeProviderOption

type CodexProvider

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

CodexProvider implements AgentProvider for Codex CLI. Invokes: codex --prompt "prompt" --quiet

func NewCodexProvider

func NewCodexProvider() *CodexProvider

func NewCodexProviderWithOptions

func NewCodexProviderWithOptions(opts ...CodexProviderOption) *CodexProvider

func (*CodexProvider) Execute

func (p *CodexProvider) Execute(ctx context.Context, prompt string, options map[string]any) (*workflow.AgentResult, error)

func (*CodexProvider) ExecuteConversation

func (p *CodexProvider) ExecuteConversation(ctx context.Context, state *workflow.ConversationState, prompt string, options map[string]any) (*workflow.ConversationResult, error)

func (*CodexProvider) Name

func (p *CodexProvider) Name() string

Name returns the provider identifier.

func (*CodexProvider) Validate

func (p *CodexProvider) Validate() error

Validate checks if the Codex CLI is installed and accessible.

type CodexProviderOption

type CodexProviderOption func(*CodexProvider)

func WithCodexExecutor

func WithCodexExecutor(executor ports.CLIExecutor) CodexProviderOption

func WithCodexLogger

func WithCodexLogger(l ports.Logger) CodexProviderOption

type ExecCLIExecutor

type ExecCLIExecutor struct{}

ExecCLIExecutor implements CLIExecutor using os/exec for direct binary execution. Unlike shell execution via detected shell ($SHELL), this executes binaries directly without shell interpretation, making it suitable for invoking external CLI tools like claude, gemini, codex, etc.

func NewExecCLIExecutor

func NewExecCLIExecutor() *ExecCLIExecutor

func (*ExecCLIExecutor) Run

func (e *ExecCLIExecutor) Run(ctx context.Context, name string, args ...string) (stdout, stderr []byte, err error)

type GeminiProvider

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

GeminiProvider implements AgentProvider for Gemini CLI. Invokes: gemini -p "prompt"

func NewGeminiProvider

func NewGeminiProvider() *GeminiProvider

func NewGeminiProviderWithOptions

func NewGeminiProviderWithOptions(opts ...GeminiProviderOption) *GeminiProvider

func (*GeminiProvider) Execute

func (p *GeminiProvider) Execute(ctx context.Context, prompt string, options map[string]any) (*workflow.AgentResult, error)

func (*GeminiProvider) ExecuteConversation

func (p *GeminiProvider) ExecuteConversation(ctx context.Context, state *workflow.ConversationState, prompt string, options map[string]any) (*workflow.ConversationResult, error)

func (*GeminiProvider) Name

func (p *GeminiProvider) Name() string

extractSessionID parses a session identifier from Gemini CLI output. Looks for a "Session: <id>" line and returns the trimmed ID. Returns empty string and error if not found (caller falls back to stateless).

func (*GeminiProvider) Validate

func (p *GeminiProvider) Validate() error

type GeminiProviderOption

type GeminiProviderOption func(*GeminiProvider)

func WithGeminiExecutor

func WithGeminiExecutor(executor ports.CLIExecutor) GeminiProviderOption

type MockCall

type MockCall struct {
	Method  string
	Prompt  string
	Options map[string]any
	State   *workflow.ConversationState
}

MockCall records a call made to the mock provider.

type MockProvider

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

MockProvider provides deterministic responses for testing without external CLI calls. It implements ports.AgentProvider interface.

func NewMockProvider

func NewMockProvider(name string) *MockProvider

NewMockProvider creates a new mock provider with the given name.

func (*MockProvider) CallCount

func (m *MockProvider) CallCount() int

CallCount returns the number of calls made.

func (*MockProvider) Calls

func (m *MockProvider) Calls() []MockCall

Calls returns all recorded calls.

func (*MockProvider) ConversationCallCount

func (m *MockProvider) ConversationCallCount() int

ConversationCallCount returns the number of ExecuteConversation calls.

func (*MockProvider) Execute

func (m *MockProvider) Execute(ctx context.Context, prompt string, options map[string]any) (*workflow.AgentResult, error)

Execute implements ports.AgentProvider.

func (*MockProvider) ExecuteCallCount

func (m *MockProvider) ExecuteCallCount() int

ExecuteCallCount returns the number of Execute calls.

func (*MockProvider) ExecuteConversation

func (m *MockProvider) ExecuteConversation(ctx context.Context, state *workflow.ConversationState, prompt string, options map[string]any) (*workflow.ConversationResult, error)

ExecuteConversation implements ports.AgentProvider.

func (*MockProvider) Name

func (m *MockProvider) Name() string

Name implements ports.AgentProvider.

func (*MockProvider) Reset

func (m *MockProvider) Reset()

Reset clears all recorded calls.

func (*MockProvider) Validate

func (m *MockProvider) Validate() error

Validate implements ports.AgentProvider.

func (*MockProvider) WithConversationResponse

func (m *MockProvider) WithConversationResponse(pattern string, result *workflow.ConversationResult) *MockProvider

WithConversationResponse configures a conversation response for prompts containing the pattern.

func (*MockProvider) WithDefaultConversationResponse

func (m *MockProvider) WithDefaultConversationResponse(result *workflow.ConversationResult) *MockProvider

WithDefaultConversationResponse sets the default conversation response.

func (*MockProvider) WithDefaultResponse

func (m *MockProvider) WithDefaultResponse(result *workflow.AgentResult) *MockProvider

WithDefaultResponse sets the default response when no pattern matches.

func (*MockProvider) WithDelay

func (m *MockProvider) WithDelay(d time.Duration) *MockProvider

WithDelay sets the simulated processing delay.

func (*MockProvider) WithResponse

func (m *MockProvider) WithResponse(pattern string, result *workflow.AgentResult) *MockProvider

WithResponse configures a response for prompts containing the given pattern.

func (*MockProvider) WithValidateError

func (m *MockProvider) WithValidateError(err error) *MockProvider

WithValidateError configures the provider to return an error on Validate().

type OpenAICompatibleProvider

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

OpenAICompatibleProvider implements AgentProvider via the Chat Completions HTTP API. Compatible with OpenAI, Ollama, vLLM, Groq, and any OpenAI-compatible backend.

func (*OpenAICompatibleProvider) Execute

func (p *OpenAICompatibleProvider) Execute(ctx context.Context, prompt string, options map[string]any) (*workflow.AgentResult, error)

func (*OpenAICompatibleProvider) ExecuteConversation

func (p *OpenAICompatibleProvider) ExecuteConversation(ctx context.Context, state *workflow.ConversationState, prompt string, options map[string]any) (*workflow.ConversationResult, error)

func (*OpenAICompatibleProvider) Name

func (p *OpenAICompatibleProvider) Name() string

func (*OpenAICompatibleProvider) Validate

func (p *OpenAICompatibleProvider) Validate() error

type OpenAICompatibleProviderOption

type OpenAICompatibleProviderOption func(*OpenAICompatibleProvider)

func WithHTTPClient

func WithHTTPClient(client *httpx.Client) OpenAICompatibleProviderOption

type OpenCodeProvider

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

OpenCodeProvider implements AgentProvider for OpenCode CLI. Invokes: opencode run "prompt"

func NewOpenCodeProvider

func NewOpenCodeProvider() *OpenCodeProvider

NewOpenCodeProvider creates a new OpenCodeProvider. If no executor is provided, ExecCLIExecutor is used by default.

func NewOpenCodeProviderWithOptions

func NewOpenCodeProviderWithOptions(opts ...OpenCodeProviderOption) *OpenCodeProvider

NewOpenCodeProviderWithOptions creates a new OpenCodeProvider with functional options.

func (*OpenCodeProvider) Execute

func (p *OpenCodeProvider) Execute(ctx context.Context, prompt string, options map[string]any) (*workflow.AgentResult, error)

Execute invokes the OpenCode CLI with the given prompt and options.

func (*OpenCodeProvider) ExecuteConversation

func (p *OpenCodeProvider) ExecuteConversation(ctx context.Context, state *workflow.ConversationState, prompt string, options map[string]any) (*workflow.ConversationResult, error)

ExecuteConversation invokes the OpenCode CLI with conversation history for multi-turn interactions.

func (*OpenCodeProvider) Name

func (p *OpenCodeProvider) Name() string

Name returns the provider identifier.

func (*OpenCodeProvider) Validate

func (p *OpenCodeProvider) Validate() error

Validate checks if the OpenCode CLI is installed and accessible.

type OpenCodeProviderOption

type OpenCodeProviderOption func(*OpenCodeProvider)

func WithOpenCodeExecutor

func WithOpenCodeExecutor(executor ports.CLIExecutor) OpenCodeProviderOption

Jump to

Keyboard shortcuts

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