I'll study it as I am toying with "what should a workflow definition language look like".<p>My current vision, and prototype, is that it should be as close as possible to a "real" language as possible so that both the user and the agent know immediately how to use it and how it functions.<p>So for `pi` it means using typescript.<p>Then the UI is derived from the AST / code as much as possible and for things that aren't neatly possible like that I eventually add small semantic helpers that define the UI.<p>For example "plan -> execute" is:<p><pre><code> await flow.unroll(
remaining.map(point => ({
key: point.id,
label: point.objective,
})),
async () => {
for (const point of remaining) {
await flow.item(point.id, async () =>
await flow.agent(executePoint, {
title: `Point ${point.id}`,
prompt: point.objective,
}));
}
},
{ title: `Plan r${planRevision}` },
);
</code></pre>
( simplified code )
in my implementation and `unroll` is only there to have a nice<p><pre><code> ● Plan r1 · 1/3 · active
1. Inspect parser behavior
● 2. Add empty-input coverage
○ 3. Run focused checks
</code></pre>
UI instead of a plain "Plan · 1/3" UI with no detail (which would happen if I just used a for loop, yes it works)