Why
The ISavedResponseStore and the four message handlers (SaveResponseRequestHandler, GetSavedResponseRequestHandler, ListSavedResponsesRequestHandler, DeleteSavedResponseRequestHandler) are already wired up — but the only thing that sends SaveResponseRequest is the Blazor UI's save button (Chat.razor:625). The agent itself can't write to the store from its LLM loop.
This blocks the elegant solution to the scheduled-task delivery problem that came up in #415: a scheduled task can produce rich output (charts, color, tables) at any time, but the user may be on a client that can't render it when it fires. The right pattern is:
- Scheduled task generates rich output
- Agent calls
save_response(label, content) to stash it
- Agent publishes a short notice on the broadcast topic ("Daily summary ready — open saved responses to view")
- User opens Blazor any time later and reads the rich version from the saved-responses panel
Without this tool, the only way to land the rich output is by broadcasting and hoping the user is on a capable client — which is exactly the audience-uncertainty problem we documented but couldn't solve cleanly in #415.
What
Add src/RockBot.Host/SavedResponseTools.cs next to MemoryTools / WorkingMemoryTools / RulesTools, with three AIFunctions:
save_response(label, content, agentName?) → calls ISavedResponseStore.SaveAsync directly (no message-bus round-trip needed; the store is an in-process singleton). Returns the new saved-response ID.
list_saved_responses(maxResults?) → returns recent labels + IDs.
get_saved_response(id) → returns content (for the agent to re-reference or rework).
Register in RockBot.Agent/Program.cs alongside the other agent tools. Skill-guide entries documenting the "rich scheduled output → save → notify" pattern.
Why deferred from #415
The capability/sanitizer scaffolding had to land first. With #415 in, this is the natural next step — small file, clean addition, unlocks the deferred "audience-uncertainty" story.
Related
Why
The
ISavedResponseStoreand the four message handlers (SaveResponseRequestHandler,GetSavedResponseRequestHandler,ListSavedResponsesRequestHandler,DeleteSavedResponseRequestHandler) are already wired up — but the only thing that sendsSaveResponseRequestis the Blazor UI's save button (Chat.razor:625). The agent itself can't write to the store from its LLM loop.This blocks the elegant solution to the scheduled-task delivery problem that came up in #415: a scheduled task can produce rich output (charts, color, tables) at any time, but the user may be on a client that can't render it when it fires. The right pattern is:
save_response(label, content)to stash itWithout this tool, the only way to land the rich output is by broadcasting and hoping the user is on a capable client — which is exactly the audience-uncertainty problem we documented but couldn't solve cleanly in #415.
What
Add
src/RockBot.Host/SavedResponseTools.csnext toMemoryTools/WorkingMemoryTools/RulesTools, with threeAIFunctions:save_response(label, content, agentName?)→ callsISavedResponseStore.SaveAsyncdirectly (no message-bus round-trip needed; the store is an in-process singleton). Returns the new saved-response ID.list_saved_responses(maxResults?)→ returns recent labels + IDs.get_saved_response(id)→ returns content (for the agent to re-reference or rework).Register in
RockBot.Agent/Program.csalongside the other agent tools. Skill-guide entries documenting the "rich scheduled output → save → notify" pattern.Why deferred from #415
The capability/sanitizer scaffolding had to land first. With #415 in, this is the natural next step — small file, clean addition, unlocks the deferred "audience-uncertainty" story.
Related
design/client-rendering-capabilities.md(the "Deferred" section explicitly describes this)