Document SolidAgent, and test the two repos together - #364
Conversation
solid_agent's gemspec has pointed its homepage and documentation_uri at docs.activeagents.ai/solid_agent since it was published, and that page did not exist — the docs mentioned the gem only in passing, as something the dashboard happens to depend on. Adds a Persistence section: an overview at /solid_agent plus a page per concern (context, memory, tools/streaming/caching, reasoning, runs and cost, manifests) and a worked-examples page mirroring examples/ in the solid_agent repo. Linked from the sidebar, the home page features, the framework overview, getting started, the agents and tools pages, and the dashboard page that already depended on the gem. These pages carry their code inline rather than importing it, because the code they document lives in another repository; contributing/documentation now says so, and points at the tested examples they mirror. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGn2NzpzFZT4JGKBdFMpxh
Three gems, two repositories, one dependency direction — and nothing ran them together, so all three suites were green while the combination a user installs was broken. test/integration/solid_agent runs both repos in the dummy app against the models solid_agent:install writes, through the mock provider: conversation persistence, memory hand-offs, run records, the tool cache, and the version constraints themselves. Two configurations. Source (solid_agent main, SOLID_AGENT_STRICT=1) is what the repos develop toward and must be green. Released (whatever Bundler resolves) is what users get; tests declare what they need and skip when the gem can't do it, printing the reason — that skip list is the report of how far the gem trails its source, not a failure. gemfiles/solid_agent_main takes SOLID_AGENT_PATH or SOLID_AGENT_REF so either repo can drive it. Runs on every PR, nightly, and as a gate before publishing; solid_agent's CI runs the same suite from its side. Two breakages it found immediately: - has_context's auto-context keyword was renamed contextable: -> contextual: in solid_agent 0.2. AgentExecutionService still passed the old one, so every dashboard run against current solid_agent died with ArgumentError. Resolved from the installed method now, since the gemspec floor admits both versions. - AgentToolbox's fallback cache key hashed arguments differently from SolidAgent::ToolCache, so upgrading the gem silently invalidated every cached tool result. Both paths now normalize identically. Also fixes the docs and examples that named a context without class_name: has_context :conversation resolves Conversation/ConversationMessage/ ConversationGeneration, not the installed AgentContext family, and raises NameError on the first request. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGn2NzpzFZT4JGKBdFMpxh
Regenerating the dump after adding migration 005 stamped it ActiveRecord::Schema[8.1], the Rails the dump ran under. The API-gem CI jobs pin rails ~> 8.0.0, whose Active Record rejects that version outright — db:migrate died on load with "Unknown migration version" before running a single test. The header tracks whoever last dumped it, so anyone regenerating on 8.1 will reintroduce this; the matrix's floor is what it has to satisfy. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGn2NzpzFZT4JGKBdFMpxh
There was a problem hiding this comment.
Pull request overview
Adds first-class documentation for the solid_agent persistence gem within the ActiveAgent docs site, and introduces a cross-repo integration test + CI workflow to continuously validate the activeagent/actionagent ↔ solid_agent compatibility seam (both against the released gem and against solid_agent main). It also updates the dashboard engine to tolerate upstream API drift (contextable: → contextual:) and to keep tool-cache keys stable across upgrades.
Changes:
- Add a new SolidAgent documentation section (
/solid_agent) with pages for context, memory, tools/caching, reasoning, runs/cost, manifests, and examples; wire it into the docs nav and cross-links. - Add a cross-repo integration suite (
test/integration/solid_agent) plus dummy-app host tables/models matchingsolid_agent:install, and a Gemfile to run againstsolid_agentsource. - Update ActionAgent’s integration points (auto-context keyword detection; tool-cache fallback key normalization) and add CI/release gating via a dedicated integration workflow.
Reviewed changes
Copilot reviewed 41 out of 41 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| test/integration/solid_agent/tool_cache_test.rb | Verifies ToolCache behavior and pins ActionAgent fallback cache key to match SolidAgent::ToolCache. |
| test/integration/solid_agent/runs_test.rb | Exercises host-app AgentRun lifecycle/events and SolidAgent::ModelPricing/fingerprinting integration. |
| test/integration/solid_agent/memory_test.rb | Validates HasMemory hand-off behavior and host-app model persistence. |
| test/integration/solid_agent/integration_case.rb | Base test harness implementing capability/constant gating with strict-mode behavior. |
| test/integration/solid_agent/context_persistence_test.rb | Ensures HasContext persists/replays messages/generations and trace/provenance. |
| test/integration/solid_agent/compatibility_test.rb | Compatibility assertions covering dependency constraints and dashboard API expectations. |
| test/dummy/db/schema.rb | Regenerated dummy schema to include unprefixed host-app persistence tables. |
| test/dummy/db/migrate/005_create_solid_agent_tables.rb | Adds dummy-app migration mirroring solid_agent:install host tables. |
| test/dummy/app/models/agent_run.rb | Adds host-app AgentRun model contract used by integration tests. |
| test/dummy/app/models/agent_message.rb | Adds host-app AgentMessage model contract used by integration tests. |
| test/dummy/app/models/agent_memory.rb | Adds host-app AgentMemory model contract used by integration tests. |
| test/dummy/app/models/agent_memory_entry.rb | Adds host-app AgentMemoryEntry model contract used by integration tests. |
| test/dummy/app/models/agent_generation.rb | Adds host-app AgentGeneration model contract used by integration tests. |
| test/dummy/app/models/agent_context.rb | Adds host-app AgentContext model contract used by integration tests. |
| test/dummy/app/agents/persistence/support_agent.rb | Adds a deterministic mock-provider agent used to drive persistence integration tests. |
| README.md | Adds badges for gem versions, downloads, CI, integration workflow, docs, Ruby/Rails, license. |
| gemfiles/solid_agent_main.gemfile | Adds a bundle configuration to run integration suite against solid_agent source (path/ref). |
| docs/solid_agent/tools.md | Documents SolidAgent tooling schema sources, streaming tool status, and ToolCache behavior. |
| docs/solid_agent/runs.md | Documents run records, progress events, cohorts, and cost estimation. |
| docs/solid_agent/reasoning.md | Documents extended-thinking capture/persistence via HasReasons/Reasonable. |
| docs/solid_agent/memory.md | Documents durable subject-scoped memory and the save_memory/recall_memory tools. |
| docs/solid_agent/manifests.md | Documents .agent.md manifests: loading, validating, exporting, building agents. |
| docs/solid_agent/examples.md | Provides worked examples and links back to the solid_agent repo’s examples/. |
| docs/solid_agent/context.md | Documents has_context behavior, naming, tool exchange persistence, provenance/trace correlation. |
| docs/solid_agent.md | Adds top-level SolidAgent overview page and navigation to subtopics. |
| docs/index.md | Adds SolidAgent “Persistence” feature tile on the docs homepage. |
| docs/getting_started.md | Adds SolidAgent persistence link to framework navigation. |
| docs/framework/dashboard.md | Updates dashboard docs to link to local SolidAgent docs and mention added persistence coverage. |
| docs/framework.md | Adds SolidAgent persistence link to framework overview. |
| docs/contributing/releasing.md | Documents cross-repo testing strategy and release ordering/constraints. |
| docs/contributing/documentation.md | Records the documented exception for sibling-gem pages carrying inline code (no <<< imports). |
| docs/agents.md | Adds SolidAgent persistence link to related topics. |
| docs/actions/tools.md | Adds SolidAgent tools/streaming/caching link to related topics. |
| docs/.vitepress/config.mts | Adds SolidAgent section to the sidebar/nav and a link to releasing docs. |
| AGENTS.md | Adds cross-repo testing instructions for contributors. |
| actionagent/lib/action_agent.rb | Adds runtime detection for has_context auto-context keyword (contextable vs contextual). |
| actionagent/app/services/action_agent/agent_toolbox.rb | Replaces cache-key fallback with normalized scheme matching ToolCache. |
| actionagent/app/services/action_agent/agent_execution_service.rb | Uses detected auto-context keyword when calling has_context for runtime-generated agents. |
| .github/workflows/release.yml | Gates release build on the cross-repo integration workflow. |
| .github/workflows/integration.yml | Adds a dedicated workflow to run integration suite against released and source solid_agent. |
| .github/workflows/ci.yml | Adds integration workflow invocation to PR/CI runs. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
gemfiles/solid_agent_main.gemfile and test/integration/solid_agent live in activeagent, so any revision without them has nothing to run — every release tag until one ships with the harness, and main until activeagents/activeagent#364 merges. Both were hard-failing on a missing BUNDLE_GEMFILE, which reads as "this gem is broken" rather than "the other side is too old". The job now checks for the harness first and skips with that reason in the step summary. The latest-release entry will keep skipping until a release carries the suite, which is the honest state of it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGn2NzpzFZT4JGKBdFMpxh
Mirrors activeagents/solid_agent#8: append_event's read-modify-write on a JSON column loses entries when two writers race, so the re-read and the write are serialized by a row lock. The dummy model tracks the install generator's template, so it moves with it. The runs page repeated the old claim that concurrent appends "interleave safely" — true of the lock, not of the re-read that was there. The context page said "turned auto_save: false off", which reads as the opposite of what it means. Both from Copilot's review. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGn2NzpzFZT4JGKBdFMpxh
|
Copilot's three findings, all accepted (c18e25b): 1. 2. 3. Also since the first review: Generated by Claude Code |
The docs deploy has failed on every push since #360. The site builds fine; upload-artifact then rejects the whole upload: The path for one of the files in artifact is not valid: /parts/examples/delegation-examples-test.rb-test-budgets-layer:-the- agent-wide-ceiling-and-the-per-delegation-limit.html Contains the following character: Colon : doc_example_output names its output after the test, "budgets layer: the agent-wide ceiling..." keeps its colon through dasherize, VitePress emits a page at that path, and the action refuses the characters NTFS cannot store. So docs.activeagents.ai has been serving pre-#360 content for three days, including the SolidAgent section merged in #364. Sanitized in the helper rather than by renaming the test: the next colon in a test name would otherwise break the deploy again, and nothing in the failure points at the test that caused it. The one include referencing the old filename moves with it. Also fixes the "no status" cross-repo integration badge. A workflow_call run is attributed to the caller, so integration.yml had no runs of its own however often it passed. It now triggers itself on main, and ci.yml calls it for pull requests only, so there is one check per PR and a badge that reflects main. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGn2NzpzFZT4JGKBdFMpxh
The docs deploy has failed on every push since #360. The site builds fine; upload-artifact then rejects the whole upload: The path for one of the files in artifact is not valid: /parts/examples/delegation-examples-test.rb-test-budgets-layer:-the- agent-wide-ceiling-and-the-per-delegation-limit.html Contains the following character: Colon : doc_example_output names its output after the test, "budgets layer: the agent-wide ceiling..." keeps its colon through dasherize, VitePress emits a page at that path, and the action refuses the characters NTFS cannot store. So docs.activeagents.ai has been serving pre-#360 content for three days, including the SolidAgent section merged in #364. Sanitized in the helper rather than by renaming the test: the next colon in a test name would otherwise break the deploy again, and nothing in the failure points at the test that caused it. The one include referencing the old filename moves with it. Also fixes the "no status" cross-repo integration badge. A workflow_call run is attributed to the caller, so integration.yml had no runs of its own however often it passed. It now triggers itself on main, and ci.yml calls it for pull requests only, so there is one check per PR and a badge that reflects main. Claude-Session: https://claude.ai/code/session_01NGn2NzpzFZT4JGKBdFMpxh Co-authored-by: Claude <noreply@anthropic.com>
Draft — for review alongside activeagents/solid_agent#8, which adds the examples these pages link to and CI on that side.
Why
solid_agent's gemspec has pointedhomepageanddocumentation_uriatdocs.activeagents.ai/solid_agentsince it was published, and that page did not exist. The docs mentioned the gem only in passing, as something the dashboard happens to depend on.Writing those pages meant running the two gems together, which nothing did — and that turned up two live breakages (below).
What's here
Docs — a Persistence section at
/solid_agent/solid_agent/solid_agent/contexthas_context: naming, options, multiple contexts, the tool exchange, provenance, trace correlation/solid_agent/memoryhas_memory, subject scoping, agent-to-agent hand-off/solid_agent/toolsHasTools,StreamsToolUpdates,ToolCache/solid_agent/reasoningHasReasons+Reasonable/solid_agent/runsAgentRun, progress events, instruction cohorts,ModelPricing/solid_agent/manifests.agent.md, validation, conversion, building classes/solid_agent/examplesexamples/in the solid_agent repo/contributing/releasingLinked from the sidebar, home-page features, framework overview, getting started,
agents.md,actions/tools.md, and the dashboard page that already depended on the gem.npm run docs:buildpasses with dead-link checking on.Cross-repo integration suite —
test/integration/solid_agent/Both gems in the dummy Rails app, against the models
rails generate solid_agent:installwrites, through the mock provider (deterministic, no API keys, no cassettes). Covers conversation persistence, memory hand-offs, run records, the tool cache, and the version constraints themselves.Two configurations, both meaningful:
main,SOLID_AGENT_STRICT=1A test declares what it needs (
requires_solid_agent, orrequires_solid_agent_capabilityfor a method signature) and skips when the resolved gem can't do it, printing the reason; strict mode turns those skips into failures. So the released run never fails for merely being behind — its skip list is the drift report.gemfiles/solid_agent_main.gemfiletakesSOLID_AGENT_PATH(a local checkout) orSOLID_AGENT_REF(branch/tag/SHA), so either repository can drive the same suite. Runs on every PR (ci.yml), nightly, onrepository_dispatch, and as a gate before publishing (release.yml).Two bugs it found immediately
The dashboard was broken against solid_agent's current main.
has_context's auto-context keyword was renamedcontextable:→contextual:in 0.2.AgentExecutionServicestill passed the old one, so every run against source solid_agent died withArgumentError: unknown keyword. Both repos' CI was green, because CI resolves the published 0.1.1 where the old keyword still works. Now resolved from the installed method (ActionAgent.solid_agent_auto_context_keyword) rather than hard-coded, since the gemspec floor admits both versions.AgentToolbox's fallback cache key didn't matchSolidAgent::ToolCache's. The fallback usedkwargs.sort.to_h.to_json; ToolCache normalizes to sorted pairs recursively. Upgrading solid_agent silently invalidated every cached tool result. Both paths normalize identically now, with a test pinning them together.Also fixes the docs and examples that named a context without
class_name:—has_context :conversationresolvesConversation/ConversationMessage/ConversationGeneration, not the installedAgentContextfamily, and raisesNameErroron the first request.Also
README badges: gem version (activeagent + actionagent), downloads, CI, cross-repo integration, docs, Ruby, Rails, license.
Testing
bin/rubocop— clean (458 files)npm run docs:build— clean, dead-link checking verified activemainin this sandbox, which has no API keys)Notes for review
<<<imports.contributing/documentation.mdrequires importing from tested files, but solid_agent's sources are in another repository. The exception is documented there and points at the testedexamples/the pages mirror. The alternative — a git-source dev dependency plustest/docs/tests — is a bigger call than a docs PR should make.HasContext,HasTools,StreamsToolUpdates.HasMemory,AgentRun,ToolCache,ModelPricing,RunFingerprintandAgentManifestexist only on solid_agent's main, which is why 20 tests skip against the real gem and why these docs describe a gem you can'tbundle addyet. Cutting solid_agent 0.2.0 closes that; afterwardsactionagent.gemspec'ssolid_agent >= 0.1floor should move to>= 0.2and the keyword detection inActionAgent.solid_agent_auto_context_keywordcan go.activeagentmain and runs the suite added here, so it stays red until this lands.test/dummy/db/schema.rbis regenerated (migration 005 adds the unprefixed host-app tables; the engine's prefixed copies in 004 are untouched).🤖 Generated with Claude Code
https://claude.ai/code/session_01NGn2NzpzFZT4JGKBdFMpxh