Skip to content

Prompt extraction migration

The migrated path composes the model-visible extraction directive and durable extraction separately. A directive tells the response model which operations to emit; MemoryExtractionService parses a separate extraction-model response and writes only validated records. Neither collaborator silently creates the other.

from symfonic import Agent
from symfonic.capabilities.memory import MemoryExtractionService, memory_capabilities
from symfonic.capabilities.prompting import ExtractionDirectiveSource, PromptingCapability, extraction_contribution

directive = ExtractionDirectiveSource(
    template_path=custom_template,
    cadence=2,
    scope_path=scope.path,
)
agent = Agent(provider, capabilities=[
    *memory_capabilities(store, scope, extractor=MemoryExtractionService(extraction_model)),
    PromptingCapability(sources=[extraction_contribution(directive)]),
])

cadence=1 renders on every turn, cadence=N renders on turns divisible by N, and cadence=0 omits the directive. For N > 1, pass a stable session_id to Agent.run() or Agent.stream(); the counter is keyed by the full scope and session, so one conversation cannot advance another's cadence. The source requires a tenant scope and does not render on an unscoped turn. For a scoped AgentHost, pass the composed scope's .path as shown above. Custom templates retain MemoryExtractionSection validation.

When the response model emits a complete <MEMORY_EXTRACT> or <GRAPH_OPERATIONS> envelope, the public Agent removes that envelope from its result and stream. MemoryExtractionService persists an inline operation only when it uses its native action/properties classification schema; rejected tagged operations fall back to the configured extraction model. The bundled legacy templates still use their graph-operation schema, so direct durable parity for those templates remains an explicit migration gap rather than a claim made by this composition.

The compiler's PromptBudget remains one total prompt ceiling. It does not recreate legacy per-region HMS or JIT manifest caps, and CompiledPrompt.budget and diagnostics are the migrated overflow evidence rather than an on_hms_budget_exceeded callback. Those different budget contracts remain migration blockers until an approved transition exists.