A support assistant takes several seconds to answer a question even though its database lookup completes quickly. The missing time might involve context retrieval, more than one model request, queueing, tool approval, or session persistence. An outer run duration cannot identify which operation dominates, and a generic diagram of “the agent runtime” can conceal important differences between implementations.
Microsoft Agent Framework provides agents, tools, sessions, middleware, workflows, and hosting integrations. This walkthrough focuses on the .NET ChatClientAgent path, using Microsoft’s documentation and public source reviewed on 24 October 2026. It is a source-based explanation, not a framework benchmark. Python, provider-managed agents, harnesses, and durable hosting can make different choices; verify behaviour against the package versions and configuration actually deployed.
Separate Agent Configuration From Conversation State
An agent object connects behaviour and dependencies such as a chat client, instructions, tools, and configured providers. Its lifetime is a hosting decision. The framework does not require every user message to deserialize a definition, construct a new agent, and discard it afterwards. Expensive per-request construction may be an application problem rather than an unavoidable runtime cost.
Conversation state belongs in the appropriate session and providers. Microsoft’s session guide describes AgentSession as the state container used across runs, with concrete implementations that can include local state or references to service-managed history. Reusing an agent is not the same thing as sharing one conversation session between users.
The guide also shows explicit serialization and deserialization. An in-memory session surviving another call in the same process does not establish durability across a restart. Determine what is persisted, where it is stored, and which hosting component performs that work.
Make those lifetimes visible in the application’s design. Identify shared clients and connection pools, per-conversation state, per-run metadata, and per-tool invocation data. Resource reuse can reduce overhead, but mutable shared objects need an appropriate concurrency model. There is no general promise that every user-provided dependency is safe to share.
Follow the Chat Client the Agent Actually Calls
The public ChatClientAgent source describes an agent that delegates to IChatClient. The run prepares session-related information, options, and messages before calling the configured chat-client pipeline. The implementation also includes provider notification and session-related handling around the response or failure.
That pipeline can contain decorators rather than a single direct network call. Function invocation can be handled through FunctionInvokingChatClient, which may be inserted by default depending on construction and configuration. Microsoft’s class reference describes its role in resolving function calls automatically.
A tool-using request may therefore involve a model response requesting a function, local execution, and another model request incorporating the result. That is a common path, not a fixed requirement of exactly two calls. The model may answer directly, request several functions, or continue through additional permitted iterations.
Inspect the resolved pipeline when investigating behaviour. A hosted provider may execute capabilities remotely, while a local function pipeline performs work in the application. An outer agent call can conceal that distinction unless tracing and configuration records show which components were involved.
Use Middleware at the Correct Boundary
Microsoft’s middleware guide distinguishes agent-run, function-calling, and chat-client middleware. They wrap different operations. A measurement around the run answers a different question from a measurement around one function or one provider request.
Use that distinction for controls too. A run-level policy can decide whether the task is permitted, while function middleware can inspect a proposed operation. The protected business service should still enforce authorisation using trusted identity and its own rules. Model-generated arguments are not proof that the caller may perform an action.
The runtime-context guide identifies .NET surfaces including AgentRunOptions.AdditionalProperties, function invocation context, and session StateBag. These have different scopes. Per-run metadata should not be mistaken for a persisted conversation record or exposed unnecessarily as model-controlled parameters.
Middleware can also add cost or change behaviour. Record ordering and avoid assuming every wrapper measures only the underlying network call. A slow authorisation lookup or repeated context fetch may be part of the application’s configured path, even when no model request is slow.
Tools Can Be Asynchronous Without Becoming Independent Workflows
Agent Framework supports function tools and asynchronous execution patterns; tools are not universally synchronous blocking functions. The function-tools guide documents language-specific configuration and limits. Do not transfer a Python default or provider setting into a claim about every .NET deployment.
Asynchronous I/O does not remove a logical dependency. If the next model response needs a database result, the run still waits for that result even when no thread is blocked. Independent tools may overlap under suitable configuration, while tools that share state or depend on one another need ordering or coordination.
Argument validation and execution failures also have configured behaviour. They may become a tool result, propagate as exceptions, or be handled by application middleware, depending on the path. Avoid assuming every exception automatically triggers another model call. Test what the selected client and options actually expose to the model and the host.
Bound model iterations, tool work, elapsed time, and cost as appropriate. SDK limits may not provide immediate cancellation of every downstream operation. A cancellation token only helps where the invoked code and transport honour it, and stopping the response does not prove that an external write was reversed.
Keep Persistence and Business Effects Separate
Session history, a workflow checkpoint, and a committed business transaction are different records. A booking tool may succeed before final response generation fails. Retrying the user’s request can repeat the booking unless the action boundary recognises the same logical operation and establishes its existing outcome.
Use idempotency, explicit operation status, and reconciliation where external effects require them. The agent-turn transaction article explains why treating an entire conversational run as one database transaction can hide those boundaries.
Concurrent requests need a defined policy as well. If two workers independently load and overwrite the same persisted conversation state without conflict protection, updates can be lost. Whether that can happen depends on the host, store, session implementation, and application controls; it is not evidence that every framework run has the same race.
Decide how overlapping messages are serialised, versioned, rejected, or otherwise coordinated. Test disconnects, timeouts after a successful tool effect, and persistence failures. Recovery needs to establish what happened to both the conversation and the business operation, not merely create a new agent instance.
Measure Streaming and Latency as Separate Properties
Streaming can expose incremental response updates and can coexist with tool use. What a user sees depends on provider behaviour, the streamed update types, and the application’s presentation. A tool-dependent final answer may still wait, but it is incorrect to say streaming is useful only when the model answers without tools.
Measure time to the first useful update, tool completion, final answer, and completed persistence where relevant. A progress event may improve responsiveness without reducing total processing time. Conversely, hiding all non-text events can make an instrumented streaming service appear silent to its user.
For illustration only, suppose five sequential phases take the following times, with no overlap or additional overhead:
| Phase | Illustrative duration |
|---|---|
| Context preparation | 120 ms |
| First model request | 1,800 ms |
| Function execution | 400 ms |
| Second model request | 1,500 ms |
| Persistence | 80 ms |
The total is 3,900 ms. This arithmetic explains how a fast tool can sit inside a slower run; it is not measured framework performance. Real traces may contain parallel work and nested spans, so adding parent and child durations would double-count time. Investigate the critical path rather than summing every number displayed by the tracing backend.
Enable Existing Telemetry and Fill Application Gaps
The framework has built-in OpenTelemetry integration. Configure the relevant agent and chat-client instrumentation, sources, exporters, and backend. Then add spans for work outside those boundaries, such as application queues, custom storage, or business-service reconciliation.
Correlate runs, provider calls, tool invocations, attempts, and business-operation identifiers. The distributed-tracing article covers how those relationships help explain latency across services. Avoid enabling sensitive prompt, argument, or response capture simply to obtain timings; telemetry needs appropriate access and retention controls.
Track loop counts, tool failures, queue age, token usage where reported, and completed outcomes. The retry-policy guide explains why attempts must be connected with logical requests. A run duration alone cannot distinguish provider delay from repeated failed work.
Choose Durability and Orchestration Deliberately
Agent Framework includes graph-based workflows with checkpoint and resume support. Microsoft also documents a Durable Extension for durable agents, orchestration, and workflows. These capabilities contradict a blanket claim that the framework has no multi-step or durable execution options.
They are still distinct choices with storage, hosting, and execution semantics to evaluate. A checkpoint is not an automatic distributed transaction across every external tool. Select the arrangement for the required pause, resume, failure, and concurrency behaviour, then test it with representative operations.
The useful runtime picture is the configured one: the agent object, session, client pipeline, tool boundaries, telemetry, and hosting model actually in use. Once those are explicit, debugging can focus on observable questions about elapsed time, persisted state, completed effects, and recovery instead of a fixed lifecycle the framework never required.





