Class: Helicone::Agent

Inherits:
Object
  • Object
show all
Defined in:
lib/helicone/agent.rb

Constant Summary collapse

MAX_ITERATIONS =
10

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(client: nil, session: nil, user: nil, tools: [], context: nil, system_prompt: nil, messages: [], model: nil, **options) ⇒ Agent

Create an agent with tools and optional context

Parameters:

  • client (Helicone::Client) (defaults to: nil) —

    Optional client (creates new one if not provided)

  • session (Hash) (defaults to: nil) —

    Session config for Helicone tracking (id:, name:) - creates client if no client provided

  • user (Hash) (defaults to: nil) —

    User config for Helicone tracking (id:, name:) - sets Helicone-User-Id header

  • tools (Array<Class>) (defaults to: []) —

    Array of Tool subclasses

  • context (Object) (defaults to: nil) —

    Context object passed to tool#initialize

  • system_prompt (String) (defaults to: nil) —

    System prompt

  • messages (Array<Helicone::Message>) (defaults to: []) —

    Initial messages (for continuing conversations)

  • model (String) (defaults to: nil) —

    Model to use (defaults to Helicone.configuration.default_model)

  • options (Hash) —

    Additional options passed through to chat calls (e.g., reasoning_effort)



20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/helicone/agent.rb', line 20

def initialize(client: nil, session: nil, user: nil, tools: [], context: nil, system_prompt: nil, messages: [], model: nil, **options)
  @client = client || build_client(session: session, user: user)
  @tools = tools
  @context = context
  @model = model
  @options = options
  @messages = messages.dup

  # Add system message at the start if provided and not already present
  if system_prompt && @messages.none? { |m| m.respond_to?(:role) && m.role == "system" }
    @messages.unshift(Message.system(system_prompt))
  end
end

Instance Attribute Details

#client ⇒ Object (readonly)

Returns the value of attribute client.



7
8
9
# File 'lib/helicone/agent.rb', line 7

def client
  @client
end

#context ⇒ Object (readonly)

Returns the value of attribute context.



7
8
9
# File 'lib/helicone/agent.rb', line 7

def context
  @context
end

#messages ⇒ Object (readonly)

Returns the value of attribute messages.



7
8
9
# File 'lib/helicone/agent.rb', line 7

def messages
  @messages
end

#model ⇒ Object (readonly)

Returns the value of attribute model.



7
8
9
# File 'lib/helicone/agent.rb', line 7

def model
  @model
end

#options ⇒ Object (readonly)

Returns the value of attribute options.



7
8
9
# File 'lib/helicone/agent.rb', line 7

def options
  @options
end

#tools ⇒ Object (readonly)

Returns the value of attribute tools.



7
8
9
# File 'lib/helicone/agent.rb', line 7

def tools
  @tools
end

Instance Method Details

#continue(prompt, max_iterations: MAX_ITERATIONS) ⇒ AgentResult

Continue the conversation with a new prompt

Parameters:

  • prompt (String) —

    User prompt to continue with

  • max_iterations (Integer) (defaults to: MAX_ITERATIONS) —

    Maximum tool execution loops

Returns:



90
91
92
# File 'lib/helicone/agent.rb', line 90

def continue(prompt, max_iterations: MAX_ITERATIONS)
  run(prompt, max_iterations: max_iterations)
end

#run(prompt = nil, max_iterations: MAX_ITERATIONS) ⇒ AgentResult

Run the agent with an optional prompt, executing tools until done

Parameters:

  • prompt (String, nil) (defaults to: nil) —

    User prompt to add (nil to use existing messages)

  • max_iterations (Integer) (defaults to: MAX_ITERATIONS) —

    Maximum tool execution loops

Returns:



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/helicone/agent.rb', line 39

def run(prompt = nil, max_iterations: MAX_ITERATIONS)
  @messages << Message.user_text(prompt) if prompt

  iterations = 0
  while iterations < max_iterations
    response = call_llm

    tool_calls = response.tool_calls
    if tool_calls && !tool_calls.empty?
      # Add assistant message with tool calls to conversation
      @messages << Message.assistant_with_tool_calls(response.message)

      # Execute each tool and add results
      response.tool_calls.each do |tc|
        tool_call = ToolCall.from_response([tc]).first
        result = execute_tool(tool_call)
        @messages << Message.tool_result(
          tool_call_id: tool_call.id,
          content: result
        )
      end

      iterations += 1
    else
      # No tool calls - we're done
      return AgentResult.new(
        content: response.content,
        messages: @messages,
        iterations: iterations,
        response: response
      )
    end
  end

  # Max iterations reached - make one final call without tools to get a response
  final_response = @client.chat(messages: @messages, model: @model)

  AgentResult.new(
    content: final_response.content,
    messages: @messages,
    iterations: iterations,
    response: final_response,
    max_iterations_reached: true
  )
end