Implementation:Microsoft Agent framework Content Function Approval Request Pattern
| Knowledge Sources | |
|---|---|
| Domains | Agent_Architecture, Safety, Human_in_the_Loop |
| Type | Pattern Doc (user-defined interface, not a library API) |
| Last Updated | 2026-02-11 17:00 GMT |
Overview
Implementation pattern for presenting function approval requests to users, enabling a human-in-the-loop safety gate before the agent executes tool calls. This is a user-defined interface pattern built on top of the Content class in the Microsoft Agent Framework.
Description
When the agent framework determines that a function call requires human approval, it wraps the pending call in a Content object of type "function_approval_request". The application developer is responsible for iterating these requests, extracting the tool name and arguments from the nested function_call field, presenting them to the user through an application-specific UI, and submitting the user's decision back to the framework.
The pattern spans two framework components:
- Content class (
_types.py:L458-509): Defines the data structure with fieldsid,function_call,user_input_request, andapproved. - AgentResponse / AgentResponseUpdate (
_types.py:L2341-2348, L2549-2551): Provide theuser_input_requestsproperty that filters Content items whereuser_input_request is True.
Usage
Import the Content class and access the approval fields after an agent run. Iterate result.user_input_requests to find all pending approvals, then call request.to_function_approval_response(approved=...) to submit each decision.
Code Reference
Source Location
- Repository: agent-framework
- File: python/packages/core/agent_framework/_types.py
- Lines: L458-509 (Content class definition), L971-989 (from_function_approval_request factory), L1013-1029 (to_function_approval_response conversion)
Key Factory Method
@classmethod
def from_function_approval_request(
cls: type[ContentT],
id: str,
function_call: Content,
*,
annotations: Sequence[Annotation] | None = None,
additional_properties: MutableMapping[str, Any] | None = None,
raw_representation: Any = None,
) -> ContentT:
"""Create function approval request content."""
return cls(
"function_approval_request",
id=id,
function_call=function_call,
user_input_request=True,
annotations=annotations,
additional_properties=additional_properties,
raw_representation=raw_representation,
)
Import
from agent_framework import Content
I/O Contract
Key Fields (Content with type="function_approval_request")
| Name | Type | Required | Description |
|---|---|---|---|
| id | str |
Yes | Unique identifier for the approval request. Used to correlate the user's response back to the correct pending function call. Typically derived from call_id of the original function call.
|
| function_call | Content |
Yes | Mapping: the arguments the LLM wants to pass). |
| user_input_request | bool |
Yes | Always True for approval requests. Signals the framework (and the AgentExecutor workflow) to pause execution and emit a request_info event.
|
| type | Literal["function_approval_request"] |
Yes | The content type discriminator. Must be "function_approval_request".
|
Nested function_call Content Fields
| Name | Type | Description |
|---|---|---|
| name | str |
The name of the tool/function the LLM wants to invoke. |
| arguments | Mapping[str, Any] | The arguments the LLM wants to pass to the tool. May be a JSON string or a parsed mapping. |
| call_id | str |
The unique identifier for this specific function call invocation. |
Response Conversion
| Method | Input | Output | Description |
|---|---|---|---|
to_function_approval_response(approved) |
bool |
Content (type="function_approval_response") |
Converts the approval request into an approval response with the user's decision. Preserves id, function_call, and annotations.
|
Interface Specification
# Pattern: Present each approval request to the user
for request in result.user_input_requests:
# Extract tool information
tool_name: str = request.function_call.name
tool_args: str | Mapping = request.function_call.arguments
request_id: str = request.id
# Display to user (application-specific)
print(f"Agent wants to call: {tool_name}")
print(f"With arguments: {tool_args}")
approved: bool = get_user_decision() # Your UI logic
Usage Examples
Basic CLI Approval Flow
from agent_framework import Agent, Content
agent = Agent(
client=client,
tools=[my_sensitive_tool],
)
result = await agent.run("Delete the temporary files")
# Check for pending approval requests
for request in result.user_input_requests:
tool_name = request.function_call.name
tool_args = request.function_call.arguments
print(f"Tool: {tool_name}")
print(f"Args: {tool_args}")
user_choice = input("Approve this call? [y/n]: ").strip().lower()
# Convert approval request to response
response = request.to_function_approval_response(approved=(user_choice == "y"))
Streaming Approval Flow
from agent_framework import Agent, Content
async for update in agent.run("Perform database migration", stream=True):
# Process text updates
if update.text:
print(update.text, end="", flush=True)
# Handle approval requests as they arrive during streaming
for request in update.user_input_requests:
tool_name = request.function_call.name
tool_args = request.function_call.arguments
print(f"\n[APPROVAL NEEDED] {tool_name}({tool_args})")
approved = await async_get_user_decision()
response = request.to_function_approval_response(approved=approved)
Framework Internal: How Approval Requests Are Created
# From agent_framework/_tools.py (internal framework logic, not user code)
# When approval_needed is True for function calls:
[
Content.from_function_approval_request(
id=fcc.call_id,
function_call=fcc,
)
for fcc in function_calls
if fcc.type == "function_call"
]
Data Flow
The approval request pattern follows this sequence:
- The LLM returns one or more
function_callContent objects in its response. - The framework's function invocation layer checks if approval is required (configured via
FunctionInvocationConfiguration). - If approval is needed, each
function_callContent is wrapped in afunction_approval_requestContent viaContent.from_function_approval_request(). - The
user_input_request=Trueflag causes theAgentExecutorto emit arequest_infoevent and pause the workflow. - The
AgentResponse.user_input_requests(orAgentResponseUpdate.user_input_requests) property exposes these to the application. - The application presents each request to the user and collects a decision.
- The application calls
request.to_function_approval_response(approved=True/False)to create the response Content. - The response is submitted back to the framework, which either executes or skips the function accordingly.