Building Workflows¶
The API to design, review, and run a workflow from intent. Two entry points: ArchitectBuilder (design + register) and ArchitectConversation (an optional requirements interview).
Build from intent¶
ArchitectBuilder.run(intent) designs and registers a workflow, returning the path to the registered package:
from neurosurfer.architect import ArchitectBuilder, WorkflowInfeasible
builder = ArchitectBuilder(provider)
try:
pkg_path = await builder.run(
"Summarise a web article and extract the 5 key takeaways as a bullet list.",
)
print("registered workflow at:", pkg_path)
except WorkflowInfeasible as e:
print("cannot build this workflow:", e)
Callbacks¶
run() accepts hooks for richer front-ends:
| Argument | Purpose |
|---|---|
answers | Pre-collected clarifying answers (question_id → answer) so the build runs non-interactively. |
on_node_event(node_id, status) | Fired live as each build node runs — for progress UI. |
progress_callback(node_id, status, duration_ms) | Post-run per-node summary. |
approve_tool(draft, sandbox_result) -> bool | Called only on a capability gap: the Architect authored a tool and sandbox-tested it; return True to register it. See How It Works. |
Clarify requirements first¶
For interactive apps, ArchitectConversation runs a short requirements interview and returns (intent, answers) you feed straight into ArchitectBuilder.run(...):
from neurosurfer.architect import ArchitectConversation
async def ask(question: str, choices: list[str]) -> str:
# render a menu / prompt and return the user's answer
...
convo = ArchitectConversation(provider)
intent, answers = await convo.run("I want a workflow that reviews pull requests", ask=ask)
pkg_path = await ArchitectBuilder(provider).run(intent, answers=answers)
This is exactly how the CLI drives its workflow builder — the REPL's /workflow command supplies ask (an arrow-key menu with a free-text escape), then builds the designed workflow.
Run what it produced¶
A registered package runs like any other Workflow:
from neurosurfer.graph.workflow import WorkflowRegistry, WorkflowRunner
pkg = WorkflowRegistry().get(pkg_path) # or load_package(pkg_path)
# The package declares what it takes — pass those names, not a generic intent.
print([i.name for i in pkg.graph.inputs]) # e.g. ['article']
result = WorkflowRunner(provider, cwd=".").run(pkg, inputs={"article": "…"})
Recommended workflow¶
Because output quality tracks the model, the reliable path is:
- Bootstrap — let the Architect design a first draft from a narrow, specific intent.
- Review — open the generated package; read the graph and any authored tool.
- Refine — edit the nodes/tools by hand where the draft is weak.
- Run — execute the refined package through the graph runtime.
Narrow intents (“summarise a URL and extract N bullets”) work far better than broad ones (“build me a research assistant”). Split big goals into smaller workflows.