microsoft / microsoft/agent-framework

Python: Design question: why do Declarative InvokeAzureAgent and WorkflowBuilder AgentExecutor differ in agent conversation semantics?

Open
#8,298 0 comments 0 reactions 0 assignees View on GitHub
.NET python triage
Dominant language
Python
Stars
13.6k
Forks
2.3k
Avg merge
2d 45m
Merged PRs (30d)
358

Description

## Summary

In Microsoft Agent Framework (Python), invoking an agent via **declarative YAML** (`InvokeAzureAgent`) and via a **hand-authored** `WorkflowBuilder` / orchestration path (`AgentExecutor`) appear to use **different conversation / history models**, even though both ultimately run an `Agent`.

From a product/design perspective, declarative vs code-first often looks like *two expression forms of the same workflow model*. If that is the intent, the **agent conversation semantics would ideally be aligned**. Today they do not seem to be. We would like to understand the **intentional design rationale** (and whether convergence is planned).

## Observed behavior (Python)

### Declarative: `InvokeAzureAgent` → `InvokeAzureAgentExecutor`

- Resolves history from declarative workflow state:
- default: `Conversation.messages`
- with `conversationId`: `System.conversations..messages`
- Calls `agent.run(messages_for_agent, ...)` **without** passing `session=`
- Appends results back into that state path
- `CreateConversation` allocates a new id + empty bucket under `System.conversations`
- Continuity is therefore **workflow-state / checkpoint scoped**, not `AgentSession` + `HistoryProvider`

### Programmatic: `WorkflowBuilder` / builders → `AgentExecutor`

- Holds `self._session` (`AgentSession`, created if none provided)
- Calls `agent.run(..., session=self._session)`
- Checkpoints `agent_session`
- With `HistoryProvider` (and related flags), history is persisted via the **session / provider** path

So the same conceptual step (“run this agent in a workflow”) has:

| Aspect | Declarative `InvokeAzureAgent` | `AgentExecutor` |
| --- | --- | --- |
| Primary history store | Declarative `Conversation*` state | `AgentSession` (+ optional `HistoryProvider`) |
| `session=` on `agent.run` | Not passed | Passed |
| Isolation knob | `conversationId` / `CreateConversation` | Separate sessions / providers |
| Role of agent | Action that mutates workflow conversation state | First-class graph participant with its own session |

## Why this matters

Integrators building a single product surface (e.g. a canvas that compiles to declarative YAML *and* orchestration / code-built graphs) currently must document **two different agent meanings**:

- Canvas declarative “Agent” node ≈ `InvokeAzureAgent` semantics
- Orchestration / `add_agent` ≈ `AgentExecutor` semantics

That is surprising if declarative is meant to be a YAML encoding of the same workflow ideas as `WorkflowBuilder`.

## Questions for maintainers

1. **Was this divergence intentional?** If so, what were the design drivers (e.g. parity with .NET / Foundry declarative / Copilot Studio conversation model vs graph executors)?
2. Should consumers treat declarative and `WorkflowBuilder` as **two different agent models** (by design), rather than two syntaxes for one model?
3. Is there a **roadmap** to converge (e.g. declarative `InvokeAzureAgent` optionally using `AgentSession` / `HistoryProvider`, or documenting a single recommended continuity model)?
4. For isolation (sub-agent private context): is `CreateConversation` + `conversationId` the declarative equivalent of “a separate `AgentSession`”, or should those concepts remain intentionally distinct?

## References (current tree)

- `python/packages/declarative/.../_executors_agents.py` — `InvokeAzureAgentExecutor` (`messages_path`, `agent.run` without session)
- `python/packages/declarative/.../_executors_basic.py` — `CreateConversationExecutor`
- `python/packages/core/.../_workflows/_agent_executor.py` — `AgentExecutor` (`self._session`, `agent.run(..., session=...)`)
- Docs: [Declarative workflows](https://learn.microsoft.com/en-us/agent-framework/workflows/declarative) (`conversationId`, `CreateConversation`, etc.)

Happy to adjust assumptions if we misread the intended layering. Thanks!

Contributor guide

Open the contributing guide

Research direction

Read python/packages/declarative/.../_executors_agents.py and _executors_basic.py alongside python/packages/core/.../_workflows/_agent_executor.py, then compare the referenced declarative workflow documentation. Trace how each executor stores history and passes sessions. Done requires a maintainer decision on whether the models should converge, remain distinct, or need clarified documentation.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
ai, backend-api-design
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.