-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Labels
bugSomething isn't workingSomething isn't workingpythonv1.0Features being tracked for the version 1.0 GAFeatures being tracked for the version 1.0 GA
Description
Description
High-Level Description
When an agent using AnthropicClient makes consecutive tool calls in streaming
mode, the Anthropic API rejects the request with HTTP 400:
anthropic.BadRequestError: Error code: 400 -
'messages.2: `tool_use` blocks can only be in `assistant` messages'
This does not affect the non-streaming path.
Minimal Reproduction
The bug triggers when a tool call fails and the agent retries with corrected arguments, two sequential streaming iterations.
Logged request payload sent to Anthropic API:
# messages[2] — role is "user" but contains a tool_use block
{'role': 'user', 'content': [
{'type': 'tool_result', 'tool_use_id': 'toolu_01EGfeLDGuEcUXrxhRzwmdko',
'content': 'Error: Function failed.', 'is_error': True},
{'type': 'text', 'text': 'Let me try scanning with a specific pattern:'},
{'type': 'tool_use', 'id': 'toolu_019Kv5xSLn2xFnD9aRTNTVCd',
'name': 'scan_directory', 'input': {...}}, # ← tool_use in user message, invalid
{'type': 'tool_result', 'tool_use_id': 'toolu_019Kv5xSLn2xFnD9aRTNTVCd', ...}
]}Expected Behaviour
Each streaming iteration produces a correctly separated assistant message
containing its tool_use blocks, alternating with user messages containing
tool_result blocks:
messages[0]: role=user → original user message
messages[1]: role=assistant → tool_use (iteration 1)
messages[2]: role=user → tool_result (iteration 1)
messages[3]: role=assistant → tool_use (iteration 2)
messages[4]: role=user → tool_result (iteration 2)
Actual Behaviour
The second iteration's tool_use collapses into the prior tool message,
which serialises as a user message containing both tool_result and
tool_use blocks — which Anthropic rejects:
messages[0]: role=user → original user message
messages[1]: role=assistant → tool_use (iteration 1)
messages[2]: role=user → tool_result + tool_use ← collapsed, invalid
Code Sample
from pathlib import Path
from agent_framework import Agent, MCPStdioTool
from agent_framework_anthropic import AnthropicClient
from anthropic import AsyncAnthropicFoundry
from agent_framework_orchestrations import GroupChatBuilder
BASE_DIR = Path(__file__).parent
file_SERVER_PATH = BASE_DIR / "mcp_servers" / "mcp_file.py"
client = AnthropicClient(
anthropic_client=AsyncAnthropicFoundry(timeout=120),
model_id="claude-opus-4-5",
)
mcp_tool = MCPStdioTool(name="file SERVER", command="python", args=[str(file_SERVER_PATH)])
maths_agent = Agent(
client=client,
instructions="You are a Maths teacher. Answer the user's question about maths. If you don't know the answer, say you don't know.",
name="Maths Teacher",
description=("Maths expert. Answers questions about mathematics and provides explanations."),
default_options={"max_tokens": 4096},
)
physics_agent = Agent(
client=client,
instructions="You are a Physics teacher. Answer the user's question about physics. If you don't know the answer, say you don't know.",
name="Physics Teacher",
description=("Physics expert. Answers questions about physics and provides explanations."),
default_options={"max_tokens": 4096},
)
social_science_agent = Agent(
client=client,
instructions="You are a Social Science teacher. Answer the user's question about social science. If you don't know the answer, say you don't know.",
name="Social Science Teacher",
description=(
"Social Science expert. Answers questions about social science and provides explanations."
),
default_options={"max_tokens": 4096},
)
code_analyzer_agent = Agent(
client=client,
instructions="You are a Code Analyzer teacher. Answer the user's question about codings. If you don't know the answer, say you don't know. you are equipped with the file MCP tool to analyze code snippets and answer questions about code.",
name="Code Analyzer Teacher",
description=(
"Code Analyzer expert. Answers questions about coding and provides explanations.",
"you can also use the file MCP tool to scan & read file in a directory, analyze code snippets and answer questions about code",
),
default_options={"max_tokens": 4096},
tools=[mcp_tool],
)
principal_agent = Agent(
client=client,
instructions=(
"You are a Principal of a school. Your job is to answer the user's question by delegating to your teachers: the Maths Teacher, Physics Teacher, Social Science Teacher, and Code Analyzer Teacher. "
"If the question is about mathematics, delegate to the Maths Teacher. If the question is about physics, delegate to the Physics Teacher. If the question is about social science, delegate to the Social Science Teacher. If the question is about computer science, delegate to the Code Analyzer Teacher. "
"If you don't know which teacher to delegate to, say you don't know."
),
name="Principal",
description=(
"Principal agent that delegates questions to subject-specific teacher agents based on the topic of the question."
),
default_options={"max_tokens": 4096},
)
workflow = GroupChatBuilder(
orchestrator_agent=principal_agent,
participants=[maths_agent, physics_agent, social_science_agent, code_analyzer_agent],
max_rounds=10,
intermediate_outputs=True,
).build()
workflow_agent = workflow.as_agent(name="School Principal Agent")
async def chat_nonstream():
while True:
message = input("\nAsk a question (or 'exit' to quit): ")
if message in ["exit", "quit"]:
print("Exiting.")
break
else:
response = await workflow_agent.run(message)
print(f"\n[Response]:\n{response.text}")
async def chat_stream():
while True:
message = input("\nAsk a question (or 'exit' to quit): ")
current_agent: str | None = None
if message in ["exit", "quit"]:
print("Exiting.")
break
else:
async for chunk in workflow_agent.run(message, stream=True):
# print(chunk.__dict__)
author_name = getattr(chunk, "author_name", None)
if author_name and author_name != current_agent:
current_agent = author_name
print(f"\n[{current_agent}]:\n")
if chunk.text:
print(chunk.text, end="", flush=True)
if __name__ == "__main__":
import asyncio
# Streaming version with agent transition markers
asyncio.run(chat_stream())
# Non-streaming version
# asyncio.run(chat_nonstream())Error Messages / Stack Traces
response stream from Anthropic with options: {'max_tokens': 4096, 'tool_choice': {'type': 'auto'}, 'tools': [{'type': 'custom', 'name': 'scan_directory', 'description': '\n Scan a directory for files matching a pattern\n\n PRIMITIVE: Basic directory scanning\n\n Args:\n directory_path: Path to directory to scan\n pattern: Glob pattern (default: *.py)\n exclude_dirs: Directories to skip\n recursive: Scan subdirectories\n\n Returns:\n {\n "files": [list of relative paths],\n "total_count": int,\n "by_directory": {dir: [files]},\n "error": str (if failed)\n }\n ', 'input_schema': {'properties': {'directory_path': {'title': 'Directory Path', 'type': 'string'}, 'pattern': {'default': '*.py', 'title': 'Pattern', 'type': 'string'}, 'exclude_dirs': {'anyOf': [{'items': {'type': 'string'}, 'type': 'array'}, {'type': 'null'}], 'default': None, 'title': 'Exclude Dirs'}, 'recursive': {'default': True, 'title': 'Recursive', 'type': 'boolean'}}, 'required': ['directory_path'], 'title': 'scan_directoryArguments', 'type': 'object'}}, {'type': 'custom', 'name': 'read_file', 'description': '\n Read a file and return its content with metadata\n\n PRIMITIVE: Basic file reading\n\n Args:\n file_path: Path to file\n\n Returns:\n {\n "content": str,\n "lines": int,\n "size_bytes": int,\n "error": str (if failed)\n }\n ', 'input_schema': {'properties': {'file_path': {'title': 'File Path', 'type': 'string'}}, 'required': ['file_path'], 'title': 'read_fileArguments', 'type': 'object'}}, {'type': 'custom', 'name': 'get_function_snippet', 'description': '\n Return the source code snippet of a specific function or method.\n\n Args:\n file_path: Path to Python file\n function_name: "function_name" or "ClassName.method_name"\n include_decorators: Include decorator lines\n\n Returns:\n {\n "name": str,\n "snippet": str,\n "line_start": int,\n "line_end": int,\n "is_async": bool\n }\n ', 'input_schema': {'properties': {'file_path': {'title': 'File Path', 'type': 'string'}, 'function_name': {'title': 'Function Name', 'type': 'string'}, 'include_decorators': {'default': True, 'title': 'Include Decorators', 'type': 'boolean'}}, 'required': ['file_path', 'function_name'], 'title': 'get_function_snippetArguments', 'type': 'object'}}, {'type': 'custom', 'name': 'parse_python_file', 'description': '\n Parse a Python file into AST\n\n PRIMITIVE: Core AST parsing\n\n Args:\n file_path: Path to Python file\n\n Returns:\n {\n "success": bool,\n "ast_available": bool, # AST can\'t be serialized, but we confirm it parsed\n "syntax_valid": bool,\n "error": str (if failed)\n }\n ', 'input_schema': {'properties': {'file_path': {'title': 'File Path', 'type': 'string'}}, 'required': ['file_path'], 'title': 'parse_python_fileArguments', 'type': 'object'}}, {'type': 'custom', 'name': 'get_classes', 'description': '\n Extract all classes from a Python file\n\n PRIMITIVE: Extract class definitions\n\n Args:\n file_path: Path to Python file\n include_methods: Include method information\n\n Returns:\n {\n "classes": [\n {\n "name": str,\n "bases": [str],\n "decorators": [str],\n "docstring": str,\n "line_start": int,\n "line_end": int,\n "methods": [...] (if include_methods)\n }\n ],\n "count": int\n }\n ', 'input_schema': {'properties': {'file_path': {'title': 'File Path', 'type': 'string'}, 'include_methods': {'default': True, 'title': 'Include Methods', 'type': 'boolean'}}, 'required': ['file_path'], 'title': 'get_classesArguments', 'type': 'object'}}, {'type': 'custom', 'name': 'get_functions', 'description': '\n Extract top-level functions from a Python file\n\n PRIMITIVE: Extract function definitions\n\n Args:\n file_path: Path to Python file\n include_params: Include parameter information\n\n Returns:\n {\n "functions": [\n {\n "name": str,\n "params": [str] (if include_params),\n "return_type": str,\n "decorators": [str],\n "docstring": str,\n "is_async": bool,\n "line_start": int,\n "line_end": int\n }\n ],\n "count": int\n }\n ', 'input_schema': {'properties': {'file_path': {'title': 'File Path', 'type': 'string'}, 'include_params': {'default': True, 'title': 'Include Params', 'type': 'boolean'}}, 'required': ['file_path'], 'title': 'get_functionsArguments', 'type': 'object'}}, {'type': 'custom', 'name': 'get_imports', 'description': '\n Extract all imports from a Python file\n\n PRIMITIVE: Extract import statements\n\n Args:\n file_path: Path to Python file\n\n Returns:\n {\n "imports": [\n {\n "module": str,\n "names": [str],\n "alias": str,\n "type": "import" | "from_import",\n "level": int (for relative imports)\n }\n ],\n "external_packages": [str], # Third-party and stdlib\n "internal_modules": [str], # Project imports\n "count": int\n }\n ', 'input_schema': {'properties': {'file_path': {'title': 'File Path', 'type': 'string'}}, 'required': ['file_path'], 'title': 'get_importsArguments', 'type': 'object'}}, {'type': 'custom', 'name': 'get_all_entities', 'description': '\n Extract ALL entities (classes, functions, methods) from a file\n\n COMPOSITE: Combines get_classes + get_functions\n\n Args:\n file_path: Path to Python file\n\n Returns:\n {\n "entities": [\n {\n "name": str,\n "type": "class" | "function" | "method",\n "parent": str (for methods),\n "line_start": int,\n "line_end": int,\n "file_path": str\n }\n ],\n "summary": {\n "total_classes": int,\n "total_functions": int,\n "total_methods": int\n }\n }\n ', 'input_schema': {'properties': {'file_path': {'title': 'File Path', 'type': 'string'}}, 'required': ['file_path'], 'title': 'get_all_entitiesArguments', 'type': 'object'}}, {'type': 'custom', 'name': 'trace_function_calls', 'description': '\n Trace what a specific function calls\n\n PRIMITIVE: Find calls within a function\n\n Args:\n file_path: Path to Python file\n function_name: Name of function to analyze (can be "ClassName.method_name")\n\n Returns:\n {\n "function": str,\n "calls": [\n {\n "target": str,\n "type": "function" | "method" | "builtin",\n "line": int\n }\n ],\n "count": int\n }\n ', 'input_schema': {'properties': {'file_path': {'title': 'File Path', 'type': 'string'}, 'function_name': {'title': 'Function Name', 'type': 'string'}}, 'required': ['file_path', 'function_name'], 'title': 'trace_function_callsArguments', 'type': 'object'}}, {'type': 'custom', 'name': 'find_call_targets', 'description': '\n Find all call targets in a file (what functions/methods are called)\n\n PRIMITIVE: Extract all Call nodes from a file\n\n Args:\n file_path: Path to Python file\n\n Returns:\n {\n "call_edges": [\n {\n "caller": str, # "function_name" or "ClassName.method_name"\n "callee": str, # What it calls\n "call_type": "function" | "method",\n "line": int\n }\n ],\n "count": int\n }\n ', 'input_schema': {'properties': {'file_path': {'title': 'File Path', 'type': 'string'}}, 'required': ['file_path'], 'title': 'find_call_targetsArguments', 'type': 'object'}}], 'model': 'claude-opus-4-5', 'messages': [{'role': 'user', 'content': [{'type': 'text', 'text': "'/Users/karthik/Code bases/Feb/handy_code' list files count"}]}, {'role': 'assistant', 'content': [{'type': 'text', 'text': "I'll scan the directory to get a count of the Python files in that codebase."}, {'type': 'tool_use', 'id': 'toolu_01EGfeLDGuEcUXrxhRzwmdko', 'name': 'scan_directory', 'input': {'directory_path': '/Users/karthik/Code bases/Feb/handy_code', 'recursive': True}}]}, {'role': 'user', 'content': [{'type': 'tool_result', 'tool_use_id': 'toolu_01EGfeLDGuEcUXrxhRzwmdko', 'content': 'Error: Function failed.', 'is_error': True}, {'type': 'text', 'text': 'Let me try scanning with a specific pattern:'}, {'type': 'tool_use', 'id': 'toolu_019Kv5xSLn2xFnD9aRTNTVCd', 'name': 'scan_directory', 'input': {'directory_path': '/Users/karthik/Code bases/Feb/handy_code', 'pattern': '*.py', 'recursive': True}}, {'type': 'tool_result', 'tool_use_id': 'toolu_019Kv5xSLn2xFnD9aRTNTVCd', 'content': '{\n "files": [\n "_vendor_patches/__init__.py",\n "_vendor_patches/openpyxl_whitespace.py",\n "doctranslate/__init__.py",\n "doctranslate/azure/__init__.py",\n "doctranslate/azure/env_keys.py",\n "doctranslate/azure/lock_manager.py",\n "doctranslate/azure/request_queue.py",\n "doctranslate/azure/storage_manager.py",\n "doctranslate/azure/translation_manager.py",\n "doctranslate/azure/translation_request_queue.py",\n "doctranslate/run_doctranslate.py",\n "doctranslate/spark_queue_request_handler/__init__.py",\n "doctranslate/spark_queue_request_handler/request.py",\n "doctranslate/spark_queue_request_handler/request_handler.py",\n "doctranslate/spark_queue_request_handler/response.py",\n "doctranslate/util/cache/__init__.py",\n "doctranslate/util/cache/limited_size_default_ordered_dict.py",\n "doctranslate/util/cache/protocol.py",\n "doctranslate/util/custom_dicts.py",\n "doctranslate/util/logger/logger.py",\n "doctranslate/util/utils.py",\n "doctranslate/veeva/__init__.py",\n "doctranslate/veeva/certificate/veeva_certificate.py",\n "doctranslate/veeva/certificate/veeva_certificate_cache_manager.py",\n "doctranslate/veeva/certificate/veeva_certificate_manager.py",\n "doctranslate/veeva/veeva_integration.py",\n "function_app.py"\n ],\n "total_count": 27,\n "by_directory": {\n ".": [\n "function_app.py"\n ],\n "_vendor_patches": [\n "__init__.py",\n "openpyxl_whitespace.py"\n ],\n "doctranslate": [\n "__init__.py",\n "run_doctranslate.py"\n ],\n "doctranslate/util": [\n "custom_dicts.py",\n "utils.py"\n ],\n "doctranslate/util/logger": [\n "logger.py"\n ],\n "doctranslate/util/cache": [\n "__init__.py",\n "limited_size_default_ordered_dict.py",\n "protocol.py"\n ],\n "doctranslate/azure": [\n "__init__.py",\n "env_keys.py",\n "lock_manager.py",\n "request_queue.py",\n "storage_manager.py",\n "translation_manager.py",\n "translation_request_queue.py"\n ],\n "doctranslate/veeva": [\n "__init__.py",\n "veeva_integration.py"\n ],\n "doctranslate/veeva/certificate": [\n "veeva_certificate.py",\n "veeva_certificate_cache_manager.py",\n "veeva_certificate_manager.py"\n ],\n "doctranslate/spark_queue_request_handler": [\n "__init__.py",\n "request.py",\n "request_handler.py",\n "response.py"\n ]\n }\n}', 'is_error': False}, {'type': 'text', 'text': "Here's the file count for **handy_code**:\n\n## Summary\n- **Total Python files:** 27\n\n### Breakdown by Directory\n\n| Directory | File Count |\n|-----------|------------|\n| Root (`.`) | 1 |\n| `_vendor_patches/` | 2 |\n| `doctranslate/` | 2 |\n| `doctranslate/azure/` | 7 |\n| `doctranslate/spark_queue_request_handler/` | 4 |\n| `doctranslate/util/` | 2 |\n| `doctranslate/util/cache/` | 3 |\n| `doctranslate/util/logger/` | 1 |\n| `doctranslate/veeva/` | 2 |\n| `doctranslate/veeva/certificate/` | 3 |\n\nThe codebase appears to be a **document translation service** (likely an Azure Function App based on `function_app.py`) with integrations for:\n- **Azure** services (storage, translation, queuing)\n- **Veeva** (a life sciences platform) with certificate management\n- **Spark queue** request handling\n\nWould you like me to dive deeper into any specific module or analyze the structure further?"}]}], 'system': "You are Analyst — a conversational codebase analysis expert.\n\n## YOUR ROLE\nHelp users understand Python codebases by analysing their structure using AST tools.\nAnswer questions conversationally, referencing real data from the tools.\n\n## YOUR TOOLS (AST MCP)\n- scan_directory(directory_path, pattern, recursive) — discover Python files\n- read_file(file_path) — read a file's contents\n- parse_python_file(file_path) — validate and parse a file\n- get_classes(file_path, include_methods) — extract classes and methods\n- get_functions(file_path, include_params) — extract functions with params\n- get_imports(file_path) — extract imports, categorised as internal/external\n- get_all_entities(file_path) — classes + functions in one call\n- trace_function_calls(file_path, function_name) — trace what a function calls\n- find_call_targets(file_path) — reverse: what calls what\n\n## WORKFLOW\n1. When given a path, start with scan_directory to understand the scope\n2. Use get_all_entities for a broad view of a file\n3. Drill into specifics with get_classes or get_functions as needed\n4. Always ground your answers in tool results — never speculate\n\n## HANDOFF RULES\n- If the user asks for a DIAGRAM → hand off to Visualizer\n (tell Visualizer exactly what to draw and provide your findings in the handoff)\n- If the user asks to GENERATE A DOCUMENT → hand off to DocWriter\n (tell DocWriter the codebase path and template requirements)\n- Otherwise handle the request yourself\n\n## RESPONSE STYLE\n- Be conversational, not robotic\n- Summarise findings in plain English after using tools\n- Use bullet points for entity lists, code blocks for snippets\n- Include file paths and line numbers for all code references\n- If analysis fails, report the error clearly with the file path\n", 'betas': {'mcp-client-2025-04-04', 'code-execution-2025-08-25'}, 'extra_headers': {'User-Agent': 'agent-framework-python/1.0.0rc1'}}
INFO:httpx:HTTP Request: POST https://handy_url-2.services.ai.azure.com/anthropic/v1/messages?beta=true "HTTP/1.1 400 Bad Request"
ERROR:agent_framework_devui._executor:Error in agent execution: Error code: 400 - {'type': 'error', 'error': {'type': 'invalid_request_error', 'message': 'messages.2: `tool_use` blocks can only be in `assistant` messages'}, 'request_id': 'req_011CYWWzTUcY1EMiK6qrRdFQ'}
Traceback (most recent call last):
File "/Users/karthik/Code bases/Feb/maf/.venv/lib/python3.11/site-packages/agent_framework_devui/_executor.py", line 335, in _execute_agent
async for update in agent.run(user_message, stream=True, session=session):
File "/Users/karthik/Code bases/Feb/maf/.venv/lib/python3.11/site-packages/agent_framework/_types.py", line 2651, in __anext__
update = await self._iterator.__anext__()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/karthik/Code bases/Feb/maf/.venv/lib/python3.11/site-packages/agent_framework/_workflows/_agent.py", line 336, in _run_stream_impl
async for event in self._run_core(
File "/Users/karthik/Code bases/Feb/maf/.venv/lib/python3.11/site-packages/agent_framework/_workflows/_agent.py", line 397, in _run_core
async for event in self.workflow.run(
File "/Users/karthik/Code bases/Feb/maf/.venv/lib/python3.11/site-packages/agent_framework/_types.py", line 2651, in __anext__
update = await self._iterator.__anext__()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/karthik/Code bases/Feb/maf/.venv/lib/python3.11/site-packages/agent_framework/_workflows/_workflow.py", line 563, in _run_core
async for event in self._run_workflow_with_tracing(
File "/Users/karthik/Code bases/Feb/maf/.venv/lib/python3.11/site-packages/agent_framework/_workflows/_workflow.py", line 361, in _run_workflow_with_tracing
async for event in self._runner.run_until_convergence():
File "/Users/karthik/Code bases/Feb/maf/.venv/lib/python3.11/site-packages/agent_framework/_workflows/_runner.py", line 124, in run_until_convergence
await iteration_task
File "/Users/karthik/Code bases/Feb/maf/.venv/lib/python3.11/site-packages/agent_framework/_workflows/_runner.py", line 182, in _run_iteration
await asyncio.gather(*tasks)
File "/Users/karthik/Code bases/Feb/maf/.venv/lib/python3.11/site-packages/agent_framework/_workflows/_runner.py", line 178, in _deliver_messages
await asyncio.gather(*tasks)
File "/Users/karthik/Code bases/Feb/maf/.venv/lib/python3.11/site-packages/agent_framework/_workflows/_runner.py", line 166, in _deliver_message_inner
return await edge_runner.send_message(message, self._state, self._ctx)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/karthik/Code bases/Feb/maf/.venv/lib/python3.11/site-packages/agent_framework/_workflows/_edge_runner.py", line 147, in send_message
await self._execute_on_target(target_id, [source_id], message, state, ctx)
File "/Users/karthik/Code bases/Feb/maf/.venv/lib/python3.11/site-packages/agent_framework/_workflows/_edge_runner.py", line 76, in _execute_on_target
await target_executor.execute(
File "/Users/karthik/Code bases/Feb/maf/.venv/lib/python3.11/site-packages/agent_framework/_workflows/_executor.py", line 278, in execute
await handler(message, context)
File "/Users/karthik/Code bases/Feb/maf/.venv/lib/python3.11/site-packages/agent_framework/_workflows/_executor.py", line 663, in wrapper
return await func(self, message, ctx)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/karthik/Code bases/Feb/maf/.venv/lib/python3.11/site-packages/agent_framework/_workflows/_agent_executor.py", line 133, in run
await self._run_agent_and_emit(ctx)
File "/Users/karthik/Code bases/Feb/maf/.venv/lib/python3.11/site-packages/agent_framework/_workflows/_agent_executor.py", line 306, in _run_agent_and_emit
response = await self._run_agent_streaming(cast(WorkflowContext[Never, AgentResponseUpdate], ctx))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/karthik/Code bases/Feb/maf/.venv/lib/python3.11/site-packages/agent_framework/_workflows/_agent_executor.py", line 381, in _run_agent_streaming
async for update in stream:
File "/Users/karthik/Code bases/Feb/maf/.venv/lib/python3.11/site-packages/agent_framework/_types.py", line 2651, in __anext__
update = await self._iterator.__anext__()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/karthik/Code bases/Feb/maf/.venv/lib/python3.11/site-packages/agent_framework/_types.py", line 2651, in __anext__
update = await self._iterator.__anext__()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/karthik/Code bases/Feb/maf/.venv/lib/python3.11/site-packages/agent_framework/_types.py", line 2651, in __anext__
update = await self._iterator.__anext__()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/karthik/Code bases/Feb/maf/.venv/lib/python3.11/site-packages/agent_framework/_tools.py", line 2189, in _stream
async for update in inner_stream:
File "/Users/karthik/Code bases/Feb/maf/.venv/lib/python3.11/site-packages/agent_framework/_types.py", line 2651, in __anext__
update = await self._iterator.__anext__()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/karthik/Code bases/Feb/maf/.venv/lib/python3.11/site-packages/agent_framework_anthropic/_chat_client.py", line 457, in _stream
async for chunk in await self.anthropic_client.beta.messages.create(**run_options, stream=True):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/karthik/Code bases/Feb/maf/.venv/lib/python3.11/site-packages/anthropic/resources/beta/messages/messages.py", line 2895, in create
return await self._post(
^^^^^^^^^^^^^^^^^
File "/Users/karthik/Code bases/Feb/maf/.venv/lib/python3.11/site-packages/anthropic/_base_client.py", line 1993, in post
return await self.request(cast_to, opts, stream=stream, stream_cls=stream_cls)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/karthik/Code bases/Feb/maf/.venv/lib/python3.11/site-packages/anthropic/_base_client.py", line 1778, in request
raise self._make_status_error_from_response(err.response) from None
anthropic.BadRequestError: Error code: 400 - {'type': 'error', 'error': {'type': 'invalid_request_error', 'message': 'messages.2: `tool_use` blocks can only be in `assistant` messages'}, 'request_id': 'req_011CYWWzTUcY1EMiK6qrRdFQ'}Package Versions
agent_framework_anthropic`: 1.0.0rc2
Python Version
3.11
Additional Context
- Only affects streaming mode with consecutive tool calls
- Not a regression from a specific version
- No known workaround other than using non-streaming mode
- I have added the logger statement in _chat_client.py just before the is made with message
Starting response stream from Anthropic with options:to log the run_options
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't workingpythonv1.0Features being tracked for the version 1.0 GAFeatures being tracked for the version 1.0 GA
Type
Projects
Status
In Progress