feat: Add agent lessons log and niagara agent playbook for incident learnings#2
Merged
Merged
Conversation
…earnings - Introduced `agent-lessons.md` to document incident learnings and corrective actions. - Created `niagara-agent-playbook.md` to provide command patterns and payload templates for nMCP workflow. - Enhanced `agent.py` with validation for wiresheet payloads and improved error handling for path discovery. - Implemented UI components for about, help, and plan review dialogs to improve user experience. - Added toggles for Plan Mode and Strict Paths in the chat widget to enhance user control over agent behavior.
There was a problem hiding this comment.
Pull request overview
This PR adds a local “memory” subsystem (SQLite-backed) to persist station context, tool learnings, and conversation history, and wires it into the Qt UI (conversation picker + memory health panel) and the agent loop (memory context injection + tool outcome observation).
Changes:
- Introduces
MemoryManager(SQLite + lightweight JSON cache) with conversation threads/messages, station profile caching, and tool “lesson” capture. - Updates the main UI to show memory health and support selecting/creating persisted conversations in the chat widget.
- Enhances the agent loop with rate-limit retries, tool result truncation, and a tool observer callback for learning capture.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
src/ui/memory_health_widget.py |
New widget to display SQLite/db counters and trigger refresh. |
src/ui/chat_widget.py |
Adds conversation picker + history rendering for persisted conversations. |
src/ui/app.py |
Integrates memory manager, persistence hooks, health widget, and conversation UX. |
src/memory/manager.py |
New SQLite-backed memory manager (profiles, preferences, lessons, conversations). |
src/memory/__init__.py |
Exposes memory manager/snapshot types. |
src/agent.py |
Adds memory context injection, rate-limit retry loop, tool result truncation, tool observer hook. |
scripts/build_windows.ps1 |
Adds Windows PyInstaller build script with bundled Candy docs + optional seed DB. |
README.md |
Documents SQLite packaging/bootstrap approach and Windows build script usage. |
config.py |
Adds memory configuration (enabled flag, token budget, paths). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+174
to
+179
| wait_seconds = _parse_rate_limit_wait_seconds(str(exc)) | ||
| is_last_attempt = attempt >= _LLM_RATE_LIMIT_MAX_RETRIES | ||
| if wait_seconds is None or is_last_attempt: | ||
| self.signals.error_occurred.emit(f"LLM error: {exc}") | ||
| logger.exception("LLM error on iteration %d", iteration + 1) | ||
| return |
Comment on lines
+378
to
+385
| def _initialize_conversations_ui(self) -> None: | ||
| station = self._config.connection.station_name | ||
| endpoint = self._config.connection.mcp_url | ||
| thread = self._memory.ensure_default_conversation(station, endpoint) | ||
| self._active_conversation_id = thread.conversation_id | ||
| self._load_conversations_ui() | ||
| self._load_active_conversation_history() | ||
|
|
Comment on lines
+418
to
+425
| def _on_new_conversation_requested(self) -> None: | ||
| station = self._config.connection.station_name | ||
| endpoint = self._mcp.endpoint_url or self._config.connection.mcp_url | ||
| thread = self._memory.create_conversation(station, endpoint) | ||
| self._active_conversation_id = thread.conversation_id | ||
| self._load_conversations_ui() | ||
| self._load_active_conversation_history() | ||
|
|
Comment on lines
+386
to
+392
| def _load_conversations_ui(self) -> None: | ||
| station = self._config.connection.station_name | ||
| endpoint = self._mcp.endpoint_url or self._config.connection.mcp_url | ||
| threads = self._memory.list_conversations(station, endpoint) | ||
| items = [(t.conversation_id, t.title) for t in threads] | ||
| self._sig_conversations_loaded.emit(items, self._active_conversation_id) | ||
|
|
Comment on lines
+404
to
+416
| station_key = self._build_station_key(station_name, endpoint_url) | ||
| working_ord = self._extract_working_ord(arguments) | ||
| if working_ord: | ||
| self._set_preference(station_key, "last_working_ord", working_ord) | ||
| self._set_preference(station_key, "last_working_tool", tool_name) | ||
|
|
||
| lesson = self._derive_tool_lesson(tool_name, arguments, result_text) | ||
| if lesson: | ||
| self._insert_tool_lesson( | ||
| scope="station", | ||
| tool_name=tool_name, | ||
| lesson=lesson, | ||
| ) |
Comment on lines
+497
to
+507
| with sqlite3.connect(self._db_path) as conn: | ||
| rows = conn.execute( | ||
| """ | ||
| SELECT lesson | ||
| FROM tool_lesson | ||
| WHERE scope IN ('global', 'station') | ||
| ORDER BY id DESC | ||
| LIMIT 3 | ||
| """ | ||
| ).fetchall() | ||
| lessons = [str(row[0]).strip() for row in rows if row and str(row[0]).strip()] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
agent-lessons.mdto document incident learnings and corrective actions.niagara-agent-playbook.mdto provide command patterns and payload templates for nMCP workflow.agent.pywith validation for wiresheet payloads and improved error handling for path discovery.