Documentation
ActiveAgent documentation is deterministic and always accurate because every code example comes from tested files. Documentation and code can't drift apart—if the code changes, the docs automatically reflect it.
Important: When updating ActiveAgent documentation, you must follow the process outlined in this file. All code examples must be imported from tested files using VitePress imports—never hardcode examples in markdown.
Why This Matters
The problem with typical docs: Code examples get hardcoded, tests don't cover them, and they become outdated as the codebase evolves.
Our solution: Import all code directly from tests and implementations using VitePress. Examples stay synchronized with the actual codebase, outputs are real, and everything is traceable.
Core Principles
- Zero hardcoded examples — Use VitePress
<<<imports only - Test everything documented — If it's in docs, it must be tested
- Generate real outputs — Use
doc_example_outputfor response examples - Maintain determinism — VCR cassettes ensure consistent API responses
Quick Start
To document a new feature:
- Write tests with region markers around example code
- Run tests to generate example outputs
- Import test regions into documentation
- Preview locally with
bin/docs
How It Works
VitePress Code Imports
Import code directly from source files instead of copying:
<!-- Import full file -->
<<< @/../test/dummy/app/agents/support_agent.rb {ruby}
<!-- Import region (recommended for tests) -->
<<< @/../test/docs/support_agent_test.rb#tool_call_example {ruby:line-numbers}When to use each:
- Full file: Complete agent implementations
- Region: Test code examples (preferred)
Code Regions in Tests
Mark code you want to reference in documentation:
# region tool_call_example
def test_tool_calling
response = SupportAgent.with(question: "Reset my password").help.generate_now
doc_example_output(response)
assert_includes response.tool_calls.map(&:name), "reset_password"
end
# endregion tool_call_exampleRegion naming: Use descriptive snake_case names unique within the file.
Generating Example Outputs
The doc_example_output helper (in test/test_helper.rb) captures test results for documentation:
def test_data_extraction
response = DataAgent.with(content: "...").extract.generate_now
doc_example_output(response) # Generates markdown file automatically
assert response.success?
endWhat it creates:
- File:
docs/parts/examples/{test-file}-{test-name}.md - Contains: Formatted output with source file link and metadata
- Supports: Ruby objects, JSON, and response objects
Include in docs:
::: details Response Example
<!-- @include: @/parts/examples/data-agent-test.rb-test-data-extraction.md -->
:::VCR for Deterministic API Responses
VCR records and replays HTTP interactions, ensuring:
- Consistent test results across runs
- No API costs during development
- Deterministic documentation examples
def test_translation
VCR.use_cassette("translation_agent_translate") do
response = TranslationAgent.with(text: "Hello", target: "fr").translate.generate_now
assert_equal "Bonjour", response.message
end
endCassettes stored in test/fixtures/vcr_cassettes/. Re-record with: VCR_RECORD_MODE=once bin/test
Workflow
1. Write Tests with Regions
# test/docs/my_agent_test.rb
class MyAgentTest < ActiveSupport::TestCase
# region basic_usage
def test_basic_feature
response = MyAgent.with(param: "value").my_action.generate_now
doc_example_output(response)
assert response.success?
end
# endregion basic_usage
end2. Run Tests
# Run specific test
bin/test test/docs/my_agent_test.rb
# Re-record VCR cassettes if needed
VCR_RECORD_MODE=once bin/test test/docs/my_agent_test.rb3. Import into Documentation
<!-- docs/examples/my-feature.md -->
## Basic Usage
<<< @/../test/docs/my_agent_test.rb#basic_usage {ruby:line-numbers}
::: details Response
<!-- @include: @/parts/examples/my-agent-test.rb-test-basic-feature.md -->
:::4. Preview
bin/docs # Starts VitePress dev server at http://localhost:5173Verify code imports render correctly and links work.
Common Patterns
Simple Example
Import a test region to show basic usage:
<<< @/../test/docs/application_agent_test.rb#basic_usage {ruby:line-numbers}Implementation + View
Show multiple related files together:
::: code-group
```ruby [translation_agent.rb]
class TranslationAgent < ApplicationAgent
def translate
prompt
end
end
\```
```ruby [translate.json.jbuilder]
json.action_name "translate"
json.message params[:message]
\```
:::Test with Output
Display test code alongside its actual result:
\```ruby
prompt = DataExtractionAgent.with(
image_path: image_path
).parse_content
response = prompt.generate_now
\```
::: details Response
<!-- @include: @/parts/examples/data-extraction-agent-test.rb-test-extract-data.md -->
:::Multiple Output Formats
Use tabs to show different perspectives of the same data:
::: tabs
== Response Object
<!-- @include: @/parts/examples/agent-test.rb-test-structured-output.md -->
== JSON
<!-- @include: @/parts/examples/agent-test.rb-json-output.md -->
:::File Structure
Source implementations:
test/dummy/app/agents/— Agent classestest/dummy/app/views/— Action View templatestest/docs/- Test files
Documentation:
docs/— All documentation markdown filesdocs/parts/examples/— Auto-generated outputs (naming:{test-file}-{test-method}.md)
Troubleshooting
Import Not Showing
- Verify file path (use
@/../prefix) - Check region name matches exactly (case-sensitive)
- Ensure region markers formatted correctly:
# region name/# endregion name - Rebuild:
bin/docs
Example File Not Generated
- Confirm test ran:
bin/test - Check
docs/parts/examples/exists - Verify
doc_example_outputis called in test
VCR Issues
- Ensure
test/dummy/config/master.keyexists - Re-record cassette:
VCR_RECORD_MODE=once bin/test - Check cassette exists in
test/fixtures/vcr_cassettes/
Import Path Not Resolving
- Use
@/../prefix for paths relative to docs root - Verify file extension correct
- Check line ranges valid (e.g.,
#5-9)
Rules
Always:
- ✅ Import all code with
<<<syntax - ✅ Test code before documenting
- ✅ Use regions for test examples
- ✅ Generate outputs with
doc_example_output - ✅ Add line numbers:
{ruby:line-numbers} - ✅ Preview locally before committing
Never:
- ❌ Hardcode examples in markdown
- ❌ Document untested features
- ❌ Copy/paste code from tests
- ❌ Break existing imports when refactoring
Contributing
When adding documentation:
- Write or identify the test demonstrating the feature
- Add descriptive region markers around example code
- Call
doc_example_outputfor response examples - Import regions into documentation
- Preview with
bin/docs - Commit generated examples and VCR cassettes
When reviewing documentation PRs:
- ✅ All examples use
<<<imports - ✅ Tests exist and pass
- ✅ Example outputs generated and committed
- ✅ VCR cassettes committed (if applicable)
- ✅ Code renders correctly in preview
- ✅ Links work