riffer 0.18.0 → 0.20.0
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.
- checksums.yaml +4 -4
- data/.agents/architecture.md +23 -0
- data/.agents/rdoc.md +16 -4
- data/.release-please-manifest.json +1 -1
- data/.ruby-version +1 -1
- data/CHANGELOG.md +21 -0
- data/README.md +1 -1
- data/Rakefile +1 -2
- data/docs/01_OVERVIEW.md +2 -2
- data/docs/02_GETTING_STARTED.md +2 -2
- data/docs/03_AGENTS.md +20 -19
- data/docs/04_TOOLS.md +35 -5
- data/docs/06_STREAM_EVENTS.md +1 -1
- data/docs/07_CONFIGURATION.md +8 -8
- data/docs/08_EVALS.md +4 -3
- data/docs/10_SKILLS.md +1 -1
- data/docs_providers/01_PROVIDERS.md +19 -13
- data/docs_providers/02_AMAZON_BEDROCK.md +7 -7
- data/docs_providers/03_ANTHROPIC.md +7 -7
- data/docs_providers/04_OPENAI.md +7 -9
- data/docs_providers/05_AZURE_OPENAI.md +165 -0
- data/lib/riffer/agent/response.rb +18 -9
- data/lib/riffer/agent.rb +60 -7
- data/lib/riffer/config.rb +8 -1
- data/lib/riffer/core.rb +2 -0
- data/lib/riffer/evals/evaluator.rb +13 -5
- data/lib/riffer/evals/evaluator_runner.rb +12 -6
- data/lib/riffer/evals/judge.rb +13 -4
- data/lib/riffer/evals/result.rb +3 -0
- data/lib/riffer/evals/run_result.rb +3 -0
- data/lib/riffer/evals/scenario_result.rb +11 -3
- data/lib/riffer/file_part.rb +7 -0
- data/lib/riffer/guardrail.rb +14 -9
- data/lib/riffer/guardrails/modification.rb +5 -3
- data/lib/riffer/guardrails/result.rb +15 -7
- data/lib/riffer/guardrails/runner.rb +10 -5
- data/lib/riffer/guardrails/tripwire.rb +6 -4
- data/lib/riffer/helpers/class_name_converter.rb +1 -0
- data/lib/riffer/helpers/dependencies.rb +1 -0
- data/lib/riffer/helpers/validations.rb +1 -0
- data/lib/riffer/messages/assistant.rb +4 -0
- data/lib/riffer/messages/base.rb +3 -0
- data/lib/riffer/messages/converter.rb +5 -2
- data/lib/riffer/messages/system.rb +1 -0
- data/lib/riffer/messages/tool.rb +4 -0
- data/lib/riffer/messages/user.rb +3 -0
- data/lib/riffer/param.rb +7 -3
- data/lib/riffer/params.rb +10 -0
- data/lib/riffer/providers/amazon_bedrock.rb +19 -0
- data/lib/riffer/providers/anthropic.rb +23 -0
- data/lib/riffer/providers/azure_open_ai.rb +41 -0
- data/lib/riffer/providers/base.rb +20 -6
- data/lib/riffer/providers/mock.rb +10 -0
- data/lib/riffer/providers/open_ai.rb +21 -0
- data/lib/riffer/providers/repository.rb +2 -0
- data/lib/riffer/providers.rb +1 -0
- data/lib/riffer/runner/fibers.rb +62 -0
- data/lib/riffer/runner/sequential.rb +3 -2
- data/lib/riffer/runner/threaded.rb +5 -3
- data/lib/riffer/runner.rb +6 -4
- data/lib/riffer/skills/activate_tool.rb +3 -2
- data/lib/riffer/skills/adapter.rb +3 -1
- data/lib/riffer/skills/backend.rb +3 -1
- data/lib/riffer/skills/config.rb +4 -0
- data/lib/riffer/skills/context.rb +8 -3
- data/lib/riffer/skills/filesystem_backend.rb +6 -2
- data/lib/riffer/skills/frontmatter.rb +9 -3
- data/lib/riffer/skills/markdown_adapter.rb +2 -1
- data/lib/riffer/skills/xml_adapter.rb +2 -1
- data/lib/riffer/stream_events/base.rb +2 -0
- data/lib/riffer/stream_events/guardrail_modification.rb +7 -2
- data/lib/riffer/stream_events/guardrail_tripwire.rb +7 -2
- data/lib/riffer/stream_events/interrupt.rb +2 -0
- data/lib/riffer/stream_events/reasoning_delta.rb +2 -0
- data/lib/riffer/stream_events/reasoning_done.rb +2 -0
- data/lib/riffer/stream_events/skill_activation.rb +2 -0
- data/lib/riffer/stream_events/text_delta.rb +2 -0
- data/lib/riffer/stream_events/text_done.rb +2 -0
- data/lib/riffer/stream_events/token_usage_done.rb +2 -0
- data/lib/riffer/stream_events/tool_call_delta.rb +2 -0
- data/lib/riffer/stream_events/tool_call_done.rb +2 -0
- data/lib/riffer/stream_events/web_search_done.rb +2 -0
- data/lib/riffer/stream_events/web_search_status.rb +2 -0
- data/lib/riffer/structured_output/result.rb +3 -0
- data/lib/riffer/structured_output.rb +3 -0
- data/lib/riffer/token_usage.rb +5 -0
- data/lib/riffer/tool.rb +11 -0
- data/lib/riffer/tool_runtime/fibers.rb +19 -0
- data/lib/riffer/tool_runtime/inline.rb +1 -0
- data/lib/riffer/tool_runtime/threaded.rb +2 -1
- data/lib/riffer/tool_runtime.rb +14 -9
- data/lib/riffer/tools/response.rb +8 -0
- data/lib/riffer/version.rb +1 -1
- data/lib/riffer.rb +5 -1
- data/sig/generated/riffer/agent/response.rbs +17 -9
- data/sig/generated/riffer/agent.rbs +59 -6
- data/sig/generated/riffer/config.rbs +15 -1
- data/sig/generated/riffer/core.rbs +2 -0
- data/sig/generated/riffer/evals/evaluator.rbs +13 -5
- data/sig/generated/riffer/evals/evaluator_runner.rbs +8 -4
- data/sig/generated/riffer/evals/judge.rbs +13 -4
- data/sig/generated/riffer/evals/result.rbs +3 -0
- data/sig/generated/riffer/evals/run_result.rbs +3 -0
- data/sig/generated/riffer/evals/scenario_result.rbs +8 -2
- data/sig/generated/riffer/file_part.rbs +7 -0
- data/sig/generated/riffer/guardrail.rbs +14 -9
- data/sig/generated/riffer/guardrails/modification.rbs +5 -3
- data/sig/generated/riffer/guardrails/result.rbs +15 -7
- data/sig/generated/riffer/guardrails/runner.rbs +10 -5
- data/sig/generated/riffer/guardrails/tripwire.rbs +6 -4
- data/sig/generated/riffer/helpers/class_name_converter.rbs +1 -0
- data/sig/generated/riffer/helpers/dependencies.rbs +1 -0
- data/sig/generated/riffer/helpers/validations.rbs +1 -0
- data/sig/generated/riffer/messages/assistant.rbs +4 -0
- data/sig/generated/riffer/messages/base.rbs +3 -0
- data/sig/generated/riffer/messages/converter.rbs +5 -2
- data/sig/generated/riffer/messages/system.rbs +1 -0
- data/sig/generated/riffer/messages/tool.rbs +4 -0
- data/sig/generated/riffer/messages/user.rbs +3 -0
- data/sig/generated/riffer/param.rbs +7 -3
- data/sig/generated/riffer/params.rbs +10 -0
- data/sig/generated/riffer/providers/amazon_bedrock.rbs +19 -0
- data/sig/generated/riffer/providers/anthropic.rbs +23 -0
- data/sig/generated/riffer/providers/azure_open_ai.rbs +25 -0
- data/sig/generated/riffer/providers/base.rbs +20 -6
- data/sig/generated/riffer/providers/mock.rbs +10 -0
- data/sig/generated/riffer/providers/open_ai.rbs +21 -0
- data/sig/generated/riffer/providers/repository.rbs +1 -0
- data/sig/generated/riffer/providers.rbs +1 -0
- data/sig/generated/riffer/runner/fibers.rbs +27 -0
- data/sig/generated/riffer/runner/sequential.rbs +3 -2
- data/sig/generated/riffer/runner/threaded.rbs +5 -3
- data/sig/generated/riffer/runner.rbs +6 -4
- data/sig/generated/riffer/skills/activate_tool.rbs +3 -2
- data/sig/generated/riffer/skills/adapter.rbs +3 -1
- data/sig/generated/riffer/skills/backend.rbs +3 -1
- data/sig/generated/riffer/skills/config.rbs +4 -0
- data/sig/generated/riffer/skills/context.rbs +8 -3
- data/sig/generated/riffer/skills/filesystem_backend.rbs +6 -2
- data/sig/generated/riffer/skills/frontmatter.rbs +9 -3
- data/sig/generated/riffer/skills/markdown_adapter.rbs +2 -1
- data/sig/generated/riffer/skills/xml_adapter.rbs +2 -1
- data/sig/generated/riffer/stream_events/base.rbs +2 -0
- data/sig/generated/riffer/stream_events/guardrail_modification.rbs +7 -2
- data/sig/generated/riffer/stream_events/guardrail_tripwire.rbs +7 -2
- data/sig/generated/riffer/stream_events/interrupt.rbs +2 -0
- data/sig/generated/riffer/stream_events/reasoning_delta.rbs +2 -0
- data/sig/generated/riffer/stream_events/reasoning_done.rbs +2 -0
- data/sig/generated/riffer/stream_events/skill_activation.rbs +2 -0
- data/sig/generated/riffer/stream_events/text_delta.rbs +2 -0
- data/sig/generated/riffer/stream_events/text_done.rbs +2 -0
- data/sig/generated/riffer/stream_events/token_usage_done.rbs +2 -0
- data/sig/generated/riffer/stream_events/tool_call_delta.rbs +2 -0
- data/sig/generated/riffer/stream_events/tool_call_done.rbs +2 -0
- data/sig/generated/riffer/stream_events/web_search_done.rbs +2 -0
- data/sig/generated/riffer/stream_events/web_search_status.rbs +2 -0
- data/sig/generated/riffer/structured_output/result.rbs +3 -0
- data/sig/generated/riffer/structured_output.rbs +3 -0
- data/sig/generated/riffer/token_usage.rbs +5 -0
- data/sig/generated/riffer/tool.rbs +11 -0
- data/sig/generated/riffer/tool_runtime/fibers.rbs +15 -0
- data/sig/generated/riffer/tool_runtime/inline.rbs +1 -0
- data/sig/generated/riffer/tool_runtime/threaded.rbs +2 -1
- data/sig/generated/riffer/tool_runtime.rbs +13 -8
- data/sig/generated/riffer/tools/response.rbs +8 -0
- data/sig/generated/riffer.rbs +3 -0
- metadata +48 -7
- /data/docs_providers/{05_MOCK_PROVIDER.md → 06_MOCK_PROVIDER.md} +0 -0
- /data/docs_providers/{06_CUSTOM_PROVIDERS.md → 07_CUSTOM_PROVIDERS.md} +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '09506e8a2dfa346e49231fa598f1e899066a5597ddd5b6738758ca49594ca7c2'
|
|
4
|
+
data.tar.gz: 684dc3caf2f6a59d052adb51a5c33bdf0a5542a2a375f188a1bc0a600a7df5ef
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2b1c4119f8afac1367aac6a7d9caddd656a598dab1ad44c921802864e73815d19c3a4f96e554483d9062c9e87864bd870e8af260b9d7f5922331bdcc714ccb52
|
|
7
|
+
data.tar.gz: 5f8387e02a6b2638550e59265980c8de6ce9422b77f905dcc019360e039d59ffb5b8d76310ba90819f7f7b51a5af34588b0de40782255c57215d4bf32ca862c8
|
data/.agents/architecture.md
CHANGED
|
@@ -107,6 +107,29 @@ MyAgent.new.stream(persisted_messages) # cross-process resume
|
|
|
107
107
|
|
|
108
108
|
On resume, `execute_pending_tool_calls` detects tool calls from the last assistant message that lack corresponding tool result messages and executes them before entering the LLM loop. This handles the case where an interrupt fired mid-way through tool execution.
|
|
109
109
|
|
|
110
|
+
### Runner (`lib/riffer/runner.rb`)
|
|
111
|
+
|
|
112
|
+
Concurrency primitive for batch execution. Subclasses implement `#map(items, context: nil, &block)` to control how items are processed. The `context` keyword carries the agent's context hash, enabling runners that need it for job serialization or routing.
|
|
113
|
+
|
|
114
|
+
Built-in runners:
|
|
115
|
+
- `Sequential` — processes items in the current thread via `Array#map`
|
|
116
|
+
- `Threaded` — processes items concurrently using a thread pool with configurable `max_concurrency`
|
|
117
|
+
|
|
118
|
+
```ruby
|
|
119
|
+
runner = Riffer::Runner::Threaded.new(max_concurrency: 3)
|
|
120
|
+
runner.map(items, context: ctx) { |item| process(item) }
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### ToolRuntime (`lib/riffer/tool_runtime.rb`)
|
|
124
|
+
|
|
125
|
+
Composes with a Runner to execute tool calls. Provides `#execute` as the public entry point and `#around_tool_call` as a hook for instrumentation. Passes the agent context through to the runner.
|
|
126
|
+
|
|
127
|
+
Built-in runtimes:
|
|
128
|
+
- `Inline` — uses `Runner::Sequential` (default)
|
|
129
|
+
- `Threaded` — uses `Runner::Threaded`
|
|
130
|
+
|
|
131
|
+
Context flow: `Agent#execute_tool_calls` → `ToolRuntime#execute(tool_calls, tools:, context:)` → `Runner#map(tool_calls, context:) { dispatch }` → `Tool#call(context:, **args)`
|
|
132
|
+
|
|
110
133
|
## Key Patterns
|
|
111
134
|
|
|
112
135
|
- Model config accepts a `provider/model` string (e.g., `openai/gpt-4`) or a Proc/lambda that returns one
|
data/.agents/rdoc.md
CHANGED
|
@@ -4,18 +4,30 @@ Use RDoc prose comments for public API descriptions and RBS inline annotations f
|
|
|
4
4
|
|
|
5
5
|
## Parameters and Return Types
|
|
6
6
|
|
|
7
|
-
Describe parameters
|
|
7
|
+
Describe parameters using RDoc labeled list syntax. Use a single `#:` line for the RBS method signature (see [rbs-inline.md](rbs-inline.md) for the full type annotation syntax):
|
|
8
8
|
|
|
9
9
|
```ruby
|
|
10
10
|
# Creates a new agent.
|
|
11
11
|
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
12
|
+
# [name] the agent name.
|
|
13
|
+
# [options] optional configuration.
|
|
14
14
|
#
|
|
15
|
+
#--
|
|
15
16
|
#: (String, ?options: Hash[Symbol, untyped]) -> void
|
|
16
17
|
def initialize(name, options: {})
|
|
17
18
|
```
|
|
18
19
|
|
|
20
|
+
Always add `#--` (RDoc stop directive) on the line before a standalone `#:` type annotation. Without it, RDoc treats `#:` as a label-list marker and corrupts the preceding comment into a `<pre>` block. Inline `#:` on the same line as code (e.g., `attr_reader :name #: String`) does not need this.
|
|
21
|
+
|
|
22
|
+
## Inline Code
|
|
23
|
+
|
|
24
|
+
Use `+word+` for single-word inline code. For multi-word expressions (containing spaces, colons, or brackets), use `<tt>multi word expression</tt>`:
|
|
25
|
+
|
|
26
|
+
```ruby
|
|
27
|
+
# Returns +nil+ when no instructions are configured.
|
|
28
|
+
# Equivalent to <tt>throw :riffer_interrupt, reason</tt>.
|
|
29
|
+
```
|
|
30
|
+
|
|
19
31
|
## Attributes and Constants
|
|
20
32
|
|
|
21
33
|
Use `#:` inline syntax (on the same line) for attribute and constant types:
|
|
@@ -37,7 +49,7 @@ Document with prose:
|
|
|
37
49
|
|
|
38
50
|
## Examples
|
|
39
51
|
|
|
40
|
-
Include usage examples as indented code blocks:
|
|
52
|
+
Include usage examples as indented code blocks (2 extra spaces of indent):
|
|
41
53
|
|
|
42
54
|
```ruby
|
|
43
55
|
# Creates a new agent.
|
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.4.8
|
|
1
|
+
3.4.8
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,27 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.20.0](https://github.com/janeapp/riffer/compare/riffer/v0.19.0...riffer/v0.20.0) (2026-03-26)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* add fibers tool runtime using async gem ([#178](https://github.com/janeapp/riffer/issues/178)) ([67fd344](https://github.com/janeapp/riffer/commit/67fd34493126559b99a00cc3402a6adabefc14ea))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Bug Fixes
|
|
17
|
+
|
|
18
|
+
* correct RDoc formatting for docs.riffer.ai ([#182](https://github.com/janeapp/riffer/issues/182)) ([2f2fbc9](https://github.com/janeapp/riffer/commit/2f2fbc997281ef4a546a58e44233e325a25c41d5))
|
|
19
|
+
|
|
20
|
+
## [0.19.0](https://github.com/janeapp/riffer/compare/riffer/v0.18.0...riffer/v0.19.0) (2026-03-25)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
### Features
|
|
24
|
+
|
|
25
|
+
* Add Azure OpenAI provider ([#167](https://github.com/janeapp/riffer/issues/167)) ([5d34fcd](https://github.com/janeapp/riffer/commit/5d34fcd4a98a6bcfa768c50fea7c25959eca5f1d))
|
|
26
|
+
* expose message history in eval results ([#171](https://github.com/janeapp/riffer/issues/171)) ([c8b1aec](https://github.com/janeapp/riffer/commit/c8b1aeceb40a173c70d4be445fb82bba10113b87))
|
|
27
|
+
* provide agent context to runners ([#181](https://github.com/janeapp/riffer/issues/181)) ([23c9282](https://github.com/janeapp/riffer/commit/23c9282d4f2076d1ff6185f99bcf855f158ccb0d))
|
|
28
|
+
|
|
8
29
|
## [0.18.0](https://github.com/janeapp/riffer/compare/riffer/v0.17.0...riffer/v0.18.0) (2026-03-13)
|
|
9
30
|
|
|
10
31
|
|
data/README.md
CHANGED
data/Rakefile
CHANGED
|
@@ -17,8 +17,7 @@ RDoc::Task.new do |rdoc|
|
|
|
17
17
|
rdoc.rdoc_files.include("README.md", "CHANGELOG.md", "LICENSE.txt", "docs/**/*.md", "docs_providers/**/*.md")
|
|
18
18
|
rdoc.rdoc_files.include("lib/**/*.rb")
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
rdoc.options << "--charset" << "utf-8" << "--markup" << "markdown"
|
|
20
|
+
rdoc.options << "--charset" << "utf-8"
|
|
22
21
|
end
|
|
23
22
|
|
|
24
23
|
task docs: :rdoc
|
data/docs/01_OVERVIEW.md
CHANGED
|
@@ -10,7 +10,7 @@ The Agent is the central orchestrator for AI interactions. It manages messages,
|
|
|
10
10
|
|
|
11
11
|
```ruby
|
|
12
12
|
class MyAgent < Riffer::Agent
|
|
13
|
-
model 'openai/gpt-
|
|
13
|
+
model 'openai/gpt-5-mini'
|
|
14
14
|
instructions 'You are a helpful assistant.'
|
|
15
15
|
end
|
|
16
16
|
```
|
|
@@ -43,7 +43,7 @@ Agents can return structured JSON responses that conform to a schema. The respon
|
|
|
43
43
|
|
|
44
44
|
```ruby
|
|
45
45
|
class SentimentAgent < Riffer::Agent
|
|
46
|
-
model 'openai/gpt-
|
|
46
|
+
model 'openai/gpt-5-mini'
|
|
47
47
|
structured_output do
|
|
48
48
|
required :sentiment, String
|
|
49
49
|
required :score, Float
|
data/docs/02_GETTING_STARTED.md
CHANGED
|
@@ -68,7 +68,7 @@ Riffer.configure do |config|
|
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
class GreetingAgent < Riffer::Agent
|
|
71
|
-
model 'openai/gpt-
|
|
71
|
+
model 'openai/gpt-5-mini'
|
|
72
72
|
instructions 'You are a friendly assistant. Greet the user warmly.'
|
|
73
73
|
end
|
|
74
74
|
|
|
@@ -109,7 +109,7 @@ class TimeTool < Riffer::Tool
|
|
|
109
109
|
end
|
|
110
110
|
|
|
111
111
|
class TimeAgent < Riffer::Agent
|
|
112
|
-
model 'openai/gpt-
|
|
112
|
+
model 'openai/gpt-5-mini'
|
|
113
113
|
instructions 'You can tell the user the current time.'
|
|
114
114
|
uses_tools [TimeTool]
|
|
115
115
|
end
|
data/docs/03_AGENTS.md
CHANGED
|
@@ -8,7 +8,7 @@ Create an agent by subclassing `Riffer::Agent`:
|
|
|
8
8
|
|
|
9
9
|
```ruby
|
|
10
10
|
class MyAgent < Riffer::Agent
|
|
11
|
-
model 'openai/gpt-
|
|
11
|
+
model 'openai/gpt-5-mini'
|
|
12
12
|
instructions 'You are a helpful assistant.'
|
|
13
13
|
end
|
|
14
14
|
```
|
|
@@ -21,9 +21,9 @@ Sets the provider and model in `provider/model` format:
|
|
|
21
21
|
|
|
22
22
|
```ruby
|
|
23
23
|
class MyAgent < Riffer::Agent
|
|
24
|
-
model 'openai/gpt-
|
|
24
|
+
model 'openai/gpt-5-mini' # OpenAI
|
|
25
25
|
# or
|
|
26
|
-
model 'amazon_bedrock/anthropic.claude-
|
|
26
|
+
model 'amazon_bedrock/us.anthropic.claude-haiku-4-5-20251001-v1:0' # Bedrock
|
|
27
27
|
# or
|
|
28
28
|
model 'mock/any' # Mock provider
|
|
29
29
|
end
|
|
@@ -33,7 +33,7 @@ Models can also be resolved dynamically with a lambda:
|
|
|
33
33
|
|
|
34
34
|
```ruby
|
|
35
35
|
class MyAgent < Riffer::Agent
|
|
36
|
-
model -> { "anthropic/claude-
|
|
36
|
+
model -> { "anthropic/claude-haiku-4-5-20251001" }
|
|
37
37
|
end
|
|
38
38
|
```
|
|
39
39
|
|
|
@@ -42,7 +42,7 @@ When the lambda accepts a parameter, it receives the `context`:
|
|
|
42
42
|
```ruby
|
|
43
43
|
class MyAgent < Riffer::Agent
|
|
44
44
|
model ->(context) {
|
|
45
|
-
context&.dig(:premium) ? "anthropic/claude-sonnet-4-
|
|
45
|
+
context&.dig(:premium) ? "anthropic/claude-sonnet-4-5-20250929" : "anthropic/claude-haiku-4-5-20251001"
|
|
46
46
|
}
|
|
47
47
|
end
|
|
48
48
|
```
|
|
@@ -55,7 +55,7 @@ Sets system instructions for the agent:
|
|
|
55
55
|
|
|
56
56
|
```ruby
|
|
57
57
|
class MyAgent < Riffer::Agent
|
|
58
|
-
model 'openai/gpt-
|
|
58
|
+
model 'openai/gpt-5-mini'
|
|
59
59
|
instructions 'You are an expert Ruby programmer. Provide concise answers.'
|
|
60
60
|
end
|
|
61
61
|
```
|
|
@@ -64,7 +64,7 @@ Instructions can also be resolved dynamically with a lambda:
|
|
|
64
64
|
|
|
65
65
|
```ruby
|
|
66
66
|
class MyAgent < Riffer::Agent
|
|
67
|
-
model 'openai/gpt-
|
|
67
|
+
model 'openai/gpt-5-mini'
|
|
68
68
|
instructions -> { "Today is #{Date.today}. You are a helpful assistant." }
|
|
69
69
|
end
|
|
70
70
|
```
|
|
@@ -73,7 +73,7 @@ When the lambda accepts a parameter, it receives the `context`:
|
|
|
73
73
|
|
|
74
74
|
```ruby
|
|
75
75
|
class MyAgent < Riffer::Agent
|
|
76
|
-
model 'openai/gpt-
|
|
76
|
+
model 'openai/gpt-5-mini'
|
|
77
77
|
instructions ->(ctx) { "You are assisting #{ctx[:name]}" }
|
|
78
78
|
end
|
|
79
79
|
|
|
@@ -88,7 +88,7 @@ Sets a custom identifier (defaults to snake_case class name):
|
|
|
88
88
|
|
|
89
89
|
```ruby
|
|
90
90
|
class MyAgent < Riffer::Agent
|
|
91
|
-
model 'openai/gpt-
|
|
91
|
+
model 'openai/gpt-5-mini'
|
|
92
92
|
identifier 'custom_agent_name'
|
|
93
93
|
end
|
|
94
94
|
|
|
@@ -101,7 +101,7 @@ Registers tools the agent can use:
|
|
|
101
101
|
|
|
102
102
|
```ruby
|
|
103
103
|
class MyAgent < Riffer::Agent
|
|
104
|
-
model 'openai/gpt-
|
|
104
|
+
model 'openai/gpt-5-mini'
|
|
105
105
|
uses_tools [WeatherTool, TimeTool]
|
|
106
106
|
end
|
|
107
107
|
```
|
|
@@ -110,7 +110,7 @@ Tools can also be resolved dynamically with a lambda:
|
|
|
110
110
|
|
|
111
111
|
```ruby
|
|
112
112
|
class MyAgent < Riffer::Agent
|
|
113
|
-
model 'openai/gpt-
|
|
113
|
+
model 'openai/gpt-5-mini'
|
|
114
114
|
|
|
115
115
|
uses_tools ->(context) {
|
|
116
116
|
tools = [PublicTool]
|
|
@@ -126,7 +126,7 @@ Passes options to the provider client:
|
|
|
126
126
|
|
|
127
127
|
```ruby
|
|
128
128
|
class MyAgent < Riffer::Agent
|
|
129
|
-
model 'openai/gpt-
|
|
129
|
+
model 'openai/gpt-5-mini'
|
|
130
130
|
provider_options api_key: ENV['CUSTOM_OPENAI_KEY']
|
|
131
131
|
end
|
|
132
132
|
```
|
|
@@ -137,7 +137,7 @@ Passes options to each LLM request:
|
|
|
137
137
|
|
|
138
138
|
```ruby
|
|
139
139
|
class MyAgent < Riffer::Agent
|
|
140
|
-
model 'openai/gpt-
|
|
140
|
+
model 'openai/gpt-5-mini'
|
|
141
141
|
model_options reasoning: 'medium', temperature: 0.7, web_search: true
|
|
142
142
|
end
|
|
143
143
|
```
|
|
@@ -148,7 +148,7 @@ Sets the maximum number of LLM call steps in the tool-use loop. When the limit i
|
|
|
148
148
|
|
|
149
149
|
```ruby
|
|
150
150
|
class MyAgent < Riffer::Agent
|
|
151
|
-
model 'openai/gpt-
|
|
151
|
+
model 'openai/gpt-5-mini'
|
|
152
152
|
max_steps 8
|
|
153
153
|
end
|
|
154
154
|
```
|
|
@@ -159,7 +159,7 @@ Configures the agent to return structured JSON responses conforming to a schema.
|
|
|
159
159
|
|
|
160
160
|
```ruby
|
|
161
161
|
class SentimentAgent < Riffer::Agent
|
|
162
|
-
model 'openai/gpt-
|
|
162
|
+
model 'openai/gpt-5-mini'
|
|
163
163
|
instructions 'Analyze the sentiment of the given text.'
|
|
164
164
|
structured_output do
|
|
165
165
|
required :sentiment, String, description: "positive, negative, or neutral"
|
|
@@ -249,7 +249,7 @@ Configures how tool calls are executed. Defaults to sequential (inline) executio
|
|
|
249
249
|
|
|
250
250
|
```ruby
|
|
251
251
|
class MyAgent < Riffer::Agent
|
|
252
|
-
model 'openai/gpt-
|
|
252
|
+
model 'openai/gpt-5-mini'
|
|
253
253
|
uses_tools [WeatherTool, SearchTool]
|
|
254
254
|
tool_runtime Riffer::ToolRuntime::Threaded
|
|
255
255
|
end
|
|
@@ -263,7 +263,7 @@ Registers guardrails for pre/post processing of messages. Pass the guardrail cla
|
|
|
263
263
|
|
|
264
264
|
```ruby
|
|
265
265
|
class MyAgent < Riffer::Agent
|
|
266
|
-
model 'openai/gpt-
|
|
266
|
+
model 'openai/gpt-5-mini'
|
|
267
267
|
|
|
268
268
|
# Input-only guardrail
|
|
269
269
|
guardrail :before, with: InputValidator
|
|
@@ -544,6 +544,7 @@ Returns `nil` if the provider doesn't report usage, or a `Riffer::TokenUsage` ob
|
|
|
544
544
|
| `modifications` | `Array` | List of guardrail modifications applied |
|
|
545
545
|
| `interrupted?` | `Boolean` | `true` if the loop was interrupted |
|
|
546
546
|
| `interrupt_reason` | `String` / `Symbol` / `nil` | The reason passed to `throw :riffer_interrupt` |
|
|
547
|
+
| `messages` | `Array` | Full message history from the conversation |
|
|
547
548
|
|
|
548
549
|
### response.structured_output
|
|
549
550
|
|
|
@@ -629,7 +630,7 @@ Guardrails are registered at class definition time and run automatically on ever
|
|
|
629
630
|
|
|
630
631
|
```ruby
|
|
631
632
|
class MyAgent < Riffer::Agent
|
|
632
|
-
model 'openai/gpt-
|
|
633
|
+
model 'openai/gpt-5-mini'
|
|
633
634
|
guardrail :before, with: ContentPolicy
|
|
634
635
|
end
|
|
635
636
|
|
|
@@ -670,7 +671,7 @@ The `max_steps` class method caps the number of LLM call steps in the tool-use l
|
|
|
670
671
|
|
|
671
672
|
```ruby
|
|
672
673
|
class MyAgent < Riffer::Agent
|
|
673
|
-
model 'openai/gpt-
|
|
674
|
+
model 'openai/gpt-5-mini'
|
|
674
675
|
max_steps 8
|
|
675
676
|
end
|
|
676
677
|
|
data/docs/04_TOOLS.md
CHANGED
|
@@ -324,7 +324,7 @@ WeatherTool.parameters_schema
|
|
|
324
324
|
|
|
325
325
|
```ruby
|
|
326
326
|
class MyAgent < Riffer::Agent
|
|
327
|
-
model 'openai/gpt-
|
|
327
|
+
model 'openai/gpt-5-mini'
|
|
328
328
|
uses_tools [WeatherTool, SearchTool]
|
|
329
329
|
end
|
|
330
330
|
```
|
|
@@ -335,7 +335,7 @@ Use a lambda for context-aware tool resolution:
|
|
|
335
335
|
|
|
336
336
|
```ruby
|
|
337
337
|
class MyAgent < Riffer::Agent
|
|
338
|
-
model 'openai/gpt-
|
|
338
|
+
model 'openai/gpt-5-mini'
|
|
339
339
|
|
|
340
340
|
uses_tools ->(context) {
|
|
341
341
|
tools = [PublicSearchTool]
|
|
@@ -384,6 +384,7 @@ By default, tool calls are executed sequentially in the current thread using `Ri
|
|
|
384
384
|
| ------------------------------- | ---------------------------------------------- |
|
|
385
385
|
| `Riffer::ToolRuntime::Inline` | Executes tool calls sequentially (default) |
|
|
386
386
|
| `Riffer::ToolRuntime::Threaded` | Executes tool calls concurrently using threads |
|
|
387
|
+
| `Riffer::ToolRuntime::Fibers` | Executes tool calls concurrently using fibers |
|
|
387
388
|
|
|
388
389
|
### Per-Agent Configuration
|
|
389
390
|
|
|
@@ -391,7 +392,7 @@ Use the `tool_runtime` class method on your agent:
|
|
|
391
392
|
|
|
392
393
|
```ruby
|
|
393
394
|
class MyAgent < Riffer::Agent
|
|
394
|
-
model 'openai/gpt-
|
|
395
|
+
model 'openai/gpt-5-mini'
|
|
395
396
|
uses_tools [WeatherTool, SearchTool]
|
|
396
397
|
tool_runtime Riffer::ToolRuntime::Threaded
|
|
397
398
|
end
|
|
@@ -409,7 +410,7 @@ Use a lambda for context-aware runtime selection:
|
|
|
409
410
|
|
|
410
411
|
```ruby
|
|
411
412
|
class MyAgent < Riffer::Agent
|
|
412
|
-
model 'openai/gpt-
|
|
413
|
+
model 'openai/gpt-5-mini'
|
|
413
414
|
uses_tools [WeatherTool, SearchTool]
|
|
414
415
|
|
|
415
416
|
tool_runtime ->(context) {
|
|
@@ -444,12 +445,41 @@ The threaded runtime accepts a `max_concurrency` option (default: 5):
|
|
|
444
445
|
|
|
445
446
|
```ruby
|
|
446
447
|
class MyAgent < Riffer::Agent
|
|
447
|
-
model 'openai/gpt-
|
|
448
|
+
model 'openai/gpt-5-mini'
|
|
448
449
|
uses_tools [WeatherTool, SearchTool]
|
|
449
450
|
tool_runtime Riffer::ToolRuntime::Threaded.new(max_concurrency: 3)
|
|
450
451
|
end
|
|
451
452
|
```
|
|
452
453
|
|
|
454
|
+
### Fibers Runtime
|
|
455
|
+
|
|
456
|
+
The fibers runtime uses the [async](https://github.com/socketry/async) gem for lightweight, cooperative concurrency. It requires the `async` gem to be installed:
|
|
457
|
+
|
|
458
|
+
```ruby
|
|
459
|
+
# Gemfile
|
|
460
|
+
gem "async"
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
```ruby
|
|
464
|
+
class MyAgent < Riffer::Agent
|
|
465
|
+
model 'openai/gpt-5-mini'
|
|
466
|
+
uses_tools [WeatherTool, SearchTool]
|
|
467
|
+
tool_runtime Riffer::ToolRuntime::Fibers
|
|
468
|
+
end
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
By default, all tool calls run as fibers without a concurrency limit. You can optionally set a limit:
|
|
472
|
+
|
|
473
|
+
```ruby
|
|
474
|
+
class MyAgent < Riffer::Agent
|
|
475
|
+
model 'openai/gpt-5-mini'
|
|
476
|
+
uses_tools [WeatherTool, SearchTool]
|
|
477
|
+
tool_runtime Riffer::ToolRuntime::Fibers.new(max_concurrency: 10)
|
|
478
|
+
end
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
Fibers use cooperative scheduling — they yield control at I/O boundaries (network calls, file reads, sleep). CPU-bound tools will not benefit from the fibers runtime. Be mindful of fiber-local state (`Fiber.[]`) and note that `Thread.current[]` values are shared across all fibers in the same thread.
|
|
482
|
+
|
|
453
483
|
### Custom Runtimes
|
|
454
484
|
|
|
455
485
|
Create a custom runtime by subclassing `Riffer::ToolRuntime` and overriding the private `dispatch_tool_call` method:
|
data/docs/06_STREAM_EVENTS.md
CHANGED
data/docs/07_CONFIGURATION.md
CHANGED
|
@@ -102,7 +102,7 @@ Pass options directly to the provider client:
|
|
|
102
102
|
|
|
103
103
|
```ruby
|
|
104
104
|
class MyAgent < Riffer::Agent
|
|
105
|
-
model 'openai/gpt-
|
|
105
|
+
model 'openai/gpt-5-mini'
|
|
106
106
|
|
|
107
107
|
# Override API key for this agent only
|
|
108
108
|
provider_options api_key: ENV['CUSTOM_OPENAI_KEY']
|
|
@@ -115,7 +115,7 @@ Pass options to each LLM request:
|
|
|
115
115
|
|
|
116
116
|
```ruby
|
|
117
117
|
class MyAgent < Riffer::Agent
|
|
118
|
-
model 'openai/gpt-
|
|
118
|
+
model 'openai/gpt-5-mini'
|
|
119
119
|
|
|
120
120
|
# These options are sent with every generate/stream call
|
|
121
121
|
model_options temperature: 0.7, reasoning: 'medium'
|
|
@@ -136,7 +136,7 @@ end
|
|
|
136
136
|
|
|
137
137
|
```ruby
|
|
138
138
|
class MyAgent < Riffer::Agent
|
|
139
|
-
model 'openai/gpt-
|
|
139
|
+
model 'openai/gpt-5-mini'
|
|
140
140
|
model_options temperature: 0.7, reasoning: 'medium'
|
|
141
141
|
end
|
|
142
142
|
```
|
|
@@ -152,7 +152,7 @@ Options are passed through to the [Bedrock Converse API](https://docs.aws.amazon
|
|
|
152
152
|
|
|
153
153
|
```ruby
|
|
154
154
|
class MyAgent < Riffer::Agent
|
|
155
|
-
model 'amazon_bedrock/anthropic.claude-
|
|
155
|
+
model 'amazon_bedrock/us.anthropic.claude-haiku-4-5-20251001-v1:0'
|
|
156
156
|
model_options inference_config: {temperature: 0.7, max_tokens: 4096}
|
|
157
157
|
end
|
|
158
158
|
```
|
|
@@ -170,13 +170,13 @@ end
|
|
|
170
170
|
|
|
171
171
|
```ruby
|
|
172
172
|
class MyAgent < Riffer::Agent
|
|
173
|
-
model 'anthropic/claude-
|
|
173
|
+
model 'anthropic/claude-haiku-4-5-20251001'
|
|
174
174
|
model_options temperature: 0.7, max_tokens: 4096
|
|
175
175
|
end
|
|
176
176
|
|
|
177
177
|
# With extended thinking (Claude 3.7+)
|
|
178
178
|
class ReasoningAgent < Riffer::Agent
|
|
179
|
-
model 'anthropic/claude-
|
|
179
|
+
model 'anthropic/claude-haiku-4-5-20251001'
|
|
180
180
|
model_options thinking: {type: "enabled", budget_tokens: 10000}
|
|
181
181
|
end
|
|
182
182
|
```
|
|
@@ -205,12 +205,12 @@ For different environments or use cases, use agent-level overrides:
|
|
|
205
205
|
|
|
206
206
|
```ruby
|
|
207
207
|
class ProductionAgent < Riffer::Agent
|
|
208
|
-
model 'openai/gpt-
|
|
208
|
+
model 'openai/gpt-5-mini'
|
|
209
209
|
provider_options api_key: ENV['PRODUCTION_OPENAI_KEY']
|
|
210
210
|
end
|
|
211
211
|
|
|
212
212
|
class DevelopmentAgent < Riffer::Agent
|
|
213
|
-
model 'openai/gpt-
|
|
213
|
+
model 'openai/gpt-5-mini'
|
|
214
214
|
provider_options api_key: ENV['DEV_OPENAI_KEY']
|
|
215
215
|
model_options temperature: 0.0 # Deterministic for testing
|
|
216
216
|
end
|
data/docs/08_EVALS.md
CHANGED
|
@@ -120,6 +120,7 @@ scenario.output # => "The capital of France is Paris."
|
|
|
120
120
|
scenario.ground_truth # => "Paris"
|
|
121
121
|
scenario.scores # => { EvaluatorClass => score } for this scenario
|
|
122
122
|
scenario.results # => Array of Result objects
|
|
123
|
+
scenario.messages # => Array of Message objects (system, user, assistant, tool)
|
|
123
124
|
scenario.to_h # => Hash representation
|
|
124
125
|
```
|
|
125
126
|
|
|
@@ -183,7 +184,7 @@ Class methods:
|
|
|
183
184
|
|
|
184
185
|
Instance methods:
|
|
185
186
|
|
|
186
|
-
- `evaluate(input:, output:, ground_truth:)` - Override for custom logic; default calls judge with `instructions`
|
|
187
|
+
- `evaluate(input:, output:, ground_truth:, messages:)` - Override for custom logic; default calls judge with `instructions`
|
|
187
188
|
- `judge` - Returns a Judge instance for LLM-as-judge calls
|
|
188
189
|
- `result(score:, reason:, metadata:)` - Helper to build Result objects
|
|
189
190
|
|
|
@@ -196,7 +197,7 @@ class CustomEvaluator < Riffer::Evals::Evaluator
|
|
|
196
197
|
higher_is_better true
|
|
197
198
|
judge_model "anthropic/claude-opus-4-5-20251101"
|
|
198
199
|
|
|
199
|
-
def evaluate(input:, output:, ground_truth: nil)
|
|
200
|
+
def evaluate(input:, output:, ground_truth: nil, messages: [])
|
|
200
201
|
evaluation = judge.evaluate(
|
|
201
202
|
instructions: "Custom evaluation criteria...",
|
|
202
203
|
input: input,
|
|
@@ -217,7 +218,7 @@ Evaluators don't have to use LLM-as-judge:
|
|
|
217
218
|
class LengthEvaluator < Riffer::Evals::Evaluator
|
|
218
219
|
higher_is_better true
|
|
219
220
|
|
|
220
|
-
def evaluate(input:, output:, ground_truth: nil)
|
|
221
|
+
def evaluate(input:, output:, ground_truth: nil, messages: [])
|
|
221
222
|
min_length = 50
|
|
222
223
|
max_length = 500
|
|
223
224
|
|
data/docs/10_SKILLS.md
CHANGED
|
@@ -44,7 +44,7 @@ Use the `skills` block DSL to configure skills:
|
|
|
44
44
|
|
|
45
45
|
```ruby
|
|
46
46
|
class MyAgent < Riffer::Agent
|
|
47
|
-
model "openai/gpt-
|
|
47
|
+
model "openai/gpt-5-mini"
|
|
48
48
|
instructions "You are a helpful assistant."
|
|
49
49
|
skills do
|
|
50
50
|
backend Riffer::Skills::FilesystemBackend.new(".skills")
|
|
@@ -7,6 +7,7 @@ Providers are adapters that connect Riffer to LLM services. They implement a com
|
|
|
7
7
|
| Provider | Identifier | Gem Required |
|
|
8
8
|
| -------------- | ---------------- | ------------------------ |
|
|
9
9
|
| OpenAI | `openai` | `openai` |
|
|
10
|
+
| Azure OpenAI | `azure_openai` | `openai` |
|
|
10
11
|
| Amazon Bedrock | `amazon_bedrock` | `aws-sdk-bedrockruntime` |
|
|
11
12
|
| Anthropic | `anthropic` | `anthropic` |
|
|
12
13
|
| Mock | `mock` | None |
|
|
@@ -17,10 +18,11 @@ Agents specify providers using the `provider/model` format:
|
|
|
17
18
|
|
|
18
19
|
```ruby
|
|
19
20
|
class MyAgent < Riffer::Agent
|
|
20
|
-
model 'openai/gpt-
|
|
21
|
-
model '
|
|
22
|
-
model 'anthropic
|
|
23
|
-
model '
|
|
21
|
+
model 'openai/gpt-5-mini' # OpenAI
|
|
22
|
+
model 'azure_openai/gpt-5-mini' # Azure OpenAI
|
|
23
|
+
model 'amazon_bedrock/us.anthropic.claude-haiku-4-5-20251001-v1:0' # Bedrock
|
|
24
|
+
model 'anthropic/claude-haiku-4-5-20251001' # Anthropic
|
|
25
|
+
model 'mock/any' # Mock provider
|
|
24
26
|
end
|
|
25
27
|
```
|
|
26
28
|
|
|
@@ -37,14 +39,14 @@ provider = Riffer::Providers::OpenAI.new(api_key: "...")
|
|
|
37
39
|
|
|
38
40
|
response = provider.generate_text(
|
|
39
41
|
prompt: "Hello!",
|
|
40
|
-
model: "gpt-
|
|
42
|
+
model: "gpt-5-mini"
|
|
41
43
|
)
|
|
42
44
|
# => Riffer::Messages::Assistant
|
|
43
45
|
|
|
44
46
|
# Or with messages
|
|
45
47
|
response = provider.generate_text(
|
|
46
48
|
messages: [Riffer::Messages::User.new("Hello!")],
|
|
47
|
-
model: "gpt-
|
|
49
|
+
model: "gpt-5-mini"
|
|
48
50
|
)
|
|
49
51
|
```
|
|
50
52
|
|
|
@@ -53,7 +55,7 @@ response = provider.generate_text(
|
|
|
53
55
|
Streams a response as an Enumerator:
|
|
54
56
|
|
|
55
57
|
```ruby
|
|
56
|
-
provider.stream_text(prompt: "Tell me a story", model: "gpt-
|
|
58
|
+
provider.stream_text(prompt: "Tell me a story", model: "gpt-5-mini").each do |event|
|
|
57
59
|
case event
|
|
58
60
|
when Riffer::StreamEvents::TextDelta
|
|
59
61
|
print event.content
|
|
@@ -90,7 +92,7 @@ provider = Riffer::Providers::OpenAI.new
|
|
|
90
92
|
# Simple prompt
|
|
91
93
|
response = provider.generate_text(
|
|
92
94
|
prompt: "What is Ruby?",
|
|
93
|
-
model: "gpt-
|
|
95
|
+
model: "gpt-5-mini"
|
|
94
96
|
)
|
|
95
97
|
puts response.content
|
|
96
98
|
|
|
@@ -98,7 +100,7 @@ puts response.content
|
|
|
98
100
|
response = provider.generate_text(
|
|
99
101
|
prompt: "Explain recursion",
|
|
100
102
|
system: "You are a programming tutor. Use simple language.",
|
|
101
|
-
model: "gpt-
|
|
103
|
+
model: "gpt-5-mini"
|
|
102
104
|
)
|
|
103
105
|
|
|
104
106
|
# With message history
|
|
@@ -111,7 +113,7 @@ messages = [
|
|
|
111
113
|
|
|
112
114
|
response = provider.generate_text(
|
|
113
115
|
messages: messages,
|
|
114
|
-
model: "gpt-
|
|
116
|
+
model: "gpt-5-mini"
|
|
115
117
|
)
|
|
116
118
|
```
|
|
117
119
|
|
|
@@ -132,7 +134,7 @@ end
|
|
|
132
134
|
|
|
133
135
|
response = provider.generate_text(
|
|
134
136
|
prompt: "What's the weather in Tokyo?",
|
|
135
|
-
model: "gpt-
|
|
137
|
+
model: "gpt-5-mini",
|
|
136
138
|
tools: [WeatherTool]
|
|
137
139
|
)
|
|
138
140
|
|
|
@@ -149,6 +151,9 @@ Riffer uses a registry to find providers by identifier:
|
|
|
149
151
|
Riffer::Providers::Repository.find(:openai)
|
|
150
152
|
# => Riffer::Providers::OpenAI
|
|
151
153
|
|
|
154
|
+
Riffer::Providers::Repository.find(:azure_openai)
|
|
155
|
+
# => Riffer::Providers::AzureOpenAI
|
|
156
|
+
|
|
152
157
|
Riffer::Providers::Repository.find(:amazon_bedrock)
|
|
153
158
|
# => Riffer::Providers::AmazonBedrock
|
|
154
159
|
|
|
@@ -164,5 +169,6 @@ Riffer::Providers::Repository.find(:mock)
|
|
|
164
169
|
- [Amazon Bedrock](02_AMAZON_BEDROCK.md) - Claude and other models via AWS
|
|
165
170
|
- [Anthropic](03_ANTHROPIC.md) - Claude models via Anthropic API
|
|
166
171
|
- [OpenAI](04_OPENAI.md) - GPT models
|
|
167
|
-
- [
|
|
168
|
-
- [
|
|
172
|
+
- [Azure OpenAI](05_AZURE_OPENAI.md) - GPT models via Azure
|
|
173
|
+
- [Mock](06_MOCK_PROVIDER.md) - Mock provider for testing
|
|
174
|
+
- [Custom Providers](07_CUSTOM_PROVIDERS.md) - Creating your own provider
|