mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Python: Fix server_tool_use input_json_delta handling and improve Anthropic samples (#5050)
* Fix server_tool_use input_json_delta handling and improve Anthropic samples - Fix: Skip input_json_delta for server_tool_use content blocks in AnthropicClient streaming. Server-managed tools (e.g., skills with code interpreter) were producing Content.from_function_call(name='') entries that caused Anthropic API 400 errors on subsequent turns. - Samples: Add dotenv loading and environment variable documentation to Anthropic Claude samples (MCP, permissions, session, shell, tools, URL, skills). * Add regression test for server_tool_use + input_json_delta skip behavior Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/7c68dcb2-b577-4e36-b423-664b8fe3ac1d Co-authored-by: chetantoshniwal <255221507+chetantoshniwal@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: chetantoshniwal <255221507+chetantoshniwal@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
339e76d51f
commit
47d82911c0
@@ -1281,8 +1281,8 @@ class RawAnthropicClient(
|
||||
)
|
||||
)
|
||||
case "input_json_delta":
|
||||
# Skip argument deltas for MCP tools — execution is handled server-side.
|
||||
if self._last_call_content_type == "mcp_tool_use":
|
||||
# Skip argument deltas for MCP and server tools — execution is handled server-side.
|
||||
if self._last_call_content_type in ("mcp_tool_use", "server_tool_use"):
|
||||
pass
|
||||
else:
|
||||
call_id = self._last_call_id_name[0] if self._last_call_id_name else ""
|
||||
|
||||
@@ -1144,6 +1144,53 @@ def test_parse_contents_from_anthropic_input_json_delta_no_duplicate_name(
|
||||
assert result[0].arguments == '"San Francisco"}'
|
||||
|
||||
|
||||
def test_parse_contents_server_tool_use_input_json_delta_ignored(
|
||||
mock_anthropic_client: MagicMock,
|
||||
) -> None:
|
||||
"""Regression test: input_json_delta events are ignored after a server_tool_use block.
|
||||
|
||||
Server-managed tools have their execution handled server-side, so streaming
|
||||
input_json_delta events must not produce Content.from_function_call(name='')
|
||||
entries that would cause Anthropic API 400 errors on subsequent turns.
|
||||
"""
|
||||
client = create_test_anthropic_client(mock_anthropic_client)
|
||||
|
||||
# Simulate a server_tool_use event that sets _last_call_content_type
|
||||
server_tool_content = MagicMock()
|
||||
server_tool_content.type = "server_tool_use"
|
||||
server_tool_content.id = "srvtool_abc"
|
||||
server_tool_content.name = "web_search"
|
||||
server_tool_content.input = {}
|
||||
|
||||
result = client._parse_contents_from_anthropic([server_tool_content])
|
||||
# server_tool_use falls through to function_call (not mcp_tool_use / code_execution)
|
||||
assert len(result) == 1
|
||||
assert result[0].type == "function_call"
|
||||
assert client._last_call_content_type == "server_tool_use" # type: ignore[attr-defined]
|
||||
|
||||
# input_json_delta events after server_tool_use must be silently ignored
|
||||
delta_content = MagicMock()
|
||||
delta_content.type = "input_json_delta"
|
||||
delta_content.partial_json = '{"query": "latest news"}'
|
||||
|
||||
result = client._parse_contents_from_anthropic([delta_content])
|
||||
assert result == [], (
|
||||
"input_json_delta after server_tool_use should produce no content, "
|
||||
"but got: %r" % result
|
||||
)
|
||||
|
||||
# A second delta must also be ignored
|
||||
delta_content_2 = MagicMock()
|
||||
delta_content_2.type = "input_json_delta"
|
||||
delta_content_2.partial_json = '{"extra": true}'
|
||||
|
||||
result = client._parse_contents_from_anthropic([delta_content_2])
|
||||
assert result == [], (
|
||||
"subsequent input_json_delta after server_tool_use should also be ignored, "
|
||||
"but got: %r" % result
|
||||
)
|
||||
|
||||
|
||||
# Stream Processing Tests
|
||||
|
||||
|
||||
|
||||
@@ -12,6 +12,9 @@ Supported MCP server types:
|
||||
- "http": Remote HTTP server
|
||||
- "sse": Remote SSE (Server-Sent Events) server
|
||||
|
||||
Environment variables:
|
||||
- ANTHROPIC_API_KEY: Your Anthropic API key
|
||||
|
||||
SECURITY NOTE: MCP servers can expose powerful capabilities. Only configure
|
||||
servers you trust. Use permission handlers to control what actions are allowed.
|
||||
"""
|
||||
|
||||
+7
@@ -15,6 +15,9 @@ Available built-in tools:
|
||||
- "Glob": Search for files by pattern
|
||||
- "Grep": Search file contents
|
||||
|
||||
Environment variables:
|
||||
- ANTHROPIC_API_KEY: Your Anthropic API key
|
||||
|
||||
SECURITY NOTE: Only enable permissions that are necessary for your use case.
|
||||
More permissions mean more potential for unintended actions.
|
||||
"""
|
||||
@@ -24,6 +27,10 @@ from typing import Any
|
||||
|
||||
from agent_framework.anthropic import ClaudeAgent
|
||||
from claude_agent_sdk import PermissionResultAllow, PermissionResultDeny
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Load environment variables from .env file
|
||||
load_dotenv()
|
||||
|
||||
|
||||
async def prompt_permission(
|
||||
|
||||
@@ -6,6 +6,9 @@ Claude Agent with Session Management
|
||||
This sample demonstrates session management with ClaudeAgent, showing
|
||||
persistent conversation capabilities. Sessions are automatically persisted
|
||||
by the Claude Code CLI.
|
||||
|
||||
Environment variables:
|
||||
- ANTHROPIC_API_KEY: Your Anthropic API key
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
@@ -14,8 +17,12 @@ from typing import Annotated
|
||||
|
||||
from agent_framework import tool
|
||||
from agent_framework.anthropic import ClaudeAgent
|
||||
from dotenv import load_dotenv
|
||||
from pydantic import Field
|
||||
|
||||
# Load environment variables from .env file
|
||||
load_dotenv()
|
||||
|
||||
|
||||
@tool
|
||||
def get_weather(
|
||||
|
||||
@@ -7,6 +7,9 @@ This sample demonstrates how to enable shell command execution with ClaudeAgent.
|
||||
By providing a permission handler via `can_use_tool`, the agent can execute
|
||||
shell commands to perform tasks like listing files, running scripts, or executing system commands.
|
||||
|
||||
Environment variables:
|
||||
- ANTHROPIC_API_KEY: Your Anthropic API key
|
||||
|
||||
SECURITY NOTE: Only enable shell permissions when you trust the agent's actions.
|
||||
Shell commands have full access to your system within the permissions of the running process.
|
||||
"""
|
||||
@@ -16,6 +19,10 @@ from typing import Any
|
||||
|
||||
from agent_framework.anthropic import ClaudeAgent
|
||||
from claude_agent_sdk import PermissionResultAllow, PermissionResultDeny
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Load environment variables from .env file
|
||||
load_dotenv()
|
||||
|
||||
|
||||
async def prompt_permission(
|
||||
|
||||
@@ -13,11 +13,18 @@ Available built-in tools:
|
||||
- "Edit": Edit existing files
|
||||
- "Glob": Search for files by pattern
|
||||
- "Grep": Search file contents
|
||||
|
||||
Environment variables:
|
||||
- ANTHROPIC_API_KEY: Your Anthropic API key
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
|
||||
from agent_framework.anthropic import ClaudeAgent
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Load environment variables from .env file
|
||||
load_dotenv()
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
|
||||
@@ -10,6 +10,9 @@ Available web tools:
|
||||
- "WebFetch": Fetch content from URLs
|
||||
- "WebSearch": Search the web
|
||||
|
||||
Environment variables:
|
||||
- ANTHROPIC_API_KEY: Your Anthropic API key
|
||||
|
||||
SECURITY NOTE: Only enable URL permissions when you trust the agent's actions.
|
||||
URL fetching allows the agent to access any URL accessible from your network.
|
||||
"""
|
||||
@@ -17,6 +20,10 @@ URL fetching allows the agent to access any URL accessible from your network.
|
||||
import asyncio
|
||||
|
||||
from agent_framework.anthropic import ClaudeAgent
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Load environment variables from .env file
|
||||
load_dotenv()
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
|
||||
@@ -21,6 +21,10 @@ This sample demonstrates using Anthropic with:
|
||||
You can also set additonal_chat_options with "additional_beta_flags" per request.
|
||||
- Creating an agent with the Code Interpreter tool and a Skill.
|
||||
- Catching and downloading generated files from the agent.
|
||||
|
||||
Environment variables:
|
||||
- ANTHROPIC_API_KEY: Your Anthropic API key
|
||||
- ANTHROPIC_CHAT_MODEL_ID: The Anthropic model to use, such as "claude-sonnet-4-5-20250929"
|
||||
"""
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user