Event Planning Team — Multi-Agent Overview
The Event Planning Team is a multi-agent system where seven specialist agents — each built with a different AI framework — coordinate through Dapr pub/sub to plan events end-to-end. An orchestrator delegates tasks to the right specialist, and Dapr handles all messaging, state, and fault tolerance.
This scenario demonstrates how the Diagrid SDK makes any Python agent framework production-ready with durable workflows, pub/sub coordination, and persistent state.
Architecture
┌─────────────────────────┐
│ Event Coordinator │
│ (Dapr Agents - 8007) │
│ Orchestrator │
└────────────┬────────────┘
│ delegates via pub/sub
┌──────────┬──────────┬────┴────┬──────────┬──────────┬──────────┐
▼ ▼ ▼ ▼ ▼ ▼ ▼
┌────────────┐┌────────────┐┌────────────┐┌────────────┐┌────────────┐┌────────────┐┌────────────┐
│ Venue ││ Catering ││Entertainment││ Budget ││ Schedule ││Invitations ││ Decoration │
│ Scout ││ Coordinator││ Planner ││ Analyst ││ Planner ││ Manager ││ Planner │
│ (CrewAI) ││ (OpenAI) ││ (ADK) ││ (Strands) ││(LangGraph) ││(Dapr Agents)││(Pydantic AI)│
│ :8001 ││ :8002 ││ :8003 ││ :8004 ││ :8005 ││ :8006 ││ :8008 │
└────────────┘└────────────┘└────────────┘└────────────┘└────────────┘└────────────┘└────────────┘
Agent Roster
| Agent | Framework | Port | Role | Pub/Sub Topics | Guide |
|---|---|---|---|---|---|
| Venue Scout | CrewAI | 8001 | Find event venues by city and capacity | venue.requests → venue.results | View |
| Catering Coordinator | OpenAI Agents | 8002 | Find catering by cuisine and guest count | catering.requests → catering.results | View |
| Entertainment Planner | Google ADK | 8003 | Find entertainment options for event types | entertainment.requests → entertainment.results | View |
| Budget Analyst | Strands | 8004 | Calculate event budget breakdowns | budget.requests → budget.results | View |
| Schedule Planner | LangGraph | 8005 | Check venue availability for dates | schedule.requests → schedule.results | View |
| Invitations Manager | Dapr Agents | 8006 | Send event invitations | events.invitations.requests | View |
| Event Coordinator | Dapr Agents | 8007 | Orchestrate all agents | events.orchestrator.requests | Below |
| Decoration Planner | Pydantic AI | 8008 | Find decoration packages by theme | decorations.requests → decorations.results | View |
Orchestrator Code
The Event Coordinator uses the Dapr Agents DurableAgent to coordinate all specialists. It delegates tasks in parallel based on each agent's role.
import logging
import os
from dapr_agents.agents import DurableAgent
from dapr_agents.agents.configs import (
AgentExecutionConfig,
AgentPubSubConfig,
AgentRegistryConfig,
AgentStateConfig,
OrchestrationMode,
)
from dapr_agents.llm import DaprChatClient
from dapr_agents.storage.daprstores.stateservice import StateStoreService
from dapr_agents.workflow.runners import AgentRunner
def main() -> None:
logging.basicConfig(level=logging.DEBUG)
orchestrator = DurableAgent(
name="EventCoordinator",
role="Event Planning Coordinator",
goal="Coordinate the event planning team to deliver a complete event plan by delegating to all available specialist agents",
instructions=[
"You coordinate a team of specialist agents to plan events. Delegate all tasks in parallel when possible.",
"For each request: 1) Find a venue, 2) Find catering, 3) Find entertainment, 4) Check date availability, 5) Calculate the budget, 6) Send invitations.",
"Delegate each task to the matching agent based on their role. Do not attempt tasks yourself.",
"Once all agents have responded, synthesize their results into a single comprehensive event plan.",
],
llm=DaprChatClient(component_name="llm-provider"),
pubsub=AgentPubSubConfig(
pubsub_name="agent-pubsub",
agent_topic="events.orchestrator.requests",
broadcast_topic="agents.broadcast",
),
state=AgentStateConfig(
store=StateStoreService(store_name="agent-workflow", key_prefix="orchestrator:"),
),
registry=AgentRegistryConfig(
store=StateStoreService(store_name="agent-registry"),
),
execution=AgentExecutionConfig(
max_iterations=25,
orchestration_mode=OrchestrationMode.AGENT,
),
)
runner = AgentRunner()
try:
runner.serve(orchestrator, port=int(os.environ.get("APP_PORT", "8007")))
finally:
runner.shutdown(orchestrator)
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
pass
How the orchestrator works
DurableAgent— A Dapr Agents agent that can delegate tasks to other agents via pub/subinstructions— Tell the LLM how to coordinate: delegate in parallel, synthesize resultsAgentPubSubConfig— Listens onevents.orchestrator.requestsand broadcasts to specialist agentsAgentRegistryConfig— Discovers available agents through a shared registry (backed by Dapr state)OrchestrationMode.AGENT— The orchestrator uses the LLM to decide which agents to delegate to and when
Shared Dapr Components
All agents share these Dapr components, defined as YAML files in the shared-resources/ directory:
Pub/Sub Broker (agent-pubsub)
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: agent-pubsub
spec:
type: pubsub.redis
version: v1
metadata:
- name: redisHost
value: localhost:6379
- name: redisPassword
value: ""
All inter-agent messaging flows through this pub/sub component. Swap Redis for Kafka, RabbitMQ, or any Dapr pub/sub broker by changing the YAML.
Agent Memory (agent-memory)
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: agent-memory
spec:
type: state.redis
version: v1
metadata:
- name: redisHost
value: localhost:6379
- name: redisPassword
value: ""
- name: actorStateStore
value: "false"
Stores agent memory and conversation state.
Workflow State (agent-workflow)
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: agent-workflow
spec:
type: state.redis
version: v1
metadata:
- name: redisHost
value: localhost:6379
- name: redisPassword
value: ""
- name: actorStateStore
value: "true"
Stores durable workflow state and actor state for the orchestrator.
Agent Registry (agent-registry)
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: agent-registry
spec:
type: state.redis
version: v1
metadata:
- name: redisHost
value: localhost:6379
- name: redisPassword
value: ""
- name: keyPrefix
value: none
Shared registry where agents register their capabilities. The orchestrator discovers agents through this registry.
LLM Provider
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: llm-provider
spec:
type: conversation.openai
version: v1
metadata:
- name: key
value: "{{OPENAI_API_KEY}}"
- name: model
value: gpt-4.1-2025-04-14
Provides LLM access through Dapr's conversation API. The API key is injected from the environment.
Run the Full Team
Clone the quickstarts repo
git clone https://github.com/diagridio/catalyst-quickstarts.git
cd catalyst-quickstarts/agents
Set your API key
export OPENAI_API_KEY="your-key-here"
Install dependencies for each agent
Each agent has its own requirements.txt. Install them all:
for dir in crewai openai-agents adk strands langgraph pydantic-ai dapr-agents/orchestrator dapr-agents/durable-agent; do
pip install -r $dir/requirements.txt
done
Run individual agents
Start each agent in a separate terminal using its dev YAML:
# Terminal 1 — Venue Scout (CrewAI)
cd crewai && diagrid dev run -f dev-python-crewai.yaml
# Terminal 2 — Catering Coordinator (OpenAI Agents)
cd openai-agents && diagrid dev run -f dev-python-openai.yaml
# Terminal 3 — Entertainment Planner (ADK)
cd adk && diagrid dev run -f dev-python-adk.yaml
# Terminal 4 — Budget Analyst (Strands)
cd strands && diagrid dev run -f dev-python-strands.yaml
# Terminal 5 — Schedule Planner (LangGraph)
cd langgraph && diagrid dev run -f dev-python-langgraph.yaml
# Terminal 6 — Invitations Manager (Dapr Agents)
cd dapr-agents/durable-agent && diagrid dev run -f dev-python-durable-agent.yaml
# Terminal 7 — Decoration Planner (Pydantic AI)
cd pydantic-ai && diagrid dev run -f dev-python-pydantic-ai.yaml
# Terminal 8 — Event Coordinator (Orchestrator)
cd dapr-agents/orchestrator && diagrid dev run -f dev-python-orchestrator.yaml
Send an event planning request
curl -X POST http://localhost:8007/agent/run \
-H "Content-Type: application/json" \
-d '{"task": "Plan a corporate gala in San Francisco for 200 guests on March 15, 2026"}'
The orchestrator will delegate tasks to all specialist agents in parallel, then synthesize their responses into a comprehensive event plan.
Key Concepts
| Concept | Description |
|---|---|
| Framework Agnostic | Each agent uses a different AI framework. The Diagrid SDK wraps them all in the same durable workflow pattern. |
| Pub/Sub Coordination | Agents communicate through Dapr topics. The orchestrator delegates tasks and collects results without direct coupling. |
| Durable Execution | Every agent runs inside a durable workflow. Crashes, restarts, and failures are handled automatically. |
| Shared Infrastructure | All agents share the same Dapr components (pub/sub, state, LLM). Swap backends by changing YAML. |
| Agent Registry | Specialist agents register their capabilities. The orchestrator discovers them dynamically. |
Next Steps
- CLI Quickstart — Deploy a durable agent to Catalyst in minutes
- Durable Agent Quickstart — Build a single durable agent step by step
- Pick a Framework — Explore individual framework guides