跳转到正文

Neuron 依赖工作流

这个示例回答了一个常见的代理式问题:

一个工作流能否决定另一个工作流只有在前一个工作流完成后才能继续?

可以。关键是,Queuety 已经通过 wait_for_workflow() 和 wait_for_workflows() 支持这种做法。

这意味着:

  • 工作流 X 可以立即调度
  • X 可以停驻在 waiting_for_workflows 中
  • 只有在工作流 Y 完成后,X 才会恢复

示例:先研究,再写作

使用一个顶层工作流生成研究资料包,再用第二个顶层工作流起草最终文案。

研究工作流

PHP
use Queuety\Enums\WaitMode;
use Queuety\Queuety;

$research_agent = Queuety::workflow('research_agent')
    ->then(ResearchTopicStep::class);

$research_id = Queuety::workflow('research_packet')
    ->then(PlanResearchTasksStep::class)
    ->start_agents('agent_tasks', $research_agent)
    ->wait_for_agents(mode: WaitMode::All, result_key: 'agent_results')
    ->then(SynthesizeResearchPacketStep::class)
    ->dispatch([
        'brief_id' => 42,
        'provider' => 'anthropic',
    ]);

写作工作流

PHP
Queuety::workflow('write_brief')
    ->wait_for_workflow('research_workflow_id', 'research')
    ->then(WriteBriefWithNeuronStep::class)
    ->wait_for_decision(result_key: 'editor_review')
    ->then(PublishBriefStep::class)
    ->dispatch([
        'brief_id' => 42,
        'research_workflow_id' => $research_id,
        'provider' => 'openai',
    ]);

写作工作流启动时,会立即在 waiting_for_workflows 中暂停,直到研究工作流成功完成。

Neuron 写作步骤

PHP
namespace App\Workflow\Steps;

use App\Neuron\WriterAgent;
use NeuronAI\Chat\Messages\UserMessage;
use Queuety\Step;

final class WriteBriefWithNeuronStep implements Step
{
    public function handle(array $state): array
    {
        $agent = new WriterAgent(
            providerName: $state['provider'] ?? 'openai',
        );

        $message = $agent->chat(
            new UserMessage(sprintf(
                "Write the final brief for brief %d using this research packet:\n\n%s",
                $state['brief_id'],
                json_encode($state['research'], JSON_PRETTY_PRINT),
            ))
        )->getMessage();

        return [
            'draft_markdown' => $message->getContent(),
        ];
    }

    public function config(): array
    {
        return [];
    }
}

之所以可以使用 $state['research'],是因为 wait_for_workflow() 已将依赖工作流完成后的公开状态复制到当前工作流的 research 键下。

何时使用这种方式,而非一个庞大的工作流

以下情况更适合使用多个独立的顶层工作流:

  • 各阶段的负责人或运维生命周期不同
  • 你希望分别检查和重试各阶段
  • 即使前一阶段尚未完成,也应当能够调度后续阶段

以下情况更适合使用单个工作流:

  • 各阶段紧密耦合
  • 各阶段共用一个生命周期和一个状态包

状态机的适用场景

如果这个写作流程属于一个持续时间较长的编辑会话,可以让 状态机 管理外层生命周期,并用这些工作流执行有界的阶段。这样既能明确表示 awaiting_brief、researching、awaiting_review 和 completed 等生命周期状态,又能保留各阶段内的工作流持久性。

一个重要区别

这种模式意味着:

  • X 现在已经存在,但会等待 Y

这并不意味着:

  • 只有在 Y 完成后才会创建 X

如果你需要第二种行为,可以让父工作流等待 Y,然后才为 X 调用 start_workflows() 或 start_agents()。