When we started building Acenta, one question kept coming up: How do you orchestrate complex workflows across multiple AI agents?
Existing workflow engines like Temporal, Airflow, and Step Functions are excellent tools, but they were designed for traditional microservices. AI agents have unique requirements that demanded a purpose-built solution.
The Challenges of Agent Orchestration
1. Non-Deterministic Execution
Traditional workflows assume deterministic steps: given the same input, you get the same output. AI agents are inherently non-deterministic. An LLM might give different responses to the same prompt.
We needed a system that embraces this uncertainty rather than fighting it.
2. Dynamic Step Selection
In traditional workflows, you define all steps upfront. But agents often need to decide which steps to take based on intermediate results. A research agent might discover that additional investigation is needed mid-workflow.
3. Cost Awareness
Every LLM call has a cost. Unlike traditional compute where you pay for time, agent workflows pay per token. We needed first-class cost tracking and budgeting.
4. Human-in-the-Loop
Many agent workflows need human oversight. Not just approvals, but the ability for humans to course-correct or provide additional context.
Our Design Decisions
Declarative Plans with Runtime Flexibility
We chose a declarative approach where plans define what should happen, but the runtime has flexibility in how it happens:
steps: - id: research type: task agent_capability: web.search input: query: "{{ input.topic }}"
- id: decide type: conditional condition: "{{ steps.research.output.results | length > 10 }}" on_true: summarize on_false: expand_searchThis gives you the predictability of declared workflows with the flexibility agents need.
LLM-Powered Plan Generation
Rather than requiring developers to manually write every plan, we integrated LLM plan generation:
plan = await client.coordination.generate_plan( goal="Research a company and write an investment memo", constraints={ "require_human_approval": True, "max_steps": 8, "available_agents": ["research-agent", "analysis-agent", "writer-agent"] })The LLM understands your goal and available agents, then generates an appropriate plan. You can review and modify before saving.
Adaptive Execution
Our most innovative feature is adaptive execution - plans that revise themselves:
run = await client.coordination.execute( plan_id=plan.id, adaptive={ "enabled": True, "triggers": ["step.failed", "output.confidence < 0.7"], "max_revisions": 3, "human_escalation": True })When a step fails or produces low-confidence output, the system:
- Analyzes what went wrong
- Uses an LLM to revise the remaining plan
- Continues execution with the new approach
If revisions are exhausted, it escalates to a human for guidance.
Sub-Plans and Composition
Complex workflows are composed of smaller, reusable plans:
steps: - id: customer_onboarding type: sub_plan plan: "onboarding-checklist" input: customer_id: "{{ input.customer_id }}"
- id: welcome_email type: task agent_capability: email.send input: template: "welcome" data: "{{ steps.customer_onboarding.output }}"This enables building a library of reusable workflow components.
Architecture Overview
┌─────────────────┐ │ Coordinator │ │ Service │ └────────┬────────┘ │ ┌────────────────────┼────────────────────┐ │ │ │ ▼ ▼ ▼┌───────────────┐ ┌───────────────┐ ┌───────────────┐│ Plan Registry │ │ Run Executor │ │ LLM Engine ││ (Storage) │ │ (Runtime) │ │ (Generation) │└───────────────┘ └───────────────┘ └───────────────┘ │ ▼ ┌───────────────┐ │ Discovery Hub │ │ (Agent Match) │ └───────────────┘The Coordinator Service manages the lifecycle:
- Plan Registry: Stores plan definitions with versioning
- Run Executor: Manages execution state, step dispatch, and result collection
- LLM Engine: Powers plan generation and adaptive revision
- Discovery Integration: Matches step capabilities to available agents
Lessons Learned
Start Simple, Add Complexity Later
Our first version only supported sequential steps. We added parallel execution, conditionals, and sub-plans over time as real use cases demanded them.
Observability is Critical
Debugging distributed agent workflows is hard. We invested heavily in tracing from day one. Every step, every decision, every cost is tracked and queryable.
Expression Language Matters
The templating syntax for referencing previous step outputs ({{ steps.research.output }}) seems simple, but getting it right took multiple iterations. It needs to be powerful enough for real use cases but simple enough to be readable.
What’s Next
We’re continuing to evolve Coordination Hub:
- Visual Plan Builder: Drag-and-drop workflow design
- Plan Analytics: Understand which plans succeed and why
- Parallel Execution Improvements: Better handling of complex parallel patterns
- Custom Step Types: Extend the system with your own step implementations
Conclusion
Building Coordination Hub taught us that agent orchestration requires rethinking traditional workflow assumptions. Non-determinism, dynamic routing, cost awareness, and human oversight aren’t edge cases - they’re core requirements.
We hope our approach helps you build better multi-agent systems. Check out our documentation to learn more.
Have questions about the architecture? Reach out on Twitter or GitHub.