The first version of this orchestration failed in a very specific way: the mapper kept producing templates that looked plausible to a human and were wrong for the platform. The failure was not that the model was incapable of reasoning. The failure was that I had asked too much of a single, broad conversation, so the wrong structure got accepted early and then propagated all the way to the end. By the time the validator complained, the chain had already lost the distinction between analysis, mapping, generation, and approval.

That is the point where I stopped treating the system like a prompt stack and started treating it like a state machine. In the workflow analyzer SaaS, the code in runner/azure_foundry/src/orchestrator.py does the important work: it creates the kernel, registers the plugins, assembles the agents, defines who speaks next, and decides when the run is done. The state manager in runner/azure_foundry/src/state_manager.py sits around that orchestration so a run can resume from the last durable message history instead of inventing a fresh conversation every time. That single design choice changed the behavior of the whole pipeline.

The architecture I wanted was simple to describe and annoying to get right: each agent gets one contract, each contract produces one kind of output, and the validator is the gate that decides whether the output can move forward. The analyzer looks at the workflow analysis and identifies automation opportunity. The mapper turns that opportunity into abstract integration steps. The generator turns the mapped steps into a platform-shaped template. The validator checks the structure and either approves the run or sends it back to the generator.