Class: AgentHarness::Providers::Anthropic

Inherits:
Base
  • Object
show all
Defined in:
lib/agent_harness/providers/anthropic.rb

Overview

Anthropic Claude Code CLI provider

Provides integration with the Claude Code CLI tool for AI-powered coding assistance.

Examples:

Basic usage

provider = AgentHarness::Providers::Anthropic.new
response = provider.send_message(prompt: "Hello!")

Constant Summary collapse

MODEL_PATTERN =

Model name pattern for Anthropic Claude models

/^claude-[\d.-]+-(?:opus|sonnet|haiku)(?:-\d{8})?$/i

Constants inherited from Base

Base::COMMON_ERROR_PATTERNS

Instance Attribute Summary

Attributes inherited from Base

#config, #executor, #logger

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

#configure, #initialize, #sandboxed_environment?

Methods included from Adapter

#health_status, included, #parse_rate_limit_reset, #session_flags, #supports_dangerous_mode?, #supports_sessions?, #validate_config, #validate_mcp_servers!

Constructor Details

This class inherits a constructor from AgentHarness::Providers::Base

Class Method Details

.available?Boolean

Returns:

  • (Boolean)


28
29
30
31
# File 'lib/agent_harness/providers/anthropic.rb', line 28

def available?
  executor = AgentHarness.configuration.command_executor
  !!executor.which(binary_name)
end

.binary_nameObject



24
25
26
# File 'lib/agent_harness/providers/anthropic.rb', line 24

def binary_name
  "claude"
end

.discover_modelsObject



54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/agent_harness/providers/anthropic.rb', line 54

def discover_models
  return [] unless available?

  begin
    require "open3"
    output, _, status = Open3.capture3("claude", "models", "list", {timeout: 10})
    return [] unless status.success?

    parse_models_list(output)
  rescue => e
    AgentHarness.logger&.debug("[AgentHarness::Anthropic] Model discovery failed: #{e.message}")
    []
  end
end

.firewall_requirementsObject



33
34
35
36
37
38
39
40
41
42
# File 'lib/agent_harness/providers/anthropic.rb', line 33

def firewall_requirements
  {
    domains: [
      "api.anthropic.com",
      "claude.ai",
      "console.anthropic.com"
    ],
    ip_ranges: []
  }
end

.instruction_file_pathsObject



44
45
46
47
48
49
50
51
52
# File 'lib/agent_harness/providers/anthropic.rb', line 44

def instruction_file_paths
  [
    {
      path: "CLAUDE.md",
      description: "Claude Code CLI agent instructions",
      symlink: true
    }
  ]
end

.model_family(provider_model_name) ⇒ Object

Normalize a provider-specific model name to its model family



70
71
72
# File 'lib/agent_harness/providers/anthropic.rb', line 70

def model_family(provider_model_name)
  provider_model_name.sub(/-\d{8}$/, "")
end

.provider_model_name(family_name) ⇒ Object

Convert a model family name to the provider’s preferred model name



75
76
77
# File 'lib/agent_harness/providers/anthropic.rb', line 75

def provider_model_name(family_name)
  family_name
end

.provider_nameObject



20
21
22
# File 'lib/agent_harness/providers/anthropic.rb', line 20

def provider_name
  :claude
end

.supports_model_family?(family_name) ⇒ Boolean

Check if this provider supports a given model family

Returns:

  • (Boolean)


80
81
82
# File 'lib/agent_harness/providers/anthropic.rb', line 80

def supports_model_family?(family_name)
  MODEL_PATTERN.match?(family_name)
end

Instance Method Details

#auth_typeObject



200
201
202
# File 'lib/agent_harness/providers/anthropic.rb', line 200

def auth_type
  :oauth
end

#build_mcp_flags(mcp_servers, working_dir: nil) ⇒ Object



189
190
191
192
193
194
# File 'lib/agent_harness/providers/anthropic.rb', line 189

def build_mcp_flags(mcp_servers, working_dir: nil)
  return [] if mcp_servers.empty?

  config_path = write_mcp_config_file(mcp_servers, working_dir: working_dir)
  ["--mcp-config", config_path]
end

#capabilitiesObject



163
164
165
166
167
168
169
170
171
172
173
# File 'lib/agent_harness/providers/anthropic.rb', line 163

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

#dangerous_mode_flagsObject



196
197
198
# File 'lib/agent_harness/providers/anthropic.rb', line 196

def dangerous_mode_flags
  ["--dangerously-skip-permissions"]
end

#display_nameObject



159
160
161
# File 'lib/agent_harness/providers/anthropic.rb', line 159

def display_name
  "Anthropic Claude CLI"
end

#error_patternsObject



217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
# File 'lib/agent_harness/providers/anthropic.rb', line 217

def error_patterns
  {
    rate_limited: [
      /rate.?limit/i,
      /too.?many.?requests/i,
      /429/,
      /overloaded/i,
      /session.?limit/i
    ],
    auth_expired: [
      /oauth.*token.*expired/i,
      /authentication.*error/i,
      /invalid.*api.*key/i,
      /unauthorized/i,
      /401/,
      /session.*expired/i,
      /not.*logged.*in/i,
      /login.*required/i,
      /credentials.*expired/i
    ],
    quota_exceeded: [
      /quota.*exceeded/i,
      /usage.*limit/i,
      /credit.*exhausted/i
    ],
    transient: [
      /timeout/i,
      /connection.*reset/i,
      /temporary.*error/i,
      /service.*unavailable/i,
      /503/,
      /502/,
      /504/
    ],
    permanent: [
      /invalid.*model/i,
      /unsupported.*operation/i,
      /not.*found/i,
      /404/,
      /bad.*request/i,
      /400/,
      /model.*deprecated/i,
      /end-of-life/i
    ]
  }
end

#execution_semanticsObject



204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/agent_harness/providers/anthropic.rb', line 204

def execution_semantics
  {
    prompt_delivery: :arg,
    output_format: :json,
    sandbox_aware: true,
    uses_subcommand: false,
    non_interactive_flag: "--print",
    legitimate_exit_codes: [0],
    stderr_is_diagnostic: true,
    parses_rate_limit_reset: false
  }
end

#fetch_mcp_serversObject



264
265
266
267
268
269
270
271
272
273
274
275
276
# File 'lib/agent_harness/providers/anthropic.rb', line 264

def fetch_mcp_servers
  return [] unless self.class.available?

  begin
    result = @executor.execute(["claude", "mcp", "list"], timeout: 5)
    return [] unless result.success?

    parse_claude_mcp_output(result.stdout)
  rescue => e
    log_debug("fetch_mcp_servers_failed", error: e.message)
    []
  end
end

#nameObject



155
156
157
# File 'lib/agent_harness/providers/anthropic.rb', line 155

def name
  "anthropic"
end

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



175
176
177
178
179
# File 'lib/agent_harness/providers/anthropic.rb', line 175

def send_message(prompt:, **options)
  super
ensure
  cleanup_mcp_tempfiles!
end

#supported_mcp_transportsObject



185
186
187
# File 'lib/agent_harness/providers/anthropic.rb', line 185

def supported_mcp_transports
  %w[stdio http sse]
end

#supports_mcp?Boolean

Returns:

  • (Boolean)


181
182
183
# File 'lib/agent_harness/providers/anthropic.rb', line 181

def supports_mcp?
  true
end