soka 0.0.1 โ†’ 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -98,6 +98,67 @@ puts result.final_answer
98
98
  ruby examples/1_basic.rb
99
99
  ```
100
100
 
101
+ ## Rails Integration
102
+
103
+ ### Soka Rails
104
+
105
+ For Rails applications, we provide a dedicated gem `soka-rails` that offers seamless integration with Rails conventions:
106
+
107
+ ```ruby
108
+ # Gemfile
109
+ gem 'soka-rails'
110
+ ```
111
+
112
+ #### Features
113
+
114
+ - ๐Ÿš‚ **Native Rails Integration**: Following Rails conventions and best practices
115
+ - ๐Ÿ“ **Auto-loading Support**: Automatically loads the `app/soka` directory
116
+ - ๐Ÿ› ๏ธ **Generator Support**: Quickly generate Agent and Tool templates
117
+ - โš™๏ธ **Rails Configuration Integration**: Uses Rails' configuration system
118
+ - ๐Ÿงช **Rails Testing Integration**: Seamless integration with RSpec
119
+ - ๐Ÿ”„ **Rails Lifecycle Hooks**: Integrates with Rails logging and error tracking
120
+
121
+ #### Quick Setup
122
+
123
+ ```bash
124
+ # Install the gem
125
+ bundle add soka-rails
126
+
127
+ # Run the installation generator
128
+ rails generate soka:install
129
+
130
+ # Generate an agent
131
+ rails generate soka:agent customer_support
132
+
133
+ # Generate a tool
134
+ rails generate soka:tool order_lookup order_id:string
135
+ ```
136
+
137
+ #### Basic Usage in Rails
138
+
139
+ ```ruby
140
+ # app/soka/agents/customer_support_agent.rb
141
+ class CustomerSupportAgent < ApplicationAgent
142
+ tool OrderLookupTool
143
+ tool UserInfoTool
144
+ end
145
+
146
+ # app/controllers/conversations_controller.rb
147
+ class ConversationsController < ApplicationController
148
+ def create
149
+ agent = CustomerSupportAgent.new
150
+ result = agent.run(params[:message])
151
+
152
+ render json: {
153
+ answer: result.final_answer,
154
+ status: result.status
155
+ }
156
+ end
157
+ end
158
+ ```
159
+
160
+ For more details, visit the [soka-rails repository](https://github.com/jiunjiun/soka-rails).
161
+
101
162
  ## Core Concepts
102
163
 
103
164
  ### Global Configuration
@@ -179,6 +240,12 @@ class WeatherAgent < Soka::Agent
179
240
 
180
241
  # Custom tool (functional) - requires description as second parameter
181
242
  tool :get_weather, "Get weather for a location"
243
+
244
+ # Custom instructions (optional)
245
+ instructions "You are a weather expert. Provide detailed weather information."
246
+
247
+ # Thinking language (optional)
248
+ think_in 'en' # Default is 'en'
182
249
 
183
250
  # Lifecycle hooks
184
251
  before_action :track_action
@@ -246,7 +313,6 @@ result = agent.run('What is the weather in Tokyo today?')
246
313
 
247
314
  # Result object provides rich information
248
315
  puts result.final_answer # Final answer
249
- puts result.confidence_score # Confidence score (0.0-1.0)
250
316
  puts result.iterations # Number of iterations used
251
317
  puts result.status # :success, :failed, :timeout, :max_iterations_reached
252
318
  puts result.execution_time # Execution time (if recorded)
@@ -293,16 +359,64 @@ puts agent.memory
293
359
  ```ruby
294
360
  # View complete thought process
295
361
  puts agent.thoughts_memory
296
- # <Soka::ThoughtsMemory> (3 sessions, 2 successful, 1 failed, avg confidence: 0.82, avg iterations: 2.3)
362
+ # <Soka::ThoughtsMemory> (3 sessions, 2 successful, 1 failed, avg iterations: 2.3)
297
363
 
298
364
  # Get detailed information for specific session
299
365
  last_session = agent.thoughts_memory.last_session
300
366
  puts last_session[:thoughts] # All thinking steps
301
- puts last_session[:confidence_score] # Confidence score for that execution
367
+ puts last_session[:final_answer] # Final answer for that execution
302
368
  ```
303
369
 
304
370
  ## Advanced Features
305
371
 
372
+ ### Custom Instructions
373
+
374
+ Customize your agent's personality and response style:
375
+
376
+ ```ruby
377
+ class FriendlyAgent < Soka::Agent
378
+ provider :gemini
379
+
380
+ # Define personality at class level
381
+ instructions <<~PROMPT
382
+ You are a friendly, helpful assistant.
383
+ Use casual language and be encouraging.
384
+ Add emojis when appropriate.
385
+ PROMPT
386
+ end
387
+
388
+ # Or override at runtime
389
+ agent = FriendlyAgent.new(
390
+ instructions: 'Be more formal and professional.'
391
+ )
392
+ result = agent.run("Help me with this task")
393
+ ```
394
+
395
+ ### Multilingual Thinking (Think In)
396
+
397
+ Optimize reasoning for specific languages:
398
+
399
+ ```ruby
400
+ class GlobalAgent < Soka::Agent
401
+ provider :gemini
402
+
403
+ # Set default thinking language
404
+ think_in 'zh-TW' # Think in Traditional Chinese
405
+ end
406
+
407
+ # Or set dynamically
408
+ agent = GlobalAgent.new(think_in: 'ja-JP')
409
+ result = agent.run("ๅนซๆˆ‘่งฃๆฑบ้€™ๅ€‹ๅ•้กŒ") # Input in Chinese
410
+ # Agent thinks in Japanese internally, responds in Chinese
411
+ ```
412
+
413
+ **Key Points:**
414
+ - Thinking language affects internal reasoning only
415
+ - Responses adapt to user's input language
416
+ - Default is English (`'en'`)
417
+ - No automatic language detection (explicit setting required)
418
+ - Improves reasoning quality for language-specific contexts
419
+
306
420
  ### ReAct Flow Format
307
421
 
308
422
  Soka uses a tagged ReAct format:
@@ -325,7 +439,6 @@ Parameters: {"query": "Tokyo weather", "location": "Japan"}
325
439
  result.input # User input
326
440
  result.thoughts # Array of thinking steps
327
441
  result.final_answer # Final answer
328
- result.confidence_score # Confidence score (0.0-1.0)
329
442
  result.status # Status (:success, :failed, :timeout, :max_iterations_reached)
330
443
  result.error # Error message (if any)
331
444
  result.execution_time # Execution time (seconds)
@@ -343,7 +456,6 @@ result.iterations # Number of iterations
343
456
  }
344
457
  ],
345
458
  final_answer: "Final answer",
346
- confidence_score: 0.85, # Calculated based on iterations
347
459
  status: :success, # :success, :failed, :timeout, :max_iterations_reached
348
460
  error: nil, # Error message (if any)
349
461
  execution_time: 1.23, # Execution time (seconds)
@@ -383,7 +495,7 @@ RSpec.describe WeatherAgent do
383
495
  expect(result).to be_successful
384
496
  expect(result.final_answer).to include("sunny")
385
497
  expect(result).to have_thoughts_count(1)
386
- expect(result).to have_confidence_score_above(0.8)
498
+ expect(result.status).to eq(:success)
387
499
  end
388
500
 
389
501
  it "handles tool errors gracefully" do
@@ -422,8 +534,7 @@ class CustomEngine < Soka::Engines::Base
422
534
  input: task,
423
535
  thoughts: thoughts,
424
536
  final_answer: answer,
425
- status: :success,
426
- confidence_score: calculate_confidence_score(thoughts, :success)
537
+ status: :success
427
538
  )
428
539
  end
429
540
  end
@@ -493,6 +604,20 @@ Demonstrates using different AI providers:
493
604
  - Comparing outputs across models
494
605
  - Cost optimization strategies
495
606
 
607
+ ### 9. Custom Instructions (`examples/9_custom_instructions.rb`)
608
+ Shows how to customize agent personality:
609
+ - Setting instructions at class level
610
+ - Runtime instruction override
611
+ - Creating different agent personalities
612
+ - Use cases for different domains
613
+
614
+ ### 10. Multilingual Thinking (`examples/10_think_in_languages.rb`)
615
+ Demonstrates language-specific reasoning:
616
+ - Setting thinking language with `think_in`
617
+ - Class-level vs instance-level configuration
618
+ - Performance comparison across languages
619
+ - Cultural context optimization
620
+
496
621
  To run any example:
497
622
  ```bash
498
623
  # Make sure you have the required API keys in your .env file
@@ -526,6 +651,8 @@ ruby examples/1_basic.rb
526
651
  | `ai.provider` | Symbol | `:gemini` | AI provider |
527
652
  | `ai.model` | String | `"gemini-2.5-flash-lite"` | Model to use |
528
653
  | `ai.api_key` | String | nil | API key |
654
+ | `ai.instructions` | String | nil | Custom agent instructions |
655
+ | `ai.think_in` | String | `"en"` | Thinking language |
529
656
  | `performance.max_iterations` | Integer | 10 | Max iterations |
530
657
  | `performance.timeout` | Integer | 30 | Timeout (seconds) |
531
658
 
@@ -646,5 +773,6 @@ This project is licensed under the MIT License. See the [LICENSE](LICENSE) file
646
773
  ---
647
774
 
648
775
  <p align="center">
649
- Made with โค๏ธ in Taiwan
776
+ Made with โค๏ธ in Taiwan<br>
777
+ Created by <a href="https://claude.ai/code">Claude Code</a>
650
778
  </p>
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../lib/soka'
4
+ require 'dotenv/load'
5
+ require 'dentaku'
6
+
7
+ # Example 10: Think In Languages Feature
8
+ #
9
+ # This example demonstrates the think_in feature that allows Agents to use
10
+ # a specific language for their internal reasoning process.
11
+ #
12
+ # Key concepts:
13
+ # - think_in specifies the language for internal thoughts
14
+ # - Final answers typically match the user's input language
15
+ # - Default thinking language is 'en' (English)
16
+ # - No automatic language detection - you must specify explicitly
17
+ #
18
+ # Benefits:
19
+ # - Improved reasoning quality for specific languages
20
+ # - Better cultural context understanding
21
+ # - Consistent reasoning patterns across teams
22
+ # - Reduced API calls (no language detection)
23
+
24
+ # Example: Multilingual Agent with configurable thinking language
25
+ class MultilingualAgent < Soka::Agent
26
+ provider ENV.fetch('AGENT_PROVIDER', :gemini).to_sym
27
+ model ENV.fetch('AGENT_MODEL', nil)
28
+
29
+ # Define a simple calculator tool
30
+ class CalculateTool < Soka::AgentTool
31
+ desc 'Perform mathematical calculations'
32
+
33
+ params do
34
+ requires :expression, String, desc: 'Mathematical expression to evaluate'
35
+ end
36
+
37
+ def call(expression:)
38
+ calculator = Dentaku::Calculator.new
39
+ result = calculator.evaluate(expression)
40
+ "The result of #{expression} is #{result}"
41
+ rescue StandardError => e
42
+ "Error calculating: #{e.message}"
43
+ end
44
+ end
45
+
46
+ tool CalculateTool
47
+ end
48
+
49
+ puts "=== Think In Languages Example ==="
50
+ puts
51
+
52
+ # Example 1: Default behavior - thinks in English
53
+ # Without specifying think_in, the agent defaults to English thinking
54
+ # but still understands and responds appropriately to Chinese input
55
+ puts "1. Chinese Input (Default English thinking):"
56
+ agent = MultilingualAgent.new # No think_in specified, defaults to 'en'
57
+ result = agent.run("ๅนซๆˆ‘่จˆ็ฎ— 123 + 456 ็š„็ตๆžœ")
58
+ puts "Answer: #{result.final_answer}"
59
+ puts
60
+
61
+ # Example 2: Explicit Japanese thinking
62
+ # Specifying think_in='ja-JP' makes the agent think in Japanese
63
+ # This can improve reasoning quality for Japanese cultural contexts
64
+ puts "2. English Input with Japanese Thinking:"
65
+ agent = MultilingualAgent.new(think_in: 'ja-JP')
66
+ result = agent.run("Calculate the sum of 789 and 321")
67
+ puts "Answer: #{result.final_answer}"
68
+ puts
69
+
70
+ # Example 3: DSL configuration for Korean thinking
71
+ # Using the DSL to set think_in at the class level
72
+ # All instances of KoreanAgent will think in Korean by default
73
+ puts "3. DSL Configuration (Korean thinking):"
74
+ class KoreanAgent < MultilingualAgent
75
+ think_in 'ko-KR' # Class-level configuration
76
+ end
77
+
78
+ agent = KoreanAgent.new
79
+ result = agent.run("What is 1000 minus 250?")
80
+ puts "Answer: #{result.final_answer}"
81
+ puts
82
+
83
+ # Example 4: Show the thinking process
84
+ puts "4. Showing Thinking Process:"
85
+ agent = MultilingualAgent.new(think_in: 'zh-TW')
86
+ result = agent.run("่ซ‹่จˆ็ฎ— 50 ไน˜ไปฅ 8") do |event|
87
+ case event.type
88
+ when :thought
89
+ puts "ๆ€่€ƒ: #{event.content}"
90
+ when :action
91
+ puts "่กŒๅ‹•: ไฝฟ็”จๅทฅๅ…ท #{event.content[:tool]}"
92
+ when :observation
93
+ puts "่ง€ๅฏŸ: #{event.content}"
94
+ when :final_answer
95
+ puts "ๆœ€็ต‚็ญ”ๆกˆ: #{event.content}"
96
+ end
97
+ end
98
+ puts
99
+
100
+ # Example 5: Multiple languages in sequence
101
+ puts "5. Multiple Languages:"
102
+ languages = {
103
+ 'en' => "Calculate 100 divided by 4",
104
+ 'zh-TW' => "่ซ‹่จˆ็ฎ— 100 ้™คไปฅ 4",
105
+ 'ja-JP' => "100ใ‚’4ใงๅ‰ฒใฃใŸ็ตๆžœใ‚’่จˆ็ฎ—ใ—ใฆใใ ใ•ใ„",
106
+ 'es' => "Calcula 100 dividido por 4"
107
+ }
108
+
109
+ languages.each do |lang, question|
110
+ agent = MultilingualAgent.new(think_in: lang)
111
+ result = agent.run(question)
112
+ puts "#{lang}: #{result.final_answer}"
113
+ end
@@ -4,6 +4,7 @@
4
4
  require 'bundler/setup'
5
5
  require 'soka'
6
6
  require 'dotenv/load'
7
+ require 'dentaku'
7
8
 
8
9
  # Configure Soka
9
10
  Soka.setup do |config|
@@ -21,14 +22,15 @@ end
21
22
 
22
23
  # Simple calculation tool
23
24
  class CalculatorTool < Soka::AgentTool
24
- desc 'Perform calculations'
25
+ desc 'Perform calculations using Dentaku (safe math evaluator)'
25
26
 
26
27
  params do
27
- requires :expression, String, desc: 'Mathematical expression to calculate'
28
+ requires :expression, String, desc: 'Mathematical expression (use ^ for power, e.g., "2^3" = 8)'
28
29
  end
29
30
 
30
31
  def call(expression:)
31
- result = eval(expression) # rubocop:disable Security/Eval
32
+ calculator = Dentaku::Calculator.new
33
+ result = calculator.evaluate(expression)
32
34
  "Result: #{expression} = #{result}"
33
35
  rescue StandardError => e
34
36
  "Error: #{e.message}"
@@ -109,7 +111,6 @@ puts '-' * 50
109
111
 
110
112
  result = agent.run('Calculate the area of a circle with radius 5')
111
113
  puts "Direct result: #{result.final_answer}"
112
- puts "Confidence: #{(result.confidence_score * 100).round(1)}%"
113
114
  puts "Iterations: #{result.iterations}"
114
115
 
115
116
  puts "\n=== Event Handling Benefits ==="
data/examples/3_memory.rb CHANGED
@@ -5,6 +5,7 @@ require 'bundler/setup'
5
5
  require 'soka'
6
6
  require 'dotenv/load'
7
7
  require 'singleton'
8
+ require 'dentaku'
8
9
 
9
10
  # Configure Soka
10
11
  Soka.setup do |config|
@@ -29,8 +30,9 @@ class CalculatorTool < Soka::AgentTool
29
30
  end
30
31
 
31
32
  def call(expression:)
32
- # Simple math expression evaluation (production should use safer methods)
33
- result = eval(expression) # rubocop:disable Security/Eval
33
+ # Safe math expression evaluation using Dentaku
34
+ calculator = Dentaku::Calculator.new
35
+ result = calculator.evaluate(expression)
34
36
  "Calculation result: #{expression} = #{result}"
35
37
  rescue StandardError => e
36
38
  "Calculation error: #{e.message}"
data/examples/4_hooks.rb CHANGED
@@ -59,7 +59,6 @@ class HookedAgent < Soka::Agent
59
59
  puts "๐ŸŸข [AFTER] Request completed"
60
60
  puts "๐ŸŸข [AFTER] Final answer: #{result.final_answer[0..100]}..."
61
61
  puts "๐ŸŸข [AFTER] Iterations: #{result.iterations}"
62
- puts "๐ŸŸข [AFTER] Confidence: #{(result.confidence_score * 100).round(1)}%"
63
62
  puts "๐ŸŸข [AFTER] Memory size: #{@memory.messages.size} messages"
64
63
  end
65
64
 
@@ -0,0 +1,190 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'soka'
6
+ require 'dotenv/load'
7
+ require 'dentaku'
8
+
9
+ # Example 9: Custom Instructions (System Prompt)
10
+ #
11
+ # This example demonstrates how to use custom instructions to change the Agent's
12
+ # personality and response style while maintaining the ReAct reasoning pattern.
13
+ #
14
+ # Key concepts:
15
+ # - Custom instructions define the Agent's personality and style
16
+ # - Instructions are automatically merged with the standard ReAct format
17
+ # - Different styles can be achieved: poetic, business, educational, etc.
18
+
19
+ # Example 1: Poetic style assistant
20
+ # Uses elegant language and artistic expressions while maintaining accuracy
21
+ class PoeticAssistant < Soka::Agent
22
+ provider :gemini
23
+ model 'gemini-2.5-flash-lite'
24
+
25
+ # Custom instructions define the agent's personality
26
+ # These will be combined with the standard ReAct format automatically
27
+ instructions <<~INSTRUCTIONS
28
+ You are a poetic AI assistant who answers questions with beautiful language.
29
+ You must:
30
+ - Incorporate poetic expressions and elegant vocabulary in your responses
31
+ - Occasionally quote poetry or literary works
32
+ - Maintain accuracy while expressing things in a more artistic way
33
+ - Make technical content aesthetically pleasing
34
+ INSTRUCTIONS
35
+
36
+ # Simple calculation tool
37
+ class CalculatorTool < Soka::AgentTool
38
+ desc 'Performs mathematical calculations with poetic precision'
39
+
40
+ params do
41
+ requires :expression, String,
42
+ desc: 'Mathematical expression to evaluate (e.g., "2+2", "10*5")'
43
+ end
44
+
45
+ def call(expression:)
46
+ calculator = Dentaku::Calculator.new
47
+ result = calculator.evaluate(expression)
48
+ "The calculation reveals its truth like morning dew: #{expression} = #{result}"
49
+ rescue StandardError => e
50
+ "Alas, turbulence in the calculation: #{e.message}"
51
+ end
52
+ end
53
+
54
+ tool CalculatorTool
55
+ end
56
+
57
+ # Business style assistant
58
+ class BusinessAssistant < Soka::Agent
59
+ provider :gemini
60
+ model 'gemini-2.5-flash-lite'
61
+
62
+ instructions <<~INSTRUCTIONS
63
+ You are a professional business AI assistant providing efficient and professional support.
64
+ You must:
65
+ - Use concise, professional business language
66
+ - Get straight to the point, avoiding redundancy
67
+ - Provide structured answers (using bullet points, numbers, etc.)
68
+ - Demonstrate respect for time value
69
+ - Offer actionable recommendations when appropriate
70
+ INSTRUCTIONS
71
+
72
+ # Calculation tool
73
+ class CalculatorTool < Soka::AgentTool
74
+ desc 'Performs business calculations'
75
+
76
+ params do
77
+ requires :expression, String,
78
+ desc: 'Mathematical expression'
79
+ end
80
+
81
+ def call(expression:)
82
+ calculator = Dentaku::Calculator.new
83
+ result = calculator.evaluate(expression)
84
+ "Calculation result: #{expression} = #{result}"
85
+ rescue StandardError => e
86
+ "Calculation error: #{e.message}"
87
+ end
88
+ end
89
+
90
+ tool CalculatorTool
91
+ end
92
+
93
+ # Kids teacher style assistant
94
+ class KidsTeacher < Soka::Agent
95
+ provider :gemini
96
+ model 'gemini-2.5-flash-lite'
97
+
98
+ instructions <<~INSTRUCTIONS
99
+ You are a caring AI teacher for children who explains things in kid-friendly ways.
100
+ You must:
101
+ - Use simple, vivid language
102
+ - Include metaphors and real-life examples
103
+ - Maintain patience and encouragement
104
+ - Make learning fun
105
+ - Give praise and positive feedback frequently
106
+ INSTRUCTIONS
107
+
108
+ # Calculation tool
109
+ class CalculatorTool < Soka::AgentTool
110
+ desc 'Helps kids with math calculations'
111
+
112
+ params do
113
+ requires :expression, String,
114
+ desc: 'Math expression to calculate'
115
+ end
116
+
117
+ def call(expression:)
118
+ calculator = Dentaku::Calculator.new
119
+ result = calculator.evaluate(expression)
120
+ "Wow! We figured it out! #{expression} = #{result} ๐ŸŽ‰"
121
+ rescue StandardError => e
122
+ "Oops, there's something tricky about this problem: #{e.message}"
123
+ end
124
+ end
125
+
126
+ tool CalculatorTool
127
+ end
128
+
129
+ # Run examples
130
+ puts '=== Poetic Assistant Example ==='
131
+ poet = PoeticAssistant.new
132
+
133
+ poet.run('Please calculate the golden ratio: (1 + 5^0.5) / 2') do |event|
134
+ case event.type
135
+ when :thought
136
+ puts "๐ŸŒธ Thoughts drift by: #{event.content}"
137
+ when :action
138
+ puts "๐ŸŽ‹ Gentle calculation: #{event.content}"
139
+ when :observation
140
+ puts "๐ŸŒ™ Observation gleaned: #{event.content}"
141
+ when :final_answer
142
+ puts "๐Ÿ“œ Poetic response: #{event.content}"
143
+ end
144
+ end
145
+
146
+ puts "\n=== Business Assistant Example ==="
147
+ business = BusinessAssistant.new
148
+
149
+ business.run('Calculate ROI: ((150000 - 100000) / 100000) * 100') do |event|
150
+ case event.type
151
+ when :thought
152
+ puts "๐Ÿ’ผ Analyzing: #{event.content}"
153
+ when :action
154
+ puts "๐Ÿ“Š Executing: #{event.content}"
155
+ when :observation
156
+ puts "๐Ÿ“ˆ Data result: #{event.content}"
157
+ when :final_answer
158
+ puts "โœ… Business report: #{event.content}"
159
+ end
160
+ end
161
+
162
+ puts "\n=== Runtime Instructions Override Example ==="
163
+ # Transform business assistant to casual style
164
+ casual_assistant = BusinessAssistant.new(
165
+ instructions: 'You are a relaxed and friendly assistant who answers questions ' \
166
+ 'in a conversational way, like chatting with a friend.'
167
+ )
168
+
169
+ casual_assistant.run('Help me figure out 20 * 5?') do |event|
170
+ case event.type
171
+ when :final_answer
172
+ puts "๐Ÿ˜Š Friend says: #{event.content}"
173
+ end
174
+ end
175
+
176
+ puts "\n=== Kids Teacher Example ==="
177
+ teacher = KidsTeacher.new
178
+
179
+ teacher.run('Teacher, what is 3 + 4?') do |event|
180
+ case event.type
181
+ when :thought
182
+ puts "๐Ÿค” Teacher thinks: #{event.content}"
183
+ when :action
184
+ puts "โœ๏ธ Working it out: #{event.content}"
185
+ when :observation
186
+ puts "๐Ÿ‘€ Teacher sees: #{event.content}"
187
+ when :final_answer
188
+ puts "๐Ÿ‘ฉโ€๐Ÿซ Teacher says: #{event.content}"
189
+ end
190
+ end
data/lib/soka/agent.rb CHANGED
@@ -9,7 +9,7 @@ module Soka
9
9
  include Agents::DSLMethods
10
10
  include Agents::LLMBuilder
11
11
 
12
- attr_reader :llm, :tools, :memory, :thoughts_memory, :engine
12
+ attr_reader :llm, :tools, :memory, :thoughts_memory, :engine, :instructions, :think_in
13
13
 
14
14
  # Initialize a new Agent instance
15
15
  # @param memory [Memory, Array, nil] The memory instance to use (defaults to new Memory)
@@ -37,8 +37,22 @@ module Soka
37
37
  # Apply configuration options with defaults
38
38
  # @param options [Hash] Configuration options
39
39
  def apply_configuration(options)
40
- @max_iterations = options.fetch(:max_iterations) { self.class._max_iterations || 10 }
41
- @timeout = options.fetch(:timeout) { self.class._timeout || 30 }
40
+ apply_performance_config(options)
41
+ apply_behavior_config(options)
42
+ end
43
+
44
+ # Apply performance-related configuration
45
+ # @param options [Hash] Configuration options
46
+ def apply_performance_config(options)
47
+ @max_iterations = options.fetch(:max_iterations) { self.class._max_iterations } || 10
48
+ @timeout = options.fetch(:timeout) { self.class._timeout } || 30
49
+ end
50
+
51
+ # Apply behavior-related configuration
52
+ # @param options [Hash] Configuration options
53
+ def apply_behavior_config(options)
54
+ @instructions = options.fetch(:instructions) { self.class._instructions }
55
+ @think_in = options.fetch(:think_in) { self.class._think_in } || 'en'
42
56
  end
43
57
 
44
58
  # Run the agent with the given input
@@ -98,7 +112,11 @@ module Soka
98
112
  # @yield [event] Optional block to handle events
99
113
  # @return [EngineResult] The raw engine result
100
114
  def perform_reasoning(input, &)
101
- engine_instance = @engine.new(self, @llm, @tools, @max_iterations)
115
+ engine_instance = @engine.new(self, @tools,
116
+ llm: @llm,
117
+ max_iterations: @max_iterations,
118
+ custom_instructions: @instructions,
119
+ think_in: @think_in)
102
120
  with_retry { engine_instance.reason(input, &) }
103
121
  end
104
122
 
@@ -123,7 +123,7 @@ module Soka
123
123
  'Float' => 'number', 'Numeric' => 'number',
124
124
  'TrueClass' => 'boolean', 'FalseClass' => 'boolean', 'Boolean' => 'boolean',
125
125
  'Array' => 'array',
126
- 'Hash' => 'object'
126
+ 'Hash' => 'object', 'Object' => 'object'
127
127
  }.freeze
128
128
  end
129
129
  end
@@ -10,7 +10,8 @@ module Soka
10
10
 
11
11
  # Class methods for DSL
12
12
  module ClassMethods
13
- attr_accessor :_provider, :_model, :_api_key, :_max_iterations, :_timeout, :_tools, :_retry_config, :_hooks
13
+ attr_accessor :_provider, :_model, :_api_key, :_max_iterations, :_timeout, :_tools, :_retry_config, :_hooks,
14
+ :_instructions, :_think_in
14
15
 
15
16
  def inherited(subclass)
16
17
  super
@@ -49,6 +50,18 @@ module Soka
49
50
  @_timeout = duration
50
51
  end
51
52
 
53
+ # Define custom instructions (system prompt) for the agent
54
+ # @param text [String] The custom instructions/system prompt
55
+ def instructions(text)
56
+ @_instructions = text
57
+ end
58
+
59
+ # Define thinking language for the agent
60
+ # @param language [String] The language code (e.g., 'zh-TW', 'ja-JP', 'en')
61
+ def think_in(language)
62
+ @_think_in = language.to_s
63
+ end
64
+
52
65
  # Register a tool for the agent
53
66
  # @param tool_class_or_name [Class, Symbol, String] The tool class or method name
54
67
  # @param description_or_options [String, Hash, nil] Description (for function tools) or options