Migrating from symfonic-core v6.x to v7.0¶
v7.0.0 is a major release. It introduces the four v7.0 Thalamic
Architecture subsystems (intent filter, N-hop spreading, STM summary,
fabrication executor, nightly_nap) and removes one long-deprecated
constructor kwarg. Everything else is additive with v6.x observable
behaviour preserved at defaults.
TL;DR — if your code does not reference
SymfonicAgent(enable_hms_prompt=...), upgrading is a drop-in.
Breaking changes¶
B1 — SymfonicAgent(enable_hms_prompt=...) removed¶
Status: Landed.
The constructor kwarg has emitted DeprecationWarning since v5.6.0.
In v7.0 it raises TypeError because Python does not accept unknown
keyword arguments.
Before (v6.x)¶
This v6.x constructor was removed in v7. It is shown only as the migration starting point.
After (v7.0)¶
Legacy 9.12 example: Install symfonic-core==9.12.* for this SymfonicAgent snippet. For version 11, see the Agent migration guide.
from symfonic.agent.config import FrameworkConfig
from symfonic.agent.engine import SymfonicAgent
config = FrameworkConfig(enable_hms_prompt=True)
agent = SymfonicAgent(
model_provider=provider,
config=config,
)
The FrameworkConfig path has been available since v6.0 and is
unchanged in v7.0.
Migration script¶
Run this one-liner to detect the pattern across a codebase:
If nothing matches, you are done.
Additive changes (no migration required)¶
FrameworkConfig knobs¶
| Field | Default | v6.x behaviour at default | To change behaviour |
|---|---|---|---|
intent_filter_mode |
"off" |
Classifier never runs; full hydration every turn | "observe" for telemetry only; "enforce" to skip semantic/episodic/procedural on action verdicts |
hydration_max_hops |
0 |
Single asyncio.gather of 1st-degree neighbours (byte-identical to v6.1.x) |
>=1 enables BFS with per-hop decay |
stm_summary_mode |
"off" |
WorkingLayer.summarize() returns "" (legacy stub) |
"extractive" produces bullets with no LLM cost; "llm" issues one micro-call with extractive fallback |
fabrication_check_mode |
"off" |
Detector never runs; v6.1.10 TOOL DISCIPLINE prompt directive is the only defence | "observe" emits telemetry; "revise" forces metacog revise; "refuse" replaces draft with safe envelope |
nightly_nap_enabled |
False |
nightly_nap method available but operator-invoked |
Schedule agent._sleep_consolidator.nightly_nap(scope) via your scheduler |
nightly_nap_cron |
"0 3 * * *" |
No effect — recommendation only | Set to your preferred off-peak cron expression |
DomainTemplate additions¶
| Field | Default | Purpose |
|---|---|---|
identifier_keys |
[] |
Extra keys the fabrication detector should flag in addition to the built-in lexicon (task_id, pid, job_id, ...). Empty preserves v6.x behaviour. |
AgentResponse additions¶
| Field | Default | Populated when |
|---|---|---|
intent_verdict |
None |
intent_filter_mode != "off" |
fabrication_findings |
None |
fabrication_check_mode != "off" AND detector fires |
Enabling the new subsystems¶
The v7.0 subsystems are opt-in. Here is a recommended adoption order:
1. Intent filter (lowest risk)¶
Start in observe mode for a burn-in week. The classifier emits
ExtensionEvent(type="intent_classified") to callback handlers that
implement on_intent_classified. Tune the corpus before flipping to
enforce.
Once confident, flip to enforce:
2. N-hop spreading¶
Start with hydration_max_hops=1 (explicit 1-hop, still a single
BFS level but now with spreading_access_count bumping per v6.2 T02).
Measure payload size and latency before raising:
The default base_decay=0.5 and max_total_nodes=50 guard against
runaway expansion.
3. STM summary¶
Start with extractive — zero LLM cost, deterministic output:
Upgrade to "llm" if your domain needs better compression and you
are willing to pay one micro-call per summary. The extractive path
is the automatic fallback on LLM failure.
4. Fabrication check¶
Start in observe to collect findings:
Implement on_fabrication_detected on your callback handler to
capture the events. When confident the detector is not producing
false positives, escalate to revise or refuse.
fabrication_check_mode='revise'requiresmetacognition_enabled=True. Therevisepath threads findings intoMetacognitiveMiddleware.evaluate()to produce a genuine revised draft. Without metacog enabled there is no reviser to run, so the agent emits aUserWarningat construction and downgrades the effective mode torefusesemantics (safe-envelope replacement +fabrication_blockedevent). If you want real revise behaviour, pair the two flags:
5. nightly_nap¶
Enable the entrypoint:
config = FrameworkConfig(
nightly_nap_enabled=True,
nightly_nap_cron="0 3 * * *", # 03:00 UTC daily
)
Wire your scheduler (APScheduler / celery-beat / external cron) to
invoke agent._sleep_consolidator.nightly_nap(scope) per tenant at
the recommended cron cadence. The engine does not schedule this
itself — operator responsibility.
Tests¶
v7.0.0 adds dedicated test files per subsystem; your test suite should remain green after the upgrade because defaults preserve v6.x behaviour. If a v6-era test fails, please file an issue — it indicates an inadvertent default flip.
tests/agent/triage/test_intent_classifier.py— T06tests/agent/triage/test_intent_wiring.py— T07tests/memory/unit/test_spreading_nhop.py— T08tests/memory/unit/working/test_stm_summary.py— T09tests/agent/middleware/test_fabrication.py— T10tests/agent/middleware/test_fabrication_wiring.py— T11tests/core/learning/test_nightly_nap.py— T12tests/release/test_v7_0_0_release_gate.py— T15 pin
v7.0.2 note — DomainTemplate.description now reaches the LLM¶
DomainTemplate.description has been a public field since v5.6.x,
but no prompt builder ever consumed it — every value set there was
silently dropped. v7.0.2 wires it into both the full HMS and JIT
system prompts for the first time.
If your v6.x / v7.0.0 / v7.0.1 deployment set
DomainTemplate(description="..."), upgrading to v7.0.2 will cause
that prose to reach the LLM's system prompt. This can affect:
- Token budgets — the prompt will be larger in both modes.
- LLM behaviour — the directives will actually steer responses. Review the description text before upgrading.
- Truncation — descriptions over 2000 chars (full HMS) or 400
chars (JIT) are capped and marked
... [truncated], with a single WARNING log per agent lifetime. Raise the caps via the newFrameworkConfig.domain_description_max_charstuple if needed:
cfg = FrameworkConfig(
domain=DomainTemplate(description="..."),
domain_description_max_chars=(5000, 800), # (full_hms, jit)
)
No migration is required for callers who never populated
domain.description — the rendered prompt shows a short fallback
which the LLM treats as a no-op.
See docs/releases/v7.0.2.md for the full
rationale including why the JIT template uses an inline line
instead of a new ## 1a. section.
References¶
docs/releases/v7.0.0.md— full release notes.docs/releases/v7.0-plan.md— execution plan with per-task acceptance criteria.docs/releases/v6.2.0.md— preceding additive carve-out (T01-T05).