Module: AgentHarness::Providers::Adapter

Included in:
Base
Defined in:
lib/agent_harness/providers/adapter.rb

Overview

Interface that all providers must implement

This module defines the contract that provider implementations must follow. Include this module in provider classes to ensure they implement the required interface.

Examples:

Implementing a provider

class MyProvider < AgentHarness::Providers::Base
  include AgentHarness::Providers::Adapter

  def self.provider_name
    :my_provider
  end
end

Defined Under Namespace

Modules: ClassMethods

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object



19
20
21
# File 'lib/agent_harness/providers/adapter.rb', line 19

def self.included(base)
  base.extend(ClassMethods)
end

Instance Method Details

#auth_typeSymbol

Authentication type for this provider

Returns:

  • (Symbol)

    :oauth for token-based auth that can expire, :api_key for static API key auth



130
131
132
# File 'lib/agent_harness/providers/adapter.rb', line 130

def auth_type
  :api_key
end

#build_mcp_flags(mcp_servers, working_dir: nil) ⇒ Array<String>

Build provider-specific MCP flags/arguments for CLI invocation

Parameters:

  • mcp_servers (Array<McpServer>)

    MCP server definitions

  • working_dir (String, nil) (defaults to: nil)

    working directory for temp files

Returns:

  • (Array<String>)

    CLI flags to append to the command



160
161
162
# File 'lib/agent_harness/providers/adapter.rb', line 160

def build_mcp_flags(mcp_servers, working_dir: nil)
  []
end

#capabilitiesHash

Provider capabilities

Returns:

  • (Hash)

    capability flags



107
108
109
110
111
112
113
114
115
116
117
# File 'lib/agent_harness/providers/adapter.rb', line 107

def capabilities
  {
    streaming: false,
    file_upload: false,
    vision: false,
    tool_use: false,
    json_mode: false,
    mcp: false,
    dangerous_mode: false
  }
end

#configuration_schemaHash

Provider configuration schema for app-driven setup UIs

Returns metadata describing the configurable fields, supported authentication modes, and backend compatibility for this provider. Applications use this to build generic provider-entry forms without hardcoding provider-specific knowledge.

Returns:

  • (Hash)

    with :fields, :auth_modes, :openai_compatible keys



96
97
98
99
100
101
102
# File 'lib/agent_harness/providers/adapter.rb', line 96

def configuration_schema
  {
    fields: [],
    auth_modes: [auth_type],
    openai_compatible: false
  }
end

#dangerous_mode_flagsArray<String>

Get dangerous mode flags

Returns:

  • (Array<String>)

    CLI flags for dangerous mode



210
211
212
# File 'lib/agent_harness/providers/adapter.rb', line 210

def dangerous_mode_flags
  []
end

#error_patternsHash<Symbol, Array<Regexp>>

Error patterns for classification

Returns:

  • (Hash<Symbol, Array<Regexp>>)

    error patterns by category



122
123
124
# File 'lib/agent_harness/providers/adapter.rb', line 122

def error_patterns
  {}
end

#execution_semanticsHash

Execution semantics for this provider

Returns a hash describing provider-specific execution behavior so downstream apps do not need to hardcode CLI quirks. This metadata can be used to select the right flags and interpret output.

Returns:

  • (Hash)

    execution semantics



250
251
252
253
254
255
256
257
258
259
260
261
# File 'lib/agent_harness/providers/adapter.rb', line 250

def execution_semantics
  {
    prompt_delivery: :arg,       # :arg, :stdin, or :flag
    output_format: :text,        # :text or :json
    sandbox_aware: false,        # adjusts behavior inside containers
    uses_subcommand: false,      # e.g. "codex exec", "opencode run"
    non_interactive_flag: nil,   # flag to suppress interactive prompts
    legitimate_exit_codes: [0],  # exit codes that are NOT errors
    stderr_is_diagnostic: true,  # stderr may contain non-error output
    parses_rate_limit_reset: false # can extract Retry-After from output
  }
end

#fetch_mcp_serversArray<Hash>

Fetch configured MCP servers

Returns:

  • (Array<Hash>)

    MCP server configurations



144
145
146
# File 'lib/agent_harness/providers/adapter.rb', line 144

def fetch_mcp_servers
  []
end

#health_statusHash

Health check

Returns:

  • (Hash)

    with :healthy, :message keys



239
240
241
# File 'lib/agent_harness/providers/adapter.rb', line 239

def health_status
  {healthy: true, message: "OK"}
end

#parse_rate_limit_reset(output) ⇒ Time?

Parse a rate-limit reset time from provider output

Providers that include rate-limit reset information in their error output can override this to extract it, so the orchestration layer can schedule retries accurately.

Parameters:

  • output (String)

    combined stdout+stderr from the CLI

Returns:

  • (Time, nil)

    when the rate limit resets, or nil if unknown



271
272
273
# File 'lib/agent_harness/providers/adapter.rb', line 271

def parse_rate_limit_reset(output)
  nil
end

#send_message(prompt:, **options) ⇒ Response

Send a message/prompt to the provider

Parameters:

  • prompt (String)

    the prompt to send

  • options (Hash)

    provider-specific options

Options Hash (**options):

  • :model (String)

    model to use

  • :timeout (Integer)

    timeout in seconds

  • :session (String)

    session identifier

  • :dangerous_mode (Boolean)

    skip permission checks

  • :provider_runtime (ProviderRuntime, Hash, nil)

    per-request runtime overrides (model, base_url, api_provider, env, flags, metadata). For providers that delegate to Providers::Base#send_message, a plain Hash is automatically coerced into a ProviderRuntime. Providers that override #send_message directly are responsible for handling this option.

Returns:

  • (Response)

    response object with output and metadata

Raises:

  • (NotImplementedError)


84
85
86
# File 'lib/agent_harness/providers/adapter.rb', line 84

def send_message(prompt:, **options)
  raise NotImplementedError, "#{self.class} must implement #send_message"
end

#session_flags(session_id) ⇒ Array<String>

Get session flags for continuation

Parameters:

  • session_id (String)

    the session ID

Returns:

  • (Array<String>)

    CLI flags for session continuation



225
226
227
# File 'lib/agent_harness/providers/adapter.rb', line 225

def session_flags(session_id)
  []
end

#supported_mcp_transportsArray<String>

Supported MCP transport types for this provider

Returns:

  • (Array<String>)

    supported transports (e.g. [“stdio”, “http”])



151
152
153
# File 'lib/agent_harness/providers/adapter.rb', line 151

def supported_mcp_transports
  []
end

#supports_dangerous_mode?Boolean

Check if provider supports dangerous mode

Returns:

  • (Boolean)

    true if dangerous mode is supported



203
204
205
# File 'lib/agent_harness/providers/adapter.rb', line 203

def supports_dangerous_mode?
  capabilities[:dangerous_mode]
end

#supports_mcp?Boolean

Check if provider supports MCP

Returns:

  • (Boolean)

    true if MCP is supported



137
138
139
# File 'lib/agent_harness/providers/adapter.rb', line 137

def supports_mcp?
  capabilities[:mcp]
end

#supports_sessions?Boolean

Check if provider supports session continuation

Returns:

  • (Boolean)

    true if sessions are supported



217
218
219
# File 'lib/agent_harness/providers/adapter.rb', line 217

def supports_sessions?
  false
end

#validate_configHash

Validate provider configuration

Returns:

  • (Hash)

    with :valid, :errors keys



232
233
234
# File 'lib/agent_harness/providers/adapter.rb', line 232

def validate_config
  {valid: true, errors: []}
end

#validate_mcp_servers!(mcp_servers) ⇒ Object

Validate that this provider can handle the given MCP servers

Parameters:

  • mcp_servers (Array<McpServer>)

    MCP server definitions

Raises:



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/agent_harness/providers/adapter.rb', line 169

def validate_mcp_servers!(mcp_servers)
  return if mcp_servers.nil? || mcp_servers.empty?

  unless supports_mcp?
    raise McpUnsupportedError.new(
      "Provider '#{self.class.provider_name}' does not support MCP servers",
      provider: self.class.provider_name
    )
  end

  supported = supported_mcp_transports

  if supported.empty?
    raise McpUnsupportedError.new(
      "Provider '#{self.class.provider_name}' does not support request-time MCP servers",
      provider: self.class.provider_name
    )
  end

  mcp_servers.each do |server|
    next if supported.include?(server.transport)

    raise McpTransportUnsupportedError.new(
      "Provider '#{self.class.provider_name}' does not support MCP transport " \
      "'#{server.transport}' (server: '#{server.name}'). " \
      "Supported transports: #{supported.join(", ")}",
      provider: self.class.provider_name
    )
  end
end