You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/workflows.md
+52-1Lines changed: 52 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -77,6 +77,7 @@ or by name through `run_workflow("deep_research", args)`.
77
77
|`agent`|`await agent(prompt, *, label, model, output_type, instructions, deps, tools, toolsets)`| Run one isolated sub-agent; returns its `output` (a `str` or a validated `output_type`). A sub-agent can use `tools=`/`toolsets=` (e.g. `ToolKit.as_toolset()` or an MCP server) just like a top-level agent. Honours the budget, the concurrency gate, and the resume journal. |
78
78
|`parallel`|`await parallel(thunks)`|**Barrier.** Run zero-arg async thunks concurrently; a thunk that raises resolves to `None` (the call never propagates). Returns a list aligned to `thunks`. |
79
79
|`pipeline`|`await pipeline(items, *stages)`|**No inter-stage barrier.** Each item flows through every stage independently (item A can be in stage 3 while B is in stage 1). Each stage receives `(prev, item, index)` — declare only the params you need. A stage that raises drops *that* item to `None`. |
80
+
|`stream`|`async with stream(prompt, ...) as s:`| Stream one sub-agent token-by-token: iterate `s.text()` for deltas; `s.output` holds the full output after the block. Same budget/journal/cost accounting as `agent`. Requires a streaming runner. See [Streaming](#streaming). |
80
81
|`phase`|`with phase("title"):`| Group enclosed work for telemetry (`phase.start` / `phase.end` events). |
81
82
|`log`|`log("message")`| Emit a narrator line to the run's event handler. |
82
83
@@ -85,6 +86,30 @@ glue between agent calls — dedup, rank, filter, branch — is ordinary
85
86
deterministic Python. Reach for an `agent()` only when you genuinely need a
86
87
model.
87
88
89
+
### Type safety
90
+
91
+
The DSL is statically typed end-to-end. `agent(output_type=T)` is typed to
92
+
return `T` (not `Any`), and `@workflow` produces a `Workflow[OutputT]` inferred
93
+
from the function's return annotation — so the awaited result is typed too:
94
+
95
+
```python
96
+
from pydantic import BaseModel
97
+
from fireflyframework_agentic.workflows import workflow, agent
98
+
99
+
classReport(BaseModel):
100
+
summary: str
101
+
sources: list[str]
102
+
103
+
@workflow(name="research")
104
+
asyncdefresearch(args, ctx) -> Report:
105
+
returnawait agent("write the report", output_type=Report) # typed Report
106
+
107
+
report: Report =await research(args) # research is Workflow[Report]; result is Report
108
+
```
109
+
110
+
Without `output_type`, `agent()` returns `Any` (the raw string output). Pyright
0 commit comments