Repository navigation
Description
Description
Summary
When using AzureAIClient with agents that have tools in a workflow, the Azure AI API returns a 400 error: "Duplicate item found with id fc_xxxxx. Remove duplicate items from your input and try again." This prevents workflows with tool-enabled agents from executing.
Environment
- agent-framework version: 1.0.0b260116
- agent-framework-azure-ai version: 1.0.0b260116
- agent-framework-core version: 1.0.0b260116
- Python version: 3.12.11
- OS: Windows 11
- Azure AI API version: 2025-11-15-preview
- Date: January 19, 2026
Steps to Reproduce
- Create a workflow with multiple agents using
AzureAIClient - Configure at least one agent with tools using the
tools=parameter inas_agent() - Run the workflow with
workflow.run_stream(query) - Observe the error when the agent with tools attempts to execute
Minimal Reproduction Code
import asyncio
import os
from dotenv import load_dotenv
from azure.ai.projects.aio import AIProjectClient
from azure.identity.aio import DefaultAzureCredential
from agent_framework import ai_function, WorkflowBuilder, executor, WorkflowContext, ChatMessage
from agent_framework.azure import AzureAIClient
load_dotenv()
# Define a simple tool
@ai_function(name="search_hotels", description="Search for hotels")
def search_hotels(location: str) -> str:
return f"Mock hotel results for {location}"
@executor(id="start")
async def start_executor(input: str, ctx: WorkflowContext[str, str]) -> None:
await ctx.send_message([ChatMessage(role="user", text=input)])
async def main():
project_client = AIProjectClient(
endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"],
credential=DefaultAzureCredential(),
api_version="2025-11-15-preview",
)
async with (
DefaultAzureCredential() as credential,
project_client,
AzureAIClient(project_client=project_client, credential=credential) as client,
):
# Create agent with tools
hotel_search_client = AzureAIClient(
project_client=project_client,
credential=credential,
agent_name="hotel-agent"
)
hotel_agent = hotel_search_client.as_agent(
id="hotel-agent",
instructions="Search for hotels using the search_hotels tool.",
name="hotel-agent",
tools=[search_hotels], # ← This causes the bug
store=True,
)
# Build simple workflow
workflow = (
WorkflowBuilder()
.set_start_executor(start_executor)
.add_edge(start_executor, hotel_agent)
.build()
)
# Run workflow - this will fail
async for event in workflow.run_stream("Find hotels in Paris"):
print(event)
if __name__ == "__main__":
asyncio.run(main())Expected Behavior
The workflow should execute successfully, with the agent calling the search_hotels tool and returning results based on the tool output.
Actual Behavior
The workflow fails with the following error:
Error during workflow execution: <class 'agent_framework_azure_ai._client.AzureAIClient'> service failed to complete the prompt: Error code: 400 - {'error': {'message': 'Duplicate item found with id fc_047d0ef380cbbb9f00696f01af725881959ee4e2494b72def8. Remove duplicate items from your input and try again.', 'type': 'invalid_request_error', 'param': 'input', 'code': None}}
Traceback (most recent call last):
File "agent_framework\openai\_responses_client.py", line 266, in _inner_get_streaming_response
async for chunk in await client.responses.create(stream=True, **run_options):
...
openai.BadRequestError: Error code: 400 - {'error': {'message': 'Duplicate item found with id fc_047d0ef380cbbb9f00696f01af725881959ee4e2494b72def8. Remove duplicate items from your input and try again.', 'type': 'invalid_request_error', 'param': 'input', 'code': None}}
The error indicates that function call items with the same ID are being duplicated in the API request payload, which the Azure AI Responses API rejects.
Code Sample
Run the sample: https://github.com/microsoft/agent-framework/tree/main/python/samples/demos/workflow_evaluation
or
### Minimal Reproduction Code
import asyncio
import os
from dotenv import load_dotenv
from azure.ai.projects.aio import AIProjectClient
from azure.identity.aio import DefaultAzureCredential
from agent_framework import ai_function, WorkflowBuilder, executor, WorkflowContext, ChatMessage
from agent_framework.azure import AzureAIClient
load_dotenv()
# Define a simple tool
@ai_function(name="search_hotels", description="Search for hotels")
def search_hotels(location: str) -> str:
return f"Mock hotel results for {location}"
@executor(id="start")
async def start_executor(input: str, ctx: WorkflowContext[str, str]) -> None:
await ctx.send_message([ChatMessage(role="user", text=input)])
async def main():
project_client = AIProjectClient(
endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"],
credential=DefaultAzureCredential(),
api_version="2025-11-15-preview",
)
async with (
DefaultAzureCredential() as credential,
project_client,
AzureAIClient(project_client=project_client, credential=credential) as client,
):
# Create agent with tools
hotel_search_client = AzureAIClient(
project_client=project_client,
credential=credential,
agent_name="hotel-agent"
)
hotel_agent = hotel_search_client.as_agent(
id="hotel-agent",
instructions="Search for hotels using the search_hotels tool.",
name="hotel-agent",
tools=[search_hotels], # ← This causes the bug
store=True,
)
# Build simple workflow
workflow = (
WorkflowBuilder()
.set_start_executor(start_executor)
.add_edge(start_executor, hotel_agent)
.build()
)
# Run workflow - this will fail
async for event in workflow.run_stream("Find hotels in Paris"):
print(event)
if __name__ == "__main__":
asyncio.run(main())Error Messages / Stack Traces
The workflow fails with the following error:
Error during workflow execution: <class 'agent_framework_azure_ai._client.AzureAIClient'> service failed to complete the prompt: Error code: 400 - {'error': {'message': 'Duplicate item found with id fc_047d0ef380cbbb9f00696f01af725881959ee4e2494b72def8. Remove duplicate items from your input and try again.', 'type': 'invalid_request_error', 'param': 'input', 'code': None}}
Traceback (most recent call last):
File "agent_framework\openai\_responses_client.py", line 266, in _inner_get_streaming_response
async for chunk in await client.responses.create(stream=True, **run_options):
...
openai.BadRequestError: Error code: 400 - {'error': {'message': 'Duplicate item found with id fc_047d0ef380cbbb9f00696f01af725881959ee4e2494b72def8. Remove duplicate items from your input and try again.', 'type': 'invalid_request_error', 'param': 'input', 'code': None}}
The error indicates that function call items with the same ID are being duplicated in the API request payload, which the Azure AI Responses API rejects.Package Versions
agent-framework version: 1.0.0b260116, agent-framework-azure-ai version: 1.0.0b260116, agent-framework-core version: 1.0.0b260116
Python Version
No response
Additional Context
What Works
- ✅ Workflows with
AzureAIClientagents WITHOUT tools work perfectly - ✅ Single agents (non-workflow) with
AzureAIClientand tools work - ✅ The official sample at
python/samples/demos/workflow_evaluation/has the same structure but appears to have the same issue
What Doesn't Work
- ❌ Multi-agent workflows with
AzureAIClientwhere agents have thetools=parameter - ❌ Both fan-out and sequential workflow patterns exhibit this issue
- ❌ Error occurs consistently across different tool configurations
Workaround
Remove the tools= parameter from agents in workflows and have them use their knowledge instead:
# Instead of:
hotel_agent = client.as_agent(
id="hotel-agent",
instructions="Use search_hotels to find hotels.",
tools=[search_hotels], # ← Remove this
store=True,
)
# Use:
hotel_agent = client.as_agent(
id="hotel-agent",
instructions="Based on the request, suggest hotels using your knowledge.",
# No tools parameter
store=True,
)Related Code References
- Official sample with same pattern:
python/samples/demos/workflow_evaluation/create_workflow.py - Error occurs in:
agent_framework/openai/_responses_client.py, line 266 - Related to Azure AI Responses API tool handling in workflow contexts
Suspected Root Cause
The agent framework appears to be sending duplicate function call items in the request payload when:
- Multiple agents in a workflow have tools
- The workflow uses fan-out or sequential patterns
- Message history is being passed between agents
This could be related to how tool definitions or function call tracking is handled across workflow agent boundaries in the AzureAIClient implementation.
Impact
- Severity: High - Blocks using tools in multi-agent workflows with AzureAIClient
- Scope: Affects Azure AI Foundry integration (AzureAIClient) specifically
- Frequency: 100% reproduction rate when tools are used in workflows
Suggested Fix Areas
- Review how
AzureAIClientconstructs the Responses API payload for agents with tools - Check for duplicate function call ID tracking across workflow agent invocations
- Verify message history sanitization when passing between workflow agents
- Ensure tool definitions aren't being registered multiple times per workflow execution
Additional Files
- Full reproduction case:
create_workflow.py(with tools - fails) - Working workaround:
create_workflow_no_tools.py(without tools - succeeds) - Tool definitions:
_tools.py
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsDone
Activity
vinhnguyen-wareflex commentedon Jan 27, 2026
I have the same issue. Is there any workaround for this error?
praneet22 commentedon Feb 11, 2026
The issue seems to be when using openai responses api, as it saves the state by default. When using chat completion api, I do not see this issue. Team need to expose the store parm in the openai client, which we can set to False and should fix this issue.
response = client.responses.create(
model="gpt-4o-mini",
input="tell me a joke",
store=False, # Set store to False
)
pamelafox commentedon Apr 3, 2026
We hit this same issue using
OpenAIChatClient(notAzureAIClient) with the built-inRedisHistoryProviderin MAF 1.0.0.Setup: A simple single-agent conversation (not a workflow) with tools and
RedisHistoryProviderfor multi-turn persistence.What happens: Turn 1 succeeds and the tool call completes. The history provider saves the response messages, which contain
rs_*-prefixed item IDs (from the Responses API output) inadditional_properties(fc_id). On Turn 2, the history provider replays those saved messages as input, and the API rejects them as duplicates.We also tested
store=Falseas Praneet Solanki (@praneet22) suggested:default_options={"store": False}on the Agent works for text-only conversations (no tools). The official Cosmos history provider sample uses this pattern.rs_*function call ID that was never persisted server-side:So
store=Falsedoesn't help when tools are involved — the tool call/result cycle within a single turn relies onstore=True.Root cause: Same as the original report — Responses API item IDs (
fc_*/rs_*) from tool call outputs get embedded in saved messages and replayed, causing either "Duplicate item" (store=True) or "Item not found" (store=False).Workaround: Remove
tools=from agents that useRedisHistoryProvider. Text-only agents with history providers work fine.Environment: agent-framework 1.0.0, agent-framework-openai 1.0.0, Python 3.12, Azure OpenAI (gpt-5-mini)
Upgrade all examples to MAF 1.0.0
Upgrade all examples to MAF 1.0.0
Upgrade all examples to MAF 1.0.0
TaoChenOSU commentedon Apr 9, 2026
I am no longer able to reproduce this error. After upgrading to 1.0, could you try the following:
CristinaStn commentedon Apr 21, 2026
Hi Tao Chen (@TaoChenOSU), do you have any resolution for Pamela Fox (@pamelafox) situation?
I am facing the same issue using CosmosHistoryProvider. Initialli discovered the bug using 1.0.0, just upgraded to agent-framework 1.1.0 and issue is replicated.
Here is my code snapshot in case you need additional insights:
Output Logs:
Python: Strip server-issued response item IDs under storage (microsof…
Python: Clear service_session_id in AgentExecutor on full-history rep…
Python: Strip server-issued response item IDs under storage (microsof…
Python: Clear service_session_id in AgentExecutor on full-history rep…
Python: Strip server-issued response item IDs under storage (microsof…
Python: Strip server-issued response item IDs under storage (microsof…
Python: Strip server-issued response item IDs under storage (microsof…
Python: Strip server-issued response item IDs under storage (microsof…