Skip to main content

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

AgentFrameworkPortRolePub/Sub TopicsGuide
Venue ScoutCrewAI8001Find event venues by city and capacityvenue.requestsvenue.resultsView
Catering CoordinatorOpenAI Agents8002Find catering by cuisine and guest countcatering.requestscatering.resultsView
Entertainment PlannerGoogle ADK8003Find entertainment options for event typesentertainment.requestsentertainment.resultsView
Budget AnalystStrands8004Calculate event budget breakdownsbudget.requestsbudget.resultsView
Schedule PlannerLangGraph8005Check venue availability for datesschedule.requestsschedule.resultsView
Invitations ManagerDapr Agents8006Send event invitationsevents.invitations.requestsView
Event CoordinatorDapr Agents8007Orchestrate all agentsevents.orchestrator.requestsBelow
Decoration PlannerPydantic AI8008Find decoration packages by themedecorations.requestsdecorations.resultsView

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.

agents/dapr-agents/orchestrator/main.py
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

  1. DurableAgent — A Dapr Agents agent that can delegate tasks to other agents via pub/sub
  2. instructions — Tell the LLM how to coordinate: delegate in parallel, synthesize results
  3. AgentPubSubConfig — Listens on events.orchestrator.requests and broadcasts to specialist agents
  4. AgentRegistryConfig — Discovers available agents through a shared registry (backed by Dapr state)
  5. 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)

shared-resources/agent-pubsub.yaml
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)

shared-resources/agent-memory.yaml
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)

shared-resources/wfstatestore.yaml
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)

shared-resources/agent-registry.yaml
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

shared-resources/llm-provider.yaml
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

1

Clone the quickstarts repo

git clone https://github.com/diagridio/catalyst-quickstarts.git
cd catalyst-quickstarts/agents
2

Set your API key

export OPENAI_API_KEY="your-key-here"
3

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
4

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
5

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

ConceptDescription
Framework AgnosticEach agent uses a different AI framework. The Diagrid SDK wraps them all in the same durable workflow pattern.
Pub/Sub CoordinationAgents communicate through Dapr topics. The orchestrator delegates tasks and collects results without direct coupling.
Durable ExecutionEvery agent runs inside a durable workflow. Crashes, restarts, and failures are handled automatically.
Shared InfrastructureAll agents share the same Dapr components (pub/sub, state, LLM). Swap backends by changing YAML.
Agent RegistrySpecialist agents register their capabilities. The orchestrator discovers them dynamically.

Next Steps