What Worked, Not Just What Happened
Memory tells Wolffish what happened. The feedback loop tells it what worked. Thebasalganglia module records the outcome of every tool call — whether it succeeded, whether you approved or denied flagged operations, and what got blocked outright. Over time, this builds learned behavioral preferences without explicit programming.
Location
Five Outcome Types
How Feedback Is Recorded
After every tool call,basalganglia.recordOutcome() appends an entry:
- Timestamp — when it happened
- Tool name — which capability was invoked
- Outcome — success, failed, denied, approved, or blocked
- Truncated args — what was passed (capped at ~200 characters; the full-fidelity copy lives in
brain/conversations/*.json) - Detail — the denial reason, the error, or an output preview, depending on outcome
Example Feedback Entries
How Feedback Influences Behavior
Raw feedback files used to be concatenated into every prompt — tens of thousands of tokens of transcript, most of it noise. That’s gone.basalganglia.getPreferences() now collapses the last 7 days into a bounded preference digest (~500 tokens, hard-capped at 2,400 characters) with three size-capped parts:
- Reliability line — total tool calls, success rate, most-used tools
- Recently-denied line — tools you rejected (don’t repeat unless asked)
- Recent corrections — the latest failures and denials with their reason, so the planner doesn’t walk into a known dead end (at most 12, newest first)
wolffish_recall away, and memory_search with sources: "feedback" searches every entry ever recorded.
The digest fills one of only two ambient memory slots in the system prompt — the other is the
<memory_map> coverage stub. Since v1.0.233 that first slot belongs to the reflection playbook once one exists; the digest remains the bootstrap fallback until the first nightly reflection has run. Everything else is retrieved on demand. Today’s file is excluded from the digest (today’s actions are already visible in the live thread), which keeps the block byte-stable across a turn’s tool loop so providers can reuse the cached prompt prefix.The Interface
basalganglia exposes two methods:
What the LLM Learns
Over time, patterns emerge from accumulated feedback:Commit style preferences
Commit style preferences
After several
success outcomes on commits with conventional format (feat:, fix:, chore:), the LLM learns to always use this format. If a non-conventional commit was ever denied, that correction rides in the digest.Safe operations
Safe operations
If you consistently approve git pushes to feature branches, Wolffish learns that these are low-risk. If you consistently deny force pushes, the denied-tools line teaches it to avoid suggesting them — or to flag them more prominently.
Error recovery
Error recovery
After a
failed outcome from a specific approach (e.g., searching an internal site that isn’t indexed), the correction — with its error detail — tells the LLM to try alternative approaches next time (e.g., asking you for the URL directly).Tool preferences
Tool preferences
If
pnpm commands always succeed but an npm command was denied once, the LLM learns your package manager preference from outcomes — not just from preferences.md.Growing With You
This is the mechanism that makes Wolffish adaptive over time. It’s not just remembering facts (knowledge files do that) — it’s remembering what worked in practice. The combination creates an agent that:- Knows your preferences (knowledge) — what you said you want
- Knows what actually works (feedback) — what produced good outcomes
- Avoids past mistakes (corrections) — what went wrong before
- Reviews whole conversations (reflection) — nightly lessons distilled into a playbook, anchored by your 0–10 turn scores
Inspecting and Editing Feedback
The feedback files are plain markdown. You can:- Read them to understand why Wolffish behaves a certain way
- Delete entries to “unlearn” a pattern (e.g., remove old denials that no longer apply)
- Add entries to seed behavior (e.g., add a denial for
rm -rf /even if it never happened)