-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
Description
When using AzureAIProjectAgentProvider with @tool decorated functions and a persistent AgentThread, subsequent turns re-submit tool call outputs from previous turns, causing Azure AI to reject the request with:
Error code: 400 - {'error': {'message': 'No tool call found for function call output with call_id call_XXXXX.', 'type': 'invalid_request_error', 'param': 'input', 'code': None}}
Environment
- agent-framework: 1.0.0b251204 (and later)
- agent-framework-azure-ai: latest
- Python: 3.12
- OS: Linux (WSL2)
Minimal Reproduction
import asyncio
from typing import Annotated
from agent_framework import tool
from agent_framework.azure import AzureAIProjectAgentProvider
from azure.identity.aio import AzureCliCredential
from pydantic import Field
@tool(approval_mode="never_require")
def calculate_tip(
bill_amount: Annotated[float, Field(description="Bill amount in dollars")],
tip_percent: Annotated[float, Field(description="Tip percentage")],
) -> str:
"""Calculate tip amount for a bill."""
tip = bill_amount * (tip_percent / 100)
return f"Tip: ${tip:.2f}, Total: ${bill_amount + tip:.2f}"
async def main():
async with (
AzureCliCredential() as credential,
AzureAIProjectAgentProvider(credential=credential) as provider,
):
agent = await provider.create_agent(
name="tip-calculator",
instructions="Use the calculate_tip tool to help with calculations.",
tools=[calculate_tip],
)
# Single thread for multi-turn (BUG TRIGGER)
thread = agent.get_new_thread()
# Turn 1: Works fine
result1 = await agent.run("Calculate 15% tip on an $85 bill", thread=thread)
print(f"Turn 1: {result1.text}")
# Turn 2: FAILS - re-submits tool output from Turn 1
result2 = await agent.run("Now calculate 20% tip on the same $85 bill", thread=thread)
print(f"Turn 2: {result2.text}")
asyncio.run(main())Expected Behavior
Multi-turn conversations with @tool functions should work on the same AgentThread. Turn 2 should only submit the new user message, not re-submit tool outputs from Turn 1.
Actual Behavior
Turn 1 succeeds, but Turn 2 fails immediately with:
Error code: 400 - {'error': {'message': 'No tool call found for function call output with call_id call_XXXXX.', 'type': 'invalid_request_error', 'param': 'input', 'code': None}}
The error indicates that AgentThread accumulates function_call_output items from prior turns and re-submits them on subsequent turns. Azure AI rejects these because there's no corresponding function_call in the current request.
Analysis
The bug appears to be in how AgentThread manages conversation state when function tools are used:
- Turn 1: User message → Agent calls tool → Tool output submitted → Agent responds ✅
- Turn 2: User message + stale tool output from Turn 1 → Azure rejects (no matching call_id) ❌
The AgentThread should either:
- Clear tool outputs after each turn completes
- Not accumulate tool outputs in the thread state
- Filter out stale tool outputs before submitting to Azure
Observed Patterns
| Scenario | Result |
|---|---|
| Hosted tools (CodeInterpreter, FileSearch, WebSearch) | ✅ Works - multi-turn stable |
Function tools (@tool) on same thread |
❌ Fails on turn 2+ |
| Function tools with fresh thread per turn | ✅ Works - but loses context |
SDK-level previous_response_id pattern |
✅ Works - canonical solution |
Workarounds
1. Use fresh thread per turn (loses context)
for message in messages:
thread = agent.get_new_thread() # Fresh thread each time
result = await agent.run(message, thread=thread)2. Use SDK-level previous_response_id pattern
# Bypass AgentThread, use azure-ai-projects SDK directly
response = await openai_client.responses.create(
input=message,
previous_response_id=last_response_id,
extra_body={"agent": {"name": agent.name, "type": "agent_reference"}},
)
# Process tool calls, chain via response.id3. Use hosted tools instead of function tools
Hosted tools (CodeInterpreter, FileSearch, WebSearch) work correctly with multi-turn on the same thread.
Impact
This bug makes @tool functions unusable for multi-turn conversations with AzureAIProjectAgentProvider, which is a core use case for the framework.
Related Issues
- Python: [Issue]: "No tool output found for function call" after handoff between Responses based Agents #3105 - Similar error but with MCP tools and agent handoffs
- Python: Workflow Agents, Threads and Tools #3172 - Workflow agents and tool state management
- Python: AzureAIAgentClient creates new thread on each invocation in Magentic workflows, losing conversation context #2903 - Thread management in Magentic workflows
Metadata
Metadata
Assignees
Labels
Type
Projects
Status