symfonic.capabilities.delegation.contracts¶
contracts ¶
The four ports delegation needs, and the tool shape it emits.
This module is the reason the capability can exist at all. Delegation's children are agents, so the naive extraction imports the engine facade to build one, type-checks against it to inspect one, and calls its config classmethod to inherit from one — three edges from a capability to the facade that composes it, and a cycle the moment the facade compiles the capability.
Each of those becomes a port here instead. The composition root implements them in about thirty lines; this package never learns what a child is made of.
All four are structural (Protocol), never nominal. A capability cannot
import the classes that would satisfy a nominal check, and — more to the point
— a test double, a remote proxy, and an adapter around somebody else's agent
are all legitimate implementations that could never inherit from anything this
package declares.
ChildBuilder ¶
Bases: Protocol
Turns a :class:~.values.ChildBuildPlan into a runner.
The one port that must live at the composition root, because it is the one that names a concrete agent class. Everything the builder needs to decide has already been decided: inheritance resolved, config sanitised, tools fixed, shared wiring attached.
ChildRunner ¶
Bases: Protocol
Anything a parent can delegate to.
The keyword arguments are the inheritance surface: the child is told which
tenant it is acting for, which run it belongs to, and how deep it already
is. A runner that ignores agent_depth cannot enforce its own ceiling,
which is why it is passed rather than re-derived — the child's context is
not the parent's, and a nested run that started its depth count from zero
would make the ceiling unreachable.
ConfigInheritance ¶
Bases: Protocol
Derives a child config from a parent config.
A port rather than a direct call for a subtle reason: the shipped inheritance primitive is a classmethod on the facade's own config class, so calling it directly would couple the capability to the whole configuration module — and through it, transitively, to most of the framework.
Implementations receive only None-meaning-inherit overrides. An
implementation that treats an explicit None as "set this to None" would
silently clear the parent's model settings on every child.
DelegationToolSpec
dataclass
¶
DelegationToolSpec(*, name: str, description: str, coroutine: Callable[..., Any], parameters: Sequence[str] = ())
A tool this capability offers, described rather than constructed.
The shipped code built framework tool objects here, which put a third-party tool library on the import path of a capability that has no other use for one. A spec carries the same four facts — name, description, parameter names, coroutine — and the composition root wraps it in whatever tool type the runtime actually uses.
Attributes:
| Name | Type | Description |
|---|---|---|
parameters |
Sequence[str]
|
The coroutine's argument names, in order — the declared signature a binder holds the coroutine to. It is read: the composition root's binder compares it against the coroutine it was handed and refuses the pair when the two disagree, so a spec cannot describe a tool the runtime would not bind. Leave it empty to declare nothing and be checked against nothing. |
RunSnapshots ¶
Bases: Protocol
Opens and closes a run-local prompt-block snapshot slot.
Two verbs, both synchronous, because opening a slot is a context-variable
write and the delegation path must be able to do it inside a finally.
A deployment that renders no prompt blocks supplies nothing at all and the
delegation context skips the slot entirely — see
:class:~.context.DelegationContext.