Flows¶
Flow graphs, nodes and the runner. Concepts: Flows, Flow pause and resume.
agent_adapter.flow.visit is a seam for flow compilers; most code never needs it.
agent_adapter.flow¶
Portable graph flows: a builder, merge rules, sub-flows, a node cache, a graph, a runner.
NodeFn = Callable[[S], Any] | Callable[[S, ToolContext], Any]
module-attribute
¶
keyed = Merge.keyed
module-attribute
¶
Call
dataclass
¶
Run one tool through the executor; args may be a function of the state.
FlowCheckpoint
dataclass
¶
Where a paused flow stopped; pass it to FlowRunner.resume (JSON: dump_checkpoint).
FlowGraph
dataclass
¶
FlowResult
dataclass
¶
Bases: Generic[S]
How a run ended: the state, the status, supersteps run and visits per node.
Join
dataclass
¶
Fan-in: runs once nothing else is pending; fn is an optional reducer step.
Map
dataclass
¶
Fan out over the list field over: one tool call (or fn call) per item.
Merge
¶
The built-in merge rules; annotate a state field with one (Annotated[T, Merge.sum]).
keyed(by)
staticmethod
¶
A list of mappings or models; a later item with the same by key replaces earlier.
Raises:
| Type | Description |
|---|---|
FlowDefinitionError
|
|
MergeRule
¶
Bases: Protocol
Combines the updates one superstep makes to a field; updates are in deterministic order.
A rule that adds a write onto the current value (like append or sum) should also set
additive = True; sub-flows then start the field empty and refuse to map it in and back.
NodeCache
dataclass
¶
Reuse a node's updates for equal inputs: the state, its reads fields, or key(state).
NodeSpec
dataclass
¶
One node: its action and run options.
Route
dataclass
¶
Bases: Generic[S]
Pick the next node(s): fn(state) returns a label or labels found in targets.
RouteSpec
dataclass
¶
A conditional exit: fn(state) returns labels; targets maps label -> node.
SubFlow
dataclass
¶
Run another Flow as one node: parent state in through input, its result out by into.
input: child field -> parent field, or fn(parent_state) -> the child's initial values;
None copies fields of the same name (additive append / sum fields start empty).
into: a parent field for the child's final state, parent field -> child field, or
fn(child_state) -> the parent update; None writes back same-named fields it changed.
apply_updates(state, updates, rules)
¶
Merge updates (in order) into a copy of state and re-validate it.
Raises:
| Type | Description |
|---|---|
FlowError
|
unknown keys, conflicting |
merge_rules(model)
¶
The merge rule of every field of model, from Annotated metadata (default replace).
Raises:
| Type | Description |
|---|---|
FlowDefinitionError
|
a field carries more than one merge rule. |
node_model(ctx)
¶
The flow runner's model, instrumented by its executor and bound to this node, or None.
node_prompt(ctx)
¶
The running node's prompt, or None.
Also exported here, documented under the canonical path: Flow, FlowRunner.
agent_adapter.flow.runner¶
The local flow runner: LangGraph-style supersteps on the executor, with pause and resume.
FlowStatus = Literal['done', 'paused', 'denied']
module-attribute
¶
Also exported here, documented under the canonical path: FlowCheckpoint, FlowResult, FlowRunner.
agent_adapter.flow.visit¶
Semi-public flow seam for flow compilers (LangGraph, ADK); not in flow.__all__.
The compilers run node visits, gates, routes, resumes and seals exactly like the local runner. They import those internals from here, never from the private modules, so a refactor there keeps this surface stable.
ItemOutcome = tuple[str, Any]
module-attribute
¶
NOT_SEALABLE = 'state-not-sealable'
module-attribute
¶
NO_PORT = 'no approval port configured'
module-attribute
¶
SPENT = SpentCheckpoints()
module-attribute
¶
SUPERSEDED = 'superseded'
module-attribute
¶
TAMPERED = 'checkpoint-tampered'
module-attribute
¶
ask_node_gate = _ask
module-attribute
¶
Ask the port for a gate: its decision, the pending request, or a denial without a port.
node_gate_request = _request
module-attribute
¶
The ApprovalRequest a gated node visit asks for (call id = the visit's id).
superseded = _superseded
module-attribute
¶
Pending records a resume never reuses: not the checkpoint's, a call id the flow did not set.
NodeEnv
dataclass
¶
What every node of one flow run shares.
NodeOutcome
dataclass
¶
A node's updates, or the approval it is waiting for.
allowed_classes(state_model)
¶
The classes a checkpoint of this state model may hold (exec._canon.reachable_types).
apply_edits(graph, state, ready, decisions)
¶
Apply each granted gate's edited_args as a state update, in node-name order.
call_route(flow, route, state)
async
¶
The labels route.fn(state) returns (sync or async), as a list.
Raises:
| Type | Description |
|---|---|
FlowError
|
the route function failed. |
describe_error(exc)
¶
An error's kind and message for AdapterErrors; only the class name otherwise.
frozen(data)
¶
A read-only copy.
graph_digest(graph)
¶
SHA-256 of the graph: names, kinds, actions, gates, edges, routes, start and ends.
Functions count by identity (module:qualname), so renaming or moving one changes it; a
changed body under the same name does not. A Call / Map counts by its tool, static
arguments and options; a SubFlow by its child graph's digest and its field mapping.
mac(key, data)
¶
HMAC-SHA256 hex of the canonical JSON of a payload.
merge_outcomes(graph, state, outcomes, step)
¶
Merge every node's updates: node-name order (LangGraph task order), then Map item order.
next_frontier(graph, frontier, ready, routed)
¶
The next frontier in declaration order: unrun nodes, ready's edges and route picks.
node_call_id(flow, node, visit, scope='')
¶
The id of one node visit (node events and the node's context); scope for sub-flows.
not_sealable(flow, exc)
¶
The FlowError for a value that cannot be sealed.
pick_targets(flow, route, labels, visits_before, loops)
¶
The nodes labels name; picking the source or an earlier-visited node counts a loop.
Raises:
| Type | Description |
|---|---|
FlowError
|
a label the route does not know. |
FlowLoopExceeded
|
|
resume_entry(pending, decision)
¶
The answer for a paused tool approval: exact call id for Call / Map calls.
route_state(graph, state, outcome)
¶
What a route sees: the superstep's input state plus its own node's updates only.
route_targets(flow, route, state, visits_before, loops)
async
¶
The nodes a route picks; picking the source or an earlier-visited node counts a loop.
run_node(env, node, state, ctx, *, visit, approval=None, answer=None, items=None, journal=None, child=None)
async
¶
Run one node visit; failures raise FlowError, a pending approval is returned.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
answer
|
ResumeAnswer | None
|
Answers the tool approvals this visit resumes; spent when the visit ends. |
None
|
items
|
Mapping[int, ItemOutcome] | None
|
|
None
|
journal
|
JournalData | None
|
Executor calls this visit finished before the pause; they replay. |
None
|
child
|
FlowCheckpoint | None
|
Where a SubFlow node's child run paused; it continues from there. |
None
|
runner_key(key)
¶
The checkpoint key a runner signs with.
Raises:
| Type | Description |
|---|---|
ToolUsageError
|
|
spend_once(pending, decision, port)
async
¶
Spend a checkpoint's pending approval: settle it in the store first, then remember it.
Raises:
| Type | Description |
|---|---|
ApprovalAlreadyDecided
|
the checkpoint was already resumed (here or via the store). |
ToolUsageError
|
the store record belongs to another request. |
withdraw(flow, ctx, pendings, reason=NOT_SEALABLE)
async
¶
Deny and consume each pending record; a record no store reaches is logged.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
reason
|
str
|
The denial reason: |
NOT_SEALABLE
|