Skip to content

Commit c638f6c

Browse files
Merge pull request #821 from MicrosoftDocs/main
update live
2 parents bc455f1 + b481ac4 commit c638f6c

49 files changed

Lines changed: 1619 additions & 810 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.openpublishing.publish.config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"build_output_subfolder": "agent-framework",
77
"locale": "en-us",
88
"monikers": [],
9-
"open_to_public_contributors": false,
9+
"open_to_public_contributors": true,
1010
"type_mapping": {
1111
"Conceptual": "Content"
1212
},

agent-framework/integrations/ag-ui/backend-tool-rendering.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ To see tool calls and results in real-time, extend the client's streaming loop t
186186

187187
```csharp
188188
// Inside the streaming loop from getting-started.md
189-
await foreach (AgentRunResponseUpdate update in agent.RunStreamingAsync(messages, thread))
189+
await foreach (AgentResponseUpdate update in agent.RunStreamingAsync(messages, thread))
190190
{
191191
ChatResponseUpdate chatUpdate = update.AsChatResponseUpdate();
192192

agent-framework/integrations/ag-ui/frontend-tools.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ AIAgent inspectableAgent = baseAgent
8585
.Use(runFunc: null, runStreamingFunc: InspectToolsMiddleware)
8686
.Build();
8787

88-
static async IAsyncEnumerable<AgentRunResponseUpdate> InspectToolsMiddleware(
88+
static async IAsyncEnumerable<AgentResponseUpdate> InspectToolsMiddleware(
8989
IEnumerable<ChatMessage> messages,
9090
AgentThread? thread,
9191
AgentRunOptions? options,
@@ -109,7 +109,7 @@ static async IAsyncEnumerable<AgentRunResponseUpdate> InspectToolsMiddleware(
109109
}
110110
}
111111

112-
await foreach (AgentRunResponseUpdate update in innerAgent.RunStreamingAsync(messages, thread, options, cancellationToken))
112+
await foreach (AgentResponseUpdate update in innerAgent.RunStreamingAsync(messages, thread, options, cancellationToken))
113113
{
114114
yield return update;
115115
}

agent-framework/integrations/ag-ui/getting-started.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ try
209209
bool isFirstUpdate = true;
210210
string? threadId = null;
211211

212-
await foreach (AgentRunResponseUpdate update in agent.RunStreamingAsync(messages, thread))
212+
await foreach (AgentResponseUpdate update in agent.RunStreamingAsync(messages, thread))
213213
{
214214
ChatResponseUpdate chatUpdate = update.AsChatResponseUpdate();
215215

@@ -257,7 +257,7 @@ catch (Exception ex)
257257
- **Server-Sent Events (SSE)**: The protocol uses SSE for streaming responses
258258
- **AGUIChatClient**: Client class that connects to AG-UI servers and implements `IChatClient`
259259
- **CreateAIAgent**: Extension method on `AGUIChatClient` to create an agent from the client
260-
- **RunStreamingAsync**: Streams responses as `AgentRunResponseUpdate` objects
260+
- **RunStreamingAsync**: Streams responses as `AgentResponseUpdate` objects
261261
- **AsChatResponseUpdate**: Extension method to access chat-specific properties like `ConversationId` and `ResponseId`
262262
- **Thread Management**: The `AgentThread` maintains conversation context across requests
263263
- **Content Types**: Responses include `TextContent` for messages and `ErrorContent` for errors
@@ -327,7 +327,7 @@ The client displays different content types with distinct colors:
327327

328328
1. `AGUIChatClient` sends HTTP POST request to server endpoint
329329
2. Server responds with SSE stream
330-
3. Client parses incoming events into `AgentRunResponseUpdate` objects
330+
3. Client parses incoming events into `AgentResponseUpdate` objects
331331
4. Each update is displayed based on its content type
332332
5. `ConversationId` is captured for conversation continuity
333333
6. Stream completes when run finishes

agent-framework/integrations/ag-ui/human-in-the-loop.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ var agent = baseAgent
126126
cancellationToken))
127127
.Build();
128128

129-
static async IAsyncEnumerable<AgentRunResponseUpdate> HandleApprovalRequestsMiddleware(
129+
static async IAsyncEnumerable<AgentResponseUpdate> HandleApprovalRequestsMiddleware(
130130
IEnumerable<ChatMessage> messages,
131131
AgentThread? thread,
132132
AgentRunOptions? options,
@@ -250,8 +250,8 @@ static async IAsyncEnumerable<AgentRunResponseUpdate> HandleApprovalRequestsMidd
250250
}
251251

252252
// Local function: Convert FunctionApprovalRequestContent to client tool calls
253-
static async IAsyncEnumerable<AgentRunResponseUpdate> ConvertFunctionApprovalsToToolCalls(
254-
AgentRunResponseUpdate update,
253+
static async IAsyncEnumerable<AgentResponseUpdate> ConvertFunctionApprovalsToToolCalls(
254+
AgentResponseUpdate update,
255255
JsonSerializerOptions jsonSerializerOptions)
256256
{
257257
// Check if this update contains a FunctionApprovalRequestContent
@@ -292,7 +292,7 @@ static async IAsyncEnumerable<AgentRunResponseUpdate> HandleApprovalRequestsMidd
292292
var approvalJson = JsonSerializer.Serialize(approvalData, jsonSerializerOptions.GetTypeInfo(typeof(ApprovalRequest)));
293293

294294
// Yield a tool call update that represents the approval request
295-
yield return new AgentRunResponseUpdate(ChatRole.Assistant, [
295+
yield return new AgentResponseUpdate(ChatRole.Assistant, [
296296
new FunctionCallContent(
297297
callId: approvalId,
298298
name: "request_approval",
@@ -337,7 +337,7 @@ var wrappedAgent = agent
337337
cancellationToken))
338338
.Build();
339339

340-
static async IAsyncEnumerable<AgentRunResponseUpdate> HandleApprovalRequestsClientMiddleware(
340+
static async IAsyncEnumerable<AgentResponseUpdate> HandleApprovalRequestsClientMiddleware(
341341
IEnumerable<ChatMessage> messages,
342342
AgentThread? thread,
343343
AgentRunOptions? options,
@@ -414,8 +414,8 @@ static async IAsyncEnumerable<AgentRunResponseUpdate> HandleApprovalRequestsClie
414414
}
415415

416416
// Local function: Convert request_approval tool calls to FunctionApprovalRequestContent
417-
static async IAsyncEnumerable<AgentRunResponseUpdate> ConvertToolCallsToApprovalRequests(
418-
AgentRunResponseUpdate update,
417+
static async IAsyncEnumerable<AgentResponseUpdate> ConvertToolCallsToApprovalRequests(
418+
AgentResponseUpdate update,
419419
JsonSerializerOptions jsonSerializerOptions)
420420
{
421421
FunctionCallContent? approvalToolCall = null;
@@ -452,7 +452,7 @@ static async IAsyncEnumerable<AgentRunResponseUpdate> HandleApprovalRequestsClie
452452
arguments: functionArguments);
453453

454454
// Yield the original tool call first (for message history)
455-
yield return new AgentRunResponseUpdate(ChatRole.Assistant, [approvalToolCall]);
455+
yield return new AgentResponseUpdate(ChatRole.Assistant, [approvalToolCall]);
456456

457457
// Create approval request with CallId stored in AdditionalProperties
458458
var approvalRequestContent = new FunctionApprovalRequestContent(
@@ -463,7 +463,7 @@ static async IAsyncEnumerable<AgentRunResponseUpdate> HandleApprovalRequestsClie
463463
approvalRequestContent.AdditionalProperties ??= new Dictionary<string, object?>();
464464
approvalRequestContent.AdditionalProperties["request_approval_call_id"] = approvalToolCall.CallId;
465465

466-
yield return new AgentRunResponseUpdate(ChatRole.Assistant, [approvalRequestContent]);
466+
yield return new AgentResponseUpdate(ChatRole.Assistant, [approvalRequestContent]);
467467
}
468468
}
469469
#pragma warning restore MEAI001
@@ -490,7 +490,7 @@ do
490490
approvalResponses.Clear();
491491
approvalToolCalls.Clear();
492492

493-
await foreach (AgentRunResponseUpdate update in wrappedAgent.RunStreamingAsync(
493+
await foreach (AgentResponseUpdate update in wrappedAgent.RunStreamingAsync(
494494
messages, thread, cancellationToken: cancellationToken))
495495
{
496496
foreach (AIContent content in update.Contents)

agent-framework/integrations/ag-ui/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ Understanding how Agent Framework concepts map to AG-UI helps you build effectiv
114114
| `AIAgent` | Agent Endpoint | Each agent becomes an HTTP endpoint |
115115
| `agent.Run()` | HTTP POST Request | Client sends messages via HTTP |
116116
| `agent.RunStreamingAsync()` | Server-Sent Events | Streaming responses via SSE |
117-
| `AgentRunResponseUpdate` | AG-UI Events | Converted to protocol events automatically |
117+
| `AgentResponseUpdate` | AG-UI Events | Converted to protocol events automatically |
118118
| `AIFunctionFactory.Create()` | Backend Tools | Executed on server, results streamed |
119119
| `ApprovalRequiredAIFunction` | Human-in-the-Loop | Middleware converts to approval protocol |
120120
| `AgentThread` | Thread Management | `ConversationId` maintains context |

agent-framework/integrations/ag-ui/state-management.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -113,17 +113,17 @@ internal sealed class SharedStateAgent : DelegatingAIAgent
113113
this._jsonSerializerOptions = jsonSerializerOptions;
114114
}
115115

116-
public override Task<AgentRunResponse> RunAsync(
116+
public override Task<AgentResponse> RunAsync(
117117
IEnumerable<ChatMessage> messages,
118118
AgentThread? thread = null,
119119
AgentRunOptions? options = null,
120120
CancellationToken cancellationToken = default)
121121
{
122122
return this.RunStreamingAsync(messages, thread, options, cancellationToken)
123-
.ToAgentRunResponseAsync(cancellationToken);
123+
.ToAgentResponseAsync(cancellationToken);
124124
}
125125

126-
public override async IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync(
126+
public override async IAsyncEnumerable<AgentResponseUpdate> RunStreamingAsync(
127127
IEnumerable<ChatMessage> messages,
128128
AgentThread? thread = null,
129129
AgentRunOptions? options = null,
@@ -187,7 +187,7 @@ internal sealed class SharedStateAgent : DelegatingAIAgent
187187
var firstRunMessages = messages.Append(stateUpdateMessage);
188188

189189
// Collect all updates from first run
190-
var allUpdates = new List<AgentRunResponseUpdate>();
190+
var allUpdates = new List<AgentResponseUpdate>();
191191
await foreach (var update in this.InnerAgent.RunStreamingAsync(firstRunMessages, thread, firstRunOptions, cancellationToken).ConfigureAwait(false))
192192
{
193193
allUpdates.Add(update);
@@ -200,7 +200,7 @@ internal sealed class SharedStateAgent : DelegatingAIAgent
200200
}
201201
}
202202

203-
var response = allUpdates.ToAgentRunResponse();
203+
var response = allUpdates.ToAgentResponse();
204204

205205
// Try to deserialize the structured state response
206206
if (response.TryDeserialize(this._jsonSerializerOptions, out JsonElement stateSnapshot))
@@ -209,7 +209,7 @@ internal sealed class SharedStateAgent : DelegatingAIAgent
209209
byte[] stateBytes = JsonSerializer.SerializeToUtf8Bytes(
210210
stateSnapshot,
211211
this._jsonSerializerOptions.GetTypeInfo(typeof(JsonElement)));
212-
yield return new AgentRunResponseUpdate
212+
yield return new AgentResponseUpdate
213213
{
214214
Contents = [new DataContent(stateBytes, "application/json")]
215215
};

agent-framework/migration-guide/from-autogen/index.md

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -221,33 +221,39 @@ def get_time() -> str:
221221
client = OpenAIChatClient(model_id="gpt-5")
222222

223223
async def example():
224-
# Direct creation
224+
# Direct creation with default options
225225
agent = ChatAgent(
226226
name="assistant",
227227
chat_client=client,
228228
instructions="You are a helpful assistant.",
229-
tools=[get_weather] # Multi-turn by default
229+
tools=[get_weather], # Multi-turn by default
230+
default_options={
231+
"temperature": 0.7,
232+
"max_tokens": 1000,
233+
}
230234
)
231235

232236
# Factory method (more convenient)
233237
agent = client.create_agent(
234238
name="assistant",
235239
instructions="You are a helpful assistant.",
236-
tools=[get_weather]
240+
tools=[get_weather],
241+
default_options={"temperature": 0.7}
237242
)
238243

239-
# Execution with runtime tool configuration
244+
# Execution with runtime tool and options configuration
240245
result = await agent.run(
241246
"What's the weather?",
242-
tools=[get_time], # Can add tools at runtime
243-
tool_choice="auto"
247+
tools=[get_time], # Can add tools at runtime (keyword arg)
248+
options={"tool_choice": "auto"} # Other options go in options dict
244249
)
245250
```
246251

247252
**Key Differences:**
248253

249254
- **Default behavior**: `ChatAgent` automatically iterates through tool calls, while `AssistantAgent` requires explicit `max_tool_iterations` setting
250-
- **Runtime configuration**: `ChatAgent.run()` accepts `tools` and `tool_choice` parameters for per-invocation customization
255+
- **Runtime configuration**: `ChatAgent.run()` accepts `tools` as a keyword argument and other options via the `options` dict parameter for per-invocation customization
256+
- **Options system**: Agent Framework uses TypedDict-based options (e.g., `OpenAIChatOptions`) for type safety and IDE autocomplete. Options are passed via `default_options` at construction and `options` at runtime
251257
- **Factory methods**: Agent Framework provides convenient factory methods directly from chat clients
252258
- **State management**: `ChatAgent` is stateless and doesn't maintain conversation history between invocations, unlike `AssistantAgent` which maintains conversation history as part of its state
253259

@@ -340,18 +346,21 @@ async for event in agent.run_stream(task="Hello"):
340346
```python
341347
# Assume we have client, agent, and tools from previous examples
342348
async def streaming_example():
343-
# Chat client streaming
344-
async for chunk in client.get_streaming_response("Hello", tools=tools):
349+
# Chat client streaming - tools go in options dict
350+
async for chunk in client.get_streaming_response(
351+
"Hello",
352+
options={"tools": tools}
353+
):
345354
if chunk.text:
346355
print(chunk.text, end="")
347356

348-
# Agent streaming
349-
async for chunk in agent.run_stream("Hello"):
357+
# Agent streaming - tools can be keyword arg on agents
358+
async for chunk in agent.run_stream("Hello", tools=tools):
350359
if chunk.text:
351360
print(chunk.text, end="", flush=True)
352361
```
353362

354-
Tip: In Agent Framework, both clients and agents yield the same update shape; you can read `chunk.text` in either case.
363+
Tip: In Agent Framework, both clients and agents yield the same update shape; you can read `chunk.text` in either case. Note that for chat clients, `tools` goes in the `options` dict, while for agents, `tools` remains a direct keyword argument.
355364

356365
### Message Types and Creation
357366

@@ -688,8 +697,8 @@ Notes:
688697
from collections.abc import AsyncIterable
689698
from typing import Any
690699
from agent_framework import (
691-
AgentRunResponse,
692-
AgentRunResponseUpdate,
700+
AgentResponse,
701+
AgentResponseUpdate,
693702
AgentThread,
694703
BaseAgent,
695704
ChatMessage,
@@ -704,7 +713,7 @@ class StaticAgent(BaseAgent):
704713
*,
705714
thread: AgentThread | None = None,
706715
**kwargs: Any,
707-
) -> AgentRunResponse:
716+
) -> AgentResponse:
708717
# Build a static reply
709718
reply = ChatMessage(role=Role.ASSISTANT, contents=[TextContent(text="Hello from AF custom agent")])
710719

@@ -713,17 +722,17 @@ class StaticAgent(BaseAgent):
713722
normalized = self._normalize_messages(messages)
714723
await self._notify_thread_of_new_messages(thread, normalized, reply)
715724

716-
return AgentRunResponse(messages=[reply])
725+
return AgentResponse(messages=[reply])
717726

718727
async def run_stream(
719728
self,
720729
messages: str | ChatMessage | list[str] | list[ChatMessage] | None = None,
721730
*,
722731
thread: AgentThread | None = None,
723732
**kwargs: Any,
724-
) -> AsyncIterable[AgentRunResponseUpdate]:
733+
) -> AsyncIterable[AgentResponseUpdate]:
725734
# Stream the same static response in a single chunk for simplicity
726-
yield AgentRunResponseUpdate(contents=[TextContent(text="Hello from AF custom agent")], role=Role.ASSISTANT)
735+
yield AgentResponseUpdate(contents=[TextContent(text="Hello from AF custom agent")], role=Role.ASSISTANT)
727736

728737
# Notify thread of input and the complete response once streaming ends
729738
if thread is not None:
@@ -1199,7 +1208,7 @@ from typing import cast
11991208
from agent_framework import (
12001209
MAGENTIC_EVENT_TYPE_AGENT_DELTA,
12011210
MAGENTIC_EVENT_TYPE_ORCHESTRATOR,
1202-
AgentRunUpdateEvent,
1211+
AgentResponseUpdateEvent,
12031212
ChatAgent,
12041213
ChatMessage,
12051214
MagenticBuilder,
@@ -1231,7 +1240,7 @@ workflow = (
12311240
async def magentic_example():
12321241
output: str | None = None
12331242
async for event in workflow.run_stream("Complex research task"):
1234-
if isinstance(event, AgentRunUpdateEvent):
1243+
if isinstance(event, AgentResponseUpdateEvent):
12351244
props = event.data.additional_properties if event.data else None
12361245
event_type = props.get("magentic_event_type") if props else None
12371246

@@ -1255,7 +1264,7 @@ The Magentic workflow provides extensive customization options:
12551264

12561265
- **Manager configuration**: Use a ChatAgent with custom instructions and model settings
12571266
- **Round limits**: `max_round_count`, `max_stall_count`, `max_reset_count`
1258-
- **Event streaming**: Use `AgentRunUpdateEvent` with `magentic_event_type` metadata
1267+
- **Event streaming**: Use `AgentResponseUpdateEvent` with `magentic_event_type` metadata
12591268
- **Agent specialization**: Custom instructions and tools per agent
12601269
- **Human-in-the-loop**: Plan review, tool approval, and stall intervention
12611270

@@ -1265,7 +1274,7 @@ from typing import cast
12651274
from agent_framework import (
12661275
MAGENTIC_EVENT_TYPE_AGENT_DELTA,
12671276
MAGENTIC_EVENT_TYPE_ORCHESTRATOR,
1268-
AgentRunUpdateEvent,
1277+
AgentResponseUpdateEvent,
12691278
ChatAgent,
12701279
MagenticBuilder,
12711280
MagenticHumanInterventionDecision,
@@ -1345,7 +1354,7 @@ Agent Framework provides built-in request-response capabilities where any execut
13451354

13461355
```python
13471356
from agent_framework import (
1348-
RequestInfoEvent, WorkflowBuilder, WorkflowContext,
1357+
RequestInfoEvent, WorkflowBuilder, WorkflowContext,
13491358
Executor, handler, response_handler
13501359
)
13511360
from dataclasses import dataclass
@@ -1361,7 +1370,7 @@ class ApprovalRequest:
13611370

13621371
# Workflow executor that requests human approval
13631372
class ReviewerExecutor(Executor):
1364-
1373+
13651374
@handler
13661375
async def review_content(
13671376
self,
@@ -1374,7 +1383,7 @@ class ReviewerExecutor(Executor):
13741383
agent_name="writer_agent"
13751384
)
13761385
await ctx.request_info(request_data=approval_request, response_type=str)
1377-
1386+
13781387
@response_handler
13791388
async def handle_approval_response(
13801389
self,

0 commit comments

Comments
 (0)