Hi HN,
I just open sourced the DSL that our harness in grep.ai uses to turn repeatable parts of agent work into workflows. You can combine tool calls, code, Jev-powered system one decisions for things like routing and screening evidence, and agents when a step needs more investigation.
Our harness uses the traces and retro notes agents leave behind when doing a job to figure out which parts can become a workflow. The idea is to make the work easier to understand and avoid paying for a full agent loop where one isn’t needed. For example, a research workflow can split a question into subquestions, send agents to research them in parallel, use Jev to screen the evidence, and have another agent write the report. You can inspect the steps, evaluate the evidence screening separately, or change one agent without rebuilding everything.
The DSL and examples are in our GitHub. There’s a scripted demo you can run without API keys: https://github.com/Parcha-ai/agentrun
You can also use it as a Pi extension to build, inspect, and run workflows: https://github.com/Parcha-ai/agentrun#use-it-in-pi
I would love to hear if this is useful to others.
More background on how AgentRun works in this video: https://www.youtube.com/watch?v=vOVhtGjtwpg. Or read about our use cases in this article: https://x.com/MiguelriosEN/status/2101029313906987422.
I'll study it as I am toying with "what should a workflow definition language look like".
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.
So for `pi` it means using typescript.
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.
For example "plan -> execute" is:
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}` },
);
( simplified code )
in my implementation and `unroll` is only there to have a nice ● Plan r1 · 1/3 · active
1. Inspect parser behavior
● 2. Add empty-input coverage
○ 3. Run focused checks
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)¡Wepa Miguel! ¡Felicidades y mucho éxito con el release!
Congratulations, and wishing you the best with this release!
[dead]
[dead]
[dead]
Graph workflows are useless if there are edges without cost or effor attribues and termination states without reward. Such workflow can be vibecoded in one-shot anyone who knows about graphs.
I thought some time ago about expressing SDLC as combination of harness tools, finite state machines with weights (efforts) on edges and rewards on some states. The goal - model queue of tasks as sub-workflows and implement the most valuable. I tried to design approach which will allow to maximize reward with minimal costs and risks via Markov Decision Process. Hypotetically i can implement it. But it all ends up being really hard to wrap your head around because of the state machines, custom runtime for scripts, the agent loop control, supervisor's control mechanisms. Then you have to tune the weighting models. The model can be similar to models from reinforcement learing. Even if I pull it off, I'd have to be damn lucky for even one other person to figure it out. And the project will have from 3 to 5 stars on GitHub because almost nobody will understand what is it and how to use.