diff --git a/daprdocs/content/en/contributing/dapr-agents.md b/daprdocs/content/en/contributing/dapr-agents.md index 696c8cff2a9..4da9d352b5a 100644 --- a/daprdocs/content/en/contributing/dapr-agents.md +++ b/daprdocs/content/en/contributing/dapr-agents.md @@ -57,7 +57,7 @@ The project uses pytest for testing. To run tests: tox -e pytest # Run specific test file -tox -e pytest tests/test_random_orchestrator.py +tox -e pytest tests/agents/durableagent/test_durable_agent.py # Run tests with coverage tox -e pytest --cov=dapr_agents diff --git a/daprdocs/content/en/developing-ai/dapr-agents/dapr-agents-core-concepts.md b/daprdocs/content/en/developing-ai/dapr-agents/dapr-agents-core-concepts.md index 54d0f60b099..98aad1de179 100644 --- a/daprdocs/content/en/developing-ai/dapr-agents/dapr-agents-core-concepts.md +++ b/daprdocs/content/en/developing-ai/dapr-agents/dapr-agents-core-concepts.md @@ -328,7 +328,7 @@ Dapr Agents supports two primary orchestration approaches via [Dapr Workflows](h - **Deterministic Workflow-based Orchestration** - Provides clear, repeatable processes with predefined sequences and decision points - **Event-driven Orchestration** - Enables dynamic, adaptive collaboration through message-based coordination among agents -Both approaches utilize a central orchestrator that coordinates multiple specialized agents, each handling specific tasks or domains, ensuring efficient task distribution and seamless collaboration across the system. +Both approaches are built on `DurableAgent`, which serves as both a standalone agent and an orchestrator depending on configuration. When you set `orchestration_mode` on its `AgentExecutionConfig`, a `DurableAgent` coordinates multiple specialized agents — selecting the next agent, managing interaction sequences, and tracking progress — while still retaining all standard agent capabilities such as LLM reasoning and tool calling. ## Deterministic Workflows @@ -522,22 +522,33 @@ asyncio.run(main()) #### Orchestrator -The orchestrator coordinates interactions between agents and manages conversation flow by selecting appropriate agents, managing interaction sequences, and tracking progress. Dapr Agents offers three orchestration strategies: Random, RoundRobin, and LLM-based orchestration. +The orchestrator coordinates interactions between agents and manages conversation flow by selecting appropriate agents, managing interaction sequences, and tracking progress. A `DurableAgent` becomes an orchestrator when you set `orchestration_mode` on its `AgentExecutionConfig`. Three modes are available via the `OrchestrationMode` enum: + +| Mode | Description | +|------|-------------| +| `OrchestrationMode.AGENT` | LLM-driven, plan-based orchestration. The orchestrator generates an execution plan, selects agents based on context, and tracks progress through steps and substeps. Best for complex tasks requiring adaptive coordination. | +| `OrchestrationMode.RANDOM` | Randomly selects an agent each turn with avoidance logic to prevent the same agent from running consecutively. Useful for load distribution and testing. | +| `OrchestrationMode.ROUNDROBIN` | Cycles through agents in a deterministic sequential order. Ensures fair, predictable task distribution across all agents. | + +Internally, each mode maps to a concrete `OrchestrationStrategy` implementation (Strategy Pattern). The `DurableAgent` delegates agent-selection, progress-checking, and finalization to the strategy, keeping the core workflow logic unchanged regardless of mode. + +The following example creates an LLM-driven orchestrator using `OrchestrationMode.AGENT`: ```python +from dapr_agents import DurableAgent from dapr_agents.agents.configs import ( AgentExecutionConfig, AgentPubSubConfig, AgentRegistryConfig, AgentStateConfig, + OrchestrationMode, ) from dapr_agents.llm.openai import OpenAIChatClient from dapr_agents.storage.daprstores.stateservice import StateStoreService from dapr_agents.workflow.runners import AgentRunner -import dapr.ext.workflow as wf -llm_orchestrator = LLMOrchestrator( - name="LLMOrchestrator", +orchestrator = DurableAgent( + name="AgentOrchestrator", llm=OpenAIChatClient(), pubsub=AgentPubSubConfig( pubsub_name="messagepubsub", @@ -553,17 +564,31 @@ llm_orchestrator = LLMOrchestrator( store=StateStoreService(store_name="agentregistrystore"), team_name="fellowship", ), - execution=AgentExecutionConfig(max_iterations=3), - runtime=wf.WorkflowRuntime(), + execution=AgentExecutionConfig( + max_iterations=3, + orchestration_mode=OrchestrationMode.AGENT, + ), ) runner = AgentRunner() -runner.serve(llm_orchestrator, port=8004) +runner.serve(orchestrator, port=8004) ``` -The LLM-based orchestrator uses intelligent agent selection for context-aware decision making, while Random and RoundRobin provide alternative coordination strategies for simpler use cases. The runner keeps the orchestrator online as a Dapr app or HTTP service so clients can publish tasks over topics or REST calls. +To switch to a different strategy, change the `orchestration_mode` value — for example, `OrchestrationMode.RANDOM` or `OrchestrationMode.ROUNDROBIN`. No other code changes are required. + +The runner keeps the orchestrator online as a Dapr app or HTTP service so clients can publish tasks over topics or REST calls. + +{{% alert title="Deprecation Notice" color="warning" %}} +The standalone `LLMOrchestrator`, `RandomOrchestrator`, and `RoundRobinOrchestrator` classes are **deprecated** and will be removed in a future release. Use `DurableAgent` with `AgentExecutionConfig(orchestration_mode=...)` instead: + +| Old class | New equivalent | +|-----------|----------------| +| `LLMOrchestrator` | `DurableAgent(execution=AgentExecutionConfig(orchestration_mode=OrchestrationMode.AGENT))` | +| `RandomOrchestrator` | `DurableAgent(execution=AgentExecutionConfig(orchestration_mode=OrchestrationMode.RANDOM))` | +| `RoundRobinOrchestrator` | `DurableAgent(execution=AgentExecutionConfig(orchestration_mode=OrchestrationMode.ROUNDROBIN))` | +{{% /alert %}} -Because both `DurableAgent.agent_workflow` and the orchestrators above are decorated with `@message_router(message_model=TriggerAction)`, `runner.subscribe(...)` automatically wires the topics declared in `AgentPubSubConfig` and validates every incoming CloudEvent against the expected schema before scheduling the `@workflow_entry`. You can add additional message routers (each with its own `message_model`) to the same agent; the runner will discover them the next time it starts and extend the subscription list automatically. +Because `DurableAgent.agent_workflow` is decorated with `@message_router(message_model=TriggerAction)`, `runner.subscribe(...)` automatically wires the topics declared in `AgentPubSubConfig` and validates every incoming CloudEvent against the expected schema before scheduling the `@workflow_entry`. You can add additional message routers (each with its own `message_model`) to the same agent; the runner will discover them the next time it starts and extend the subscription list automatically. ### Communication Flow diff --git a/daprdocs/content/en/developing-ai/dapr-agents/dapr-agents-introduction.md b/daprdocs/content/en/developing-ai/dapr-agents/dapr-agents-introduction.md index 0b9083fbd2d..2baf5ec11ef 100644 --- a/daprdocs/content/en/developing-ai/dapr-agents/dapr-agents-introduction.md +++ b/daprdocs/content/en/developing-ai/dapr-agents/dapr-agents-introduction.md @@ -38,7 +38,7 @@ Dapr Agents provides specialized modules designed for creating intelligent, auto | [**Durable Agents**]({{% ref "dapr-agents-core-concepts.md#durable-agents" %}}) | Workflow-backed agents that provide fault-tolerant execution with persistent state management and automatic retry mechanisms for long-running processes. | [**Agent Runner**]({{% ref "dapr-agents-core-concepts.md#agent-runner" %}}) | Expose agents over HTTP or subscribe to a PubSub for long-running tasks, enabling API access to agents without requiring a user interface or human intervention. | [**Event-Driven Communication**]({{% ref "dapr-agents-core-concepts.md#event-driven-orchestration" %}}) | Enable agent collaboration through [Pub/Sub messaging]({{% ref pubsub-overview.md %}}) for event-driven communication, task distribution, and real-time coordination in distributed systems. -| [**Agent Orchestration**]({{% ref "dapr-agents-core-concepts.md#deterministic-workflows" %}}) | Deterministic agent orchestration using [Dapr Workflows]({{% ref workflow-overview.md %}}) with higher-level tasks that interact with LLMs for complex multi-step processes. +| [**Agent Orchestration**]({{% ref "dapr-agents-core-concepts.md#multi-agent-systems-mas" %}}) | Orchestrate multi-agent systems using `DurableAgent` — either through [deterministic workflows]({{% ref "dapr-agents-core-concepts.md#deterministic-workflows" %}}) or [event-driven orchestration]({{% ref "dapr-agents-core-concepts.md#event-driven-orchestration" %}}) with configurable `OrchestrationMode` (agent, random, round-robin). ## Agentic Patterns diff --git a/daprdocs/content/en/developing-ai/dapr-agents/dapr-agents-quickstarts.md b/daprdocs/content/en/developing-ai/dapr-agents/dapr-agents-quickstarts.md index facb20f1bd3..c79e22cf38f 100644 --- a/daprdocs/content/en/developing-ai/dapr-agents/dapr-agents-quickstarts.md +++ b/daprdocs/content/en/developing-ai/dapr-agents/dapr-agents-quickstarts.md @@ -24,7 +24,7 @@ aliases: | [LLM Call with OpenAI Client](https://github.com/dapr/dapr-agents/tree/main/quickstarts/02-llm-call-open-ai)
Leverage native LLM client libraries with Dapr Agents using the OpenAI Client for chat completion, audio processing, and embeddings. | - **Text Completion**: Generating responses to prompts
- **Structured Outputs**: Converting LLM responses to Pydantic objects

*Note: Other quickstarts for specific clients are available for [Elevenlabs](https://github.com/dapr/dapr-agents/tree/main/quickstarts/02-llm-call-elevenlabs), [Hugging Face](https://github.com/dapr/dapr-agents/tree/main/quickstarts/02-llm-call-hugging-face), and [Nvidia](https://github.com/dapr/dapr-agents/tree/main/quickstarts/02-llm-call-nvidia).* | | Standalone & Durable Agents
[Standalone Agent Tool Call](https://github.com/dapr/dapr-agents/tree/main/quickstarts/03-standalone-agent-tool-call) · [Durable Agent Tool Call](https://github.com/dapr/dapr-agents/tree/main/quickstarts/03-durable-agent-tool-call) | - **Standalone Agents**: Build conversational agents with tools in under 20 lines using the `Agent` class
- **Durable Agents**: Upgrade to workflow-backed `DurableAgent` instances with `AgentRunner.run/subscribe/serve`
- **Tool Definition**: Reuse tools with the `@tool` decorator and structured args models
- **Function Calling**: Let LLMs invoke Python functions safely | | [Agentic Workflow](https://github.com/dapr/dapr-agents/tree/main/quickstarts/04-llm-based-workflows)
Dive into stateful workflows with Dapr Agents by orchestrating sequential and parallel tasks through powerful workflow capabilities. | - **LLM-powered Tasks**: Using language models in workflows
- **Task Chaining**: Creating resilient multi-step processes executing in sequence
- **Fan-out/Fan-in**: Executing activities in parallel; then synchronizing these activities until all preceding activities have completed | -| [Multi-Agent Workflows](https://github.com/dapr/dapr-agents/tree/main/quickstarts/05-multi-agent-workflows)
Explore advanced event-driven workflows featuring a Lord of the Rings themed multi-agent system where autonomous agents collaborate to solve problems. | - **Multi-agent Systems**: Creating a network of specialized agents
- **Event-driven Architecture**: Implementing pub/sub messaging between agents
- **Workflow Orchestration**: Coordinating agents through different selection strategies| +| [Multi-Agent Workflows](https://github.com/dapr/dapr-agents/tree/main/quickstarts/05-multi-agent-workflows)
Explore advanced event-driven workflows featuring a Lord of the Rings themed multi-agent system where autonomous agents collaborate to solve problems. | - **Multi-agent Systems**: Creating a network of specialized agents
- **Event-driven Architecture**: Implementing pub/sub messaging between agents
- **Workflow Orchestration**: Coordinating agents using `DurableAgent` with `OrchestrationMode` (agent, random, round-robin)| | [Multi-Agent Workflow on Kubernetes](https://github.com/dapr/dapr-agents/tree/main/quickstarts/05-multi-agent-workflow-k8s)
Run multi-agent workflows in Kubernetes, demonstrating deployment and orchestration of event-driven agent systems in a containerized environment. | - **Kubernetes Deployment**: Running agents on Kubernetes
- **Container Orchestration**: Managing agent lifecycles with K8s
- **Service Communication**: Inter-agent communication in K8s | | [Document Agent with Chainlit](https://github.com/dapr/dapr-agents/tree/main/quickstarts/06-document-agent-chainlit)
Create a conversational agent with an operational UI that can upload, and learn unstructured documents while retaining long-term memory. | - **Conversational Document Agent**: Upload and converse over unstructured documents
- **Cloud Agnostic Storage**: Upload files to multiple storage providers
- **Conversation Memory Storage**: Persists conversation history using external storage. | | [Data Agent with MCP and Chainlit](https://github.com/dapr/dapr-agents/tree/main/quickstarts/08-data-agent-mcp-chainlit)
Build a conversational agent over a Postgres database using Model Composition Protocol (MCP) with a ChatGPT-like interface. | - **Database Querying**: Natural language queries to relational databases
- **MCP Integration**: Connecting to databases without DB-specific code
- **Data Analysis**: Complex data analysis through conversation | \ No newline at end of file