riffer 0.39.0 → 0.40.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 +2 -2
- data/.agents/code-style.md +4 -3
- data/.agents/providers.md +2 -2
- data/.release-please-manifest.json +1 -1
- data/.rubocop.yml +112 -0
- data/AGENTS.md +6 -6
- data/CHANGELOG.md +7 -0
- data/README.md +35 -33
- data/Rakefile +26 -6
- data/Steepfile +2 -0
- data/docs/{03_AGENTS.md → AGENTS.md} +12 -12
- data/docs/{04_AGENT_LIFECYCLE.md → AGENT_LIFECYCLE.md} +1 -1
- data/docs/{10_CONFIGURATION.md → CONFIGURATION.md} +10 -10
- data/docs/{02_GETTING_STARTED.md → GETTING_STARTED.md} +6 -6
- data/docs/{14_MCP.md → MCP.md} +1 -1
- data/docs/{08_MESSAGES.md → MESSAGES.md} +4 -4
- data/docs/{01_OVERVIEW.md → OVERVIEW.md} +15 -15
- data/docs/{15_SERIALIZATION.md → SERIALIZATION.md} +4 -4
- data/docs/{09_STREAM_EVENTS.md → STREAM_EVENTS.md} +4 -4
- data/docs/{06_TOOLS.md → TOOLS.md} +1 -1
- data/docs/{16_TRACING.md → TRACING.md} +6 -6
- data/docs/providers/{07_CUSTOM_PROVIDERS.md → CUSTOM_PROVIDERS.md} +2 -2
- data/docs/providers/{01_PROVIDERS.md → PROVIDERS.md} +8 -8
- data/docs-site/404.html +51 -0
- data/docs-site/build.rb +144 -0
- data/docs-site/check.rb +64 -0
- data/docs-site/copy.js +20 -0
- data/docs-site/favicon.svg +18 -0
- data/docs-site/index.html.erb +194 -0
- data/docs-site/landing.css +315 -0
- data/docs-site/layout.html.erb +101 -0
- data/docs-site/manifest.yml +96 -0
- data/docs-site/site.css +598 -0
- data/lib/riffer/agent/config.rb +34 -9
- data/lib/riffer/agent/context.rb +6 -6
- data/lib/riffer/agent/response.rb +24 -2
- data/lib/riffer/agent/run.rb +121 -30
- data/lib/riffer/agent/serializer.rb +17 -8
- data/lib/riffer/agent/session/repair.rb +12 -11
- data/lib/riffer/agent/session.rb +16 -15
- data/lib/riffer/agent.rb +49 -11
- data/lib/riffer/config.rb +35 -12
- data/lib/riffer/evals/evaluator.rb +10 -3
- data/lib/riffer/evals/evaluator_runner.rb +3 -2
- data/lib/riffer/evals/judge.rb +4 -3
- data/lib/riffer/evals/result.rb +1 -1
- data/lib/riffer/evals/run_result.rb +3 -3
- data/lib/riffer/evals/scenario_result.rb +2 -2
- data/lib/riffer/guardrails/modification.rb +1 -1
- data/lib/riffer/guardrails/runner.rb +14 -9
- data/lib/riffer/guardrails/tripwire.rb +1 -1
- data/lib/riffer/helpers/boolean.rb +1 -1
- data/lib/riffer/helpers/call_or_value.rb +1 -0
- data/lib/riffer/helpers/class_name_converter.rb +6 -6
- data/lib/riffer/mcp/authenticated_tool.rb +2 -4
- data/lib/riffer/mcp/client.rb +2 -4
- data/lib/riffer/mcp/registry.rb +6 -2
- data/lib/riffer/mcp/search_tool.rb +1 -1
- data/lib/riffer/mcp/tool_factory.rb +5 -5
- data/lib/riffer/mcp.rb +1 -1
- data/lib/riffer/messages/assistant.rb +4 -3
- data/lib/riffer/messages/base.rb +13 -11
- data/lib/riffer/messages/file_part.rb +7 -6
- data/lib/riffer/messages/tool.rb +2 -2
- data/lib/riffer/messages/user.rb +2 -2
- data/lib/riffer/params/param.rb +8 -8
- data/lib/riffer/params.rb +31 -31
- data/lib/riffer/providers/amazon_bedrock.rb +64 -59
- data/lib/riffer/providers/anthropic.rb +66 -56
- data/lib/riffer/providers/azure_open_ai.rb +7 -13
- data/lib/riffer/providers/base.rb +40 -21
- data/lib/riffer/providers/gemini.rb +38 -35
- data/lib/riffer/providers/mock.rb +22 -10
- data/lib/riffer/providers/open_ai.rb +40 -32
- data/lib/riffer/providers/open_router.rb +35 -36
- data/lib/riffer/providers/repository.rb +1 -1
- data/lib/riffer/providers/token_usage.rb +10 -8
- data/lib/riffer/runner/fibers.rb +7 -6
- data/lib/riffer/runner/sequential.rb +2 -2
- data/lib/riffer/runner/threaded.rb +4 -3
- data/lib/riffer/skills/adapter.rb +4 -2
- data/lib/riffer/skills/config.rb +7 -1
- data/lib/riffer/skills/context.rb +5 -1
- data/lib/riffer/skills/filesystem_backend.rb +2 -0
- data/lib/riffer/skills/frontmatter.rb +27 -5
- data/lib/riffer/stream_events/finish_reason_done.rb +3 -2
- data/lib/riffer/stream_events/guardrail_modification.rb +1 -1
- data/lib/riffer/stream_events/guardrail_tripwire.rb +1 -1
- data/lib/riffer/stream_events/interrupt.rb +1 -1
- data/lib/riffer/stream_events/reasoning_delta.rb +1 -1
- data/lib/riffer/stream_events/reasoning_done.rb +1 -1
- data/lib/riffer/stream_events/skill_activation.rb +1 -1
- data/lib/riffer/stream_events/text_delta.rb +1 -1
- data/lib/riffer/stream_events/text_done.rb +1 -1
- data/lib/riffer/stream_events/token_usage_done.rb +1 -1
- data/lib/riffer/stream_events/tool_call_delta.rb +1 -1
- data/lib/riffer/stream_events/tool_call_done.rb +1 -1
- data/lib/riffer/stream_events/web_search_done.rb +1 -1
- data/lib/riffer/stream_events/web_search_status.rb +1 -1
- data/lib/riffer/tools/response.rb +3 -3
- data/lib/riffer/tools/runtime.rb +15 -7
- data/lib/riffer/tools/toolable.rb +17 -5
- data/lib/riffer/tracing/capture.rb +7 -7
- data/lib/riffer/tracing/no_op.rb +4 -8
- data/lib/riffer/tracing/otel.rb +8 -4
- data/lib/riffer/tracing/stream_recorder.rb +5 -1
- data/lib/riffer/tracing.rb +9 -6
- data/lib/riffer/version.rb +1 -1
- data/lib/riffer.rb +2 -2
- data/sig/generated/riffer/agent/config.rbs +14 -1
- data/sig/generated/riffer/agent/response.rbs +12 -1
- data/sig/generated/riffer/agent/run.rbs +12 -1
- data/sig/generated/riffer/agent.rbs +1 -1
- data/sig/generated/riffer/mcp.rbs +1 -1
- data/sig/generated/riffer/providers/mock.rbs +2 -1
- metadata +38 -229
- data/.standard.yml +0 -1
- /data/docs/{05_AGENT_LOOP.md → AGENT_LOOP.md} +0 -0
- /data/docs/{11_EVALS.md → EVALS.md} +0 -0
- /data/docs/{12_GUARDRAILS.md → GUARDRAILS.md} +0 -0
- /data/docs/{13_SKILLS.md → SKILLS.md} +0 -0
- /data/docs/{07_TOOL_ADVANCED.md → TOOL_ADVANCED.md} +0 -0
- /data/docs/providers/{02_AMAZON_BEDROCK.md → AMAZON_BEDROCK.md} +0 -0
- /data/docs/providers/{03_ANTHROPIC.md → ANTHROPIC.md} +0 -0
- /data/docs/providers/{05_AZURE_OPENAI.md → AZURE_OPENAI.md} +0 -0
- /data/docs/providers/{08_GEMINI.md → GEMINI.md} +0 -0
- /data/docs/providers/{06_MOCK_PROVIDER.md → MOCK_PROVIDER.md} +0 -0
- /data/docs/providers/{04_OPENAI.md → OPENAI.md} +0 -0
- /data/docs/providers/{09_OPENROUTER.md → OPENROUTER.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: 6c89776aeb032fbf837df103366fed830edcc20769cc9d4958a3a9bfa56a7803
|
|
4
|
+
data.tar.gz: 2153cf2967b9b70366987aeb9e59b215ff641bcd44668525c07d822ff9757579
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: edfb2a10f17e1c0f6fb0630f5c2244370e01c5f32d05e9f065183da0b5b2d2cfec2453cac9a08714bd921716cd747609e4db61fb105a57769d79ab2f8988356a
|
|
7
|
+
data.tar.gz: 7d6dcdbab4be152033fcf75581252d3c9bda60c9e49825e75028d19670bae0490087ee8a90267a2af2f4fd8daabb5f370c8c2b7bb7cdcffe77a75b94a6b190ff
|
data/.agents/architecture.md
CHANGED
|
@@ -136,7 +136,7 @@ Context flow: `Agent#execute_tool_calls` → `Tools::Runtime#execute(tool_calls,
|
|
|
136
136
|
|
|
137
137
|
### MCP Integration (`lib/riffer/mcp/`)
|
|
138
138
|
|
|
139
|
-
Register third-party MCP servers globally; agents opt-in by tag via `use_mcp`. Tags are application-defined (manifests may list several; any overlap with `use_mcp` opts in—see `docs/
|
|
139
|
+
Register third-party MCP servers globally; agents opt-in by tag via `use_mcp`. Tags are application-defined (manifests may list several; any overlap with `use_mcp` opts in—see `docs/MCP.md`).
|
|
140
140
|
|
|
141
141
|
```ruby
|
|
142
142
|
Riffer::Mcp.register(
|
|
@@ -146,7 +146,7 @@ Riffer::Mcp.register(
|
|
|
146
146
|
discovery_headers: -> { {"Authorization" => "Bearer #{ENV['GITHUB_TOKEN']}"} }
|
|
147
147
|
)
|
|
148
148
|
|
|
149
|
-
# Optional: per-run tools/call headers (see docs/
|
|
149
|
+
# Optional: per-run tools/call headers (see docs/MCP.md)
|
|
150
150
|
Riffer.configure { |c| c.mcp.credentials = ->(manifest:, matched_tags:, context:) { ... } }
|
|
151
151
|
|
|
152
152
|
class ResearchAgent < Riffer::Agent
|
data/.agents/code-style.md
CHANGED
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
## Formatting
|
|
4
4
|
|
|
5
|
-
- Use
|
|
6
|
-
-
|
|
7
|
-
- Run `bin/lint` to check, `bin/lint
|
|
5
|
+
- Use RuboCop for linting and formatting
|
|
6
|
+
- Config lives in `.rubocop.yml`, with cops sorted alphabetically
|
|
7
|
+
- Run `bin/lint` to check, `bin/lint -a` to auto-fix (safe autocorrect), `bin/lint -A` for unsafe autocorrect
|
|
8
|
+
- Never silence violations with inline `rubocop:disable` comments — fix them, or when an exception is genuinely warranted add a narrowly scoped override in `.rubocop.yml` with a comment explaining why
|
|
8
9
|
|
|
9
10
|
## Required Header
|
|
10
11
|
|
data/.agents/providers.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
## Steps
|
|
4
4
|
|
|
5
5
|
1. Create `lib/riffer/providers/your_provider.rb` extending `Riffer::Providers::Base`
|
|
6
|
-
2. Implement the required hook methods (see [Custom Providers](../docs/providers/
|
|
6
|
+
2. Implement the required hook methods (see [Custom Providers](../docs/providers/CUSTOM_PROVIDERS.md) for the full API)
|
|
7
7
|
3. Register in `Riffer::Providers::Repository::REPO`
|
|
8
8
|
4. Add provider config to `Riffer::Config` if needed
|
|
9
9
|
5. Create tests in `test/riffer/providers/your_provider_test.rb`
|
|
@@ -42,4 +42,4 @@ Use `depends_on` helper for runtime dependency checking if your provider require
|
|
|
42
42
|
|
|
43
43
|
## Reference
|
|
44
44
|
|
|
45
|
-
For hook method signatures, structured output handling, file handling, and complete examples, see [Custom Providers](../docs/providers/
|
|
45
|
+
For hook method signatures, structured output handling, file handling, and complete examples, see [Custom Providers](../docs/providers/CUSTOM_PROVIDERS.md).
|
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
plugins:
|
|
2
|
+
- rubocop-minitest
|
|
3
|
+
- rubocop-performance
|
|
4
|
+
- rubocop-rake
|
|
5
|
+
|
|
6
|
+
# ── Tier 1: house style — settings changed from RuboCop defaults everywhere ──
|
|
7
|
+
|
|
8
|
+
Layout/BlockAlignment:
|
|
9
|
+
EnforcedStyleAlignWith: start_of_block
|
|
10
|
+
|
|
11
|
+
Layout/DotPosition:
|
|
12
|
+
EnforcedStyle: trailing
|
|
13
|
+
|
|
14
|
+
Layout/MultilineMethodCallIndentation:
|
|
15
|
+
EnforcedStyle: indented
|
|
16
|
+
|
|
17
|
+
Style/HashSyntax:
|
|
18
|
+
EnforcedShorthandSyntax: either_consistent
|
|
19
|
+
|
|
20
|
+
Style/NonNilCheck:
|
|
21
|
+
IncludeSemanticChanges: true
|
|
22
|
+
|
|
23
|
+
Style/StringLiterals:
|
|
24
|
+
EnforcedStyle: double_quotes
|
|
25
|
+
|
|
26
|
+
Style/TrailingCommaInArguments:
|
|
27
|
+
EnforcedStyleForMultiline: consistent_comma
|
|
28
|
+
|
|
29
|
+
Style/TrailingCommaInArrayLiteral:
|
|
30
|
+
EnforcedStyleForMultiline: consistent_comma
|
|
31
|
+
|
|
32
|
+
Style/TrailingCommaInHashLiteral:
|
|
33
|
+
EnforcedStyleForMultiline: consistent_comma
|
|
34
|
+
|
|
35
|
+
# ── Tier 2: shared base — additions and deviations from the house style ──
|
|
36
|
+
|
|
37
|
+
AllCops:
|
|
38
|
+
DisabledByDefault: false
|
|
39
|
+
# Stricter than the house style, which leaves pending cops as warnings;
|
|
40
|
+
# enabling adopts new cops automatically and kills the warning spam.
|
|
41
|
+
NewCops: enable
|
|
42
|
+
SuggestExtensions: false
|
|
43
|
+
|
|
44
|
+
# Size thresholds are noise; BlockNesting stays — deep nesting is the one
|
|
45
|
+
# limit worth enforcing.
|
|
46
|
+
Metrics:
|
|
47
|
+
Enabled: false
|
|
48
|
+
|
|
49
|
+
Metrics/BlockNesting:
|
|
50
|
+
Enabled: true
|
|
51
|
+
|
|
52
|
+
# A comment on every class is a "what" — conflicts with the comments rule.
|
|
53
|
+
Style/Documentation:
|
|
54
|
+
Enabled: false
|
|
55
|
+
|
|
56
|
+
# The function-module pattern needs a working `private`.
|
|
57
|
+
Style/ModuleFunction:
|
|
58
|
+
EnforcedStyle: extend_self
|
|
59
|
+
|
|
60
|
+
# Compact (`class Foo::Bar`) cuts LOC and nesting and ends the nested/compact
|
|
61
|
+
# mix across codebases.
|
|
62
|
+
Style/ClassAndModuleChildren:
|
|
63
|
+
EnforcedStyle: compact
|
|
64
|
+
|
|
65
|
+
# Keyword arguments often stay unused to keep signatures uniform across
|
|
66
|
+
# interchangeable implementations.
|
|
67
|
+
Lint/UnusedMethodArgument:
|
|
68
|
+
AllowUnusedKeywordArguments: true
|
|
69
|
+
|
|
70
|
+
# Additions, not overrides: RBS-inline annotations must lint.
|
|
71
|
+
Layout/LeadingCommentSpace:
|
|
72
|
+
AllowRBSInlineAnnotation: true
|
|
73
|
+
|
|
74
|
+
Layout/LineLength:
|
|
75
|
+
AllowedPatterns: ['#:']
|
|
76
|
+
|
|
77
|
+
Minitest/MultipleAssertions:
|
|
78
|
+
Max: 3
|
|
79
|
+
|
|
80
|
+
# ── Tier 3: riffer deviations, each with its reason ──
|
|
81
|
+
|
|
82
|
+
# Tests use deliberately empty blocks: `.each { |_| }` to drain a stream for
|
|
83
|
+
# its side effects, empty `in_span` bodies to assert span lifecycle, and no-op
|
|
84
|
+
# stream doubles.
|
|
85
|
+
Lint/EmptyBlock:
|
|
86
|
+
Exclude:
|
|
87
|
+
- test/**/*
|
|
88
|
+
|
|
89
|
+
# Keyword-argument names are the calling contract for riffer's block-based
|
|
90
|
+
# hooks (tool `execute` blocks, evaluator lambdas, dynamic instructions) —
|
|
91
|
+
# underscore-prefixing a block keyword renames the keyword and breaks callers.
|
|
92
|
+
Lint/UnusedBlockArgument:
|
|
93
|
+
AllowUnusedKeywordArguments: true
|
|
94
|
+
|
|
95
|
+
# validate_as_tool! follows the validate!/save! idiom: raise or return true.
|
|
96
|
+
# Its return value is not a predicate.
|
|
97
|
+
Naming/PredicateMethod:
|
|
98
|
+
AllowBangMethods: true
|
|
99
|
+
|
|
100
|
+
# has_tool_calls? is shipped public API — renaming it breaks consumers.
|
|
101
|
+
Naming/PredicatePrefix:
|
|
102
|
+
AllowedMethods:
|
|
103
|
+
- has_tool_calls?
|
|
104
|
+
|
|
105
|
+
# Riffer::Messages::Base#+ and Riffer::Providers::TokenUsage#+ merge objects;
|
|
106
|
+
# the cop's `sum` rewrite starts the fold from 0 and raises on non-numeric
|
|
107
|
+
# elements.
|
|
108
|
+
Performance/Sum:
|
|
109
|
+
Exclude:
|
|
110
|
+
- lib/riffer/providers/base.rb
|
|
111
|
+
- lib/riffer/evals/run_result.rb
|
|
112
|
+
- lib/riffer/evals/scenario_result.rb
|
data/AGENTS.md
CHANGED
|
@@ -5,16 +5,16 @@ Ruby gem framework for building AI-powered agents with LLM provider adapters.
|
|
|
5
5
|
## Quick Reference
|
|
6
6
|
|
|
7
7
|
- **Ruby**: 3.3.0+ (CI: 3.3, 3.4, 4.0)
|
|
8
|
-
- **Lint + Test**: `bin/rake` (runs the default task: test +
|
|
8
|
+
- **Lint + Test**: `bin/rake` (runs the default task: test + rubocop + steep:check)
|
|
9
9
|
- **Autoloading**: Zeitwerk (file paths must match module/class names)
|
|
10
10
|
- **Model format**: `provider/model` (e.g., `openai/gpt-4`)
|
|
11
|
-
- **Docs**: when adding a public config option or message attribute, update the matching page in `docs/` (e.g., `docs/
|
|
11
|
+
- **Docs**: when adding a public config option or message attribute, update the matching page in `docs/` (e.g., `docs/CONFIGURATION.md`, `docs/MESSAGES.md`). Adding a NEW page under `docs/` also requires a `docs-site/manifest.yml` entry — the site build fails without one. RDoc ≠ user docs.
|
|
12
12
|
|
|
13
13
|
## Topic Guides
|
|
14
14
|
|
|
15
15
|
- [Architecture](.agents/architecture.md) - Core components and project structure
|
|
16
16
|
- [Testing](.agents/testing.md) - Minitest spec DSL and VCR cassettes
|
|
17
|
-
- [Code Style](.agents/code-style.md) -
|
|
17
|
+
- [Code Style](.agents/code-style.md) - RuboCop, comment, and RDoc conventions
|
|
18
18
|
- [Providers](.agents/providers.md) - Adding new LLM provider adapters
|
|
19
19
|
- [RBS Inline](.agents/rbs-inline.md) - Type annotations with rbs-inline
|
|
20
20
|
|
|
@@ -24,13 +24,13 @@ All wrappers `exec bundle exec …` under the hood.
|
|
|
24
24
|
|
|
25
25
|
| Command | Description |
|
|
26
26
|
| --------------- | -------------------------------------------- |
|
|
27
|
-
| `bin/rake` | Default task: test +
|
|
27
|
+
| `bin/rake` | Default task: test + rubocop + steep:check |
|
|
28
28
|
| `bin/test` | Run tests |
|
|
29
|
-
| `bin/lint` | Check code style (pass
|
|
29
|
+
| `bin/lint` | Check code style (pass `-a` to auto-fix) |
|
|
30
30
|
| `bin/typecheck` | Run Steep type checker |
|
|
31
31
|
| `bin/rbs` | Generate RBS type signatures |
|
|
32
32
|
| `bin/rbs-watch` | Watch and regenerate RBS files |
|
|
33
|
-
| `bin/docs` | Build
|
|
33
|
+
| `bin/docs` | Build the docs site + API reference |
|
|
34
34
|
| `bin/build` | Build the gem package |
|
|
35
35
|
| `bin/console` | Interactive console |
|
|
36
36
|
| `bin/setup` | Install dependencies |
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,13 @@ 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.40.0](https://github.com/janeapp/riffer/compare/riffer/v0.39.0...riffer/v0.40.0) (2026-08-12)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* replace RDoc guide pages with a static docs site ([#390](https://github.com/janeapp/riffer/issues/390)) ([eef94e1](https://github.com/janeapp/riffer/commit/eef94e140b618ae55a0dea2e0e94cf91462ae169))
|
|
14
|
+
|
|
8
15
|
## [0.39.0](https://github.com/janeapp/riffer/compare/riffer/v0.38.1...riffer/v0.39.0) (2026-07-29)
|
|
9
16
|
|
|
10
17
|
|
data/README.md
CHANGED
|
@@ -45,35 +45,37 @@ puts agent.generate('Hello world')
|
|
|
45
45
|
|
|
46
46
|
## Documentation
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
- [Overview](docs/
|
|
51
|
-
- [Getting Started](docs/
|
|
52
|
-
- [Agents](docs/
|
|
53
|
-
- [Agent Lifecycle](docs/
|
|
54
|
-
- [Agent Loop](docs/
|
|
55
|
-
- [Tools](docs/
|
|
56
|
-
- [Advanced Tools](docs/
|
|
57
|
-
- [Messages](docs/
|
|
58
|
-
- [Stream Events](docs/
|
|
59
|
-
- [Configuration](docs/
|
|
60
|
-
- [Evals](docs/
|
|
61
|
-
- [Guardrails](docs/
|
|
62
|
-
- [Skills](docs/
|
|
63
|
-
- [MCP](docs/
|
|
64
|
-
- [Serialization](docs/
|
|
65
|
-
- [Tracing](docs/
|
|
66
|
-
- [Providers](docs/providers/
|
|
48
|
+
Comprehensive guides live at [docs.riffer.ai](https://docs.riffer.ai):
|
|
49
|
+
|
|
50
|
+
- [Overview](https://docs.riffer.ai/guides/overview/) - Core concepts and architecture
|
|
51
|
+
- [Getting Started](https://docs.riffer.ai/guides/getting-started/) - Installation and first steps
|
|
52
|
+
- [Agents](https://docs.riffer.ai/guides/agents/) - Defining and configuring agents
|
|
53
|
+
- [Agent Lifecycle](https://docs.riffer.ai/guides/agent-lifecycle/) - Generate, stream, and responses
|
|
54
|
+
- [Agent Loop](https://docs.riffer.ai/guides/agent-loop/) - Tool execution flow and stopping
|
|
55
|
+
- [Tools](https://docs.riffer.ai/guides/tools/) - Creating tools for agents
|
|
56
|
+
- [Advanced Tools](https://docs.riffer.ai/guides/advanced-tools/) - Timeouts, runtime, and registration
|
|
57
|
+
- [Messages](https://docs.riffer.ai/guides/messages/) - Message types and formats
|
|
58
|
+
- [Stream Events](https://docs.riffer.ai/guides/stream-events/) - Streaming responses
|
|
59
|
+
- [Configuration](https://docs.riffer.ai/guides/configuration/) - Framework configuration
|
|
60
|
+
- [Evals](https://docs.riffer.ai/guides/evals/) - Evaluating agent quality
|
|
61
|
+
- [Guardrails](https://docs.riffer.ai/guides/guardrails/) - Input/output validation
|
|
62
|
+
- [Skills](https://docs.riffer.ai/guides/skills/) - Packaged agent capabilities
|
|
63
|
+
- [MCP](https://docs.riffer.ai/guides/mcp/) - Integrating third-party MCP servers
|
|
64
|
+
- [Serialization](https://docs.riffer.ai/guides/serialization/) - Persisting and transferring agent definitions
|
|
65
|
+
- [Tracing](https://docs.riffer.ai/guides/tracing/) - OpenTelemetry span contract and host wiring
|
|
66
|
+
- [Providers](https://docs.riffer.ai/guides/providers/overview/) - LLM provider adapters
|
|
67
|
+
|
|
68
|
+
The guide sources are in the [docs](docs/) directory.
|
|
67
69
|
|
|
68
70
|
### API Reference
|
|
69
71
|
|
|
70
|
-
|
|
72
|
+
The full API reference is published at [docs.riffer.ai/api](https://docs.riffer.ai/api/). Preview the site locally with:
|
|
71
73
|
|
|
72
74
|
```bash
|
|
73
|
-
bin/docs
|
|
75
|
+
bin/rake docs:serve
|
|
74
76
|
```
|
|
75
77
|
|
|
76
|
-
Then open `
|
|
78
|
+
Then open <http://localhost:8000>. The site uses root-absolute paths, so it must be served over HTTP — opening `_site/index.html` via `file://` won't work.
|
|
77
79
|
|
|
78
80
|
## Development
|
|
79
81
|
|
|
@@ -86,17 +88,17 @@ bin/setup
|
|
|
86
88
|
Common workflows are wrapped in `bin/`. Each is a thin `exec bundle exec …` script — use them
|
|
87
89
|
instead of typing `bundle exec` yourself:
|
|
88
90
|
|
|
89
|
-
| Command | Description
|
|
90
|
-
| --------------- |
|
|
91
|
-
| `bin/rake` | Default task: test +
|
|
92
|
-
| `bin/test` | Run tests
|
|
93
|
-
| `bin/lint` | Check code style (pass
|
|
94
|
-
| `bin/typecheck` | Run Steep type checker
|
|
95
|
-
| `bin/rbs` | Generate RBS type signatures
|
|
96
|
-
| `bin/rbs-watch` | Watch and regenerate RBS files
|
|
97
|
-
| `bin/docs` | Build
|
|
98
|
-
| `bin/build` | Build the gem package
|
|
99
|
-
| `bin/console` | Interactive console
|
|
91
|
+
| Command | Description |
|
|
92
|
+
| --------------- | ------------------------------------------ |
|
|
93
|
+
| `bin/rake` | Default task: test + rubocop + steep:check |
|
|
94
|
+
| `bin/test` | Run tests |
|
|
95
|
+
| `bin/lint` | Check code style (pass `-a` to auto-fix) |
|
|
96
|
+
| `bin/typecheck` | Run Steep type checker |
|
|
97
|
+
| `bin/rbs` | Generate RBS type signatures |
|
|
98
|
+
| `bin/rbs-watch` | Watch and regenerate RBS files |
|
|
99
|
+
| `bin/docs` | Build the docs site + API reference |
|
|
100
|
+
| `bin/build` | Build the gem package |
|
|
101
|
+
| `bin/console` | Interactive console |
|
|
100
102
|
|
|
101
103
|
`bin/rake <task>` is the escape hatch for any rake task without a named wrapper (e.g.
|
|
102
104
|
`bin/rake test:slow`, `bin/rake release`).
|
data/Rakefile
CHANGED
|
@@ -5,20 +5,40 @@ require "minitest/test_task"
|
|
|
5
5
|
|
|
6
6
|
Minitest::TestTask.create
|
|
7
7
|
|
|
8
|
-
require "
|
|
8
|
+
require "rubocop/rake_task"
|
|
9
|
+
|
|
10
|
+
RuboCop::RakeTask.new
|
|
11
|
+
|
|
9
12
|
require "rdoc/task"
|
|
10
13
|
|
|
11
14
|
RDoc::Task.new do |rdoc|
|
|
12
|
-
rdoc.rdoc_dir = "
|
|
13
|
-
rdoc.title = "Riffer
|
|
15
|
+
rdoc.rdoc_dir = "_site/api"
|
|
16
|
+
rdoc.title = "Riffer API Reference"
|
|
14
17
|
rdoc.main = "README.md"
|
|
15
18
|
rdoc.rdoc_files.include("README.md", "CHANGELOG.md", "LICENSE.txt")
|
|
16
19
|
rdoc.rdoc_files.include("lib/**/*.rb")
|
|
17
20
|
rdoc.options << "--charset" << "utf-8"
|
|
18
|
-
rdoc.options << "--page-dir" << "docs"
|
|
19
21
|
end
|
|
20
22
|
|
|
21
|
-
|
|
23
|
+
namespace :docs do
|
|
24
|
+
desc "Build the docs site (landing, guides, 404, assets) into _site/"
|
|
25
|
+
task :site do
|
|
26
|
+
ruby "docs-site/build.rb"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
desc "Build the docs site and validate all internal links and anchors"
|
|
30
|
+
task check: :site do
|
|
31
|
+
ruby "docs-site/check.rb"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
desc "Build the docs site and serve it at http://localhost:8000"
|
|
35
|
+
task serve: :site do
|
|
36
|
+
ruby "-run -e httpd _site -p 8000"
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
desc "Build the full deployable docs tree (site + API reference) into _site/"
|
|
41
|
+
task docs: %w[docs:site rdoc]
|
|
22
42
|
|
|
23
43
|
namespace :rbs do
|
|
24
44
|
desc "Generate RBS type signatures from inline annotations"
|
|
@@ -42,4 +62,4 @@ namespace :steep do
|
|
|
42
62
|
end
|
|
43
63
|
end
|
|
44
64
|
|
|
45
|
-
task default: %i[test
|
|
65
|
+
task default: %i[test rubocop steep:check]
|
data/Steepfile
CHANGED
|
@@ -126,7 +126,7 @@ end
|
|
|
126
126
|
|
|
127
127
|
### use_mcp
|
|
128
128
|
|
|
129
|
-
Loads tools from registered [MCP](
|
|
129
|
+
Loads tools from registered [MCP](MCP.md) servers by tag. Like `uses_tools`, **`use_mcp` is not inherited**—add it on each subclass that should include MCP tools.
|
|
130
130
|
|
|
131
131
|
### provider_options
|
|
132
132
|
|
|
@@ -263,7 +263,7 @@ class MyAgent < Riffer::Agent
|
|
|
263
263
|
end
|
|
264
264
|
```
|
|
265
265
|
|
|
266
|
-
Accepts a `Riffer::Tools::Runtime` subclass, a `Riffer::Tools::Runtime` instance, or a `Proc`. When unset, defaults to `Riffer.config.tool_runtime` (captured at agent class definition time). See [Tools — Tool Runtime](
|
|
266
|
+
Accepts a `Riffer::Tools::Runtime` subclass, a `Riffer::Tools::Runtime` instance, or a `Proc`. When unset, defaults to `Riffer.config.tool_runtime` (captured at agent class definition time). See [Tools — Tool Runtime](TOOL_ADVANCED.md#tool-runtime-experimental) for details.
|
|
267
267
|
|
|
268
268
|
### guardrail
|
|
269
269
|
|
|
@@ -284,7 +284,7 @@ class MyAgent < Riffer::Agent
|
|
|
284
284
|
end
|
|
285
285
|
```
|
|
286
286
|
|
|
287
|
-
See [Guardrails](
|
|
287
|
+
See [Guardrails](GUARDRAILS.md) for detailed documentation.
|
|
288
288
|
|
|
289
289
|
## Configuration Object
|
|
290
290
|
|
|
@@ -333,7 +333,7 @@ Keys and values may be `String` or `Symbol`; both are stringified, and entries w
|
|
|
333
333
|
Tags propagate to **two** places:
|
|
334
334
|
|
|
335
335
|
1. The provider's native per-request metadata field (see the mapping below).
|
|
336
|
-
2. Observability — stamped as `riffer.tag.<key>` on **every** span the call emits (`invoke_agent`, `chat`, `execute_tool`, `execute_guardrail`). See [Tracing](
|
|
336
|
+
2. Observability — stamped as `riffer.tag.<key>` on **every** span the call emits (`invoke_agent`, `chat`, `execute_tool`, `execute_guardrail`). See [Tracing](TRACING.md).
|
|
337
337
|
|
|
338
338
|
### Reserved key: `user_id`
|
|
339
339
|
|
|
@@ -361,12 +361,12 @@ Riffer does not validate tag count, key/value length, or charset — it forwards
|
|
|
361
361
|
|
|
362
362
|
| Goal | Feature | Guide |
|
|
363
363
|
| ----------------------------- | ----------------- | -------------------------------------------------------------------- |
|
|
364
|
-
| Call APIs or run functions | Tools | [Tools](
|
|
364
|
+
| Call APIs or run functions | Tools | [Tools](TOOLS.md) |
|
|
365
365
|
| Return structured JSON | Structured Output | [structured_output](#structured_output) |
|
|
366
|
-
| Validate or filter content | Guardrails | [Guardrails](
|
|
367
|
-
| Measure output quality | Evals | [Evals](
|
|
368
|
-
| Add packaged capabilities | Skills | [Skills](
|
|
369
|
-
| Control the tool-use loop | Agent Loop | [Agent Loop](
|
|
370
|
-
| Human-in-the-loop approval | Interrupts | [Agent Lifecycle](
|
|
371
|
-
| Run tools concurrently | Tool Runtime | [Advanced Tools](
|
|
372
|
-
| Stream responses in real time | Streaming | [Agent Lifecycle](
|
|
366
|
+
| Validate or filter content | Guardrails | [Guardrails](GUARDRAILS.md) |
|
|
367
|
+
| Measure output quality | Evals | [Evals](EVALS.md) |
|
|
368
|
+
| Add packaged capabilities | Skills | [Skills](SKILLS.md) |
|
|
369
|
+
| Control the tool-use loop | Agent Loop | [Agent Loop](AGENT_LOOP.md) |
|
|
370
|
+
| Human-in-the-loop approval | Interrupts | [Agent Lifecycle](AGENT_LIFECYCLE.md#interrupting-the-agent-loop) |
|
|
371
|
+
| Run tools concurrently | Tool Runtime | [Advanced Tools](TOOL_ADVANCED.md#tool-runtime-experimental) |
|
|
372
|
+
| Stream responses in real time | Streaming | [Agent Lifecycle](AGENT_LIFECYCLE.md#stream) |
|
|
@@ -341,7 +341,7 @@ msg.structured_output? # => true
|
|
|
341
341
|
msg.structured_output # => {sentiment: "positive", score: 0.95}
|
|
342
342
|
```
|
|
343
343
|
|
|
344
|
-
See [Messages — Structured Output on Messages](
|
|
344
|
+
See [Messages — Structured Output on Messages](MESSAGES.md#structured-output-on-messages) for details.
|
|
345
345
|
|
|
346
346
|
## Class Methods
|
|
347
347
|
|
|
@@ -32,11 +32,11 @@ Riffer.config.anthropic.api_key
|
|
|
32
32
|
|
|
33
33
|
## Provider-Specific Configuration
|
|
34
34
|
|
|
35
|
-
For provider credentials and setup, see the individual [Provider guides](providers/).
|
|
35
|
+
For provider credentials and setup, see the individual [Provider guides](providers/PROVIDERS.md).
|
|
36
36
|
|
|
37
37
|
### MCP (Model Context Protocol)
|
|
38
38
|
|
|
39
|
-
Optional settings for [MCP server integrations](
|
|
39
|
+
Optional settings for [MCP server integrations](MCP.md):
|
|
40
40
|
|
|
41
41
|
| Option | Description |
|
|
42
42
|
| ------------------ | --------------------------------------------------------------------------------------------------------------- |
|
|
@@ -51,7 +51,7 @@ Riffer.configure do |config|
|
|
|
51
51
|
end
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
See [MCP](
|
|
54
|
+
See [MCP](MCP.md) for registration, tags, and agent `use_mcp`.
|
|
55
55
|
|
|
56
56
|
### Tool Runtime (Experimental)
|
|
57
57
|
|
|
@@ -71,7 +71,7 @@ end
|
|
|
71
71
|
| `Riffer::Tools::Runtime` instance | Custom runtime with specific options |
|
|
72
72
|
| `Proc` | Dynamic resolution |
|
|
73
73
|
|
|
74
|
-
Per-agent configuration overrides this global default. See [Advanced Tool Configuration — Tool Runtime](
|
|
74
|
+
Per-agent configuration overrides this global default. See [Advanced Tool Configuration — Tool Runtime](TOOL_ADVANCED.md#tool-runtime-experimental) for details.
|
|
75
75
|
|
|
76
76
|
### Skills
|
|
77
77
|
|
|
@@ -87,7 +87,7 @@ Riffer.configure do |config|
|
|
|
87
87
|
end
|
|
88
88
|
```
|
|
89
89
|
|
|
90
|
-
Per-agent override is available inside the `skills` block via `activate_tool MyCustomActivateTool`. See [Skills — Custom Activation Tool](
|
|
90
|
+
Per-agent override is available inside the `skills` block via `activate_tool MyCustomActivateTool`. See [Skills — Custom Activation Tool](SKILLS.md#custom-activation-tool).
|
|
91
91
|
|
|
92
92
|
#### Default backend
|
|
93
93
|
|
|
@@ -117,11 +117,11 @@ end
|
|
|
117
117
|
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
118
118
|
| `enabled` | The kill switch, consulted on every span — flipping it at runtime takes effect immediately, short-circuiting to a no-op ahead of the backend. Accepts booleans or `'true'`/`'false'`/`'1'`/`'0'`. Defaults to `true`. |
|
|
119
119
|
| `capture_messages` | Opt-in capture of full message content on LLM-call spans (`gen_ai.input.messages`, `gen_ai.output.messages`, `gen_ai.system_instructions`) as GenAI-semconv JSON. Defaults to `false` — message content routinely carries sensitive data. File attachments serialize as metadata-only stubs (media type and name, never bytes), and riffer applies no size limit of its own — cap oversized attributes with the OTEL SDK attribute length limits. |
|
|
120
|
-
| `backend` | The backend riffer routes spans through. Assign `Riffer::Tracing::Otel.build` (pass `provider:` to override the global tracer provider — e.g. an in-memory provider in tests), or any object satisfying the duck-typed contract (`in_span` / `current_context` / `with_context`) to route into a non-OTEL system (e.g. Datadog APM). Defaults to `nil` — a no-op. Raises `Riffer::ArgumentError` unless the value is `nil` or responds to `in_span`. See [Tracing → Routing to a non-OpenTelemetry backend](
|
|
120
|
+
| `backend` | The backend riffer routes spans through. Assign `Riffer::Tracing::Otel.build` (pass `provider:` to override the global tracer provider — e.g. an in-memory provider in tests), or any object satisfying the duck-typed contract (`in_span` / `current_context` / `with_context`) to route into a non-OTEL system (e.g. Datadog APM). Defaults to `nil` — a no-op. Raises `Riffer::ArgumentError` unless the value is `nil` or responds to `in_span`. See [Tracing → Routing to a non-OpenTelemetry backend](TRACING.md#routing-to-a-non-opentelemetry-backend). |
|
|
121
121
|
|
|
122
122
|
### Pricing
|
|
123
123
|
|
|
124
|
-
Configure per-model token prices and riffer computes the cost of each LLM call onto its [`TokenUsage`](
|
|
124
|
+
Configure per-model token prices and riffer computes the cost of each LLM call onto its [`TokenUsage`](MESSAGES.md#token-usage-semantics). Riffer ships **no** price table — so an unconfigured model simply carries no cost (`token_usage.cost` is `nil`).
|
|
125
125
|
|
|
126
126
|
```ruby
|
|
127
127
|
Riffer.configure do |config|
|
|
@@ -151,7 +151,7 @@ cost = (input − cache_read − cache_write) × input_rate
|
|
|
151
151
|
+ output × output_rate
|
|
152
152
|
```
|
|
153
153
|
|
|
154
|
-
(all rates ÷ 1,000,000; an unset cache rate falls back to `input_rate`.) Cost is for observability, not billing — it's a `Float`, and sub-cent rounding can accumulate over a long run. See [Messages → Token Usage Semantics](
|
|
154
|
+
(all rates ÷ 1,000,000; an unset cache rate falls back to `input_rate`.) Cost is for observability, not billing — it's a `Float`, and sub-cent rounding can accumulate over a long run. See [Messages → Token Usage Semantics](MESSAGES.md#token-usage-semantics) for how cost surfaces and aggregates.
|
|
155
155
|
|
|
156
156
|
### Message ID Strategy
|
|
157
157
|
|
|
@@ -173,7 +173,7 @@ When the strategy is not `:none`, every `Riffer::Messages::Base` instance — us
|
|
|
173
173
|
|
|
174
174
|
When constructing a `Riffer::Agent::Session` from persisted history with the strategy enabled, supply ids on every seeded message yourself — Riffer never fabricates identifiers for pre-existing history. Messages built via the `Riffer::Messages::*` constructors auto-generate ids per the strategy, so as long as those constructors are used at message-creation time, ids flow through.
|
|
175
175
|
|
|
176
|
-
See [Messages — IDs](
|
|
176
|
+
See [Messages — IDs](MESSAGES.md#ids) for more details.
|
|
177
177
|
|
|
178
178
|
### Experimental: History Healing
|
|
179
179
|
|
|
@@ -194,7 +194,7 @@ When enabled, two repairs run automatically:
|
|
|
194
194
|
|
|
195
195
|
Defaults to `false` — pre-healing behavior. Seeded sessions pass through untouched, and orphan `tool_use` left by an interrupt remain in history for `execute_pending_tool_calls` to re-run on the next call.
|
|
196
196
|
|
|
197
|
-
There is no per-call override and no customizable placeholder. Callers needing finer control can call `agent.session.update(tool_call_id:, ...)` after the interrupt returns to upgrade a placeholder in place. See [Agent Lifecycle — Healing pending tool results on interrupt](
|
|
197
|
+
There is no per-call override and no customizable placeholder. Callers needing finer control can call `agent.session.update(tool_call_id:, ...)` after the interrupt returns to upgrade a placeholder in place. See [Agent Lifecycle — Healing pending tool results on interrupt](AGENT_LIFECYCLE.md#healing-pending-tool-results-on-interrupt-experimental).
|
|
198
198
|
|
|
199
199
|
## Agent-Level Configuration
|
|
200
200
|
|
|
@@ -24,7 +24,7 @@ gem install riffer
|
|
|
24
24
|
|
|
25
25
|
## Provider Setup
|
|
26
26
|
|
|
27
|
-
Riffer requires an LLM provider. See [Providers](providers/
|
|
27
|
+
Riffer requires an LLM provider. See [Providers](providers/PROVIDERS.md) for setup instructions for each supported provider.
|
|
28
28
|
|
|
29
29
|
## Creating Your First Agent
|
|
30
30
|
|
|
@@ -91,8 +91,8 @@ puts agent.generate("What time is it?")
|
|
|
91
91
|
|
|
92
92
|
## Next Steps
|
|
93
93
|
|
|
94
|
-
- [Agents](
|
|
95
|
-
- [Tools](
|
|
96
|
-
- [Messages](
|
|
97
|
-
- [Stream Events](
|
|
98
|
-
- [Providers](providers/
|
|
94
|
+
- [Agents](AGENTS.md) - Agent configuration options
|
|
95
|
+
- [Tools](TOOLS.md) - Creating tools with parameters
|
|
96
|
+
- [Messages](MESSAGES.md) - Message types and history
|
|
97
|
+
- [Stream Events](STREAM_EVENTS.md) - Streaming event types
|
|
98
|
+
- [Providers](providers/PROVIDERS.md) - Provider-specific guides
|
data/docs/{14_MCP.md → MCP.md}
RENAMED
|
@@ -91,7 +91,7 @@ Tool names must be unique across `uses_tools` and all included MCP servers; dupl
|
|
|
91
91
|
|
|
92
92
|
### Subclassing
|
|
93
93
|
|
|
94
|
-
Like [`uses_tools`](
|
|
94
|
+
Like [`uses_tools`](AGENTS.md#uses_tools), **`use_mcp` is not inherited** from the superclass. Declare `use_mcp` on each agent class that should load MCP tools.
|
|
95
95
|
|
|
96
96
|
## Progressive Tool Discovery
|
|
97
97
|
|
|
@@ -77,7 +77,7 @@ end
|
|
|
77
77
|
|
|
78
78
|
The cache buckets are subsets of `input_tokens`, never additions to it — summing `input_tokens + cache_read_tokens` double-counts. `total_tokens` (input + output) matches the totals providers report on their dashboards.
|
|
79
79
|
|
|
80
|
-
- `cost` — the computed cost of the call, set when pricing is configured for the model in use (see [Configuration → Pricing](
|
|
80
|
+
- `cost` — the computed cost of the call, set when pricing is configured for the model in use (see [Configuration → Pricing](CONFIGURATION.md#pricing)); `nil` when the model is unpriced. It's for observability, not billing. Run-level usage sums per-call costs through `TokenUsage#+`, so `response.token_usage.cost` is the total spend across the run — but the sum is `nil` if any call in the run used an unpriced model, rather than silently under-reporting.
|
|
81
81
|
|
|
82
82
|
#### Finish Reasons
|
|
83
83
|
|
|
@@ -269,7 +269,7 @@ When creating tool result messages, use the `id` as `tool_call_id`.
|
|
|
269
269
|
|
|
270
270
|
Agents can emit messages as they're added during generation via the `on_message` callback. This is useful for persistence or real-time logging. Only agent-generated messages (Assistant, Tool) are emitted—not inputs (System, User).
|
|
271
271
|
|
|
272
|
-
See [Agent Lifecycle - on_message](
|
|
272
|
+
See [Agent Lifecycle - on_message](AGENT_LIFECYCLE.md#on_message) for details.
|
|
273
273
|
|
|
274
274
|
## Consecutive Message Merging
|
|
275
275
|
|
|
@@ -317,7 +317,7 @@ msg.id # => "0195a2e1-..." (auto-generated UUIDv7)
|
|
|
317
317
|
msg.to_h # => {role: :user, content: "Hello", id: "0195a2e1-..."}
|
|
318
318
|
```
|
|
319
319
|
|
|
320
|
-
Supported strategies: `:none` (default), `:uuid`, `:uuidv7`. See [Configuration — Message ID Strategy](
|
|
320
|
+
Supported strategies: `:none` (default), `:uuid`, `:uuidv7`. See [Configuration — Message ID Strategy](CONFIGURATION.md#message-id-strategy) for the full reference.
|
|
321
321
|
|
|
322
322
|
Ids pass through to subclass constructors via an `id:` kwarg and are preserved when set explicitly:
|
|
323
323
|
|
|
@@ -357,4 +357,4 @@ Subclasses implement `role` and optionally extend `to_h` with additional fields.
|
|
|
357
357
|
|
|
358
358
|
## Editing history after the fact
|
|
359
359
|
|
|
360
|
-
The session's `messages` array is mutable, but the message value objects themselves are immutable. To edit recorded history — truncate an assistant message, rewrite a tool result, fill an orphan `tool_use` — use the mutators on `agent.session` (`update`, `remove`). Each one enforces the `tool_use` ↔ `tool_result` invariant. See [Mutating history](
|
|
360
|
+
The session's `messages` array is mutable, but the message value objects themselves are immutable. To edit recorded history — truncate an assistant message, rewrite a tool result, fill an orphan `tool_use` — use the mutators on `agent.session` (`update`, `remove`). Each one enforces the `tool_use` ↔ `tool_result` invariant. See [Mutating history](AGENT_LIFECYCLE.md#mutating-history) for the full list.
|