GoalPipeline is a pipeline of two agents: an executor produces a result, a verifier judges it against the goal, and a refusal goes back to the executor with its reason, until the work passes or the attempts run out.
The loop runs like this:
Agent, not a special kind of object. Its verdict comes back as structured output, so a check that has to read files, run commands or ask a person goes through exactly the machinery the executor does.
Running a Pipeline
The example below has two agents collaborate on a programming task: the executor writes the code, the verifier checks it.goal_pipeline.py
Constructor Arguments
GoalPipeline takes the following arguments:
The goal is not given at construction. It arrives with the task: the first message the pipeline receives is both what the executor is asked to do and what the verifier judges against.
Verification and Retries
Both agents hand their results to the pipeline as structured output:message reaches the executor verbatim, so it has to say what is missing rather than that something is. A full round goes:
1
The executor works
The executor takes the task, leaves its output in the shared workspace, and hands back a
report.2
The verifier judges
The verifier checks the output against the goal and returns
result and message.3
Passing ends the run
On
pass or impossible the pipeline finishes and the event stream closes.4
A refusal goes back
message is wrapped in a reminder and handed to the executor, which starts the round again.
The second is a malfunction rather than a judgement; charging it would quietly cost the executor attempts. Once
max_iters is reached the pipeline stops, the stream ends, and the last message stays in the verifier’s conversation.
Interruption and Resuming
When either agent stops for tool authorization,reply_stream simply ends: no coroutine pinned, no lock held, no polling. Feed the result back in to carry on:
Resuming after an interruption
reply_id of whichever agent parked, and the pipeline routes the result there.
reply_stream accepts these inputs:
The attempt budget lives on the pipeline instance rather than inside
reply_stream, so resuming does not hand the run a fresh set of attempts.Debugging in the Terminal
The quickest way to watch a pipeline is to hand the whole thing to the console, with no adapter code:Running a pipeline in the terminal
Answering an authorization prompt with
Ctrl+D sends a UserInterruptEvent: the parked agent closes its pending tool calls and the pipeline ends with it. An interruption abandons the run rather than continuing it.