-
Notifications
You must be signed in to change notification settings - Fork 52
Expand file tree
/
Copy path12_compile.py
More file actions
90 lines (69 loc) · 3.25 KB
/
Copy path12_compile.py
File metadata and controls
90 lines (69 loc) · 3.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
"""12 · Workflow compile — static resource manifest & lifecycle (no LLM key).
`Workflow.compile()` is OpenRath's torch-like static pass: before a workflow
runs, it walks the module tree and produces a `ResourceManifest` of every
reachable provider, memory binding, and agent — plus any `Selector` nodes,
recorded as *dynamic* (their runtime routing is decided by the model, never
guessed). Use it to:
* inspect the static graph (`cw.manifest`, `repr(cw)`),
* fail fast before a run (`cw.validate()` — offline, no model call),
* acquire/release planned resources deterministically (`with wf.compile():`).
Compiling runs no model and materializes no session, so this needs **no key**.
Run:
python example/12_compile.py
"""
from __future__ import annotations
from rath import flow
from rath.flow.agent_param import AgentParam
from rath.llm import Provider
from rath.session import Session
class ResearchTeam(flow.Workflow):
"""A tiny nested workflow: a coordinator with two specialist sub-agents."""
def __init__(self) -> None:
super().__init__(description="research team")
# Nested Workflow children register into the module tree (torch-like).
self.triage = _Specialist("Triage quickly.", "gpt-5.5")
self.deep = _Specialist("Answer in depth.", "claude-sonnet-4-6")
# A leaf AgentParam registered directly on this workflow.
self.summarizer = AgentParam(
agent_session=Session.from_agent_prompt("Summarize the team's findings."),
provider=Provider(model="gpt-5.5", api_key="sk-example"),
)
def forward(self, session: Session) -> Session: # pragma: no cover - demo only
return session
class _Specialist(flow.Workflow):
def __init__(self, prompt: str, model: str) -> None:
super().__init__(description=prompt)
self.agent = AgentParam(
agent_session=Session.from_agent_prompt(prompt),
provider=Provider(model=model, api_key="sk-example"),
)
def forward(self, session: Session) -> Session: # pragma: no cover - demo only
return session
def main() -> None:
team = ResearchTeam()
# 1) Compile: a static pass over the module tree. No model runs.
compiled = team.compile()
print("Compiled workflow:")
print(repr(compiled))
# 2) Inspect the static resource manifest.
manifest = compiled.manifest
print("\nReachable provider models:", manifest.provider_models())
print("Agents:")
for agent in manifest.agents:
print(
f" - {agent.path}: model={agent.provider.model} memory={agent.has_memory}"
)
if manifest.dynamic_nodes:
print("Dynamic nodes (runtime-decided):")
for node in manifest.dynamic_nodes:
print(f" - {node.path} [{node.kind}]: {node.reason}")
# 3) Pre-flight validation — offline, before any run.
problems = compiled.validate()
print("\nvalidate() problems:", problems or "none — ready to run")
# 4) Deterministic resource lifecycle. Bound memory stores (none here) are
# acquired on enter and released on exit.
with team.compile() as live:
print(f"\nInside lifecycle: {len(live.manifest.agents)} agents ready.")
print("Resources released on exit.")
if __name__ == "__main__":
main()