Skip to content

feat: Add agent lessons log and niagara agent playbook for incident learnings#2

Merged
makeitworkok merged 1 commit into
mainfrom
feature/memory-layer-mvp
May 31, 2026
Merged

feat: Add agent lessons log and niagara agent playbook for incident learnings#2
makeitworkok merged 1 commit into
mainfrom
feature/memory-layer-mvp

Conversation

@makeitworkok

Copy link
Copy Markdown
Owner
  • 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.

Copilot AI review requested due to automatic review settings May 25, 2026 01:31
…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.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 thread src/agent.py
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 thread src/ui/app.py
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 thread src/ui/app.py
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 thread src/ui/app.py
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 thread src/memory/manager.py
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 thread src/memory/manager.py
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()]
@makeitworkok makeitworkok merged commit f1939f8 into main May 31, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants