rath.flow#
Workflow composition layer. Normal transforming workflows organize Session -> Session paths, AgentParam stores agent-side state, and Selector is the explicit routing exception that returns a workflow choice.
Source#
Module |
Source |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Public contract#
Workflow#
Method |
Returns |
Behavior |
|---|---|---|
|
|
Execution logic implemented by subclasses. |
|
|
Calls |
|
|
Returns agent params registered as attributes. |
|
|
Returns directly registered nested workflows. |
|
|
Returns this workflow and descendants in depth-first pre-order. |
|
|
Rebinds direct AgentParams only and returns |
|
|
Builds a static resource snapshot without running a model. |
Workflow(description="...") stores an optional description used when the
workflow is offered to a Selector.
When an AgentParam is assigned to a workflow as an attribute, Workflow.__setattr__ adds it to _agents.
AgentParam#
Field |
Type |
Description |
|---|---|---|
|
|
Agent/system transcript. |
|
|
Model and request parameters. |
|
|
Optional memory store bound to the agent. |
AgentParam.to(...) accepts an explicit Provider, provider="config-name",
or model="...". A named provider is resolved immediately. There is no
Provider.to() method.
Preset workflows#
Class |
Constructor arguments |
Behavior |
|---|---|---|
|
|
Creates an agent session and stores provider/runtime options. |
|
|
|
|
|
|
|
|
|
Agent.register_tool(tool) adds tools and deduplicates by name. Agent.unregister_tool(tool_name) removes the tool with the same name.
Dynamic routing#
Selector.forward(...) intentionally does not follow the normal
Session -> Session return contract. It makes a routing decision; the caller
then dispatches the returned workflow.
Result |
Meaning |
|---|---|
Candidate |
The model selected its zero-based menu index. |
|
No candidate, |
Descriptions are the selector’s routing surface. Empty descriptions are valid but usually provide too little information for a reliable choice.
Static compilation#
compiled = workflow.compile()
manifest = compiled.manifest
problems = compiled.validate()
Type |
Key members |
|---|---|
|
|
|
|
|
|
|
|
The manifest is a snapshot. validate() checks only provider registration and
offline credential resolution. The compiled wrapper delegates execution to the
current workflow; context entry/exit manages distinct bound memory stores.
Agent memory helpers#
Method |
Behavior |
|---|---|
|
Writes an explicit memory entry through the attached store. |
|
Retrieves relevant memory entries. |
|
Commits the session transcript through the attached store. |
|
Runs a best-effort commit after each forward call. |
Runnable workflow examples#
Example |
Path |
Description |
|---|---|---|
Hello agent |
|
Minimal provider and |
Session lineage |
|
Key-free fork/detach/merge graph mechanics. |
Memory |
|
Key-free local memory plus optional model-assisted commit. |
Provider variation |
|
Provider config, Anthropic, embeddings, and VLM setup. |
Dynamic selector |
|
Model-routed branching and bounded loops. |
Workflow compile |
|
Key-free static manifest and lifecycle inspection. |
These examples use the public Workflow, AgentParam, Provider, and run_session_loop(...) APIs, so they are useful source references for multi-agent composition.
Autodoc#
- class rath.flow.Workflow(description: str = '')[source]#
Collects attached
AgentParaminstances and subclasses run sessions here.- named_agents() tuple[tuple[str, AgentParam], ...][source]#
Agent params registered directly on this workflow (sorted by name).
- named_children() tuple[tuple[str, Workflow], ...][source]#
Nested
Workflow/Agentchildren registered by attribute (sorted).
- modules() list[Workflow][source]#
This workflow followed by every descendant (pre-order, depth-first).
- to(target: Provider | None = None, *, provider: str | None = None, model: str | None = None) Workflow[source]#
Rebind the provider on every registered
AgentParam(chainable).Fans
AgentParam.to()out to each agent fromnamed_agents(), soworkflow.to(Provider(...))/workflow.to(provider="name")/workflow.to(model="m")apply uniformly. A workflow with no agents is a no-op. A bare positional string is rejected (same rule asAgentParam.to()).
- compile() object[source]#
Return a
CompiledWorkflowfor this workflow.A static pass over the module tree (P5.1) that builds a resource manifest for pre-flight validation, deterministic resource lifecycle, and inspection. Opt-in and non-breaking: the returned object is callable exactly like this workflow. Runs no model and materializes no session.
- compile_plan(*, revision_id: UUID) ExecutionPlan[source]#
Compile explicit
@stepboundaries into an immutable v2 plan.
- class rath.flow.AgentParam(agent_session: Session, provider: Provider, memory: MemoryStore | None = None)[source]#
System session plus LLM options for
run_session_loop.- to(target: Provider | None = None, *, provider: str | None = None, model: str | None = None) AgentParam[source]#
Rebind this param’s
Provider(chainable, returnsself).Type-dispatched, mirroring
Session.tofor sandboxes:ap.to(Provider(...))— bind an explicit provider (positional);ap.to(provider="name")— resolve a config preset lazily;ap.to(model="m")— overlay just the model on the current provider.
The positional argument accepts only a
Provider; a bare string is rejected because — unlikeSession.to("local")(a sandbox backend name) — the LLM path has no unambiguous string form. Useprovider="name"for a config preset instead.
- class rath.flow.Agent(system_prompt: str, provider: Provider | None = None, tools: list[FlowToolCall] | None = None, *, model: str | None = None, on_event: Callable[[RathLLMStreamDelta], None] | None = None, memory: MemoryStore | MemoryStoreSpec | str | None = None, memory_inject: MemoryInjectionPolicy | None = None, commit_on_forward: bool = False, description: str = '')[source]#
-
- remember_memory(content: str, *, scope: str = 'user', category: str = 'preferences', wait: bool = False) object[source]#
Persist a free-form note under
memory://{scope}/memories/{category}/....scopeis intentionally permissive (user/agent/session) so user code can decide which namespace to target; the URI prefix is adapter-coupled and other backends may rewrite it. SeeOpenVikingBackend.
- recall_memory(query: str, *, top_k: int = 4, target_uri: str | None = None) object[source]#
Issue a
MemoryOpFindagainst the bound store and return the result.
- class rath.flow.Compressor(compress_instruction: str, provider: Provider, *, on_event: Callable[[RathLLMStreamDelta], None] | None = None, description: str = '')[source]#
- class rath.flow.Selector(provider: Provider, *, select_instruction: str = 'You are a router. Given the conversation and a numbered menu of candidate workflows, reply with the single best index, or -1 if none applies / the task is already complete.', description: str = '', on_event: Callable[[RathLLMStreamDelta], None] | None = None)[source]#
Pick the next
Workflowfor a session.Sibling of
Agent/Compressor.- forward(session: Session, *workflows: Workflow) Workflow[source]#
Return the workflow the model picks for
session, or anEmptyWorkflowwhen no candidate fits / the session is complete.NOTE: this deliberately deviates from the base
forward(session) -> Sessioncontract.Selectoris a routing decision component, not a session transformer: it returns the chosenWorkflow(neverNone), and the caller dispatches it (session = chosen(session)). Completion is signalled by returning anEmptyWorkflow(a no-op), detected viaisinstance(result, EmptyWorkflow).
- class rath.flow.EmptyWorkflow(description: str = '')[source]#
No-op workflow:
forwardreturns the input session unchanged.Returned by
Selectorwhen no candidate fits / the session is complete, so callers can dispatch unconditionally and detect completion viaisinstance(result, EmptyWorkflow).
- class rath.flow.CompiledWorkflow(workflow: Workflow)[source]#
Static, callable wrapper around a
Workflow.Produced by
Workflow.compile(). It is callable exactly like the workflow —cw(session)delegates toworkflow.forward— so compiling is opt-in and non-breaking. It also exposes the staticResourceManifest, the module tree, and a graphrepr.Compiling runs no model and materializes no session; it only walks the static module tree (P5.1) to build the manifest.
- validate(*, raise_on_error: bool = False) list[str][source]#
Pre-flight check every reachable provider (offline; no model call).
For each agent in the manifest, verify (1) its
provider_kindis a registered chat-client kind, and (2) a credential resolves for it via the same Provider → env → config chain the client uses at construction — without building an SDK client or hitting the network.Returns a list of human-readable problems (empty when clean). With
raise_on_error=True, raisesValueErrorif any problem is found. This lets callers fail fast before a run instead of deep inside the first completion.
- class rath.flow.ResourceManifest(agents: list[~rath.flow.compile.AgentResource] = <factory>, dynamic_nodes: list[~rath.flow.compile.DynamicNode] = <factory>)[source]#
The static resource inventory of a compiled workflow.
- class rath.flow.compile.AgentResource(path: str, provider: Provider, has_memory: bool, agent_session_id: str)[source]#
One reachable
AgentParamin the compiled module tree.