As AI agents moved from single-prompt chatbots to multi-step, tool-using systems, a wave of orchestration frameworks emerged to manage that complexity — each with genuinely different philosophies worth understanding before picking one.
What These Frameworks Actually Solve
- Chaining multiple LLM calls together, passing context between steps
- Giving a model access to tools (search, code execution, APIs) and parsing its requests to use them
- Managing memory/state across a multi-turn agent interaction
- Coordinating multiple specialized agents working on sub-tasks of a larger goal
# The core loop most orchestration frameworks formalize:
def agent_loop(goal, tools, model, max_steps=10):
history = [{"role": "user", "content": goal}]
for _ in range(max_steps):
response = model.generate(history, available_tools=tools)
if response.is_final_answer:
return response.content
result = execute_tool(response.tool_call)
history.append({"role": "tool", "content": result})
Genuinely Different Philosophies
Some frameworks favor heavily declarative, graph-based workflows (explicit state machines defining exactly what can happen next); others favor a more freeform, model-driven loop where the LLM itself decides the next step dynamically. Graph-based approaches are more predictable and debuggable; freeform loops are more flexible but genuinely harder to reason about and constrain.
Before adopting a heavy framework, it’s worth prototyping the simple loop above directly — a surprising number of agent use cases don’t actually need the full complexity a framework adds, and understanding the underlying loop makes evaluating frameworks far more informed.