symfonic.capabilities.prompting.request¶
request ¶
The compiler's only accepted input, and the one legal way to derive a child.
:class:PromptCompileRequest is a normalized value rather than adopter
configuration. Re-parsing a config file inside the compiler is how a second,
subtly different interpretation of context_strategy gets born; the facade
normalizes once and hands the result here.
:func:derive_child_request is the delegation half of the same rule. A child
narrows: it may drop contributions and lower its budget, and every widening
attempt is refused here rather than at the point of use, because a child that
could add a contribution or raise a ceiling its parent did not have would make
the parent's compile a suggestion.
PromptCompileRequest
dataclass
¶
PromptCompileRequest(instructions: str | None = None, contributions: tuple[PromptContribution, ...] = (), strategy: ContextStrategy = ContextStrategy.STRATIFIED, budget: PromptBudget = PromptBudget(), policy: RenderPolicy = DEFAULT_POLICY, scope_path: str = '', turn: int = 0, last_known_good: InMemoryLastKnownGood | None = None, estimator: object | None = None, principal_grants: frozenset[str] = frozenset(), operator_overrides: Mapping[str, str] | None = None)
Everything one prompt compile is allowed to depend on.
derive_child_request ¶
derive_child_request(parent: PromptCompileRequest, *, contributions: Sequence[PromptContribution] | None = None, budget: PromptBudget | None = None, scope_path: str | None = None, instructions: str | None = None, principal_grants: frozenset[str] | None = None, operator_overrides: Mapping[str, str] | None = None) -> PromptCompileRequest
Derive a delegated child's request by narrowing parent.
Omitting contributions inherits the parent's inheritable set — the safe
default, since a child silently losing its boundaries is the failure that
matters. Naming them narrows: every named id must already be inheritable on
the parent, so a child cannot promote a contribution its parent marked
non-inheritable by re-declaring it under the same name.
The two S01 access axes inherit, and the rule is stated rather than
implied. Delegation here is the same principal on the same turn, so a
child that dropped principal_grants would silently withhold from the
subagent a contribution the parent was entitled to, and one that dropped
operator_overrides would serve the source's own text where the operator
had replaced it — a divergence between what the parent and the child read
that no diagnostic would explain. Inheriting is therefore the default, and
both axes narrow the same way everything else here does:
principal_grantsmust be a subset of the parent's. A child cannot hand itself a verb the turn's principal was not granted.operator_overridesmust be a sub-mapping of the parent's — the same text under a subset of the same ids. A child may drop an override; it may not introduce one, nor change the text of one, because either would make the operator's decision for the parent turn something the child rewrites.
Delegation is a block-visibility boundary elsewhere in this repo
(tests/agent/subagents/test_child_block_lockdown.py), and that boundary
is drawn by inherit on the contribution, which is enforced above. These
two axes are about the principal and the operator, not about which blocks a
child may see.