Autonomous Learning Pipeline¶
symfonic-core agents can learn procedures from their own experience without compromising production safety. The pipeline has four stages with a human review gate before any learned skill influences agent behaviour.
The Pipeline¶
Episodic Memory --> SleepConsolidator --> Human Review --> Approved Skill
(observation) Phase 12 (draft/approve) (execution)
Stage 1: Observation (Episodic Memory)¶
Every chat turn writes a timestamped event to episodic memory. No special annotation is required. Action patterns emerge naturally:
- "I ran EXPLAIN ANALYZE on the slow query"
- "I checked CloudWatch for the 5xx spike"
- "I deployed the hotfix via the rollback script"
These entries accumulate across conversations and become the raw material for Phase 12 promotion.
Stage 2: Promotion (SleepConsolidator Phase 12)¶
During deep sleep (POST /memory/consolidate), Phase 12 scans recent episodic
entries for repeated action patterns. When a pattern crosses the frequency
threshold within the recency window, it is extracted as a candidate procedural
skill in draft status.
Pattern extraction uses a two-pass heuristic:
1. Explicit metadata["action_type"] field on the episodic entry (preferred).
2. Action-verb prefix regex matching: phrases like "I ran X", "Then I deployed Y",
"I checked Z" are parsed into normalised action tokens.
Config knobs (on FrameworkConfig and forwarded to SleepConsolidator):
| Field | Default | Effect |
|---|---|---|
promotion_min_pattern_count |
3 | Minimum occurrences before a pattern is promoted |
promotion_recency_days |
30 | Only consider episodic entries within this window |
promotion_max_drafts_per_run |
5 | Cap on new drafts per consolidation run |
SemanticMerge runs inside store_skill to dedup against existing procedural
nodes (draft or approved). Repeated consolidation runs do not flood the review
queue with near-duplicates (similarity threshold: 0.65).
Phase 12 is silently skipped when either episodic_layer or procedural_layer
is absent from the SleepConsolidator — backward-compatible with deployments
that do not use full HMS.
ConsolidationReport.draft_skills_promoted surfaces the per-run count.
Stage 3: Review (Draft/Approve Endpoints)¶
Draft skills are invisible to the agent until a human approves them. Review happens via three endpoints:
| Method | Path | Action |
|---|---|---|
| GET | /api/v1/procedures/drafts |
List all skills awaiting review |
| POST | /api/v1/procedures/{id}/approve |
Approve — skill becomes active |
| POST | /api/v1/procedures/{id}/reject |
Reject — skill is archived |
These REST endpoints are the shipped review surface. The scaffold does not include a skills-review UI — its admin dashboard is metrics-only — so build your own "Pending Skills" view (or an ops script) against these endpoints. Every approve/reject emits an audit event (see below).
GET /api/v1/procedures defaults to approved-only. Pass ?status=draft,
?status=rejected, or ?status=all to change the filter.
Approve and reject operations emit audit events to GET /api/v1/admin/audit.
Stage 4: Execution (Approved Skills + CorePreferences)¶
Once approved, a skill becomes visible to the agent during hydration. The
ProceduralLayer.query_skills() method returns only active (approved) skills
by default.
On real-time register_skill operations (agent-initiated, not Phase 12),
MetacognitiveMiddleware can gate the skill before it is stored. When
FrameworkConfig.metacognition_enabled = True, the middleware evaluates the
draft response against active CorePreferences and returns one of:
approve— skill stored as active (or draft ifskill_auto_approve=False)revise— skill stored as draft with revised contentrefuse— skill rejected; not persisted
Configuration Reference¶
from symfonic.agent import FrameworkConfig
config = FrameworkConfig(
# Real-time skill gating
metacognition_enabled=True, # default: False
skill_auto_approve=False, # default: True (back-compat)
# Phase 12 offline promotion
promotion_min_pattern_count=3, # default: 3
promotion_recency_days=30, # default: 30
promotion_max_drafts_per_run=5, # default: 5
)
Setting skill_auto_approve=False forces every new skill (real-time or
Phase 12) into draft state regardless of metacognition verdict. Recommended
for production deployments.
Safety Rails¶
The pipeline has five independent safety mechanisms:
- Draft-by-default — Phase 12 always stores as
draft. The agent never acts on a learned skill until a human approves it. - MetacognitiveMiddleware — gates real-time
register_skillops againstCorePreferenceswhenmetacognition_enabled=True. - CorePreferences — domain-owned behavioural rules with priority 1-10. Higher-priority preferences can override or block lower-priority skill candidates.
- Audit trail — approve/reject/erase operations emit
AuditLogEntryrecords to the registeredAuditLogger. Query viaGET /admin/audit. - SemanticMerge dedup — prevents near-duplicate skills from accumulating across consolidation runs (cosine similarity threshold: 0.65).
retract_node— an explicit user correction retires a wrong fact/skill (soft-retract: hidden from all reads immediately, pruned after a grace window). See below.
The correctness caveat¶
These rails constrain what gets promoted and acted on — they do not make
the pipeline able to tell a correct memory from a wrong one on its own.
Reinforcement is frequency-based: what recurs gets stronger. There is no
outcome/reward signal, so a behavior the agent learned wrong and keeps
repeating is reinforced, not flagged. The only things that retire a
reinforced-but-wrong memory are external signals — the human review gate,
an explicit correction (retract_node / SOUL user_manual_edit), or the
metacognitive gate.
retract_node (reactive correction). When the user explicitly corrects or
invalidates a stored memory, the model emits a retract_node op; the engine
soft-retracts the target node (flag + audit trail), which drops it from every
read path at once, and Deep Sleep's prune_retracted phase deletes it after a
grace window. Full details in
Consolidation & Deep Sleep § Retracting a false-positive memory.
Closing the proactive case (self-detecting a wrong memory from bad outcomes)
would require an outcome-feedback signal that does not exist yet.
Example: Store Copilot¶
A typical Store Copilot workflow through the pipeline:
Day 1-30 — Observation.
The Store Copilot helps the owner run the shop. Each turn writes episodic
entries: "I called sales_trend and reported the weekend beverage spike",
"I flagged energy drinks trending up over 90 days", "I updated stock via
update_stock after confirming the delivery with the owner".
Night consolidation — Promotion.
Phase 12 detects that "reported sales with the window and figures cited"
appears 6 times in 30 days. A candidate skill "Cite the window and revenue
figures when answering a sales question" is created as a draft.
ConsolidationReport.draft_skills_promoted = 1.
Human review — Approve.
An operator lists the draft (GET /api/v1/procedures/drafts) and calls
POST /api/v1/procedures/{id}/approve — from a review UI you build on these
endpoints, or directly. The skill is now active, and an audit event is emitted.
Next question — Execution.
During hydration, the approved skill surfaces in the procedural context. The
agent follows the documented procedure. The Store Copilot's sales_trend /
revenue_summary tools read the seeded demo dataset (or the store's real
sales DB / read-only DSN once wired in demo_data.py).
CorePreferences guard.
The store-starter plugin ships CorePreferences at priority 9-10:
never register a product or change stock without confirming first, treat any
connected store database as read-only (never write/update/delete against the
owner's DB), and cite the numbers behind every sales claim. These take
precedence over any learned skill that would violate them — a skill that
proposed calling update_stock without confirmation, or writing to the
external store DB, is blocked.
Cross-temporal recall via autonomous entity linking¶
The procedural-learning pipeline above is one of two autonomous learning paths that ship in 7.2. The second one — Roadmap Item 12, the EntityLinker phase — solves a separate cognitive problem: the agent needs to remember entities across time, not just patterns.
The cognitive story¶
Imagine a user who visits the same restaurant three times over six months. Each visit produces an episodic memory in plain natural language: "had dinner at Bistro Nico", "took the team to Bistro Nico for the launch celebration", "Bistro Nico's lasagna is still the best in town". A month later, the user passes the restaurant's logo on a T-shirt at the mall and says "that uniform reminds me of somewhere".
For the agent to make that leap — T-shirt at the mall → Bistro Nico → three past dinners — spreading activation needs edges to traverse between the three temporally-distant episodics. Episodic similarity alone is not enough: the three episodics share a name, not a phrasing.
Before 7.2, the only way to build those edges was either:
- planting
[semantic:Bistro Nico]markers in every episodic by hand (Phase 11synthetic_linkswould then link them), or - calling
semantic_layer.link()manually from a domain plugin every time the agent mentioned the entity.
The EntityLinker phase replaces both workarounds. It scans the
natural language of recent episodics, extracts entity mentions,
mints a canonical Entity:place:Bistro Nico semantic node, and emits
MENTIONS edges from each episodic to the canonical node. The three
dinners and the T-shirt sighting now share a graph neighbourhood;
spreading activation crosses time.
Where it fits in the broader pipeline¶
| Phase | Promotes... | Output |
|---|---|---|
Phase 12 procedural_promotion |
recurring action patterns ("I ran EXPLAIN ANALYZE") | draft procedural skills awaiting human review |
Phase 12.5 entity_links |
recurring entity mentions ("Bistro Nico") | semantic Entity:<kind>:<surface> nodes + MENTIONS edges |
Both paths feed the same hydration pipeline at the next turn — the agent retrieves a richer, more cross-linked context.
Safety rails¶
Unlike procedural promotion, entity linking does not require human
review. The output is data, not behaviour: a new Entity node and an
edge between two existing nodes cannot make the agent do anything new.
The risk surface is therefore narrower (false-positive entities pollute
spreading activation, they do not cause autonomous action), and the
mitigation is the confidence threshold + the
entity_linker_min_mention_count floor.
For the configuration recipe — extractor trade-offs, tuning knobs, and the runnable demo — see Guide 09 — Consolidation & Deep Sleep.
Related Docs¶
- Deep Sleep Phases — full Phase 1-11 reference including Phase 12
- Architecture — where the learning pipeline fits in the overall data flow
- Streaming Events —
ReflectionEventemitted by metacognition - Guide 09 — Consolidation & Deep Sleep — operator-facing reference for the EntityLinker phase (v7.2 Item 12)