picoflow.io

Lesson 8: NameStep + InContext Sub-Agent + Step Fan-Out


Prompt + Tools

public getPrompt(): string {
  return `
    ${DemoPrompt.TravelRole}
    Please collect name from customer.
    Once you capture the name, immediately call tool 'user_name'.
    Pay attention to the tool respond if the name is validated or not.
    If user prefer to exit, call tool 'end_chat'.
  `;
}

defineTool(): [{ name: 'user_name', schema: z.object({ name: z.string() }) }];
getTool(): ['user_name', 'end_chat'];

Handler: Context + Sub-Agent + Validation

protected async user_name(tool: ToolCall): Promise<ToolResponseType> {
  this.saveState({ name: tool.args?.name });

  if (tool.args?.name === 'John Doe') {
    return {
      step: NameStep,
      tool: 'Cannot accept John Doe, please choose a different name.',
    };
  }

  const runData = this.flow.getContext<object>('myRunData');
  this.saveState(runData);

  this.flow.saveTransientStepState(InContextStep, {
    msg: 'transient variable passed from NameStep',
  });
  const answer = await this.runStep(InContextStep);
  this.saveState({ inContext: answer });
  return DOBStep;
}
  • Merges request-time context into state.
  • Calls InContextStep as a nested sub-agent; the result is captured synchronously.
  • Rejects a banned name by retrying the same step with an error tool message.

Step-Level Fan-Out

The demo goes one step further. InContextStep does not only produce an answer — it also fans out into child steps from inside the step lifecycle:

protected async onEnter() {
  await super.onEnter();
  const msg = this.getTransientState<string>('msg');
  const [concurStep1, concurStep2] = await this.runSteps([
    {
      step: ConcurStep1,
      userMessage: 'Run the first concurrent follow-up task.',
    },
    {
      step: ConcurStep2,
      userMessage: 'Run the second concurrent follow-up task.',
    },
  ]);
  this.saveState({ concurStep1, concurStep2 });
}
  • runStep and runSteps trigger child steps from inside a parent step.
  • This is step-level fan-out, which is different from the document-flow fan-out you will see in the next lesson.
  • The child steps run as part of the current step’s orchestration rather than as separate top-level flow documents.

Next: DOBStep — prompt templating from captured name.