symfonic.capabilities.delegation.context¶
context ¶
One run-local scope for depth, snapshot, and delegated metadata.
These three used to be three context variables and two nearly-identical decorators, opened and closed by hand at every entry point. The streaming entry points opened one of the three, which is how a streamed delegated child ended up re-resolving its prompt blocks every turn while the identical agent driven through the non-streaming path did not.
They are one object here because they have one lifetime — the run — and one
trigger. depth > 0 is "this run is delegated"; it decides the snapshot,
and the snapshot is the only reason a top-level run must not open a slot (with
no slot open, block resolution is byte-for-byte what it was, so the feature
cannot change what a parent sees).
Concurrency¶
Every piece of run state is a :class:~contextvars.ContextVar, so isolation
between concurrent runs is inherited from the task that started them rather
than maintained by this class. A parent delegating to four children
concurrently gets four independent tallies, four independent depths, and four
independent snapshot slots, and a cancelled sibling unwinds only its own —
the finally runs in the task that opened it.
ActiveRun ¶
The delegation facts one run accumulates.
Handed out by :meth:DelegationContext.run_scope and readable after the
scope closes — the caller stamping delegated_to onto a response reads
it once the run has finished, and a value that evaporated with the scope
would be unreadable exactly when it is needed.
Source code in src/symfonic/capabilities/delegation/context.py
delegated_to
property
¶
The children this run delegated to, in order, with repeats.
Repeats are kept. "The parent asked the researcher three times" is a different run from "the parent asked once", and de-duplicating would erase the loop an operator is usually looking for.
DelegationContext ¶
Opens and closes the run-local scope delegation needs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
snapshots
|
Any | None
|
The prompt-block snapshot port, or |
None
|
resolve_scope
|
Callable[[], Any] | None
|
Returns the tenant scope a delegated child should inherit. A callable rather than a value because the scope belongs to the run in flight, not to the wiring: the capability is built once and serves every tenant that arrives. |
None
|
Source code in src/symfonic/capabilities/delegation/context.py
current_depth ¶
current_run ¶
current_scope ¶
delegated_to ¶
record_delegation ¶
Note a completed hand-off on the run in flight.
A no-op outside a run rather than an error. The tool surface is reachable from a direct call in a test or a script that never opened a scope, and refusing there would make the observability feature able to break a delegation that otherwise worked.
Source code in src/symfonic/capabilities/delegation/context.py
run_scope
async
¶
Open the scope one run needs; close it whatever happens.
Yields the run's :class:ActiveRun. A delegated run (depth > 0)
also holds a snapshot slot for its whole lifetime; a top-level run does
not open one at all.