A multi-agent AI workflow is just several model calls in a row, each with its own role prompt, where every call gets the previous call’s output as its task. Whether it survives on a real site depends on the parts the demo leaves out: where the key lives, what happens when call three of four dies, and what each agent gets to see. Mahnoor Javed’s tutorial on Towards Data Science builds it as a travel planner: a research agent finds attractions, an activity agent turns that into a daily plan, a budget agent prices it, a final assistant writes the itinerary.
What the multi-agent AI workflow is
The Agent class is short. It holds a name and a role string, and run() fires one chat completion request, role as the system message, task as the user message, through OpenRouter against gpt-4.1-mini with max_tokens at 1200. The multi-agent part is four of those calls chained: research feeds the activity agent, activities feed the budget agent, the final agent gets all three outputs stitched into one prompt. No framework involved; the big frameworks are mostly bookkeeping around this same shape.
What breaks when you port it to PHP
The tutorial runs in a terminal, so four blocking calls are fine. Inside a WordPress request they are not. The HTTP API defaults to a 5 second timeout, so you raise it per call in wp_remote_post, and even then four sequential generations can outrun what the host lets a PHP request run. If call three dies, the first two already succeeded, you paid for them, and nothing was saved because the results live in local variables.
The key handling is the other gap. The tutorial pastes the key into main.py, which is fine when the laptop is yours. In WordPress the key belongs in wp-config.php as a constant, never inside plugin code.
Moving the chain into Action Scheduler
On a real site the chain belongs in the background, and WordPress has the tool for it, because WooCommerce bundles Action Scheduler. Each step runs as one action, the handoff to the next step is a scheduled action, and intermediate results go into post meta or a custom table so a retry starts where it stopped:
add_action( 'bbioon_agent_step', 'bbioon_run_agent_step' );
function bbioon_run_agent_step( $step ) {
$response = wp_remote_post( 'https://openrouter.ai/api/v1/chat/completions', array(
'timeout' => 60,
'headers' => array(
'Authorization' => 'Bearer ' . BBIOON_AI_KEY,
'Content-Type' => 'application/json',
),
'body' => wp_json_encode( array(
'model' => 'gpt-4.1-mini',
'messages' => array(
array( 'role' => 'system', 'content' => $step['role'] ),
array( 'role' => 'user', 'content' => $step['input'] ),
),
) ),
) );
if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
as_schedule_single_action( time() + 300, 'bbioon_agent_step', array( $step ), 'bbioon-agents' ); // retry later
return;
}
$data = json_decode( wp_remote_retrieve_body( $response ) );
$step['output'] = $data->choices[0]->message->content;
if ( ! empty( $step['next'] ) ) {
$next = $step['next'];
$next['input'] = $step['output'];
as_schedule_single_action( time() + 10, 'bbioon_agent_step', array( $next ), 'bbioon-agents' );
}
}A failed step now shows up under WooCommerce > Status > Scheduled Actions instead of dying silently, and the retry runs it again five minutes later. I’m not sure this holds for long chains on multisite, where one site’s backlog can slow a shared queue runner, but for four steps it fits. It’s the same rule I’ve held since the pasted-prompts post: anything slower than a page load goes in the queue.
If you want a pipeline like this on a client site, with agent calls queued, retried and logged instead of blocking a page load, that’s work I take on. Send me what you have and I’ll say where it fits.
What gets dropped in the handoff
The demo has one bug that’s easy to copy without noticing. The budget agent runs with budget_agent.run(activities), so it receives the activity plan and nothing else. The user typed a budget and interests into input(), but that raw request only ever reaches the research agent. The budget agent sees the constraints only if the activity agent happened to paraphrase them into its own output. In the sample run the totals landed under the $4k the user typed, but nothing in the code guarantees that. Pass the original request along the chain, or store it once and include it in every step’s prompt.
Where it stops paying for itself
The article is honest that the agents have no memory, tools or live data, so the research step is one completion with a good prompt. For a trip plan a single structured prompt would probably get close. The split earns its keep when steps need different models, separate rate limits, retries, or human review in between, say support tickets where one step reads the order and another drafts the reply.
I still don’t know where the crossover sits: at what point a chain of small agents beats one bigger prompt, measured in latency and cost rather than by how the demo felt. Every agent you add multiplies the places the thing can fail.